Example #1
0
DiskLoc NamespaceDetails::cappedAlloc(const char *ns, int len) {
    // signal done allocating new extents.
    if ( !cappedLastDelRecLastExtent().isValid() )
        getDur().writingDiskLoc( cappedLastDelRecLastExtent() ) = DiskLoc();

    assert( len < 400000000 );
    int passes = 0;
    int maxPasses = ( len / 30 ) + 2; // 30 is about the smallest entry that could go in the oplog
    if ( maxPasses < 5000 ) {
        // this is for bacwards safety since 5000 was the old value
        maxPasses = 5000;
    }
    DiskLoc loc;

    // delete records until we have room and the max # objects limit achieved.

    /* this fails on a rename -- that is ok but must keep commented out */
    //assert( theCapExtent()->ns == ns );

    theCapExtent()->assertOk();
    DiskLoc firstEmptyExtent;
    while ( 1 ) {
        if ( stats.nrecords < max ) {
            loc = __capAlloc( len );
            if ( !loc.isNull() )
                break;
        }

        // If on first iteration through extents, don't delete anything.
        if ( !capFirstNewRecord.isValid() ) {
            advanceCapExtent( ns );

            if ( capExtent != firstExtent )
                capFirstNewRecord.writing().setInvalid();
            // else signal done with first iteration through extents.
            continue;
        }

        if ( !capFirstNewRecord.isNull() &&
                theCapExtent()->firstRecord == capFirstNewRecord ) {
            // We've deleted all records that were allocated on the previous
            // iteration through this extent.
            advanceCapExtent( ns );
            continue;
        }

        if ( theCapExtent()->firstRecord.isNull() ) {
            if ( firstEmptyExtent.isNull() )
                firstEmptyExtent = capExtent;
            advanceCapExtent( ns );
            if ( firstEmptyExtent == capExtent ) {
                maybeComplain( ns, len );
                return DiskLoc();
            }
            continue;
        }

        DiskLoc fr = theCapExtent()->firstRecord;
        theDataFileMgr.deleteRecord(ns, fr.rec(), fr, true); // ZZZZZZZZZZZZ
        compact();
        if( ++passes > maxPasses ) {
            log() << "passes ns:" << ns << " len:" << len << " maxPasses: " << maxPasses << '\n';
            log() << "passes max:" << max << " nrecords:" << stats.nrecords << " datasize: " << stats.datasize << endl;
            massert( 10345 ,  "passes >= maxPasses in capped collection alloc", false );
        }
    }

    // Remember first record allocated on this iteration through capExtent.
    if ( capFirstNewRecord.isValid() && capFirstNewRecord.isNull() )
        getDur().writingDiskLoc(capFirstNewRecord) = loc;

    return loc;
}
Example #2
0
    DiskLoc NamespaceDetails::cappedAlloc(const char *ns, int len) {
        
        if ( len > theCapExtent()->length ) {
            // the extent check is a way to try and improve performance
            uassert( 16328 , str::stream() << "document is larger than capped size " 
                     << len << " > " << storageSize() , len <= storageSize() );
        }
        
        // signal done allocating new extents.
        if ( !cappedLastDelRecLastExtent().isValid() )
            getDur().writingDiskLoc( cappedLastDelRecLastExtent() ) = DiskLoc();

        verify( len < 400000000 );
        int passes = 0;
        int maxPasses = ( len / 30 ) + 2; // 30 is about the smallest entry that could go in the oplog
        if ( maxPasses < 5000 ) {
            // this is for bacwards safety since 5000 was the old value
            maxPasses = 5000;
        }
        DiskLoc loc;

        // delete records until we have room and the max # objects limit achieved.

        /* this fails on a rename -- that is ok but must keep commented out */
        //verify( theCapExtent()->ns == ns );

        theCapExtent()->assertOk();
        DiskLoc firstEmptyExtent;
        while ( 1 ) {
            if ( stats.nrecords < maxCappedDocs() ) {
                loc = __capAlloc( len );
                if ( !loc.isNull() )
                    break;
            }

            // If on first iteration through extents, don't delete anything.
            if ( !capFirstNewRecord.isValid() ) {
                advanceCapExtent( ns );

                if ( capExtent != firstExtent )
                    capFirstNewRecord.writing().setInvalid();
                // else signal done with first iteration through extents.
                continue;
            }

            if ( !capFirstNewRecord.isNull() &&
                    theCapExtent()->firstRecord == capFirstNewRecord ) {
                // We've deleted all records that were allocated on the previous
                // iteration through this extent.
                advanceCapExtent( ns );
                continue;
            }

            if ( theCapExtent()->firstRecord.isNull() ) {
                if ( firstEmptyExtent.isNull() )
                    firstEmptyExtent = capExtent;
                advanceCapExtent( ns );
                if ( firstEmptyExtent == capExtent ) {
                    maybeComplain( ns, len );
                    return DiskLoc();
                }
                continue;
            }

            DiskLoc fr = theCapExtent()->firstRecord;
            theDataFileMgr.deleteRecord(this, ns, fr.rec(), fr, true); // ZZZZZZZZZZZZ
            compact();
            if( ++passes > maxPasses ) {
                StringBuilder sb;
                sb << "passes >= maxPasses in NamespaceDetails::cappedAlloc: ns: " << ns
                   << ", len: " << len
                   << ", maxPasses: " << maxPasses
                   << ", _maxDocsInCapped: " << _maxDocsInCapped
                   << ", nrecords: " << stats.nrecords
                   << ", datasize: " << stats.datasize;
                msgasserted(10345, sb.str());
            }
        }

        // Remember first record allocated on this iteration through capExtent.
        if ( capFirstNewRecord.isValid() && capFirstNewRecord.isNull() )
            getDur().writingDiskLoc(capFirstNewRecord) = loc;

        return loc;
    }