main -》 mongoDbMain -> dataFileSync.go -> DataFileSync -> run
该线程不停运行下面的while循环。
可以看出每次检查的时间间隔1分钟。
这里主要的功能就是清空内存文件: MemoryMappedFile::flushAll
419 void run() {
420 Client::initThread( name().c_str() );
421 if( cmdLine.syncdelay == 0 )
422 log() << "warning: --syncdelay 0 is not recommended and can have strange performance" << endl;
423 else if( cmdLine.syncdelay == 1 )
424 log() << "--syncdelay 1" << endl;
425 else if( cmdLine.syncdelay != 60 )
426 LOG(1) << "--syncdelay " << cmdLine.syncdelay << endl;
427 int time_flushing = 0;
428 while ( ! inShutdown() ) {
429 _diaglog.flush();
430 log() << "[KAI] DataFileSync, start while" << endl;
431 if ( cmdLine.syncdelay == 0 ) {
432 // in case at some point we add an option to change at runtime
433 sleepsecs(5);
434 continue;
435 }
436
437 sleepmillis( (long long) std::max(0.0, (cmdLine.syncdelay * 1000) - time_flushing) );
438 log() << "[KAI] DataFileSync, start while 2" << endl;
439
440 if ( inShutdown() ) {
441 // occasional issue trying to flush during shutdown when sleep interrupted
442 break;
443 }
444
445 Date_t start = jsTime();
446 int numFiles = MemoryMappedFile::flushAll( true );
447 time_flushing = (int) (jsTime() - start);
448 log() << "[KAI] DataFileSync, start while 3" << endl;
449
450 _flushed(time_flushing);
451
452 if( logLevel >= 1 || time_flushing >= 10000 ) {
453 log() << "flushing mmaps took " << time_flushing << "ms " << " for " << numFiles << " files" << endl;
454 }
455 }
456 }
日志:
Fri Mar 8 14:18:20.824 [DataFileSync] [KAI] DataFileSync, start while
Fri Mar 8 14:19:20.810 [DataFileSync] [KAI] DataFileSync, start while 2
Fri Mar 8 14:19:20.838 [DataFileSync] [KAI] DataFileSync, start while 3
Fri Mar 8 14:19:20.838 [DataFileSync] [KAI] DataFileSync, start while
Fri Mar 8 14:20:20.837 [DataFileSync] [KAI] DataFileSync, start while 2
Fri Mar 8 14:20:20.838 [DataFileSync] [KAI] DataFileSync, start while 3
Fri Mar 8 14:20:20.838 [DataFileSync] [KAI] DataFileSync, start while
Fri Mar 8 14:21:20.838 [DataFileSync] [KAI] DataFileSync, start while 2
Fri Mar 8 14:21:20.855 [DataFileSync] [KAI] DataFileSync, start while 3
Fri Mar 8 14:21:20.855 [DataFileSync] [KAI] DataFileSync, start while
其中
446 int numFiles = MemoryMappedFile::flushAll( true );
调用的是基类的flushAll :
148 /*static*/ int MongoFile::flushAll( bool sync ) {
149 notifyPreFlush(); // 为空,还没有干什么事
150 int x = _flushAll(sync);
151 notifyPostFlush(); // 目前为空
152 return x;
153 }
-->
155 /*static*/ int MongoFile::_flushAll( bool sync ) {
156 if ( ! sync ) {
157 int num = 0;
158 LockMongoFilesShared lk;
159 for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) {
160 num++;
161 MongoFile * mmf = *i;
162 if ( ! mmf )
163 continue;
164
165 mmf->flush( sync );
166 }
167 return num;
168 }
169
170 // want to do it sync
171 set<MongoFile*> seen;//集合存放已经被flush过的 MF
172 while ( true ) {
173 auto_ptr<Flushable> f;
174 LockMongoFilesShared lk;
175 for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) {
176 MongoFile * mmf = *i;
177 if ( ! mmf )
178 continue;
179 if ( seen.count( mmf ) )
180 continue;
181 f.reset( mmf->prepareFlush() ); // 准备flush
182 seen.insert( mmf );
183 break;
184 }
185 if ( ! f.get() )
186 break;
187
188 f->flush(); // 准备flush // 执行flush
189 }
190 return seen.size();
191 }
这里面的for循环和while一起在用感觉有点多余,也许只需要一个for循环就行了,不知道为什么还要在外面加上一层while。 目前的时间复杂度就是O(n ^ 2) 了.
LockMongoFilesShared lk;
这里加锁,应该是为了防止其它插入的修改。 有待验证。
prepareFlush 为纯虚函数,在子类的实现是在 ./util/mmap_posix.cpp :
215 MemoryMappedFile::Flushable * MemoryMappedFile::prepareFlush() {
216 return new PosixFlushable( viewForFlushing() , fd , len );
217 }
218
148 virtual void* viewForFlushing() {
149 if( views.size() == 0 )
150 return 0;
151 verify( views.size() == 1 );
152 return views[0];
153 }
看样子,只取views[0] 了。 views是MemoryMappedFile 的private变量,之后我们去分析views是怎么来的? 为什么只认定为views.size为1的时候取出views[0]?
197 class PosixFlushable : public MemoryMappedFile::Flushable {
198 public:
199 PosixFlushable( void * view , HANDLE fd , long len )
200 : _view( view ) , _fd( fd ) , _len(len) {
201 }
202
203 void flush() {
204 if ( _view && _fd )
205 if ( msync(_view, _len, MS_SYNC ) )
206 problem() << "msync " << errnoWithDescription() << endl;
207
208 }
209
210 void * _view;
211 HANDLE _fd;
212 long _len;
213 };
在f->flush() 就调用了上面的 系统函数msync (内存同步文件)。
http://linux.die.net/man/3/msync http://hi.baidu.com/xwp007/item/9a6caed4492a4ee3b3f777f9