diff options
author | Aaron <aaron@10gen.com> | 2009-02-03 19:13:27 -0500 |
---|---|---|
committer | Aaron <aaron@10gen.com> | 2009-02-03 19:13:27 -0500 |
commit | 48cfea2b1afd3fcc2ec5d0f423c9d952bae1f71c (patch) | |
tree | f5f0ec9c876518b686841cd245ba4558bfdf7f07 /db | |
parent | b4976fcb194d2ba5cbea9b5959ea448eea374607 (diff) | |
download | mongo-48cfea2b1afd3fcc2ec5d0f423c9d952bae1f71c.tar.gz |
Preserve old id on ipdate with no id spec
Diffstat (limited to 'db')
-rw-r--r-- | db/jsobj.h | 5 | ||||
-rw-r--r-- | db/pdfile.cpp | 51 | ||||
-rw-r--r-- | db/pdfile.h | 2 |
3 files changed, 39 insertions, 19 deletions
diff --git a/db/jsobj.h b/db/jsobj.h index bcd729b6518..c133b8db203 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -337,7 +337,7 @@ namespace mongo { */ int woCompare( const BSONElement &e, bool considerFieldName = true ) const; - const char * rawdata() { + const char * rawdata() const { return data; } @@ -356,7 +356,7 @@ namespace mongo { type() == CodeWScope; } - private: + protected: // If maxLen is specified, don't scan more than maxLen bytes. BSONElement(const char *d, int maxLen = -1) : data(d) { if ( eoo() ) @@ -372,6 +372,7 @@ namespace mongo { } totalSize = -1; } + private: const char *data; int fieldNameSize; mutable int totalSize; /* caches the computed size */ diff --git a/db/pdfile.cpp b/db/pdfile.cpp index 3515174f50d..226e37375f3 100644 --- a/db/pdfile.cpp +++ b/db/pdfile.cpp @@ -677,14 +677,15 @@ namespace mongo { NamespaceDetails *d = nsdetails(ns); + BSONObj objOld(toupdate); + BSONElement idOld; + int addID = 0; { /* duplicate _id check... */ BSONObj objNew(buf); - BSONObj objOld(toupdate); BSONElement idNew; + objOld.getObjectID(idOld); if( objNew.getObjectID(idNew) ) { - BSONElement idOld; - objOld.getObjectID(idOld); if( idOld == idNew ) ; else { @@ -699,8 +700,12 @@ namespace mongo { !Helpers::findOne(ns, b.done(), result)); } } + } else { + if ( !idOld.eoo() ) { + addID = len; + len += idOld.size(); + } } - } if ( toupdate->netLength() < len ) { @@ -715,7 +720,7 @@ namespace mongo { if ( database->profile ) ss << " moved "; deleteRecord(ns, toupdate, dl); - insert(ns, buf, len); + insert(ns, buf, len, false, idOld); return; } @@ -770,7 +775,13 @@ namespace mongo { } // update in place - memcpy(toupdate->data, buf, len); + if ( addID ) { + ((int&)*toupdate->data) = *((int*) buf) + idOld.size(); + memcpy(toupdate->data+4, idOld.rawdata(), idOld.size()); + memcpy(toupdate->data+4+idOld.size(), ((char *)buf)+4, addID-4); + } else { + memcpy(toupdate->data, buf, len); + } } int followupExtentSize(int len, int lastExtentLen) { @@ -892,19 +903,22 @@ namespace mongo { } #pragma pack(1) - struct IDToInsert { + struct IDToInsert_ { char type; char _id[4]; OID oid; - IDToInsert() { + IDToInsert_() { type = (char) jstOID; strcpy(_id, "_id"); - assert( sizeof(IDToInsert) == 17 ); + assert( sizeof(IDToInsert_) == 17 ); } + } idToInsert_; + struct IDToInsert : public BSONElement { + IDToInsert() : BSONElement( ( char * )( &idToInsert_ ) ) {} } idToInsert; #pragma pack() - - DiskLoc DataFileMgr::insert(const char *ns, const void *obuf, int len, bool god) { + + DiskLoc DataFileMgr::insert(const char *ns, const void *obuf, int len, bool god, const BSONElement &writeId) { bool addIndex = false; const char *sys = strstr(ns, "system."); if ( sys ) { @@ -988,6 +1002,7 @@ namespace mongo { //indexFullNS += name; // database.table.$index -- note this doesn't contain jsobjs, it contains BtreeBuckets. } + const BSONElement *newId = &writeId; int addID = 0; if( !god ) { /* Check if we have an _id field. If we don't, we'll add it. @@ -996,7 +1011,12 @@ namespace mongo { BSONObj io((const char *) obuf); if( !io.hasField("_id") && !addIndex && strstr(ns, ".local.") == 0 ) { addID = len; - len += sizeof(IDToInsert); + if ( writeId.eoo() ) { + // Very likely we'll add this elt, so little harm in init'ing here. + idToInsert_.oid.init(); + newId = &idToInsert; + } + len += newId->size(); } } @@ -1028,10 +1048,9 @@ namespace mongo { assert( r->lengthWithHeaders >= lenWHdr ); if( addID ) { /* a little effort was made here to avoid a double copy when we add an ID */ - idToInsert.oid.init(); - ((int&)*r->data) = *((int*) obuf) + sizeof(idToInsert); - memcpy(r->data+4, &idToInsert, sizeof(idToInsert)); - memcpy(r->data+4+sizeof(idToInsert), ((char *)obuf)+4, addID-4); + ((int&)*r->data) = *((int*) obuf) + newId->size(); + memcpy(r->data+4, newId->rawdata(), newId->size()); + memcpy(r->data+4+newId->size(), ((char *)obuf)+4, addID-4); // TEMP: BSONObj foo(r->data); cout << "TEMP:" << foo.toString() << endl; diff --git a/db/pdfile.h b/db/pdfile.h index 5358b91bfbd..7dc870adcfb 100644 --- a/db/pdfile.h +++ b/db/pdfile.h @@ -87,7 +87,7 @@ namespace mongo { const char *ns, Record *toupdate, const DiskLoc& dl, const char *buf, int len, stringstream& profiling); - DiskLoc insert(const char *ns, const void *buf, int len, bool god = false); + DiskLoc insert(const char *ns, const void *buf, int len, bool god = false, const BSONElement &writeId = BSONElement()); void deleteRecord(const char *ns, Record *todelete, const DiskLoc& dl, bool cappedOK = false); static auto_ptr<Cursor> findAll(const char *ns); |