void extentMap_freelist()
    {
        ExtentMap em;
        int i, allocdSize, iterations = 1400;  // (EM_INITIAL_SIZE + 4*EM_INCREMENT)
        vector<LBID_t> lbids;
        const int extentSize = em.getExtentSize();

        for (i = 0; i < iterations; i++)
        {
            em.createExtent(extentSize, i, lbids, allocdSize);
            em.confirmChanges();
            CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>(i * extentSize));
        }

        em.checkConsistency();

        //frag the lbid space to blow up the free list
        for (i = 0; i < iterations; i += 2)
        {
            em.deleteOID(i);
            em.confirmChanges();
        }

        em.checkConsistency();

        //fill in the holes
        for (i = 0; i < iterations; i += 2)
        {
            em.createExtent(extentSize, i, lbids, allocdSize);
            em.confirmChanges();
        }

        for (i = 0; i < iterations; i += 2)
        {
            em.deleteOID(i);
            em.confirmChanges();
        }

        for (i = 1; i < iterations; i += 2)
        {
            em.deleteOID(i);
            em.confirmChanges();
        }

        em.checkConsistency();
    }
    void extentMap_good_1()
    {
        ExtentMap em;
        int i, err, oid, iterations = 1300;  // (EM_INITIAL_SIZE + 3*EM_INCREMENT)
        int caughtException = 0, allocdSize;
        uint32_t fbo, hwm;
        BRM::HWM_t hwm2;
        BRM::VER_t txnID;
        vector<LBID_t> lbids;
        const uint32_t extentSize = em.getExtentSize();

        em.load(string("EMImage"));
        em.checkConsistency();

        for (i = 0; i < iterations; i++)
        {
            err = em.lookup(static_cast<LBID_t>(i * extentSize), oid, fbo);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(oid == i);
            CPPUNIT_ASSERT(fbo == 0);

            if (i != 0)
            {
                err = em.lookup(static_cast<LBID_t>(i * extentSize - 1), oid, fbo);
                CPPUNIT_ASSERT(err == 0);
                CPPUNIT_ASSERT(oid == i - 1);
                CPPUNIT_ASSERT(fbo == extentSize - 1);
            }

            if (i != iterations - 1)
            {
                err = em.lookup(static_cast<LBID_t>(i * extentSize + 1), oid, fbo);
                CPPUNIT_ASSERT(err == 0);
                CPPUNIT_ASSERT(oid == i);
                CPPUNIT_ASSERT(fbo == 1);
            }
        }

        em.checkConsistency();

        err = em.lookup(static_cast<LBID_t>(i * extentSize), oid, fbo);
        CPPUNIT_ASSERT(err == -1);

        for (i = 0; i < iterations; i++)
        {
            err = em.getBulkInsertVars(static_cast<LBID_t>(i * extentSize),
                                       hwm2, txnID);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(hwm2 == 0);
            CPPUNIT_ASSERT(txnID == 0);
            err = em.setBulkInsertVars(static_cast<LBID_t>(i * extentSize),
                                       i, i + 1);
            em.confirmChanges();
            CPPUNIT_ASSERT(err == 0);
            err = em.getBulkInsertVars(static_cast<LBID_t>(i * extentSize),
                                       hwm2, txnID);
            CPPUNIT_ASSERT(err == 0);
            CPPUNIT_ASSERT(hwm2 == static_cast<LBID_t>(i));
            CPPUNIT_ASSERT(txnID == static_cast<VER_t>(i + 1));

            hwm = em.getHWM(i);
            CPPUNIT_ASSERT(hwm == 0);
            em.setHWM(i, (i > (extentSize - 1) ? extentSize - 1 : i));
            em.confirmChanges();
            hwm = em.getHWM(i);
            CPPUNIT_ASSERT(hwm == static_cast<uint32_t>(i > extentSize - 1 ? extentSize - 1 : i));
        }

        em.checkConsistency();

#ifdef BRM_DEBUG
        caughtException = 0;

        try
        {
            em.setHWM(i, hwm);
        }
        catch (std::invalid_argument e)
        {
            caughtException = 1;
        }

        em.undoChanges();
        CPPUNIT_ASSERT(caughtException == 1);
#endif

        for (i = 0; i < iterations; i++)
        {
            em.deleteOID(i);
            em.confirmChanges();
        }

#ifdef BRM_DEBUG
        caughtException = 0;

        try
        {
            em.deleteOID(i);
        }
        catch (std::invalid_argument& e)
        {
            caughtException = 1;
        }

        em.undoChanges();
        CPPUNIT_ASSERT(caughtException == 1);
#endif

        em.checkConsistency();
    }
Beispiel #3
0
static void* EMRunner(void *arg)
{
	
	// keep track of LBID ranges allocated here and
	// randomly allocate, lookup, delete, get/set HWM, and
	// destroy the EM object.
	
	struct EMEntries {
		u_int64_t LBIDstart;
		u_int32_t size;
		int OID;
		u_int32_t FBO;
		u_int32_t HWM;
		u_int32_t secondHWM;
		u_int32_t txnID;
		struct EMEntries *next;
		EMEntries() { next = NULL; HWM = 0; secondHWM = 0; txnID = 0; }
	};
	
#ifdef BRM_VERBOSE
	int threadNum = reinterpret_cast<int>(arg);
#endif
	int op, listSize = 0, i;
	uint randstate;
	struct EMEntries *head = NULL, *tmp;
	struct timeval tv;
	ExtentMap *em;
	vector<LBID_t> lbids;

#ifdef BRM_VERBOSE
	cerr << "thread number " << threadNum << " started." << endl;
#endif
	
	gettimeofday(&tv, NULL);
	randstate = static_cast<uint>(tv.tv_usec);
	em = new ExtentMap();
	
	while (!threadStop) {
		op = rand_r(&randstate) % 10;
#ifdef BRM_VERBOSE
		cerr << "next op is " << op << endl;
#endif
		switch (op) {
			case 0:   //allocate space for a new file
			{
				struct EMEntries *newEm;
				int size = rand_r(&randstate) % 102399 + 1;
				int entries, OID, allocdSize;
				
				pthread_mutex_lock(&mutex);
				OID = oid++;
				pthread_mutex_unlock(&mutex);
				
				em->createExtent(size, OID, lbids, allocdSize);
				em->confirmChanges();
				
				entries = size/em->getExtentSize();
				if ((size % em->getExtentSize()) != 0)
					entries++;
				
				CPPUNIT_ASSERT((uint)entries == lbids.size());
				
				for (i = 0 ; i < entries; i++) {
				
					newEm = new EMEntries();
					newEm->size = em->getExtentSize();
					newEm->OID = OID;
					newEm->FBO = i * em->getExtentSize();
					newEm->LBIDstart = lbids[i];
				
					newEm->next = head;
					head = newEm;
					listSize++;
				}
#ifdef BRM_VERBOSE
				cerr << "created new space for OID " << newEm->OID << endl;
#endif
				em->checkConsistency();
				break;
			}
			case 1:		//allocate space for an existing file
			{
				if (listSize == 0)
					break;
				
				struct EMEntries *newEm, *tmp;
				int size = rand_r(&randstate) % 102399 + 1;
				int fileRand = rand_r(&randstate) % listSize;
				int i, lastExtent, blockEnd, oid;
				int tmpHWM, entries, allocdSize;
				vector<LBID_t> lbids;

				for (i = 0, tmp = head; i < fileRand; i++)
					tmp = tmp->next;
				
				oid = tmp->OID;
				
				for (lastExtent = 0, tmp = head; tmp != NULL; tmp = tmp->next) {
					if (tmp->OID != oid) 
						continue;
					
					tmpHWM = tmp->HWM;
					blockEnd = tmp->FBO + tmp->size;
					if (lastExtent < blockEnd)
						lastExtent = blockEnd;
				}
				
				em->createExtent(size, oid, lbids, allocdSize);
				em->confirmChanges();				

				entries = size/em->getExtentSize();
				if ((size % em->getExtentSize()) != 0)
					entries++;
				
				CPPUNIT_ASSERT((uint)entries == lbids.size());
				for (i = 0; i < entries; i++) {
				
					newEm = new EMEntries();
					if (i != entries)
						newEm->size = em->getExtentSize();
					else
						newEm->size = size % em->getExtentSize();
					newEm->OID = oid;
					newEm->FBO = lastExtent + (i*em->getExtentSize());
					newEm->LBIDstart = lbids[i];
					newEm->HWM = tmpHWM;
				
					newEm->next = head;
					head = newEm;
					listSize++;
				}
#ifdef BRM_VERBOSE
				cerr << "created another extent for OID " << newEm->OID << endl;
#endif
				em->checkConsistency();
				break;
			}
			case 2:  			//delete an OID
			{
				if (listSize == 0)
					break;
				
				struct EMEntries *tmp, *prev;
				int fileRand = rand_r(&randstate) % listSize;
				int i, oid;
				
				for (i = 0, tmp = head; i < fileRand; i++)
					tmp = tmp->next;
				oid = tmp->OID;
				
				em->deleteOID(oid);
				em->confirmChanges();				

				for (tmp = head; tmp != NULL;) {
					if (tmp->OID == oid) {
						if (tmp == head) {
							head = head->next;
							delete tmp;
							tmp = head;
						}
						else {
							prev->next = tmp->next;
							delete tmp;
							tmp = prev->next;
						}
						listSize--;
					}
					else {
						prev = tmp;
						tmp = tmp->next;
					}
				}
#ifdef BRM_VERBOSE
				cerr << "deleted OID " << oid << endl;
#endif
				em->checkConsistency();
				break;
			}
			case 3:   //lookup by LBID
			{
				if (listSize == 0)
					break;
				
				int entryRand = rand_r(&randstate) % listSize;
				int i, err, offset, oid;
				struct EMEntries *tmp;
				LBID_t target;
				u_int32_t fbo;
				
				for (i = 0, tmp = head; i < entryRand; i++)
					tmp = tmp->next;
				offset = rand_r(&randstate) % tmp->size;
	
				target = tmp->LBIDstart + offset;
				err = em->lookup(target, oid, fbo);
#ifdef BRM_VERBOSE
				cerr << "looked up LBID " << target << " got oid " << oid << " fbo " << fbo << endl;
				cerr << "   oid should be " << tmp->OID << " fbo should be " << offset+tmp->FBO << endl;
#endif
				CPPUNIT_ASSERT(err == 0);
				CPPUNIT_ASSERT(oid == tmp->OID);
				CPPUNIT_ASSERT(fbo == offset + tmp->FBO);
				em->checkConsistency();
				break;
			}
			case 4:   //lookup by OID, FBO
			{
				if (listSize == 0)
					break;
				
				int entryRand = rand_r(&randstate) % listSize;
				int i, oid, err, offset;
				struct EMEntries *tmp;
				LBID_t lbid;
				
				for (i = 0, tmp = head; i < entryRand; i++)
					tmp = tmp->next;
				offset = rand_r(&randstate) % tmp->size;	
				oid = tmp->OID;
				
				err = em->lookup(oid, offset + tmp->FBO, lbid);
#ifdef BRM_VERBOSE
				cerr << "looked up OID " << oid << " fbo " << offset + tmp->FBO <<
						" got lbid " << lbid << endl;
				cerr << "  lbid should be " << tmp->LBIDstart + offset << endl;
#endif
				CPPUNIT_ASSERT(err == 0);
				CPPUNIT_ASSERT(lbid == tmp->LBIDstart + offset);
				em->checkConsistency();
				break;
			}
			case 5:		//getHWM
			{
				if (listSize == 0)
					break;
				
				int entryRand = rand_r(&randstate) % listSize;
				int i;
				struct EMEntries *tmp;
				u_int32_t hwm;
				
				for (i = 0, tmp = head; i < entryRand; i++)
					tmp = tmp->next;
				
				hwm = em->getHWM(tmp->OID);
#ifdef BRM_VERBOSE
				cerr << "stored HWM for OID " << tmp->OID << " is " << tmp->HWM 
						<< " BRM says it's " << hwm << endl;
#endif
				CPPUNIT_ASSERT(hwm == tmp->HWM);
				em->checkConsistency();
				break;
			}
			case 6: 		//setHWM
			{
				if (listSize == 0)
					break;
				
				int entryRand = rand_r(&randstate) % listSize;
				int i, hwm, oid;
				struct EMEntries *tmp;
				
				for (i = 0, tmp = head; i < entryRand; i++)
					tmp = tmp->next;
				
				oid = tmp->OID;
				hwm = rand_r(&randstate) % (tmp->FBO + em->getExtentSize());
				em->setHWM(oid, hwm);
				em->confirmChanges();				

				for (tmp = head; tmp != NULL; tmp = tmp->next)
					if (tmp->OID == oid)
						tmp->HWM = hwm;
#ifdef BRM_VERBOSE		
				cerr << "setHWM of OID " << oid << " to " << hwm << endl;
#endif
				em->checkConsistency();
				break;
			}
			case 7:			// renew this EM object
			{
				delete em;
				em = new ExtentMap();
#ifdef BRM_VERBOSE
				cerr << "got a new EM instance" << endl;
#endif
				em->checkConsistency();
				break;
			}
			case 8:			//getBulkInsertVars
			{
				if (listSize == 0)
					break;
				
				HWM_t hwm;
				VER_t txnID;
				int entryRand = rand_r(&randstate) % listSize;
				int i, err, offset;
				EMEntries *tmp;
				LBID_t lbid;
				
				for (i = 0, tmp = head; i < entryRand; i++)
					tmp = tmp->next;
				
				offset = rand_r(&randstate) % tmp->size;
				lbid = tmp->LBIDstart + offset;
				err = em->getBulkInsertVars(lbid, hwm, txnID);
				CPPUNIT_ASSERT(err == 0);
				CPPUNIT_ASSERT(hwm == tmp->secondHWM);
				CPPUNIT_ASSERT(txnID == tmp->txnID);
				break;
			}
			case 9:			//setBulkInsertVars
			{
				if (listSize == 0)
					break;
				
				int entryRand = rand_r(&randstate) % listSize;
				int i, err, offset;
				EMEntries *tmp;
				
				for (i = 0, tmp = head; i < entryRand; i++)
					tmp = tmp->next;
				
				offset = rand_r(&randstate) % tmp->size;
				tmp->secondHWM = rand_r(&randstate) % MAXINT;
				tmp->txnID = rand_r(&randstate) % MAXINT;
				err = em->setBulkInsertVars(tmp->LBIDstart + offset,
											tmp->secondHWM, tmp->txnID);
				em->confirmChanges();
				CPPUNIT_ASSERT(err == 0);
				break;
			}
			default:
				break;
		}
	}
	delete em;
	while (head != NULL) {
		tmp = head->next;
		delete head;
		head = tmp;
	}

#ifdef BRM_VERBOSE
	cerr << "thread " << threadNum << " exiting" << endl;
#endif
	return NULL;
}