示例#1
0
void dbrm_clear()
{
	DBRM dbrm;
	VSS vss;
	VBBM vbbm;
	int err, vssShmid, vbbmShmid, txnID = 1, i;
	struct shmid_ds vssShminfo[3], vbbmShminfo[3];
	LBIDRange_v ranges;
	LBIDRange range;
	VBRange_v freelist;

 	err = dbrm.clear();
 	CPPUNIT_ASSERT(err == ERR_OK);
	
	// grab the size of vss and vbbm shmsegs somehow
	vss.lock(VSS::READ);
	vbbm.lock(VBBM::READ);
	vssShmid = vss.getShmid();
	vbbmShmid = vbbm.getShmid();
	err = shmctl(vssShmid, IPC_STAT, &vssShminfo[0]);
	CPPUNIT_ASSERT(err == 0);
	err = shmctl(vbbmShmid, IPC_STAT, &vbbmShminfo[0]);
	CPPUNIT_ASSERT(err == 0);
	vss.release(VSS::READ);
	vbbm.release(VBBM::READ);

	// do begin, write, end vbcopy for 150k blocks
	cerr << endl << "Adding 150k block entries. ";
	range.start = 1;
	range.size = 150000;
	ranges.push_back(range);
	err = dbrm.beginVBCopy(txnID, ranges, freelist);
	CPPUNIT_ASSERT(err == 0);

	for (i = range.start; (uint32_t) i < range.size; i++) {
		if (i % 50000 == 0)
			cerr << " ... " << i;
		err = dbrm.writeVBEntry(txnID, i, 1, i);
		CPPUNIT_ASSERT(err == 0);
	}
	err = dbrm.endVBCopy(txnID, ranges);
	CPPUNIT_ASSERT(err == 0);
	cerr << "  done." << endl;

	// grab the sizes again
	vss.lock(VSS::READ);
	vbbm.lock(VBBM::READ);
	vssShmid = vss.getShmid();
	vbbmShmid = vbbm.getShmid();
	err = shmctl(vssShmid, IPC_STAT, &vssShminfo[1]);
	CPPUNIT_ASSERT(err == 0);
	err = shmctl(vbbmShmid, IPC_STAT, &vbbmShminfo[1]);
	CPPUNIT_ASSERT(err == 0);
	vss.release(VSS::READ);
	vbbm.release(VBBM::READ);

	// make sure they grew
	CPPUNIT_ASSERT(vssShminfo[0].shm_segsz < vssShminfo[1].shm_segsz);
	CPPUNIT_ASSERT(vbbmShminfo[0].shm_segsz < vbbmShminfo[1].shm_segsz);

	dbrm.clear();

	// check that the new size is the same as the original
	vss.lock(VSS::READ);
	vbbm.lock(VBBM::READ);
	vssShmid = vss.getShmid();
	vbbmShmid = vbbm.getShmid();
	err = shmctl(vssShmid, IPC_STAT, &vssShminfo[2]);
	CPPUNIT_ASSERT(err == 0);
	err = shmctl(vbbmShmid, IPC_STAT, &vbbmShminfo[2]);
	CPPUNIT_ASSERT(err == 0);
	vss.release(VSS::READ);
	vbbm.release(VBBM::READ);

	CPPUNIT_ASSERT(vssShminfo[0].shm_segsz == vssShminfo[2].shm_segsz);
	CPPUNIT_ASSERT(vbbmShminfo[0].shm_segsz == vbbmShminfo[2].shm_segsz);

}
示例#2
0
//assumes write lock
void VBBM::getBlocks(int num, OID_t vbOID, vector<VBRange>& freeRanges, VSS& vss, bool flushPMCache)
{
	int blocksLeftInFile, blocksGathered = 0, i;
	uint32_t fileIndex;
	uint32_t firstFBO, lastFBO;
	VBRange range;
	vector<VBRange>::iterator it;
	vector<LBID_t> flushList;

	freeRanges.clear();

	fileIndex = addVBFileIfNotExists(vbOID);

	/*
	for (i = 0; i < vbbm->nFiles; i++) {
		cout << "file " << i << " vbOID=" << files[i].OID << " size=" << files[i].fileSize
				<< endl;
	}
	*/

	if ((uint32_t) num > files[fileIndex].fileSize/BLOCK_SIZE) {
		cout << "num = " << num << " filesize = " << files[fileIndex].fileSize << endl;
		log("VBBM::getBlocks(): num is larger than the size of the version buffer",
				logging::LOG_TYPE_DEBUG);
		throw logging::VBBMBufferOverFlowExcept
			("VBBM::getBlocks(): num is larger than the size of the version buffer");
	}

	while ((vbbm->vbCurrentSize + num) > vbbm->vbCapacity) {
		growVBBM();
		//cout << " requested num = " << num << " and Growing vbbm ... " << endl;
	}

	while (blocksGathered < num) {
		blocksLeftInFile = (files[fileIndex].fileSize - files[fileIndex].nextOffset)/BLOCK_SIZE;
		int blocksLeft = num - blocksGathered;

		range.vbOID = files[fileIndex].OID;
		range.vbFBO = files[fileIndex].nextOffset/BLOCK_SIZE;
		range.size = (blocksLeftInFile >= blocksLeft ? blocksLeft : blocksLeftInFile);
		makeUndoRecord(&files[fileIndex], sizeof(VBFileMetadata));
		if (range.size == (uint32_t) blocksLeftInFile)
			files[fileIndex].nextOffset = 0;
		else
			files[fileIndex].nextOffset += range.size * BLOCK_SIZE;
		blocksGathered += range.size;
		freeRanges.push_back(range);
	}

	//age the returned blocks out of the VB
	for (it = freeRanges.begin(); it != freeRanges.end(); it++) {
		uint32_t firstChunk, lastChunk;

		vbOID = it->vbOID;
		firstFBO = it->vbFBO;
		lastFBO = it->vbFBO + it->size - 1;

		/* Age out at least 100 blocks at a time to reduce the # of times we have to do it.
		 * How to detect when it needs to be done and when it doesn't?
		 *
		 * Split VB space into 100-block chunks.  When a chunk boundary is crossed,
		 * clear the whole chunk.
		 */

		firstChunk = firstFBO/VBBM_CHUNK_SIZE;
		lastChunk = lastFBO/VBBM_CHUNK_SIZE;

		// if the current range falls in the middle of a chunk and doesn't span chunks,
		// there's nothing to do b/c the chunk is assumed to have been cleared already
		if (((firstFBO % VBBM_CHUNK_SIZE) != 0) && (firstChunk == lastChunk))
			continue;

		// round up to the next chunk boundaries
		if ((firstFBO % VBBM_CHUNK_SIZE) != 0)   // this implies the range spans chunks
			firstFBO = (firstChunk + 1) * VBBM_CHUNK_SIZE;  // the first FBO of the next chunk
		lastFBO = ((lastChunk + 1) * VBBM_CHUNK_SIZE - 1);  // the last FBO of the last chunk

		// don't go past the end of the file
		if (lastFBO > files[fileIndex].fileSize/BLOCK_SIZE)
			lastFBO = files[fileIndex].fileSize/BLOCK_SIZE;

		// at this point [firstFBO, lastFBO] is the range to age out.

		// ugh, walk the whole vbbm looking for matches.
		for (i = 0; i < vbbm->vbCapacity; i++)
			if (storage[i].lbid != -1 && storage[i].vbOID == vbOID &&
			  storage[i].vbFBO >= firstFBO && storage[i].vbFBO <= lastFBO) {
				if (vss.isEntryLocked(storage[i].lbid, storage[i].verID)) {
					ostringstream msg;
					msg << "VBBM::getBlocks(): version buffer overflow. Increase VersionBufferFileSize. Overflow occured in aged blocks. Requested NumBlocks:VbOid:vbFBO:lastFBO = "
					<< num << ":" << vbOID <<":" << firstFBO << ":" << lastFBO <<" lbid locked is " << storage[i].lbid << endl;
					log(msg.str(), logging::LOG_TYPE_CRITICAL);
					freeRanges.clear();
					throw logging::VBBMBufferOverFlowExcept(msg.str());
				}
				vss.removeEntry(storage[i].lbid, storage[i].verID, &flushList);
				removeEntry(storage[i].lbid, storage[i].verID);
			}
	}
	if (flushPMCache && !flushList.empty())
		cacheutils::flushPrimProcAllverBlocks(flushList);
}
示例#3
0
	// cut & pasted from brm_good_2(), but with rollback instead of commit.
	void brm_good_3()
	{
		DBRM brm;
		VBBM vbbm;
		VSS vss;
		CopyLocks cl;
		int i, err, size;
		vector<LBID_t> lbids;
		vector<LBID_t>::iterator lbid;
		vector<EMEntry> extents;
		LBIDRange_v ranges;
		LBIDRange_v::iterator lbidRangeIT;
		VBRange_v vbRanges, vbRanges2;
		VBRange_v::iterator vbRangesIT;
		LBIDRange_v tmp;
		EMEntry em;
		OID_t oid;
		uint32_t fbo;
		LBIDRange range;
		VBRange vbRange;
		VER_t verID;
		bool vbFlag;
		bool caughtException;
		
		// Buildbot times out on the getBlocks() call during leakcheck b/c it takes
		// > 5 mins for some reason.  Have to ping it before 300 seconds go by.
		void (*oldsig)(int);
		
 		cerr << "brm_good_3" << endl;

		oldsig = signal(SIGALRM, keepalive);
		alarm(290);
		
 		err = brm.lookup(0, 0, false, oid, fbo);
 		CPPUNIT_ASSERT(err != 0); 
		err = brm.lookup(0, 0, true, oid, fbo);
		CPPUNIT_ASSERT(err != 0);
		
 		err = brm.createExtent(8000, 1, lbids, size);
 		CPPUNIT_ASSERT(err == 0);
 		CPPUNIT_ASSERT(size == brm.getExtentSize());
 		CPPUNIT_ASSERT(lbids.size() == 1);
  		CPPUNIT_ASSERT(*(lbids.begin()) == 0);
		
		err = brm.getExtents(1, extents);
		CPPUNIT_ASSERT(err == 0);
		CPPUNIT_ASSERT(extents.size() == 1);
		
		em = *(extents.begin());
 		CPPUNIT_ASSERT(em.range.start == 0);
		CPPUNIT_ASSERT(em.range.size*1024 == static_cast<uint32_t>(brm.getExtentSize()));
		CPPUNIT_ASSERT(em.HWM == 0);
		CPPUNIT_ASSERT(em.blockOffset == 0);
		
		for (i = 0; i < 5; i++) {
			range.start = i * 100;
			range.size = 100;
			ranges.push_back(range);
		}

		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		err = brm.beginVBCopy(1, ranges, vbRanges);
		CPPUNIT_ASSERT(err == 0);
		
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		cl.lock(CopyLocks::READ);
		for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end(); 
				   lbidRangeIT++)
			CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));
		cl.release(CopyLocks::READ);
		
		err = brm.beginVBCopy(1, ranges, vbRanges2);
		CPPUNIT_ASSERT(err != 0);
		
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		cl.lock(CopyLocks::READ);
		for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end(); 
				   lbidRangeIT++)
			CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));
		cl.release(CopyLocks::READ);
		
		for (i = 0; i < 500; i++) {
			verID = MAXINT;
			err = brm.vssLookup(i, verID, 1, vbFlag);
			CPPUNIT_ASSERT(err != 0);
		}
		
		vbRange = *(vbRanges.begin());
// 		CPPUNIT_ASSERT(vbRange.vbFBO == 0);
		for (i = 0; i < (int)vbRange.size; i++) {
			err = brm.writeVBEntry(1, i, vbRange.vbOID, vbRange.vbFBO + i);
			CPPUNIT_ASSERT(err == 0);
		}
		
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		for (i = 0; i < (int)vbRange.size; i++) { 
			verID = MAXINT;
			err = brm.vssLookup(i, verID, 1, vbFlag);
			CPPUNIT_ASSERT(err == 0);
			CPPUNIT_ASSERT(verID == 1);
			CPPUNIT_ASSERT(vbFlag == false);
			verID = MAXINT;
			err = brm.vssLookup(i, verID, 0, vbFlag);
			CPPUNIT_ASSERT(err == 0);
			CPPUNIT_ASSERT(verID == 0);
			CPPUNIT_ASSERT(vbFlag == true);
		}
		
		for (; i < 500; i++) {
			verID = MAXINT;
			err = brm.vssLookup(i, verID, 1, vbFlag);
			CPPUNIT_ASSERT(err != 0);
		}
					
		err = brm.endVBCopy(0, ranges);
			
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		cl.lock(CopyLocks::READ);
		for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end(); 
				   lbidRangeIT++)
			CPPUNIT_ASSERT(!cl.isLocked(*lbidRangeIT));
		cl.release(CopyLocks::READ);
		
		err = brm.getUncommittedLBIDs(1, lbids);
		CPPUNIT_ASSERT(err == 0);
		CPPUNIT_ASSERT(lbids.size() == vbRange.size);
		sort<vector<LBID_t>::iterator>(lbids.begin(), lbids.end());
		lbid = lbids.begin();
		for (i = 0; i < static_cast<int>(lbids.size()); i++, lbid++)
			CPPUNIT_ASSERT((*lbid) == static_cast<LBID_t>(i));
		
		range.start = 0;
		range.size = i;
		tmp.push_back(range);
		err = brm.vbRollback(1, tmp);
		CPPUNIT_ASSERT(err == 0);
		
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		for (i = 0; i < (int)vbRange.size; i++) { 
			verID = MAXINT;
			
			err = brm.vssLookup(i, verID, 0, vbFlag);
			CPPUNIT_ASSERT(err == 0);
			CPPUNIT_ASSERT(verID == 0);
			CPPUNIT_ASSERT(vbFlag == false);
			
			err = brm.lookup(i, verID, vbFlag, oid, fbo);
			CPPUNIT_ASSERT(err == 0);
 			CPPUNIT_ASSERT(oid == 1);
			CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i));
			
			vbbm.lock(VBBM::WRITE);
			vss.lock(VSS::WRITE);

#ifdef BRM_DEBUG
 			caughtException = false;
			try {
				vbbm.removeEntry(i, verID);
				vbbm.confirmChanges();
			}
			catch (logic_error &e) {
				vbbm.undoChanges();
				caughtException = true;
			}
			CPPUNIT_ASSERT(caughtException);
			caughtException = false;
			try {
				vss.removeEntry(i, 1);
				vss.confirmChanges();
			}
			catch (logic_error &e) {
				vss.undoChanges();
				caughtException = true;
			}
			CPPUNIT_ASSERT(caughtException);
#endif

			vss.removeEntry(i, verID);
			vss.confirmChanges();
			vss.release(VSS::WRITE);
			vbbm.release(VBBM::WRITE);
		}
		
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);
		
		brm.deleteOID(1);
		
		vbbm.lock(VBBM::READ);
		vss.lock(VSS::READ);
		CPPUNIT_ASSERT(vbbm.size() == 0);
		CPPUNIT_ASSERT(vbbm.hashEmpty());
		CPPUNIT_ASSERT(vss.size() == 0);
		CPPUNIT_ASSERT(vss.hashEmpty());
		vss.release(VSS::READ);
		vbbm.release(VBBM::READ);
		
		CPPUNIT_ASSERT(brm.checkConsistency() == 0);

		err = brm.saveState();
		CPPUNIT_ASSERT(err==0);
	}
    void brm_good_2()
    {
        BlockResolutionManager brm;
        VBBM vbbm;
        VSS vss;
        CopyLocks cl;
        int i, err, size;
        vector<LBID_t> lbids;
        vector<EMEntry> extents;
        LBIDRange_v ranges;
        LBIDRange_v::iterator lbidRangeIT;
        VBRange_v vbRanges, vbRanges2;
        VBRange_v::iterator vbRangesIT;
        EMEntry em;
        OID_t oid;
        uint32_t fbo;
        LBIDRange range;
        VBRange vbRange;
        VER_t verID;
        bool vbFlag;

        // Buildbot times out on the getBlocks() call during leakcheck b/c it takes
        // > 5 mins for some reason.  Have to ping it before 300 seconds go by.
        void (*oldsig)(int);

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        oldsig = signal(SIGALRM, keepalive);
        alarm(290);

        err = brm.lookup(0, 0, false, oid, fbo);
        CPPUNIT_ASSERT(err == -1);
        err = brm.lookup(0, 0, true, oid, fbo);
        CPPUNIT_ASSERT(err == -1);

        err = brm.createExtent(10000, 0, lbids, size);
        CPPUNIT_ASSERT(err == 0);
        CPPUNIT_ASSERT(size == brm.getExtentSize());
        CPPUNIT_ASSERT(lbids.size() == 1);
//  		CPPUNIT_ASSERT(*(lbids.begin()) == 0);

        err = brm.getExtents(0, extents);
        CPPUNIT_ASSERT(err == 0);
        CPPUNIT_ASSERT(extents.size() == 1);

        em = *(extents.begin());
// 		CPPUNIT_ASSERT(em.range.start == 0);
        CPPUNIT_ASSERT(em.range.size * 1024 == static_cast<uint32_t>(brm.getExtentSize()));
        CPPUNIT_ASSERT(em.HWM == 0);
        CPPUNIT_ASSERT(em.blockOffset == 0);

        for (i = 0; i < 50; i++)
        {
            range.start = i * 100;
            range.size = 100;
            ranges.push_back(range);
        }

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        err = brm.beginVBCopy(1, ranges, vbRanges);
        CPPUNIT_ASSERT(err == 0);

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        cl.lock(CopyLocks::READ);

        for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
                lbidRangeIT++)
            CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));

        cl.release(CopyLocks::READ);

        err = brm.beginVBCopy(1, ranges, vbRanges2);
        CPPUNIT_ASSERT(err == -1);

        cl.lock(CopyLocks::READ);

        for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
                lbidRangeIT++)
            CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));

        cl.release(CopyLocks::READ);

        for (i = 0; i < 5000; i++)
        {
            verID = MAXINT;
            err = brm.vssLookup(i, verID, 1, vbFlag);
            CPPUNIT_ASSERT(err == -1);
        }

        vbRange = *(vbRanges.begin());

// 		CPPUNIT_ASSERT(vbRange.vbFBO == 0);
        for (i = 0; i < (int)vbRange.size; i++)
        {
            err = brm.writeVBEntry(1, i, vbRange.vbOID, vbRange.vbFBO + i);
            CPPUNIT_ASSERT(err == 0);
        }

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        for (i = 0; i < (int)vbRange.size; i++)
        {
            verID = MAXINT;
            err = brm.vssLookup(i, verID, 1, vbFlag);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(verID == 1);
            CPPUNIT_ASSERT(vbFlag == false);
            verID = MAXINT;
            err = brm.vssLookup(i, verID, 0, vbFlag);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(verID == 0);
            CPPUNIT_ASSERT(vbFlag == true);
        }

        for (; i < 5000; i++)
        {
            verID = MAXINT;
            err = brm.vssLookup(i, verID, 1, vbFlag);
            CPPUNIT_ASSERT(err == -1);
        }

        err = brm.endVBCopy(0, ranges);

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        cl.lock(CopyLocks::READ);

        for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
                lbidRangeIT++)
            CPPUNIT_ASSERT(!cl.isLocked(*lbidRangeIT));

        cl.release(CopyLocks::READ);

        brm.vbCommit(1);

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        for (i = 0; i < (int)vbRange.size; i++)
        {
            verID = MAXINT;
            err = brm.vssLookup(i, verID, 0, vbFlag);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(verID == 1);
            CPPUNIT_ASSERT(vbFlag == false);

            verID = 0;
            err = brm.vssLookup(i, verID, 0, vbFlag);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(verID == 0);
            CPPUNIT_ASSERT(vbFlag == true);

            err = brm.lookup(i, verID, vbFlag, oid, fbo);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(oid == vbRange.vbOID);
            CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i + vbRange.vbFBO));

            vbbm.lock(VBBM::WRITE);
            vss.lock(VSS::WRITE);
            vbbm.removeEntry(i, verID);
// 			vss.removeEntry(i, 1);
            vss.removeEntry(i, verID);
            vss.release(VSS::WRITE);
            vbbm.release(VBBM::WRITE);
        }

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

        brm.deleteOID(0);

        vss.lock(VSS::READ);
        vbbm.lock(VBBM::READ);
        CPPUNIT_ASSERT(vbbm.size() == 0);
        CPPUNIT_ASSERT(vbbm.hashEmpty());
        CPPUNIT_ASSERT(vss.size() == 0);
        CPPUNIT_ASSERT(vss.hashEmpty());
        vss.release(VSS::READ);
        vbbm.release(VBBM::READ);

        CPPUNIT_ASSERT(brm.checkConsistency() == 0);

    }