NamespaceDetails::Extra* NamespaceDetails::allocExtra(OperationContext* txn, StringData ns, NamespaceIndex& ni, int nindexessofar) { // Namespace details must always be changed under an exclusive DB lock const NamespaceString nss(ns); invariant(txn->lockState()->isDbLockedForMode(nss.db(), MODE_X)); int i = (nindexessofar - NIndexesBase) / NIndexesExtra; verify(i >= 0 && i <= 1); Namespace fullns(ns); Namespace extrans(fullns.extraName(i)); // throws UserException if ns name too long massert(10350, "allocExtra: base ns missing?", this); massert(10351, "allocExtra: extra already exists", ni.details(extrans) == 0); Extra temp; temp.init(); ni.add_ns(txn, extrans, reinterpret_cast<NamespaceDetails*>(&temp)); Extra* e = reinterpret_cast<NamespaceDetails::Extra*>(ni.details(extrans)); long ofs = e->ofsFrom(this); if (i == 0) { verify(_extraOffset == 0); *txn->recoveryUnit()->writing(&_extraOffset) = ofs; verify(extra() == e); } else { Extra* hd = extra(); verify(hd->next(this) == 0); hd->setNext(txn, ofs); } return e; }
// must be called when renaming a NS to fix up extra void NamespaceDetails::copyingFrom( OperationContext* txn, const StringData& thisns, NamespaceIndex& ni, NamespaceDetails* src) { _extraOffset = 0; // we are a copy -- the old value is wrong. fixing it up below. Extra *se = src->extra(); int n = NIndexesBase; if( se ) { Extra *e = allocExtra(txn, thisns, ni, n); while( 1 ) { n += NIndexesExtra; e->copy(this, *se); se = se->next(src); if( se == 0 ) break; Extra *nxt = allocExtra(txn, thisns, ni, n); e->setNext( txn, nxt->ofsFrom(this) ); e = nxt; } verify( _extraOffset ); } }