00001
00002
00019 #pragma once
00020
00021 #include "../pch.h"
00022 #include "jsobj.h"
00023 #include "namespace-inl.h"
00024 #include "curop-inl.h"
00025 #include "../util/array.h"
00026
00027 namespace mongo {
00028
00029
00033 class BSONObjExternalSorter : boost::noncopyable {
00034 public:
00035
00036 typedef pair<BSONObj,DiskLoc> Data;
00037
00038 private:
00039 static BSONObj extSortOrder;
00040
00041 static int extSortComp( const void *lv, const void *rv ) {
00042 RARELY killCurrentOp.checkForInterrupt();
00043 _compares++;
00044 Data * l = (Data*)lv;
00045 Data * r = (Data*)rv;
00046 int cmp = l->first.woCompare( r->first , extSortOrder );
00047 if ( cmp )
00048 return cmp;
00049 return l->second.compare( r->second );
00050 };
00051
00052 class FileIterator : boost::noncopyable {
00053 public:
00054 FileIterator( string file );
00055 ~FileIterator();
00056 bool more();
00057 Data next();
00058 private:
00059 MemoryMappedFile _file;
00060 char * _buf;
00061 char * _end;
00062 };
00063
00064 class MyCmp {
00065 public:
00066 MyCmp( const BSONObj & order = BSONObj() ) : _order( order ) {}
00067 bool operator()( const Data &l, const Data &r ) const {
00068 RARELY killCurrentOp.checkForInterrupt();
00069 _compares++;
00070 int x = l.first.woCompare( r.first , _order );
00071 if ( x )
00072 return x < 0;
00073 return l.second.compare( r.second ) < 0;
00074 };
00075
00076 private:
00077 BSONObj _order;
00078 };
00079
00080 public:
00081
00082 typedef FastArray<Data> InMemory;
00083
00084 class Iterator : boost::noncopyable {
00085 public:
00086
00087 Iterator( BSONObjExternalSorter * sorter );
00088 ~Iterator();
00089 bool more();
00090 Data next();
00091
00092 private:
00093 MyCmp _cmp;
00094 vector<FileIterator*> _files;
00095 vector< pair<Data,bool> > _stash;
00096
00097 InMemory * _in;
00098 InMemory::iterator _it;
00099
00100 };
00101
00102 BSONObjExternalSorter( const BSONObj & order = BSONObj() , long maxFileSize = 1024 * 1024 * 100 );
00103 ~BSONObjExternalSorter();
00104
00105 void add( const BSONObj& o , const DiskLoc & loc );
00106 void add( const BSONObj& o , int a , int b ) {
00107 add( o , DiskLoc( a , b ) );
00108 }
00109
00110
00111 void sort();
00112
00113 auto_ptr<Iterator> iterator() {
00114 uassert( 10052 , "not sorted" , _sorted );
00115 return auto_ptr<Iterator>( new Iterator( this ) );
00116 }
00117
00118 int numFiles() {
00119 return _files.size();
00120 }
00121
00122 long getCurSizeSoFar() { return _curSizeSoFar; }
00123
00124 void hintNumObjects( long long numObjects ) {
00125 if ( numObjects < _arraySize )
00126 _arraySize = (int)(numObjects + 100);
00127 }
00128
00129 private:
00130
00131 void _sortInMem();
00132
00133 void sort( string file );
00134 void finishMap();
00135
00136 BSONObj _order;
00137 long _maxFilesize;
00138 path _root;
00139
00140 int _arraySize;
00141 InMemory * _cur;
00142 long _curSizeSoFar;
00143
00144 list<string> _files;
00145 bool _sorted;
00146
00147 static unsigned long long _compares;
00148 };
00149 }