mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-04-18 21:44:02 +03:00
1914 lines
58 KiB
C++
1914 lines
58 KiB
C++
/* Copyright (C) 2014 InfiniDB, Inc.
|
|
Copyright (C) 2016-2021 MariaDB Corporation
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; version 2 of
|
|
the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
/*****************************************************************************
|
|
* $Id: tdriver-dbrm2.cpp 1823 2013-01-21 14:13:09Z rdempsey $
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <pthread.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/shm.h>
|
|
#include <stdexcept>
|
|
#include <pthread.h>
|
|
#include <sys/time.h>
|
|
#include <values.h>
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#include "brm.h"
|
|
#include "extentmap.h"
|
|
#include "IDBPolicy.h"
|
|
|
|
//#define BRM_VERBOSE 1
|
|
|
|
using namespace BRM;
|
|
using namespace std;
|
|
|
|
int threadStop;
|
|
int oid = 1;
|
|
uint64_t opCount = 0;
|
|
LBID_t lbidCounter = 0;
|
|
VER_t nextTxnID = 1;
|
|
u_int64_t vbOffset = 0;
|
|
pthread_mutex_t pthreadMutex;
|
|
const std::vector<uint32_t> colWidthsAvailable = {1, 2, 4, 8, 16};
|
|
const DBRootT dbroot = 1;
|
|
|
|
struct Range
|
|
{
|
|
LBID_t start, end, nextBlock;
|
|
VER_t txnID;
|
|
Range()
|
|
{
|
|
start = end = nextBlock = 0;
|
|
txnID = 0;
|
|
}
|
|
};
|
|
|
|
struct EMEntries
|
|
{
|
|
LBID_t LBIDstart;
|
|
uint32_t size;
|
|
OID_t OID;
|
|
uint32_t FBO;
|
|
uint32_t HWM;
|
|
uint32_t secondHWM;
|
|
int32_t txnID;
|
|
DBRootT dbroot;
|
|
PartitionNumberT partNum;
|
|
SegmentT segNum;
|
|
struct EMEntries* next;
|
|
EMEntries() : HWM(0), secondHWM(0), txnID(0), next(nullptr)
|
|
{ }
|
|
EMEntries(const uint32_t aSize, const OID_t aOid, const uint32_t aFbo,
|
|
const LBID_t aLBIDStart, EMEntries* aNext)
|
|
: LBIDstart(aLBIDStart), size(aSize), OID(aOid), FBO(aFbo), HWM(0),
|
|
secondHWM(0), txnID(0), next(aNext)
|
|
{ }
|
|
EMEntries(const uint32_t aSize, const OID_t aOid, const uint32_t aFbo,
|
|
const LBID_t aLBIDStart, EMEntries* aNext, const DBRootT aDbroot,
|
|
const PartitionNumberT aPartNum, const SegmentT aSegNum)
|
|
: LBIDstart(aLBIDStart), size(aSize), OID(aOid), FBO(aFbo), HWM(0),
|
|
secondHWM(0), txnID(0), dbroot(aDbroot), partNum(aPartNum),
|
|
segNum(aSegNum), next(aNext)
|
|
{ }
|
|
};
|
|
/*
|
|
static void* BRMRunner_2(void* arg)
|
|
{
|
|
|
|
vector<Range> copyList, copiedList, committedList;
|
|
vector<Range>::iterator rit;
|
|
vector<LBID_t> writtenList;
|
|
vector<LBID_t>::iterator lit;
|
|
|
|
pthread_mutex_t listMutex;
|
|
int op;
|
|
uint32_t randstate;
|
|
DBRM* brm;
|
|
struct timeval tv;
|
|
VER_t txnID;
|
|
|
|
pthread_mutex_init(&listMutex, NULL);
|
|
gettimeofday(&tv, NULL);
|
|
randstate = static_cast<uint32_t>(tv.tv_usec);
|
|
brm = new DBRM();
|
|
|
|
while (!threadStop)
|
|
{
|
|
op = rand_r(&randstate) % 9;
|
|
|
|
switch (op)
|
|
{
|
|
case 0: // beginVBCopy
|
|
{
|
|
int blockCount, size, err;
|
|
Range newEntry;
|
|
VBRange_v vbRanges;
|
|
VBRange_v::iterator vit;
|
|
LBIDRange_v ranges;
|
|
LBIDRange range;
|
|
|
|
size = rand_r(&randstate) % 10000;
|
|
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
newEntry.start = lbidCounter;
|
|
lbidCounter += size;
|
|
txnID = nextTxnID++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
|
|
newEntry.nextBlock = newEntry.start;
|
|
newEntry.end = newEntry.start + size;
|
|
range.start = newEntry.start;
|
|
range.size = size;
|
|
|
|
err = brm->beginVBCopy(txnID, dbroot, ranges, vbRanges);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
for (blockCount = 0, vit = vbRanges.begin(); vit != vbRanges.end(); vit++)
|
|
blockCount += (*vit).size;
|
|
|
|
CPPUNIT_ASSERT(blockCount == size);
|
|
|
|
pthread_mutex_lock(&listMutex);
|
|
copyList.push_back(newEntry);
|
|
pthread_mutex_unlock(&listMutex);
|
|
|
|
err = brm->beginVBCopy(txnID, dbroot, ranges, vbRanges);
|
|
CPPUNIT_ASSERT(err == -1);
|
|
break;
|
|
}
|
|
|
|
case 1: // writeVBEntry
|
|
{
|
|
int randIndex;
|
|
Range* entry;
|
|
|
|
pthread_mutex_lock(&listMutex);
|
|
|
|
if (copyList.size() == 0)
|
|
break;
|
|
|
|
randIndex = rand_r(&randstate) % copyList.size();
|
|
entry = &(copyList[randIndex]);
|
|
entry->nextBlock++;
|
|
txnID = entry->txnID;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
cerr << "not finished yet" << endl;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
static void* BRMRunner_1(void* arg)
|
|
{
|
|
|
|
// keep track of LBID ranges allocated here and
|
|
// randomly allocate, lookup, delete, get/set HWM, and
|
|
// destroy the EM object.
|
|
|
|
#ifdef BRM_VERBOSE
|
|
int threadNum = reinterpret_cast<int>(arg);
|
|
#endif
|
|
int op, listSize = 0, i;
|
|
uint32_t randstate;
|
|
struct EMEntries* head = NULL, *tmp;
|
|
struct timeval tv;
|
|
DBRM* brm;
|
|
ExtentMap em;
|
|
vector<LBID_t> lbids;
|
|
LBID_t lbid;
|
|
uint32_t colWidth;
|
|
PartitionNumberT partNum;
|
|
SegmentT segmentNum;
|
|
execplan::CalpontSystemCatalog::ColDataType colDataType;
|
|
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "thread number " << threadNum << " started." << endl;
|
|
#endif
|
|
|
|
gettimeofday(&tv, NULL);
|
|
randstate = static_cast<uint32_t>(tv.tv_usec);
|
|
brm = new DBRM();
|
|
|
|
|
|
while (!threadStop)
|
|
{
|
|
auto randNumber = rand_r(&randstate);
|
|
op = randNumber % 10;
|
|
colWidth = colWidthsAvailable[randNumber % colWidthsAvailable.size()];
|
|
partNum = randNumber % std::numeric_limits<PartitionNumberT>::max();
|
|
segmentNum = randNumber % std::numeric_limits<SegmentT>::max();
|
|
colDataType = (execplan::CalpontSystemCatalog::ColDataType) (randNumber % (int)execplan::CalpontSystemCatalog::ColDataType::TIMESTAMP);
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "next op is " << op << endl;
|
|
#endif
|
|
|
|
switch (op)
|
|
{
|
|
case 0: //allocate space for a new file
|
|
{
|
|
struct EMEntries* newEm;
|
|
size_t size = rand_r(&randstate) % 102399 + 1;
|
|
int entries, OID, allocdSize, err;
|
|
uint32_t startBlockOffset;
|
|
|
|
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
OID = oid++;
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
lbids.clear();
|
|
for (size_t i = 0; i < size; ++i)
|
|
{
|
|
err = brm->createColumnExtent_DBroot(OID, colWidth, dbroot,
|
|
partNum, segmentNum, colDataType, lbid, allocdSize, startBlockOffset);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
lbids.push_back(lbid);
|
|
}
|
|
|
|
entries = size / brm->getExtentSize();
|
|
|
|
if ((size % brm->getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
if ((uint32_t)entries != lbids.size())
|
|
cerr << "entries = " << entries << " lbids.size = " << lbids.size() << endl;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0 ; i < entries; i++)
|
|
{
|
|
|
|
newEm = new EMEntries(brm->getExtentSize(), OID, brm->getExtentSize(), lbids[i],
|
|
head, dbroot, partNum, segmentNum);
|
|
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, err;
|
|
uint32_t startBlockOffset;
|
|
vector<LBID_t> lbids;
|
|
LBID_t lbid;
|
|
|
|
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;
|
|
}
|
|
|
|
err = brm->createColumnExtentExactFile(oid, colWidth, dbroot,
|
|
partNum, segmentNum, colDataType, lbid, allocdSize, startBlockOffset);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
entries = size / brm->getExtentSize();
|
|
|
|
if ((size % brm->getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0; i < entries; i++)
|
|
{
|
|
|
|
newEm = new EMEntries((i != entries) ? brm->getExtentSize() : size % brm->getExtentSize(),
|
|
oid, lastExtent + (i * brm->getExtentSize()),
|
|
lbids[i], head, dbroot, partNum, segmentNum);
|
|
newEm->HWM = tmpHWM;
|
|
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, err;
|
|
|
|
for (i = 0, tmp = head; i < fileRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
oid = tmp->OID;
|
|
|
|
err = brm->deleteOID(oid);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
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;
|
|
uint32_t fbo;
|
|
DBRootT localDbroot;
|
|
PartitionNumberT localPartNum;
|
|
SegmentT localSegmentNum;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
offset = rand_r(&randstate) % tmp->size;
|
|
|
|
target = tmp->LBIDstart + offset;
|
|
err = brm->lookupLocal(target, 0, false, oid, localDbroot, localPartNum,
|
|
localSegmentNum, fbo);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
#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 = brm->lookupLocal(oid, partNum, segmentNum, offset + tmp->FBO, lbid);
|
|
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
#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 == static_cast<LBID_t>(tmp->LBIDstart + offset));
|
|
em.checkConsistency();
|
|
break;
|
|
}
|
|
|
|
case 5: //getHWM
|
|
{
|
|
if (listSize == 0)
|
|
break;
|
|
|
|
int entryRand = rand_r(&randstate) % listSize;
|
|
int i, err, status;
|
|
struct EMEntries* tmp;
|
|
uint32_t hwm;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
err = brm->getLocalHWM(tmp->OID, partNum, segmentNum, hwm, status);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
#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, err;
|
|
struct EMEntries* tmp;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
oid = tmp->OID;
|
|
hwm = rand_r(&randstate) % (tmp->FBO + brm->getExtentSize());
|
|
err = brm->setLocalHWM(oid, tmp->partNum, tmp->segNum, hwm);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
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 brm;
|
|
brm = new DBRM();
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "got a new BRM instance" << endl;
|
|
#endif
|
|
em.checkConsistency();
|
|
break;
|
|
}
|
|
#if 0
|
|
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 = brm->getBulkInsertVars(lbid, hwm, txnID);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
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 = brm->setBulkInsertVars(tmp->LBIDstart + offset,
|
|
tmp->secondHWM, tmp->txnID);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete brm;
|
|
|
|
while (head != NULL)
|
|
{
|
|
tmp = head->next;
|
|
delete head;
|
|
head = tmp;
|
|
}
|
|
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "thread " << threadNum << " exiting" << endl;
|
|
#endif
|
|
return NULL;
|
|
}
|
|
*/
|
|
DBRM brm_si;
|
|
/*
|
|
static void* BRMRunner_si(void* arg)
|
|
{
|
|
|
|
// keep track of LBID ranges allocated here and
|
|
// randomly allocate, lookup, delete, get/set HWM, and
|
|
// destroy the EM object.
|
|
|
|
#ifdef BRM_VERBOSE
|
|
int threadNum = reinterpret_cast<int>(arg);
|
|
#endif
|
|
int op, listSize = 0, i;
|
|
uint32_t 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<uint32_t>(tv.tv_usec);
|
|
|
|
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, err;
|
|
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
OID = oid++;
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
|
|
err = brm_si.createExtent(size, OID, lbids, allocdSize);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
entries = size / brm_si.getExtentSize();
|
|
|
|
if ((size % brm_si.getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0 ; i < entries; i++)
|
|
{
|
|
|
|
newEm = new EMEntries();
|
|
newEm->size = brm_si.getExtentSize();
|
|
newEm->OID = OID;
|
|
newEm->FBO = i * brm_si.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, err;
|
|
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;
|
|
}
|
|
|
|
err = brm_si.createExtent(size, oid, lbids, allocdSize);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
entries = size / brm_si.getExtentSize();
|
|
|
|
if ((size % brm_si.getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0; i < entries; i++)
|
|
{
|
|
|
|
newEm = new EMEntries();
|
|
|
|
if (i != entries)
|
|
newEm->size = brm_si.getExtentSize();
|
|
else
|
|
newEm->size = size % brm_si.getExtentSize();
|
|
|
|
newEm->OID = oid;
|
|
newEm->FBO = lastExtent + (i * brm_si.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, err;
|
|
|
|
for (i = 0, tmp = head; i < fileRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
oid = tmp->OID;
|
|
|
|
err = brm_si.deleteOID(oid);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
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;
|
|
uint32_t fbo;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
offset = rand_r(&randstate) % tmp->size;
|
|
|
|
target = tmp->LBIDstart + offset;
|
|
err = brm_si.lookup(target, 0, false, oid, fbo);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
#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 = brm_si.lookup(oid, offset + tmp->FBO, lbid);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
#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 == static_cast<LBID_t>(tmp->LBIDstart + offset));
|
|
em.checkConsistency();
|
|
break;
|
|
}
|
|
|
|
case 5: //getHWM
|
|
{
|
|
if (listSize == 0)
|
|
break;
|
|
|
|
int entryRand = rand_r(&randstate) % listSize;
|
|
int i, err;
|
|
struct EMEntries* tmp;
|
|
uint32_t hwm;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
err = brm_si.getHWM(tmp->OID, hwm);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
#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, err;
|
|
struct EMEntries* tmp;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
oid = tmp->OID;
|
|
hwm = rand_r(&randstate) % (tmp->FBO + brm_si.getExtentSize());
|
|
err = brm_si.setHWM(oid, hwm);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
|
|
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: //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 = brm_si.getBulkInsertVars(lbid, hwm, txnID);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
CPPUNIT_ASSERT(hwm == tmp->secondHWM);
|
|
CPPUNIT_ASSERT(txnID == tmp->txnID);
|
|
break;
|
|
}
|
|
|
|
case 8: //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 = brm_si.setBulkInsertVars(tmp->LBIDstart + offset,
|
|
tmp->secondHWM, tmp->txnID);
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
opCount++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (head != NULL)
|
|
{
|
|
tmp = head->next;
|
|
delete head;
|
|
head = tmp;
|
|
}
|
|
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "thread " << threadNum << " exiting" << endl;
|
|
#endif
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
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.
|
|
|
|
#ifdef BRM_VERBOSE
|
|
uint64_t threadNum = (uint64_t)arg;
|
|
#endif
|
|
int op, listSize = 0;
|
|
uint32_t randstate;
|
|
struct EMEntries* head = NULL, *tmp;
|
|
struct timeval tv;
|
|
ExtentMap* em;
|
|
LBID_t lbid;
|
|
uint32_t colWidth;
|
|
PartitionNumberT partNum;
|
|
SegmentT segmentNum;
|
|
execplan::CalpontSystemCatalog::ColDataType colDataType;
|
|
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "thread number " << threadNum << " started." << endl;
|
|
#endif
|
|
|
|
gettimeofday(&tv, NULL);
|
|
randstate = static_cast<uint32_t>(tv.tv_usec);
|
|
//pthread_mutex_lock(&pthreadMutex);
|
|
em = new ExtentMap();
|
|
//pthread_mutex_unlock(&pthreadMutex);
|
|
|
|
while (!threadStop)
|
|
{
|
|
auto randNumber = rand_r(&randstate);
|
|
op = randNumber % 10;
|
|
|
|
colWidth = colWidthsAvailable[randNumber % colWidthsAvailable.size()];
|
|
partNum = randNumber % std::numeric_limits<PartitionNumberT>::max();
|
|
segmentNum = randNumber % std::numeric_limits<SegmentT>::max();
|
|
colDataType = (execplan::CalpontSystemCatalog::ColDataType) (randNumber % (int)execplan::CalpontSystemCatalog::ColDataType::TIMESTAMP);
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "next op is " << op << endl;
|
|
#endif
|
|
|
|
switch (op)
|
|
{
|
|
case 0: //allocate space for a new file
|
|
{
|
|
vector<struct EMEntry> emEntriesVec;
|
|
struct EMEntries* newEm;
|
|
size_t numberOfExtents = randNumber % 4 + 1;
|
|
int OID;
|
|
uint32_t startBlockOffset;
|
|
|
|
pthread_mutex_lock(&pthreadMutex);
|
|
OID = oid++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
|
|
em->getExtents(OID, emEntriesVec, false, false, true);
|
|
size_t extentsNumberBefore = emEntriesVec.size();
|
|
int allocdsize;
|
|
for (size_t i = 0; i < numberOfExtents; ++i)
|
|
{
|
|
em->createColumnExtent_DBroot(OID, colWidth, dbroot, colDataType,
|
|
partNum, segmentNum, lbid, allocdsize, startBlockOffset);
|
|
em->confirmChanges();
|
|
|
|
newEm = new EMEntries(allocdsize, OID, startBlockOffset, lbid,
|
|
head, dbroot, partNum, segmentNum);
|
|
head = newEm;
|
|
listSize++;
|
|
}
|
|
|
|
emEntriesVec.clear();
|
|
em->getExtents(OID, emEntriesVec, false, false, true);
|
|
size_t extentsNumberAfter = emEntriesVec.size();
|
|
|
|
CPPUNIT_ASSERT(extentsNumberBefore + numberOfExtents == extentsNumberAfter);
|
|
|
|
#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;
|
|
size_t size = rand_r(&randstate) % 10;
|
|
int fileRand = rand_r(&randstate) % listSize;
|
|
int i, lastExtent, blockEnd, oid;
|
|
int tmpHWM, entries, allocdSize;
|
|
uint32_t startBlockOffset;
|
|
lbids.clear();
|
|
|
|
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;
|
|
}
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
{
|
|
em->createColumnExtent_DBroot(oid, colWidth, dbroot, colDataType,
|
|
partNum, segmentNum, lbid, allocdSize, startBlockOffset);
|
|
em->confirmChanges();
|
|
lbids.push_back(lbid);
|
|
}
|
|
|
|
//em->createExtent(size, oid, lbids, allocdSize);
|
|
//em->confirmChanges();
|
|
|
|
entries = size / em->getExtentSize();
|
|
|
|
if ((size % em->getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0; i < entries; i++)
|
|
{
|
|
newEm = new EMEntries((i != entries) ? em->getExtentSize() : size % em->getExtentSize(),
|
|
oid, lastExtent + (i * em->getExtentSize()),
|
|
lbids[i], head, dbroot, partNum, segmentNum);
|
|
newEm->HWM = tmpHWM;
|
|
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 = nullptr, *prev = nullptr;
|
|
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();
|
|
|
|
vector<struct EMEntry> emEntriesVec;
|
|
em->getExtents(oid, emEntriesVec, false, false, true);
|
|
CPPUNIT_ASSERT(emEntriesVec.empty());
|
|
|
|
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;
|
|
uint32_t fbo;
|
|
DBRootT localDbroot;
|
|
PartitionNumberT localPartNum;
|
|
SegmentT localSegmentNum;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
offset = rand_r(&randstate) % (tmp->size - 1);
|
|
|
|
target = tmp->LBIDstart + offset;
|
|
err = em->lookupLocal(target, oid, localDbroot, localPartNum, localSegmentNum, 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;
|
|
cerr << "op 3 fbo " << fbo << " offset + tmp->FBO " << 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 - 1);
|
|
oid = tmp->OID;
|
|
|
|
err = em->lookupLocal(oid, tmp->partNum, tmp->segNum, 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, status;
|
|
struct EMEntries* tmp;
|
|
uint32_t hwm;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
hwm = em->getLocalHWM(tmp->OID, tmp->partNum, tmp->segNum, status);
|
|
#ifdef BRM_VERBOSE_I
|
|
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->size - 1);
|
|
bool firstNode = true;
|
|
em->setLocalHWM(oid, tmp->partNum, tmp->segNum, hwm, firstNode);
|
|
|
|
em->confirmChanges();
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
ExtentMap em_si;
|
|
static void* EMRunner_si(void* arg)
|
|
{
|
|
|
|
// keep track of LBID ranges allocated here and
|
|
// randomly allocate, lookup, delete, get/set HWM, and
|
|
// destroy the EM object.
|
|
|
|
#ifdef BRM_VERBOSE
|
|
int threadNum = reinterpret_cast<int>(arg);
|
|
#endif
|
|
int op, listSize = 0, i;
|
|
uint32_t randstate;
|
|
struct EMEntries* head = NULL, *tmp;
|
|
struct timeval tv;
|
|
vector<LBID_t> lbids;
|
|
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "thread number " << threadNum << " started." << endl;
|
|
#endif
|
|
|
|
gettimeofday(&tv, NULL);
|
|
randstate = static_cast<uint32_t>(tv.tv_usec);
|
|
|
|
while (!threadStop)
|
|
{
|
|
op = rand_r(&randstate) % 9;
|
|
#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(&pthreadMutex);
|
|
OID = oid++;
|
|
pthread_mutex_unlock(&pthreadMutex);
|
|
|
|
em_si.createExtent(size, OID, lbids, allocdSize);
|
|
em_si.confirmChanges();
|
|
|
|
entries = size / em_si.getExtentSize();
|
|
|
|
if ((size % em_si.getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0 ; i < entries; i++)
|
|
{
|
|
|
|
newEm = new EMEntries();
|
|
newEm->size = em_si.getExtentSize();
|
|
newEm->OID = OID;
|
|
newEm->FBO = i * em_si.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_si.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_si.createExtent(size, oid, lbids, allocdSize);
|
|
em_si.confirmChanges();
|
|
|
|
entries = size / em_si.getExtentSize();
|
|
|
|
if ((size % em_si.getExtentSize()) != 0)
|
|
entries++;
|
|
|
|
CPPUNIT_ASSERT((uint32_t)entries == lbids.size());
|
|
|
|
for (i = 0; i < entries; i++)
|
|
{
|
|
|
|
newEm = new EMEntries();
|
|
|
|
if (i != entries)
|
|
newEm->size = em_si.getExtentSize();
|
|
else
|
|
newEm->size = size % em_si.getExtentSize();
|
|
|
|
newEm->OID = oid;
|
|
newEm->FBO = lastExtent + (i * em_si.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_si.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_si.deleteOID(oid);
|
|
em_si.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_si.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;
|
|
uint32_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_si.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_si.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_si.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_si.checkConsistency();
|
|
break;
|
|
}
|
|
|
|
case 5: //getHWM
|
|
{
|
|
if (listSize == 0)
|
|
break;
|
|
|
|
int entryRand = rand_r(&randstate) % listSize;
|
|
int i;
|
|
struct EMEntries* tmp;
|
|
uint32_t hwm;
|
|
|
|
for (i = 0, tmp = head; i < entryRand; i++)
|
|
tmp = tmp->next;
|
|
|
|
hwm = em_si.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_si.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_si.getExtentSize());
|
|
em_si.setHWM(oid, hwm);
|
|
em_si.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_si.checkConsistency();
|
|
break;
|
|
}
|
|
|
|
case 7: //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_si.getBulkInsertVars(lbid, hwm, txnID);
|
|
CPPUNIT_ASSERT(err == 0);
|
|
CPPUNIT_ASSERT(hwm == tmp->secondHWM);
|
|
CPPUNIT_ASSERT(txnID == tmp->txnID);
|
|
break;
|
|
}
|
|
|
|
case 8: //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_si.setBulkInsertVars(tmp->LBIDstart + offset,
|
|
tmp->secondHWM, tmp->txnID);
|
|
em_si.confirmChanges();
|
|
CPPUNIT_ASSERT(err == 0);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (head != NULL)
|
|
{
|
|
tmp = head->next;
|
|
delete head;
|
|
head = tmp;
|
|
}
|
|
|
|
#ifdef BRM_VERBOSE
|
|
cerr << "thread " << threadNum << " exiting" << endl;
|
|
#endif
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
|
|
class LongBRMTests : public CppUnit::TestFixture
|
|
{
|
|
|
|
CPPUNIT_TEST_SUITE(LongBRMTests);
|
|
|
|
CPPUNIT_TEST(longEMTest_1);
|
|
// CPPUNIT_TEST(longEMTest_2);
|
|
// CPPUNIT_TEST(longBRMTest_1);
|
|
// CPPUNIT_TEST(longBRMTest_2);
|
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
private:
|
|
public:
|
|
void longEMTest_1()
|
|
{
|
|
const int threadCount = 10;
|
|
int i;
|
|
pthread_t threads[threadCount];
|
|
|
|
cerr << endl << "Multithreaded, multiple instance ExtentMap test. "
|
|
"This runs for 5 minutes." << endl;
|
|
|
|
threadStop = 0;
|
|
pthread_mutex_init(&pthreadMutex, nullptr);
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
if (pthread_create(&threads[i], NULL, EMRunner,
|
|
reinterpret_cast<void*>(i + 1)) < 0)
|
|
throw logic_error("Error creating threads for the ExtentMap test");
|
|
|
|
usleep(1000);
|
|
}
|
|
|
|
sleep(300);
|
|
threadStop = 1;
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
cerr << "Waiting for thread #" << i << endl;
|
|
pthread_join(threads[i], nullptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
void longEMTest_2()
|
|
{
|
|
const int threadCount = 10;
|
|
int i;
|
|
pthread_t threads[threadCount];
|
|
|
|
cerr << endl << "Multithreaded, single instance ExtentMap test. "
|
|
"This runs for 5 minutes." << endl;
|
|
|
|
threadStop = 0;
|
|
pthread_mutex_init(&pthreadMutex, NULL);
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
if (pthread_create(&threads[i], NULL, EMRunner_si,
|
|
reinterpret_cast<void*>(i + 1)) < 0)
|
|
throw logic_error("Error creating threads for the ExtentMap test");
|
|
|
|
usleep(1000);
|
|
}
|
|
|
|
sleep(60);
|
|
threadStop = 1;
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
cerr << "Waiting for thread #" << i << endl;
|
|
pthread_join(threads[i], NULL);
|
|
}
|
|
}
|
|
void longBRMTest_1()
|
|
{
|
|
const int threadCount = 10;
|
|
int i;
|
|
pthread_t threads[threadCount];
|
|
|
|
cerr << endl << "Multithreaded, multiple instance DBRM test. "
|
|
"This runs for 5 minutes." << endl;
|
|
|
|
threadStop = 0;
|
|
pthread_mutex_init(&pthreadMutex, NULL);
|
|
opCount = 0;
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
if (pthread_create(&threads[i], NULL, BRMRunner_1,
|
|
reinterpret_cast<void*>(i + 1)) < 0)
|
|
throw logic_error("Error creating threads for the DBRM test");
|
|
|
|
usleep(1000);
|
|
}
|
|
|
|
sleep(300);
|
|
threadStop = 1;
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
cerr << "Waiting for thread #" << i << endl;
|
|
pthread_join(threads[i], NULL);
|
|
}
|
|
|
|
cerr << "opCount = " << opCount << endl;
|
|
}
|
|
void longBRMTest_2()
|
|
{
|
|
const int threadCount = 10;
|
|
int i;
|
|
pthread_t threads[threadCount];
|
|
|
|
cerr << endl << "Multithreaded, single instance DBRM test. "
|
|
"This runs for 5 minutes." << endl;
|
|
|
|
threadStop = 0;
|
|
pthread_mutex_init(&pthreadMutex, NULL);
|
|
opCount = 0;
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
if (pthread_create(&threads[i], NULL, BRMRunner_si,
|
|
reinterpret_cast<void*>(i + 1)) < 0)
|
|
throw logic_error("Error creating threads for the DBRM test");
|
|
|
|
usleep(1000);
|
|
}
|
|
|
|
sleep(300);
|
|
threadStop = 1;
|
|
|
|
for (i = 0; i < threadCount; i++)
|
|
{
|
|
cerr << "Waiting for thread #" << i << endl;
|
|
pthread_join(threads[i], NULL);
|
|
}
|
|
|
|
cerr << "opCount = " << opCount << endl;
|
|
}
|
|
*/
|
|
|
|
};
|
|
CPPUNIT_TEST_SUITE_REGISTRATION( LongBRMTests );
|
|
|
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
|
#include <cppunit/ui/text/TestRunner.h>
|
|
|
|
int main( int argc, char** argv)
|
|
{
|
|
CppUnit::TextUi::TestRunner runner;
|
|
CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
|
|
runner.addTest( registry.makeTest() );
|
|
idbdatafile::IDBPolicy::configIDBPolicy();
|
|
bool wasSuccessful = runner.run( "", false );
|
|
return (wasSuccessful ? 0 : 1);
|
|
}
|