1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

clang format apply

This commit is contained in:
Leonid Fedorov
2022-02-11 12:24:40 +00:00
parent 509f005be7
commit 7c808317dc
1367 changed files with 394342 additions and 413129 deletions

View File

@ -33,7 +33,6 @@ using namespace boost::posix_time;
namespace BRM
{
AutoincrementManager::AutoincrementManager()
{
}
@ -43,118 +42,116 @@ AutoincrementManager::~AutoincrementManager()
}
void AutoincrementManager::startSequence(uint32_t oid, uint64_t firstNum, uint32_t colWidth,
execplan::CalpontSystemCatalog::ColDataType colDataType)
execplan::CalpontSystemCatalog::ColDataType colDataType)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
sequence s;
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
sequence s;
it = sequences.find(oid);
it = sequences.find(oid);
if (it != sequences.end())
return;
if (it != sequences.end())
return;
s.value = firstNum;
s.value = firstNum;
if (isUnsigned(colDataType))
{
s.overflow = (0xFFFFFFFFFFFFFFFFULL >> (64 - colWidth * 8)) - 1;
}
else
{
s.overflow = (1ULL << (colWidth * 8 - 1));
}
if (isUnsigned(colDataType))
{
s.overflow = (0xFFFFFFFFFFFFFFFFULL >> (64 - colWidth * 8)) - 1;
}
else
{
s.overflow = (1ULL << (colWidth * 8 - 1));
}
sequences[oid] = s;
sequences[oid] = s;
}
bool AutoincrementManager::getAIRange(uint32_t oid, uint64_t count, uint64_t* firstNum)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
it = sequences.find(oid);
it = sequences.find(oid);
if (it == sequences.end())
throw runtime_error("There is no sequence with that lock");
if (it == sequences.end())
throw runtime_error("There is no sequence with that lock");
if ((count >= it->second.overflow ||
count + it->second.value > it->second.overflow ||
count + it->second.value <= it->second.value)
&& count != 0)
return false;
if ((count >= it->second.overflow || count + it->second.value > it->second.overflow ||
count + it->second.value <= it->second.value) &&
count != 0)
return false;
*firstNum = it->second.value;
it->second.value += count;
return true;
*firstNum = it->second.value;
it->second.value += count;
return true;
}
void AutoincrementManager::resetSequence(uint32_t oid, uint64_t value)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
it = sequences.find(oid);
it = sequences.find(oid);
if (it == sequences.end())
return;
if (it == sequences.end())
return;
it->second.value = value;
it->second.value = value;
}
const uint32_t AutoincrementManager::lockTime = 30;
void AutoincrementManager::getLock(uint32_t oid)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
ptime stealTime = microsec_clock::local_time() + seconds(lockTime);
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
ptime stealTime = microsec_clock::local_time() + seconds(lockTime);
bool gotIt = false;
bool gotIt = false;
it = sequences.find(oid);
it = sequences.find(oid);
if (it == sequences.end())
throw runtime_error("There is no sequence with that lock");
if (it == sequences.end())
throw runtime_error("There is no sequence with that lock");
lk.unlock();
lk.unlock();
while (!gotIt && microsec_clock::local_time() < stealTime)
{
gotIt = it->second.lock.try_lock();
while (!gotIt && microsec_clock::local_time() < stealTime)
{
gotIt = it->second.lock.try_lock();
if (!gotIt)
usleep(100000);
}
if (!gotIt)
usleep(100000);
}
// If !gotIt, take possession
// If !gotIt, take possession
}
void AutoincrementManager::releaseLock(uint32_t oid)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
it = sequences.find(oid);
it = sequences.find(oid);
if (it == sequences.end())
return; // it's unlocked if the lock doesn't exist...
if (it == sequences.end())
return; // it's unlocked if the lock doesn't exist...
lk.unlock();
lk.unlock();
it->second.lock.unlock();
it->second.lock.unlock();
}
void AutoincrementManager::deleteSequence(uint32_t oid)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
it = sequences.find(oid);
it = sequences.find(oid);
if (it != sequences.end())
sequences.erase(it);
if (it != sequences.end())
sequences.erase(it);
}
} /* namespace BRM */

View File

@ -38,40 +38,43 @@
namespace BRM
{
class AutoincrementManager
{
public:
EXPORT AutoincrementManager();
EXPORT virtual ~AutoincrementManager();
public:
EXPORT AutoincrementManager();
EXPORT virtual ~AutoincrementManager();
EXPORT void startSequence(uint32_t OID, uint64_t firstNum, uint32_t colWidth,
execplan::CalpontSystemCatalog::ColDataType colDataType);
EXPORT bool getAIRange(uint32_t OID, uint64_t count, uint64_t* firstNum);
EXPORT void resetSequence(uint32_t OID, uint64_t value);
EXPORT void getLock(uint32_t OID);
EXPORT void releaseLock(uint32_t OID);
EXPORT void deleteSequence(uint32_t OID);
EXPORT void startSequence(uint32_t OID, uint64_t firstNum, uint32_t colWidth,
execplan::CalpontSystemCatalog::ColDataType colDataType);
EXPORT bool getAIRange(uint32_t OID, uint64_t count, uint64_t* firstNum);
EXPORT void resetSequence(uint32_t OID, uint64_t value);
EXPORT void getLock(uint32_t OID);
EXPORT void releaseLock(uint32_t OID);
EXPORT void deleteSequence(uint32_t OID);
private:
static const uint32_t lockTime; // 30 seconds
struct sequence
private:
static const uint32_t lockTime; // 30 seconds
struct sequence
{
sequence() : value(0), overflow(0)
{
sequence() : value(0), overflow(0) { }
sequence(const sequence& s) : value(s.value), overflow(s.overflow) { }
sequence& operator=(const sequence& s)
{
value = s.value;
overflow = s.overflow;
return *this;
}
uint64_t value;
uint64_t overflow;
boost::mutex lock;
};
}
sequence(const sequence& s) : value(s.value), overflow(s.overflow)
{
}
sequence& operator=(const sequence& s)
{
value = s.value;
overflow = s.overflow;
return *this;
}
uint64_t value;
uint64_t overflow;
boost::mutex lock;
std::map<uint64_t, sequence> sequences;
};
boost::mutex lock;
std::map<uint64_t, sequence> sequences;
};
} /* namespace BRM */

View File

@ -3,7 +3,6 @@
#include "dbrm.h"
#include "IDBPolicy.h"
using namespace std;
using namespace BRM;
@ -20,173 +19,134 @@ DBRM dbrm;
void doStartSeq()
{
try
{
dbrm.startAISequence(12345, 67890, 1, execplan::CalpontSystemCatalog::INT);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
try
{
dbrm.startAISequence(12345, 67890, 1, execplan::CalpontSystemCatalog::INT);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
cout << "OK.\n";
}
void doGetRange()
{
uint64_t firstNum;
bool ret;
uint64_t firstNum;
bool ret;
try
{
ret = dbrm.getAIRange(12345, 110000, &firstNum);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
try
{
ret = dbrm.getAIRange(12345, 110000, &firstNum);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
if (!ret)
cout << "getAIRange failed\n";
else
cout << "got firstNum " << firstNum << endl;
if (!ret)
cout << "getAIRange failed\n";
else
cout << "got firstNum " << firstNum << endl;
}
void doGetValue()
{
uint64_t val;
bool ret;
uint64_t val;
bool ret;
try
{
ret = dbrm.getAIValue(12345, &val);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
try
{
ret = dbrm.getAIValue(12345, &val);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
if (!ret)
cout << "getAIValue failed\n";
else
cout << "got val " << val << endl;
if (!ret)
cout << "getAIValue failed\n";
else
cout << "got val " << val << endl;
}
void doReset()
{
try
{
dbrm.resetAISequence(12345, 11111);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
try
{
dbrm.resetAISequence(12345, 11111);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
cout << "OK.\n";
}
void doLock()
{
try
{
dbrm.getAILock(12345);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
try
{
dbrm.getAILock(12345);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
cout << "OK.\n";
}
void doUnlock()
{
try
{
dbrm.releaseAILock(12345);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
try
{
dbrm.releaseAILock(12345);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
cout << "OK.\n";
}
int main(int argc, char** argv)
{
if (argc < 2)
{
cout << "Usage: " << argv[0] << " s | r | v | R | l | u. Check the code to see what they do. :P\n";
exit(1);
}
if (argc < 2)
{
cout << "Usage: " << argv[0] << " s | r | v | R | l | u. Check the code to see what they do. :P\n";
exit(1);
}
char cmd = argv[1][0];
char cmd = argv[1][0];
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
switch (cmd)
{
case 's': doStartSeq(); break;
switch (cmd)
{
case 's':
doStartSeq();
break;
case 'r': doGetRange(); break;
case 'r':
doGetRange();
break;
case 'v': doGetValue(); break;
case 'v':
doGetValue();
break;
case 'R': doReset(); break;
case 'R':
doReset();
break;
case 'l': doLock(); break;
case 'l':
doLock();
break;
case 'u': doUnlock(); break;
case 'u':
doUnlock();
break;
default:
cout << "Usage: " << argv[0] << " s | r | v | R | l | u. Check the code to see what they do. :P\n";
exit(1);
}
default:
cout << "Usage: " << argv[0] << " s | r | v | R | l | u. Check the code to see what they do. :P\n";
exit(1);
}
}

View File

@ -50,21 +50,20 @@ using namespace std;
namespace BRM
{
BlockResolutionManager::BlockResolutionManager(bool ronly) throw()
{
if (ronly)
{
em.setReadOnly();
vss.setReadOnly();
vbbm.setReadOnly();
copylocks.setReadOnly();
}
if (ronly)
{
em.setReadOnly();
vss.setReadOnly();
vbbm.setReadOnly();
copylocks.setReadOnly();
}
}
BlockResolutionManager::BlockResolutionManager(const BlockResolutionManager& brm)
{
throw logic_error("BRM: Don't use the copy constructor.");
throw logic_error("BRM: Don't use the copy constructor.");
}
BlockResolutionManager::~BlockResolutionManager() throw()
@ -73,124 +72,122 @@ BlockResolutionManager::~BlockResolutionManager() throw()
BlockResolutionManager& BlockResolutionManager::operator=(const BlockResolutionManager& brm)
{
throw logic_error("BRM: Don't use the = operator.");
throw logic_error("BRM: Don't use the = operator.");
}
int BlockResolutionManager::loadExtentMap(const string& filename, bool fixFL)
{
em.load(filename, fixFL);
return 0;
em.load(filename, fixFL);
return 0;
}
int BlockResolutionManager::saveExtentMap(const string& filename)
{
em.save(filename);
return 0;
em.save(filename);
return 0;
}
int BlockResolutionManager::saveState(string filename) throw()
{
string emFilename = filename + "_em";
string vssFilename = filename + "_vss";
string vbbmFilename = filename + "_vbbm";
string journalFilename = filename + "_journal";
string emFilename = filename + "_em";
string vssFilename = filename + "_vss";
string vbbmFilename = filename + "_vbbm";
string journalFilename = filename + "_journal";
bool locked[2] = { false, false };
bool locked[2] = {false, false};
try
{
vbbm.lock(VBBM::READ);
locked[0] = true;
vss.lock(VSS::READ);
locked[1] = true;
try
{
vbbm.lock(VBBM::READ);
locked[0] = true;
vss.lock(VSS::READ);
locked[1] = true;
saveExtentMap(emFilename);
saveExtentMap(emFilename);
// truncate teh file if already exists since no truncate in HDFS.
const char* filename_p = journalFilename.c_str();
// truncate teh file if already exists since no truncate in HDFS.
const char* filename_p = journalFilename.c_str();
IDBDataFile* journal = IDBDataFile::open(
IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG), filename_p, "wb", 0);
delete journal;
IDBDataFile* journal =
IDBDataFile::open(IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG), filename_p, "wb", 0);
delete journal;
vbbm.save(vbbmFilename);
vss.save(vssFilename);
vbbm.save(vbbmFilename);
vss.save(vssFilename);
vss.release(VSS::READ);
locked[1] = false;
vbbm.release(VBBM::READ);
locked[0] = false;
}
catch (exception& e)
{
if (locked[1])
vss.release(VSS::READ);
vss.release(VSS::READ);
locked[1] = false;
vbbm.release(VBBM::READ);
locked[0] = false;
}
catch (exception& e)
{
if (locked[1])
vss.release(VSS::READ);
if (locked[0])
vbbm.release(VBBM::READ);
if (locked[0])
vbbm.release(VBBM::READ);
cout << e.what() << endl;
return -1;
}
cout << e.what() << endl;
return -1;
}
return 0;
return 0;
}
int BlockResolutionManager::loadState(string filename, bool fixFL) throw()
{
string emFilename = filename + "_em";
string vssFilename = filename + "_vss";
string vbbmFilename = filename + "_vbbm";
bool locked[2] = { false, false};
string emFilename = filename + "_em";
string vssFilename = filename + "_vss";
string vbbmFilename = filename + "_vbbm";
bool locked[2] = {false, false};
try
{
vbbm.lock(VBBM::WRITE);
locked[0] = true;
vss.lock(VSS::WRITE);
locked[1] = true;
try
{
vbbm.lock(VBBM::WRITE);
locked[0] = true;
vss.lock(VSS::WRITE);
locked[1] = true;
loadExtentMap(emFilename, fixFL);
vbbm.load(vbbmFilename);
vss.load(vssFilename);
loadExtentMap(emFilename, fixFL);
vbbm.load(vbbmFilename);
vss.load(vssFilename);
vss.release(VSS::WRITE);
locked[1] = false;
vbbm.release(VBBM::WRITE);
locked[0] = false;
}
catch (exception& e)
{
if (locked[1])
vss.release(VSS::WRITE);
vss.release(VSS::WRITE);
locked[1] = false;
vbbm.release(VBBM::WRITE);
locked[0] = false;
}
catch (exception& e)
{
if (locked[1])
vss.release(VSS::WRITE);
if (locked[0])
vbbm.release(VBBM::WRITE);
if (locked[0])
vbbm.release(VBBM::WRITE);
cout << e.what() << endl;
return -1;
}
cout << e.what() << endl;
return -1;
}
return 0;
return 0;
}
int BlockResolutionManager::replayJournal(string prefix) throw()
{
SlaveComm sc;
int err = -1;
SlaveComm sc;
int err = -1;
try
{
err = sc.replayJournal(prefix);
}
catch (exception& e)
{
cout << e.what();
}
try
{
err = sc.replayJournal(prefix);
}
catch (exception& e)
{
cout << e.what();
}
return err;
return err;
}
} //namespace
} // namespace BRM

View File

@ -46,7 +46,6 @@
namespace BRM
{
/** @brief The BlockResolutionManager manages the Logical Block ID space.
*
* The BlockResolutionManager manages the Logical Block ID space. Its
@ -57,73 +56,72 @@ namespace BRM
*/
class BlockResolutionManager
{
public:
EXPORT explicit BlockResolutionManager(bool ronly = false) throw();
EXPORT ~BlockResolutionManager() throw();
public:
EXPORT explicit BlockResolutionManager(bool ronly = false) throw();
EXPORT ~BlockResolutionManager() throw();
/** @brief Persistence API. Loads the local Extent Map from a file.
*
* Persistence API. Loads the <b>local</b> Extent Map from a file.
*
* @warning The load must be done on each slave node atomically wrt
* writing operations, otherwise nodes may be out of synch.
* @param filename Relative or absolute path to a file saved with saveExtentMap.
* @return 0, throws if EM throws
*/
EXPORT int loadExtentMap(const std::string& filename, bool fixFL);
/** @brief Persistence API. Loads the local Extent Map from a file.
*
* Persistence API. Loads the <b>local</b> Extent Map from a file.
*
* @warning The load must be done on each slave node atomically wrt
* writing operations, otherwise nodes may be out of synch.
* @param filename Relative or absolute path to a file saved with saveExtentMap.
* @return 0, throws if EM throws
*/
EXPORT int loadExtentMap(const std::string& filename, bool fixFL);
/** @brief Persistence API. Saves the local Extent Map to a file.
*
* Persistence API. Saves the <b>local</b> Extent Map to a file.
*
* @param filename Relative or absolute path to save to.
* @return 0 on success, throws if EM throws
*/
EXPORT int saveExtentMap(const std::string& filename);
/** @brief Persistence API. Saves the local Extent Map to a file.
*
* Persistence API. Saves the <b>local</b> Extent Map to a file.
*
* @param filename Relative or absolute path to save to.
* @return 0 on success, throws if EM throws
*/
EXPORT int saveExtentMap(const std::string& filename);
/** @brief Persistence API. Loads all BRM snapshots.
*
* Loads all <b>local</b> BRM structures from files saved with saveState().
*
* @warning The load must be done on each slave node atomically wrt
* writing operations, otherwise nodes may be out of synch.
* @param filename The filename prefix to use. Loads 4 files with that prefix.
* @return 0 on success, -1 on error
*/
EXPORT int loadState(std::string filename, bool fixFL = false) throw();
/** @brief Persistence API. Loads all BRM snapshots.
*
* Loads all <b>local</b> BRM structures from files saved with saveState().
*
* @warning The load must be done on each slave node atomically wrt
* writing operations, otherwise nodes may be out of synch.
* @param filename The filename prefix to use. Loads 4 files with that prefix.
* @return 0 on success, -1 on error
*/
EXPORT int loadState(std::string filename, bool fixFL = false) throw();
/** @brief Persistence API. Loads the BRM deltas since the last snapshot.
*
* Loads all <b>local</b> BRM structures from files saved with saveState().
*
* @warning The load must be done on each slave node atomically wrt
* writing operations, otherwise nodes may be out of synch.
* @param filename The filename prefix to use. Loads 4 files with that prefix.
* @return 0 on success, -1 on error
*/
EXPORT int replayJournal(std::string filename) throw();
/** @brief Persistence API. Loads the BRM deltas since the last snapshot.
*
* Loads all <b>local</b> BRM structures from files saved with saveState().
*
* @warning The load must be done on each slave node atomically wrt
* writing operations, otherwise nodes may be out of synch.
* @param filename The filename prefix to use. Loads 4 files with that prefix.
* @return 0 on success, -1 on error
*/
EXPORT int replayJournal(std::string filename) throw();
/** @brief Persistence API. Saves all BRM structures.
*
* Saves all <b>local</b> BRM structures to files.
*
* @param filename The filename prefix to use. Saves 4 files with that prefix.
* @return 0 on success, -1 on error
*/
EXPORT int saveState(std::string filename) throw();
private:
explicit BlockResolutionManager(const BlockResolutionManager& brm);
BlockResolutionManager& operator=(const BlockResolutionManager& brm);
MasterSegmentTable mst;
ExtentMap em;
VBBM vbbm;
VSS vss;
CopyLocks copylocks;
/** @brief Persistence API. Saves all BRM structures.
*
* Saves all <b>local</b> BRM structures to files.
*
* @param filename The filename prefix to use. Saves 4 files with that prefix.
* @return 0 on success, -1 on error
*/
EXPORT int saveState(std::string filename) throw();
private:
explicit BlockResolutionManager(const BlockResolutionManager& brm);
BlockResolutionManager& operator=(const BlockResolutionManager& brm);
MasterSegmentTable mst;
ExtentMap em;
VBBM vbbm;
VSS vss;
CopyLocks copylocks;
};
}
} // namespace BRM
#undef EXPORT

View File

@ -40,199 +40,204 @@ namespace bi = boost::interprocess;
namespace BRM
{
BRMShmImpl::BRMShmImpl(unsigned key, off_t size, bool readOnly) :
fKey(key), fSize(size), fReadOnly(readOnly)
BRMShmImpl::BRMShmImpl(unsigned key, off_t size, bool readOnly) : fKey(key), fSize(size), fReadOnly(readOnly)
{
string keyName = ShmKeys::keyToName(fKey);
string keyName = ShmKeys::keyToName(fKey);
if (fSize == 0)
{
unsigned tries = 0;
again:
try
{
bi::shared_memory_object shm(bi::open_only, keyName.c_str(), bi::read_write);
off_t curSize = 0;
#ifdef _MSC_VER
bi::offset_t tmp = 0;
shm.get_size(tmp);
curSize = static_cast<off_t>(tmp);
#else
shm.get_size(curSize);
#endif
if (curSize == 0) throw
bi::interprocess_exception("shm size is zero");
}
catch (bi::interprocess_exception&)
{
if (++tries > 10)
{
log("BRMShmImpl::BRMShmImpl(): retrying on size==0");
throw;
}
cerr << "BRMShmImpl::BRMShmImpl(): retrying on size==0" << endl;
usleep(500 * 1000);
goto again;
}
}
if (fSize == 0)
{
unsigned tries = 0;
again:
try
{
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
idbassert(fSize > 0);
shm.truncate(fSize);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception &b)
{
if (b.get_error_code() != bi::already_exists_error) {
ostringstream o;
o << "BRM caught an exception creating a shared memory segment: " << b.what();
log(o.str());
throw;
}
bi::shared_memory_object *shm = NULL;
try {
shm = new bi::shared_memory_object(bi::open_only, keyName.c_str(), bi::read_write);
}
catch (exception &e) {
ostringstream o;
o << "BRM caught an exception attaching to a shared memory segment (" << keyName << "): " << b.what();
log(o.str());
throw;
}
off_t curSize = 0;
bi::shared_memory_object shm(bi::open_only, keyName.c_str(), bi::read_write);
off_t curSize = 0;
#ifdef _MSC_VER
bi::offset_t tmp = 0;
shm->get_size(tmp);
curSize = static_cast<off_t>(tmp);
bi::offset_t tmp = 0;
shm.get_size(tmp);
curSize = static_cast<off_t>(tmp);
#else
shm->get_size(curSize);
shm.get_size(curSize);
#endif
idbassert(curSize > 0);
idbassert(curSize >= fSize);
fShmobj.swap(*shm);
delete shm;
fSize = curSize;
}
if (fReadOnly)
{
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
if (curSize == 0)
throw bi::interprocess_exception("shm size is zero");
}
else
catch (bi::interprocess_exception&)
{
bi::mapped_region region(fShmobj, bi::read_write);
fMapreg.swap(region);
if (++tries > 10)
{
log("BRMShmImpl::BRMShmImpl(): retrying on size==0");
throw;
}
cerr << "BRMShmImpl::BRMShmImpl(): retrying on size==0" << endl;
usleep(500 * 1000);
goto again;
}
}
try
{
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
idbassert(fSize > 0);
shm.truncate(fSize);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception& b)
{
if (b.get_error_code() != bi::already_exists_error)
{
ostringstream o;
o << "BRM caught an exception creating a shared memory segment: " << b.what();
log(o.str());
throw;
}
bi::shared_memory_object* shm = NULL;
try
{
shm = new bi::shared_memory_object(bi::open_only, keyName.c_str(), bi::read_write);
}
catch (exception& e)
{
ostringstream o;
o << "BRM caught an exception attaching to a shared memory segment (" << keyName << "): " << b.what();
log(o.str());
throw;
}
off_t curSize = 0;
#ifdef _MSC_VER
bi::offset_t tmp = 0;
shm->get_size(tmp);
curSize = static_cast<off_t>(tmp);
#else
shm->get_size(curSize);
#endif
idbassert(curSize > 0);
idbassert(curSize >= fSize);
fShmobj.swap(*shm);
delete shm;
fSize = curSize;
}
if (fReadOnly)
{
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
}
else
{
bi::mapped_region region(fShmobj, bi::read_write);
fMapreg.swap(region);
}
}
int BRMShmImpl::grow(unsigned newKey, off_t newSize)
{
idbassert(newKey != fKey);
idbassert(newSize >= fSize);
idbassert(newKey != fKey);
idbassert(newSize >= fSize);
string oldName = fShmobj.get_name();
string oldName = fShmobj.get_name();
string keyName = ShmKeys::keyToName(newKey);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
shm.truncate(newSize);
string keyName = ShmKeys::keyToName(newKey);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
shm.truncate(newSize);
bi::mapped_region region(shm, bi::read_write);
bi::mapped_region region(shm, bi::read_write);
//Copy old data into new region
memcpy(region.get_address(), fMapreg.get_address(), fSize);
//clear new region
//make some versions of gcc happier...
memset(reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(region.get_address()) + fSize), 0, newSize - fSize);
// Copy old data into new region
memcpy(region.get_address(), fMapreg.get_address(), fSize);
// clear new region
// make some versions of gcc happier...
memset(reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(region.get_address()) + fSize), 0,
newSize - fSize);
fShmobj.swap(shm);
fMapreg.swap(region);
fShmobj.swap(shm);
fMapreg.swap(region);
if (!oldName.empty()) bi::shared_memory_object::remove(oldName.c_str());
if (!oldName.empty())
bi::shared_memory_object::remove(oldName.c_str());
fKey = newKey;
fSize = newSize;
fKey = newKey;
fSize = newSize;
if (fReadOnly)
{
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
}
if (fReadOnly)
{
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
}
return 0;
return 0;
}
int BRMShmImpl::clear(unsigned newKey, off_t newSize)
{
idbassert(newKey != fKey);
idbassert(newKey != fKey);
string oldName = fShmobj.get_name();
string oldName = fShmobj.get_name();
string keyName = ShmKeys::keyToName(newKey);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
shm.truncate(newSize);
string keyName = ShmKeys::keyToName(newKey);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
shm.truncate(newSize);
bi::mapped_region region(shm, bi::read_write);
bi::mapped_region region(shm, bi::read_write);
//clear new region
memset(region.get_address(), 0, newSize);
// clear new region
memset(region.get_address(), 0, newSize);
fShmobj.swap(shm);
fMapreg.swap(region);
fShmobj.swap(shm);
fMapreg.swap(region);
if (!oldName.empty()) bi::shared_memory_object::remove(oldName.c_str());
if (!oldName.empty())
bi::shared_memory_object::remove(oldName.c_str());
fKey = newKey;
fSize = newSize;
fKey = newKey;
fSize = newSize;
if (fReadOnly)
{
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
}
if (fReadOnly)
{
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
}
return 0;
return 0;
}
void BRMShmImpl::setReadOnly()
{
if (fReadOnly) return;
if (fReadOnly)
return;
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
bi::mapped_region ro_region(fShmobj, bi::read_only);
fMapreg.swap(ro_region);
fReadOnly = true;
fReadOnly = true;
}
void BRMShmImpl::swap(BRMShmImpl& rhs)
{
fShmobj.swap(rhs.fShmobj);
fMapreg.swap(rhs.fMapreg);
std::swap(fKey, rhs.fKey);
std::swap(fSize, rhs.fSize);
std::swap(fReadOnly, rhs.fReadOnly);
fShmobj.swap(rhs.fShmobj);
fMapreg.swap(rhs.fMapreg);
std::swap(fKey, rhs.fKey);
std::swap(fSize, rhs.fSize);
std::swap(fReadOnly, rhs.fReadOnly);
}
void BRMShmImpl::destroy()
{
string oldName = fShmobj.get_name();
string oldName = fShmobj.get_name();
if (!oldName.empty()) bi::shared_memory_object::remove(oldName.c_str());
if (!oldName.empty())
bi::shared_memory_object::remove(oldName.c_str());
}
} //namespace
} // namespace BRM
// vim:ts=4 sw=4:

View File

@ -35,45 +35,46 @@
namespace BRM
{
class BRMShmImpl
{
public:
BRMShmImpl(unsigned key, off_t size, bool readOnly = false);
~BRMShmImpl() { }
public:
BRMShmImpl(unsigned key, off_t size, bool readOnly = false);
~BRMShmImpl()
{
}
inline unsigned key() const
{
return fKey;
}
inline off_t size() const
{
return fSize;
}
inline bool isReadOnly() const
{
return fReadOnly;
}
inline unsigned key() const
{
return fKey;
}
inline off_t size() const
{
return fSize;
}
inline bool isReadOnly() const
{
return fReadOnly;
}
void setReadOnly();
int grow(unsigned newKey, off_t newSize);
int clear(unsigned newKey, off_t newSize);
void setReadOnly();
int grow(unsigned newKey, off_t newSize);
int clear(unsigned newKey, off_t newSize);
void swap(BRMShmImpl& rhs);
void destroy();
void swap(BRMShmImpl& rhs);
void destroy();
boost::interprocess::shared_memory_object fShmobj;
boost::interprocess::mapped_region fMapreg;
boost::interprocess::shared_memory_object fShmobj;
boost::interprocess::mapped_region fMapreg;
private:
BRMShmImpl(const BRMShmImpl& rhs);
BRMShmImpl& operator=(const BRMShmImpl& rhs);
private:
BRMShmImpl(const BRMShmImpl& rhs);
BRMShmImpl& operator=(const BRMShmImpl& rhs);
unsigned fKey;
off_t fSize;
bool fReadOnly;
unsigned fKey;
off_t fSize;
bool fReadOnly;
};
} //namespace
} // namespace BRM
#endif

View File

@ -53,29 +53,27 @@ using namespace idbdatafile;
// local unnamed namespace
namespace
{
unsigned int subSystemLoggingId =
(unsigned int)BRM::SubSystemLogId_controllerNode;
unsigned int subSystemLoggingId = (unsigned int)BRM::SubSystemLogId_controllerNode;
}
namespace BRM
{
LBIDRange::LBIDRange()
{
start = 0;
size = 0;
start = 0;
size = 0;
}
LBIDRange::LBIDRange(const LBIDRange& l)
{
start = l.start;
size = l.size;
start = l.start;
size = l.size;
}
LBIDRange::LBIDRange(const InlineLBIDRange& l)
{
start = l.start;
size = l.size;
start = l.start;
size = l.size;
}
LBIDRange::~LBIDRange()
@ -84,16 +82,16 @@ LBIDRange::~LBIDRange()
LBIDRange& LBIDRange::operator=(const LBIDRange& l)
{
start = l.start;
size = l.size;
return *this;
start = l.start;
size = l.size;
return *this;
}
LBIDRange& LBIDRange::operator=(const InlineLBIDRange& l)
{
start = l.start;
size = l.size;
return *this;
start = l.start;
size = l.size;
return *this;
}
// this value should be impossible in version 1
@ -105,184 +103,162 @@ LBIDRange& LBIDRange::operator=(const InlineLBIDRange& l)
void LBIDRange::deserialize(ByteStream& bs)
{
uint64_t tmp;
uint64_t tmp;
bs >> tmp;
if (tmp == RANGE_V2_MAGIC)
{
bs >> tmp;
if (tmp == RANGE_V2_MAGIC)
{
bs >> tmp;
start = tmp;
bs >> size;
}
else
{
// version 1
size = (tmp & 0xffffffff00000000ULL) >> 32;
start = (tmp & 0x00000000ffffffffULL);
}
start = tmp;
bs >> size;
}
else
{
// version 1
size = (tmp & 0xffffffff00000000ULL) >> 32;
start = (tmp & 0x00000000ffffffffULL);
}
}
void LBIDRange::serialize(ByteStream& bs) const
{
bs << (uint64_t) RANGE_V2_MAGIC;
bs << (uint64_t) start;
bs << size;
bs << (uint64_t)RANGE_V2_MAGIC;
bs << (uint64_t)start;
bs << size;
}
_TxnID::_TxnID()
{
id = 0;
valid = false;
id = 0;
valid = false;
}
_SIDTIDEntry::_SIDTIDEntry()
{
init();
init();
}
void _SIDTIDEntry::init()
{
sessionid = 0;
txnid.id = 0;
txnid.valid = false;
sessionid = 0;
txnid.id = 0;
txnid.valid = false;
}
VBRange::VBRange()
{
vbOID = 0;
vbFBO = 0;
size = 0;
vbOID = 0;
vbFBO = 0;
size = 0;
}
VBRange::VBRange(const VBRange& v)
{
vbOID = v.vbOID;
vbFBO = v.vbFBO;
size = v.size;
vbOID = v.vbOID;
vbFBO = v.vbFBO;
size = v.size;
}
VBRange::~VBRange()
{
}
VBRange& VBRange::operator= (const VBRange& v)
VBRange& VBRange::operator=(const VBRange& v)
{
vbOID = v.vbOID;
vbFBO = v.vbFBO;
size = v.size;
return *this;
vbOID = v.vbOID;
vbFBO = v.vbFBO;
size = v.size;
return *this;
}
void VBRange::deserialize(ByteStream& bs)
{
uint32_t tmp;
uint32_t tmp;
bs >> tmp;
vbOID = tmp;
bs >> vbFBO;
bs >> size;
bs >> tmp;
vbOID = tmp;
bs >> vbFBO;
bs >> size;
}
void VBRange::serialize(ByteStream& bs) const
{
bs << (uint32_t) vbOID;
bs << vbFBO;
bs << size;
bs << (uint32_t)vbOID;
bs << vbFBO;
bs << size;
}
void logInit ( SubSystemLogId subSystemId )
void logInit(SubSystemLogId subSystemId)
{
subSystemLoggingId = (unsigned int)subSystemId;
subSystemLoggingId = (unsigned int)subSystemId;
}
void log(const string& msg, logging::LOG_TYPE level)
{
logging::MessageLog logger((logging::LoggingID(subSystemLoggingId)));
logging::Message message;
logging::Message::Args args;
logging::MessageLog logger((logging::LoggingID(subSystemLoggingId)));
logging::Message message;
logging::Message::Args args;
args.add(msg);
message.format(args);
args.add(msg);
message.format(args);
switch (level)
{
case logging::LOG_TYPE_DEBUG:
logger.logDebugMessage(message);
break;
switch (level)
{
case logging::LOG_TYPE_DEBUG: logger.logDebugMessage(message); break;
case logging::LOG_TYPE_INFO:
logger.logInfoMessage(message);
break;
case logging::LOG_TYPE_INFO: logger.logInfoMessage(message); break;
case logging::LOG_TYPE_WARNING:
logger.logWarningMessage(message);
break;
case logging::LOG_TYPE_WARNING: logger.logWarningMessage(message); break;
case logging::LOG_TYPE_ERROR:
logger.logErrorMessage(message);
break;
case logging::LOG_TYPE_ERROR: logger.logErrorMessage(message); break;
case logging::LOG_TYPE_CRITICAL:
logger.logCriticalMessage(message);
break;
case logging::LOG_TYPE_CRITICAL: logger.logCriticalMessage(message); break;
default:
logger.logInfoMessage(message);
}
default: logger.logInfoMessage(message);
}
}
void log_errno(const string& msg, logging::LOG_TYPE level)
{
int tmp = errno;
char test[1000];
logging::MessageLog logger((logging::LoggingID(subSystemLoggingId)));
logging::Message message;
logging::Message::Args args;
int tmp = errno;
char test[1000];
logging::MessageLog logger((logging::LoggingID(subSystemLoggingId)));
logging::Message message;
logging::Message::Args args;
args.add(msg + ": ");
args.add(msg + ": ");
#if STRERROR_R_CHAR_P
const char* cMsg;
cMsg = strerror_r(tmp, &test[0], 1000);
const char* cMsg;
cMsg = strerror_r(tmp, &test[0], 1000);
if (cMsg == NULL)
args.add(string("strerror failed"));
else
args.add(string(cMsg));
if (cMsg == NULL)
args.add(string("strerror failed"));
else
args.add(string(cMsg));
#else
int cMsg;
cMsg = strerror_r(tmp, &test[0], 1000);
args.add(string(test));
int cMsg;
cMsg = strerror_r(tmp, &test[0], 1000);
args.add(string(test));
#endif
message.format(args);
message.format(args);
switch (level)
{
case logging::LOG_TYPE_DEBUG:
logger.logDebugMessage(message);
break;
switch (level)
{
case logging::LOG_TYPE_DEBUG: logger.logDebugMessage(message); break;
case logging::LOG_TYPE_INFO:
logger.logInfoMessage(message);
break;
case logging::LOG_TYPE_INFO: logger.logInfoMessage(message); break;
case logging::LOG_TYPE_WARNING:
logger.logWarningMessage(message);
break;
case logging::LOG_TYPE_WARNING: logger.logWarningMessage(message); break;
case logging::LOG_TYPE_ERROR:
logger.logErrorMessage(message);
break;
case logging::LOG_TYPE_ERROR: logger.logErrorMessage(message); break;
case logging::LOG_TYPE_CRITICAL:
logger.logCriticalMessage(message);
break;
case logging::LOG_TYPE_CRITICAL: logger.logCriticalMessage(message); break;
default:
logger.logInfoMessage(message);
}
default: logger.logInfoMessage(message);
}
}
//------------------------------------------------------------------------------
@ -290,245 +266,245 @@ void log_errno(const string& msg, logging::LOG_TYPE level)
//------------------------------------------------------------------------------
void errString(int rc, string& errMsg)
{
switch (rc)
switch (rc)
{
case ERR_OK:
{
case ERR_OK:
{
errMsg = "OKAY";
break;
}
case ERR_FAILURE:
{
errMsg = "FAILED";
break;
}
case ERR_SLAVE_INCONSISTENCY:
{
errMsg = "image inconsistency";
break;
}
case ERR_NETWORK:
{
errMsg = "network error";
break;
}
case ERR_TIMEOUT:
{
errMsg = "network timeout";
break;
}
case ERR_READONLY:
{
errMsg = "DBRM is in READ-ONLY mode";
break;
}
case ERR_DEADLOCK:
{
errMsg = "deadlock reserving LBID range";
break;
}
case ERR_KILLED:
{
errMsg = "killed reserving LBID range";
break;
}
case ERR_VBBM_OVERFLOW:
{
errMsg = "VBBM overflow";
break;
}
case ERR_TABLE_LOCKED_ALREADY:
{
errMsg = "table already locked";
break;
}
case ERR_INVALID_OP_LAST_PARTITION:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_LAST_PARTITION);
break;
}
case ERR_PARTITION_DISABLED:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PARTITION_ALREADY_DISABLED);
break;
}
case ERR_NOT_EXIST_PARTITION:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PARTITION_NOT_EXIST);
break;
}
case ERR_PARTITION_ENABLED:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PARTITION_ALREADY_ENABLED);
break;
}
case ERR_OLDTXN_OVERWRITING_NEWTXN:
{
errMsg = "A newer transaction has already written to the same block(s)";
break;
}
default:
{
ostringstream oss;
oss << "UNKNOWN (" << rc << ")";
errMsg = oss.str();
break;
}
errMsg = "OKAY";
break;
}
case ERR_FAILURE:
{
errMsg = "FAILED";
break;
}
case ERR_SLAVE_INCONSISTENCY:
{
errMsg = "image inconsistency";
break;
}
case ERR_NETWORK:
{
errMsg = "network error";
break;
}
case ERR_TIMEOUT:
{
errMsg = "network timeout";
break;
}
case ERR_READONLY:
{
errMsg = "DBRM is in READ-ONLY mode";
break;
}
case ERR_DEADLOCK:
{
errMsg = "deadlock reserving LBID range";
break;
}
case ERR_KILLED:
{
errMsg = "killed reserving LBID range";
break;
}
case ERR_VBBM_OVERFLOW:
{
errMsg = "VBBM overflow";
break;
}
case ERR_TABLE_LOCKED_ALREADY:
{
errMsg = "table already locked";
break;
}
case ERR_INVALID_OP_LAST_PARTITION:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_LAST_PARTITION);
break;
}
case ERR_PARTITION_DISABLED:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PARTITION_ALREADY_DISABLED);
break;
}
case ERR_NOT_EXIST_PARTITION:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PARTITION_NOT_EXIST);
break;
}
case ERR_PARTITION_ENABLED:
{
errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PARTITION_ALREADY_ENABLED);
break;
}
case ERR_OLDTXN_OVERWRITING_NEWTXN:
{
errMsg = "A newer transaction has already written to the same block(s)";
break;
}
default:
{
ostringstream oss;
oss << "UNKNOWN (" << rc << ")";
errMsg = oss.str();
break;
}
}
}
/* Tablelock impl */
bool TableLockInfo::overlaps(const TableLockInfo& t, const std::set<uint32_t>& sDbrootList) const
{
if (tableOID != t.tableOID)
return false;
for (uint32_t i = 0; i < dbrootList.size(); i++)
if (sDbrootList.find(dbrootList[i]) != sDbrootList.end())
return true;
if (tableOID != t.tableOID)
return false;
for (uint32_t i = 0; i < dbrootList.size(); i++)
if (sDbrootList.find(dbrootList[i]) != sDbrootList.end())
return true;
return false;
}
void TableLockInfo::serialize(ByteStream& bs) const
{
bs << id << tableOID << ownerName << ownerPID << (uint32_t) ownerSessionID <<
(uint32_t) ownerTxnID << (uint8_t) state;
bs << (uint64_t) creationTime;
serializeInlineVector(bs, dbrootList);
bs << id << tableOID << ownerName << ownerPID << (uint32_t)ownerSessionID << (uint32_t)ownerTxnID
<< (uint8_t)state;
bs << (uint64_t)creationTime;
serializeInlineVector(bs, dbrootList);
}
void TableLockInfo::deserialize(ByteStream& bs)
{
uint8_t tmp8;
uint32_t tmp321, tmp322;
uint64_t tmp64;
bs >> id >> tableOID >> ownerName >> ownerPID >> tmp321 >> tmp322 >> tmp8 >> tmp64;
ownerSessionID = tmp321;
ownerTxnID = tmp322;
state = (LockState) tmp8;
creationTime = tmp64;
deserializeInlineVector(bs, dbrootList);
uint8_t tmp8;
uint32_t tmp321, tmp322;
uint64_t tmp64;
bs >> id >> tableOID >> ownerName >> ownerPID >> tmp321 >> tmp322 >> tmp8 >> tmp64;
ownerSessionID = tmp321;
ownerTxnID = tmp322;
state = (LockState)tmp8;
creationTime = tmp64;
deserializeInlineVector(bs, dbrootList);
}
void TableLockInfo::serialize(ostream& o) const
{
uint16_t nameLen = ownerName.length();
uint16_t dbrootListSize = dbrootList.size();
uint16_t nameLen = ownerName.length();
uint16_t dbrootListSize = dbrootList.size();
o.write((char*) &id, 8);
o.write((char*) &tableOID, 4);
o.write((char*) &ownerPID, 4);
o.write((char*) &state, 4);
o.write((char*) &ownerSessionID, 4);
o.write((char*) &ownerTxnID, 4);
o.write((char*) &creationTime, sizeof(time_t));
o.write((char*) &nameLen, 2);
o.write((char*) ownerName.c_str(), nameLen);
o.write((char*) &dbrootListSize, 2);
o.write((char*)&id, 8);
o.write((char*)&tableOID, 4);
o.write((char*)&ownerPID, 4);
o.write((char*)&state, 4);
o.write((char*)&ownerSessionID, 4);
o.write((char*)&ownerTxnID, 4);
o.write((char*)&creationTime, sizeof(time_t));
o.write((char*)&nameLen, 2);
o.write((char*)ownerName.c_str(), nameLen);
o.write((char*)&dbrootListSize, 2);
for (uint32_t j = 0; j < dbrootListSize; j++)
o.write((char*) &dbrootList[j], 4);
for (uint32_t j = 0; j < dbrootListSize; j++)
o.write((char*)&dbrootList[j], 4);
}
void TableLockInfo::deserialize(istream& i)
{
uint16_t nameLen;
uint16_t dbrootListSize;
boost::scoped_array<char> buf;
uint16_t nameLen;
uint16_t dbrootListSize;
boost::scoped_array<char> buf;
i.read((char*) &id, 8);
i.read((char*) &tableOID, 4);
i.read((char*) &ownerPID, 4);
i.read((char*) &state, 4);
i.read((char*) &ownerSessionID, 4);
i.read((char*) &ownerTxnID, 4);
i.read((char*) &creationTime, sizeof(time_t));
i.read((char*) &nameLen, 2);
buf.reset(new char[nameLen]);
i.read(buf.get(), nameLen);
ownerName = string(buf.get(), nameLen);
i.read((char*) &dbrootListSize, 2);
dbrootList.resize(dbrootListSize);
i.read((char*)&id, 8);
i.read((char*)&tableOID, 4);
i.read((char*)&ownerPID, 4);
i.read((char*)&state, 4);
i.read((char*)&ownerSessionID, 4);
i.read((char*)&ownerTxnID, 4);
i.read((char*)&creationTime, sizeof(time_t));
i.read((char*)&nameLen, 2);
buf.reset(new char[nameLen]);
i.read(buf.get(), nameLen);
ownerName = string(buf.get(), nameLen);
i.read((char*)&dbrootListSize, 2);
dbrootList.resize(dbrootListSize);
for (uint32_t j = 0; j < dbrootListSize; j++)
i.read((char*) &dbrootList[j], 4);
for (uint32_t j = 0; j < dbrootListSize; j++)
i.read((char*)&dbrootList[j], 4);
}
void TableLockInfo::serialize(IDBDataFile* o) const
{
uint16_t nameLen = ownerName.length();
uint16_t dbrootListSize = dbrootList.size();
uint16_t nameLen = ownerName.length();
uint16_t dbrootListSize = dbrootList.size();
o->write((char*) &id, 8);
o->write((char*) &tableOID, 4);
o->write((char*) &ownerPID, 4);
o->write((char*) &state, 4);
o->write((char*) &ownerSessionID, 4);
o->write((char*) &ownerTxnID, 4);
o->write((char*) &creationTime, sizeof(time_t));
o->write((char*) &nameLen, 2);
o->write((char*) ownerName.c_str(), nameLen);
o->write((char*) &dbrootListSize, 2);
o->write((char*)&id, 8);
o->write((char*)&tableOID, 4);
o->write((char*)&ownerPID, 4);
o->write((char*)&state, 4);
o->write((char*)&ownerSessionID, 4);
o->write((char*)&ownerTxnID, 4);
o->write((char*)&creationTime, sizeof(time_t));
o->write((char*)&nameLen, 2);
o->write((char*)ownerName.c_str(), nameLen);
o->write((char*)&dbrootListSize, 2);
for (uint32_t j = 0; j < dbrootListSize; j++)
o->write((char*) &dbrootList[j], 4);
for (uint32_t j = 0; j < dbrootListSize; j++)
o->write((char*)&dbrootList[j], 4);
}
void TableLockInfo::deserialize(IDBDataFile* i)
{
uint16_t nameLen;
uint16_t dbrootListSize;
boost::scoped_array<char> buf;
uint16_t nameLen;
uint16_t dbrootListSize;
boost::scoped_array<char> buf;
i->read((char*) &id, 8);
i->read((char*) &tableOID, 4);
i->read((char*) &ownerPID, 4);
i->read((char*) &state, 4);
i->read((char*) &ownerSessionID, 4);
i->read((char*) &ownerTxnID, 4);
i->read((char*) &creationTime, sizeof(time_t));
i->read((char*) &nameLen, 2);
buf.reset(new char[nameLen]);
i->read(buf.get(), nameLen);
ownerName = string(buf.get(), nameLen);
i->read((char*) &dbrootListSize, 2);
dbrootList.resize(dbrootListSize);
i->read((char*)&id, 8);
i->read((char*)&tableOID, 4);
i->read((char*)&ownerPID, 4);
i->read((char*)&state, 4);
i->read((char*)&ownerSessionID, 4);
i->read((char*)&ownerTxnID, 4);
i->read((char*)&creationTime, sizeof(time_t));
i->read((char*)&nameLen, 2);
buf.reset(new char[nameLen]);
i->read(buf.get(), nameLen);
ownerName = string(buf.get(), nameLen);
i->read((char*)&dbrootListSize, 2);
dbrootList.resize(dbrootListSize);
for (uint32_t j = 0; j < dbrootListSize; j++)
i->read((char*) &dbrootList[j], 4);
for (uint32_t j = 0; j < dbrootListSize; j++)
i->read((char*)&dbrootList[j], 4);
}
bool TableLockInfo::operator<(const TableLockInfo& tli) const
{
return (id < tli.id);
return (id < tli.id);
}
ostream& operator<<(ostream& os, const QueryContext& qc)
{
os << " SCN: " << qc.currentScn << endl;
os << " Txns: ";
os << " SCN: " << qc.currentScn << endl;
os << " Txns: ";
for (uint32_t i = 0; i < qc.currentTxns->size(); i++)
os << (*qc.currentTxns)[i] << " ";
for (uint32_t i = 0; i < qc.currentTxns->size(); i++)
os << (*qc.currentTxns)[i] << " ";
return os;
return os;
}
} //namespace
} // namespace BRM

View File

@ -47,25 +47,23 @@ namespace std
{
namespace tr1
{
template<>
struct hash<long long int>
: public std::unary_function<long long int, std::size_t>
template <>
struct hash<long long int> : public std::unary_function<long long int, std::size_t>
{
std::size_t
operator()(long long int val) const
{
return static_cast<std::size_t>(val);
}
std::size_t operator()(long long int val) const
{
return static_cast<std::size_t>(val);
}
};
}
}
#endif //if __GNUC__
} // namespace tr1
} // namespace std
#endif // if __GNUC__
#endif //if !__LP64__
#endif //_UNORDERED_MAP_FIX_
#endif // if !__LP64__
#endif //_UNORDERED_MAP_FIX_
#else
#include <unordered_map>
#endif //_MSC_VER
#endif //_MSC_VER
#include "calpontsystemcatalog.h"
#include "bytestream.h"
@ -84,12 +82,10 @@ namespace idbdatafile
class IDBDataFile;
}
namespace BRM
{
/* these types should be defined in the system catalog header */
typedef int64_t LBID_t; /// The LBID space is currently 36 bits. We use 64 here.
typedef int64_t LBID_t; /// The LBID space is currently 36 bits. We use 64 here.
typedef uint32_t HWM_t;
typedef int32_t VER_t;
/// Object ID type. Currently a 32-bit number. 24 for Object number, 8 for partition number.
@ -105,10 +101,10 @@ to inherit Serializeable, hence the all-public definitions */
/// The InlineLBIDRange struct is for use internally by the ExtentMap
struct InlineLBIDRange
{
LBID_t start;
uint32_t size;
LBID_t start;
uint32_t size;
#ifndef __LP64__
int32_t pad1;
int32_t pad1;
#endif
};
@ -119,11 +115,11 @@ typedef uint32_t SID;
/** @brief A type describing a single transaction ID */
struct _TxnID
{
/// The TransactionID number
execplan::CalpontSystemCatalog::SCN id;
/// True iff the id is valid.
bool valid;
EXPORT _TxnID();
/// The TransactionID number
execplan::CalpontSystemCatalog::SCN id;
/// True iff the id is valid.
bool valid;
EXPORT _TxnID();
};
/** @brief A type describing a single transaction ID */
typedef struct _TxnID TxnID;
@ -132,63 +128,62 @@ typedef struct _TxnID TxnID;
*/
struct _SIDTIDEntry
{
/// The Transaction ID. txnid.valid determines whether or not this SIDTIDEntry is valid
TxnID txnid;
/// The session doing the transaction
SID sessionid;
EXPORT _SIDTIDEntry();
EXPORT void init();
/// The Transaction ID. txnid.valid determines whether or not this SIDTIDEntry is valid
TxnID txnid;
/// The session doing the transaction
SID sessionid;
EXPORT _SIDTIDEntry();
EXPORT void init();
};
/** @brief A type associating a session with a transaction */
typedef struct _SIDTIDEntry SIDTIDEntry;
// @bug 1970 - Added CPInfo and CPMaxMin structs used by new interface that allows setting the max and min CP data
// for multiple extents.
// @bug 1970 - Added CPInfo and CPMaxMin structs used by new interface that allows setting the max and min CP
// data for multiple extents.
// Special seqNum field values.
#define SEQNUM_MARK_INVALID (-1)
#define SEQNUM_MARK_INVALID_SET_RANGE (-2)
#define SEQNUM_MARK_INVALID (-1)
#define SEQNUM_MARK_INVALID_SET_RANGE (-2)
#define SEQNUM_MARK_UPDATING_INVALID_SET_RANGE (-3)
// Used in vectors.
struct CPInfo
{
LBID_t firstLbid;
int64_t max;
int64_t min;
int32_t seqNum;
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
bool isBinaryColumn; // XXX: we should remove these two fields and replace it with type handler.
LBID_t firstLbid;
int64_t max;
int64_t min;
int32_t seqNum;
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
bool isBinaryColumn; // XXX: we should remove these two fields and replace it with type handler.
};
typedef std::vector<CPInfo> CPInfoList_t;
// Used for map where lbid is the key.
struct CPMaxMin
{
int64_t max;
int64_t min;
int32_t seqNum;
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
bool isBinaryColumn; // XXX: these two fields should be replaced with type handler pointer.
int64_t max;
int64_t min;
int32_t seqNum;
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
bool isBinaryColumn; // XXX: these two fields should be replaced with type handler pointer.
};
typedef std::tr1::unordered_map<LBID_t, CPMaxMin> CPMaxMinMap_t;
@ -196,23 +191,23 @@ typedef std::tr1::unordered_map<LBID_t, CPMaxMin> CPMaxMinMap_t;
struct CPInfoMerge
{
LBID_t startLbid; // starting LBID for relevant extent
int64_t max; // max value to be merged with current max value
int64_t min; // min value to be merged with current min value
int32_t seqNum; // sequence number (not currently used)
execplan::CalpontSystemCatalog::ColDataType type;
int32_t colWidth;
bool newExtent; // is this to be treated as a new extent
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
LBID_t startLbid; // starting LBID for relevant extent
int64_t max; // max value to be merged with current max value
int64_t min; // min value to be merged with current min value
int32_t seqNum; // sequence number (not currently used)
execplan::CalpontSystemCatalog::ColDataType type;
int32_t colWidth;
bool newExtent; // is this to be treated as a new extent
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
};
typedef std::vector<CPInfoMerge> CPInfoMergeList_t;
@ -220,144 +215,145 @@ typedef std::vector<CPInfoMerge> CPInfoMergeList_t;
// those in CPInfoMerge.
struct CPMaxMinMerge
{
int64_t max;
int64_t min;
int32_t seqNum;
execplan::CalpontSystemCatalog::ColDataType type;
int32_t colWidth;
bool newExtent;
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
int64_t max;
int64_t min;
int32_t seqNum;
execplan::CalpontSystemCatalog::ColDataType type;
int32_t colWidth;
bool newExtent;
union
{
int128_t bigMax;
int64_t max_;
};
union
{
int128_t bigMin;
int64_t min_;
};
};
typedef std::tr1::unordered_map<LBID_t, CPMaxMinMerge> CPMaxMinMergeMap_t;
// end of bug 2117
typedef std::tr1::unordered_map<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::OID> OidsMap_t;
typedef std::tr1::unordered_map<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::OID>
OidsMap_t;
struct ExtentInfo
{
execplan::CalpontSystemCatalog::OID oid;
uint32_t partitionNum; // starts at 0
uint16_t segmentNum; // starts at 0
uint16_t dbRoot; // starts at 1 to match Columnstore.xml
HWM_t hwm;
bool newFile;
execplan::CalpontSystemCatalog::OID oid;
uint32_t partitionNum; // starts at 0
uint16_t segmentNum; // starts at 0
uint16_t dbRoot; // starts at 1 to match Columnstore.xml
HWM_t hwm;
bool newFile;
};
struct FileInfo
{
execplan::CalpontSystemCatalog::OID oid;
uint32_t partitionNum; // starts at 0
uint16_t segmentNum; // starts at 0
uint16_t dbRoot; // starts at 1 to match Columnstore.xml
uint16_t compType; // compression type
execplan::CalpontSystemCatalog::OID oid;
uint32_t partitionNum; // starts at 0
uint16_t segmentNum; // starts at 0
uint16_t dbRoot; // starts at 1 to match Columnstore.xml
uint16_t compType; // compression type
};
typedef std::tr1::unordered_map<execplan::CalpontSystemCatalog::OID, ExtentInfo> ExtentsInfoMap_t;
enum LockState
{
LOADING,
CLEANUP
LOADING,
CLEANUP
};
struct TableLockInfo : public messageqcpp::Serializeable
{
uint64_t id;
uint32_t tableOID;
std::string ownerName;
uint32_t ownerPID;
int32_t ownerSessionID;
int32_t ownerTxnID;
LockState state;
time_t creationTime;
std::vector<uint32_t> dbrootList;
uint64_t id;
uint32_t tableOID;
std::string ownerName;
uint32_t ownerPID;
int32_t ownerSessionID;
int32_t ownerTxnID;
LockState state;
time_t creationTime;
std::vector<uint32_t> dbrootList;
bool overlaps(const TableLockInfo&, const std::set<uint32_t>& sPMList) const;
EXPORT void serialize(messageqcpp::ByteStream& bs) const;
EXPORT void serialize(std::ostream&) const;
EXPORT void deserialize(std::istream&);
EXPORT void deserialize(messageqcpp::ByteStream& bs);
EXPORT void serialize(idbdatafile::IDBDataFile*) const;
EXPORT void deserialize(idbdatafile::IDBDataFile*);
bool operator<(const TableLockInfo&) const;
bool overlaps(const TableLockInfo&, const std::set<uint32_t>& sPMList) const;
EXPORT void serialize(messageqcpp::ByteStream& bs) const;
EXPORT void serialize(std::ostream&) const;
EXPORT void deserialize(std::istream&);
EXPORT void deserialize(messageqcpp::ByteStream& bs);
EXPORT void serialize(idbdatafile::IDBDataFile*) const;
EXPORT void deserialize(idbdatafile::IDBDataFile*);
bool operator<(const TableLockInfo&) const;
};
/// A Serializeable version of InlineLBIDRange
class LBIDRange : public messageqcpp::Serializeable
{
public:
LBID_t start;
uint32_t size;
public:
LBID_t start;
uint32_t size;
EXPORT LBIDRange();
EXPORT LBIDRange(const LBIDRange& l);
EXPORT LBIDRange(const InlineLBIDRange& l);
EXPORT LBIDRange& operator=(const LBIDRange& l);
EXPORT LBIDRange& operator=(const InlineLBIDRange& l);
EXPORT virtual ~LBIDRange();
EXPORT LBIDRange();
EXPORT LBIDRange(const LBIDRange& l);
EXPORT LBIDRange(const InlineLBIDRange& l);
EXPORT LBIDRange& operator=(const LBIDRange& l);
EXPORT LBIDRange& operator=(const InlineLBIDRange& l);
EXPORT virtual ~LBIDRange();
/** The Serializeable interface. Exports the instance to the bytestream */
EXPORT virtual void serialize(messageqcpp::ByteStream& bs) const;
/** The Serializeable interface. Initializes itself from the bytestrem. */
EXPORT virtual void deserialize(messageqcpp::ByteStream& bs);
/** The Serializeable interface. Exports the instance to the bytestream */
EXPORT virtual void serialize(messageqcpp::ByteStream& bs) const;
/** The Serializeable interface. Initializes itself from the bytestrem. */
EXPORT virtual void deserialize(messageqcpp::ByteStream& bs);
};
/* To support bulkVSSLookup() */
struct VSSData
{
VER_t verID;
bool vbFlag;
int returnCode;
VER_t verID;
bool vbFlag;
int returnCode;
};
/* Arg type for DBRM::bulkSetHWM() */
struct BulkSetHWMArg
{
OID_t oid;
uint32_t partNum;
uint16_t segNum;
HWM_t hwm;
OID_t oid;
uint32_t partNum;
uint16_t segNum;
HWM_t hwm;
};
/* Arg type for DBRM::bulkUpdateDBRoot() */
struct BulkUpdateDBRootArg
{
LBID_t startLBID; // starting LBID for the extent to update
uint16_t dbRoot; // the new dbRoot
LBID_t startLBID; // starting LBID for the extent to update
uint16_t dbRoot; // the new dbRoot
inline bool operator<(const BulkUpdateDBRootArg& b) const
{
return startLBID < b.startLBID;
}
BulkUpdateDBRootArg(LBID_t l = 0, uint16_t d = 0) : startLBID(l), dbRoot(d) {}
inline bool operator<(const BulkUpdateDBRootArg& b) const
{
return startLBID < b.startLBID;
}
BulkUpdateDBRootArg(LBID_t l = 0, uint16_t d = 0) : startLBID(l), dbRoot(d)
{
}
};
/* Input Arg type for DBRM::createStripeColumnExtents() */
struct CreateStripeColumnExtentsArgIn
{
OID_t oid; // column OID
uint32_t width; // column width in bytes
execplan::CalpontSystemCatalog::ColDataType colDataType;
OID_t oid; // column OID
uint32_t width; // column width in bytes
execplan::CalpontSystemCatalog::ColDataType colDataType;
};
/* Output Arg type for DBRM:createStripeColumnExtents() */
struct CreateStripeColumnExtentsArgOut
{
LBID_t startLbid; // starting LBID of allocated extent
int allocSize; // number of blocks in allocated extent
uint32_t startBlkOffset; // starting file block offset for allocated extent
LBID_t startLbid; // starting LBID of allocated extent
int allocSize; // number of blocks in allocated extent
uint32_t startBlkOffset; // starting file block offset for allocated extent
};
/// A container for LBIDRanges
@ -366,55 +362,54 @@ typedef std::vector<LBIDRange> LBIDRange_v;
/// Describes a contiguous range of blocks in the Version Buffer
class VBRange : public messageqcpp::Serializeable
{
public:
OID_t vbOID;
uint32_t vbFBO;
uint32_t size;
public:
OID_t vbOID;
uint32_t vbFBO;
uint32_t size;
EXPORT VBRange();
EXPORT VBRange(const VBRange& v);
EXPORT VBRange& operator= (const VBRange& v);
EXPORT virtual ~VBRange();
EXPORT virtual void serialize(messageqcpp::ByteStream& bs) const;
EXPORT virtual void deserialize(messageqcpp::ByteStream& bs);
EXPORT VBRange();
EXPORT VBRange(const VBRange& v);
EXPORT VBRange& operator=(const VBRange& v);
EXPORT virtual ~VBRange();
EXPORT virtual void serialize(messageqcpp::ByteStream& bs) const;
EXPORT virtual void deserialize(messageqcpp::ByteStream& bs);
};
// Structure used to return HWM information for each DbRoot in a PM
struct EmDbRootHWMInfo
{
uint32_t partitionNum; // last partition in dbRoot
uint16_t dbRoot; // applicable dbRoot
uint16_t segmentNum; // last segment file in dbRoot
HWM_t localHWM; // local HWM in last file for this dbRoot
uint32_t fbo; // starting block offset to HWM extent
LBID_t startLbid; // starting LBID for HWM extent
uint64_t totalBlocks; // cumulative non-outOfService blks for this dbRoot.
// 0 block count means no extents in this dbRoot,
// unless status is OutOfService; in which case
// the dbRoot has blocks that are all OutOfService
int hwmExtentIndex;//Internal use (idx to HWM extent in extent map)
int16_t status; // Avail, unAvail, outOfService
EmDbRootHWMInfo()
{
init(0);
}
EmDbRootHWMInfo(uint16_t root)
{
init(root);
}
void init (uint16_t root)
{
partitionNum = 0;
dbRoot = root;
segmentNum = 0;
localHWM = 0;
fbo = 0;
startLbid = 0;
hwmExtentIndex = -1;
totalBlocks = 0;
status = 0;
}
uint32_t partitionNum; // last partition in dbRoot
uint16_t dbRoot; // applicable dbRoot
uint16_t segmentNum; // last segment file in dbRoot
HWM_t localHWM; // local HWM in last file for this dbRoot
uint32_t fbo; // starting block offset to HWM extent
LBID_t startLbid; // starting LBID for HWM extent
uint64_t totalBlocks; // cumulative non-outOfService blks for this dbRoot.
// 0 block count means no extents in this dbRoot,
// unless status is OutOfService; in which case
// the dbRoot has blocks that are all OutOfService
int hwmExtentIndex; // Internal use (idx to HWM extent in extent map)
int16_t status; // Avail, unAvail, outOfService
EmDbRootHWMInfo()
{
init(0);
}
EmDbRootHWMInfo(uint16_t root)
{
init(root);
}
void init(uint16_t root)
{
partitionNum = 0;
dbRoot = root;
segmentNum = 0;
localHWM = 0;
fbo = 0;
startLbid = 0;
hwmExtentIndex = -1;
totalBlocks = 0;
status = 0;
}
};
typedef std::vector<EmDbRootHWMInfo> EmDbRootHWMInfo_v;
@ -439,35 +434,35 @@ typedef std::vector<VBRange> VBRange_v;
*/
struct ImageDelta
{
void* start;
int size;
char data[ID_MAXSIZE]; /// Has to be as large as the largest change
void* start;
int size;
char data[ID_MAXSIZE]; /// Has to be as large as the largest change
};
// SubSystemLogId enumeration values should be in sync with SubsystemID[]
// that is defined in messagelog.cpp
enum SubSystemLogId
{
SubSystemLogId_controllerNode = 29,
SubSystemLogId_workerNode = 30
SubSystemLogId_controllerNode = 29,
SubSystemLogId_workerNode = 30
};
EXPORT void logInit ( SubSystemLogId subSystemId );
EXPORT void logInit(SubSystemLogId subSystemId);
EXPORT void log(const std::string& msg, logging::LOG_TYPE = logging::LOG_TYPE_CRITICAL);
EXPORT void log_errno(const std::string& msg, logging::LOG_TYPE = logging::LOG_TYPE_CRITICAL);
EXPORT void errString( int rc, std::string& errMsg );
EXPORT void errString(int rc, std::string& errMsg);
const struct timespec FIVE_MIN_TIMEOUT = {300, 0};
/* Function identifiers used for master-slave communication.
The format of the messages from DBRM to Master and from Master to Slaves
will look like
<fcnID, in-params>
The format of the messages from the Slaves to Master and Master to DBRM
will look like
<error code, out-params>
The format of the messages from DBRM to Master and from Master to Slaves
will look like
<fcnID, in-params>
The format of the messages from the Slaves to Master and Master to DBRM
will look like
<error code, out-params>
*/
//FIXME: put these in a enum. The current arrangement is error-prone.
// FIXME: put these in a enum. The current arrangement is error-prone.
const uint8_t DELETE_OID = 1;
const uint8_t WRITE_VB_ENTRY = 3;
const uint8_t BEGIN_VB_COPY = 4;
@ -499,7 +494,7 @@ const uint8_t MERGEMANYEXTENTSMAXMIN = 32;
const uint8_t DELETE_PARTITION = 33;
const uint8_t MARK_PARTITION_FOR_DELETION = 34;
const uint8_t RESTORE_PARTITION = 35;
const uint8_t CREATE_COLUMN_EXTENT_DBROOT = 36; // @bug 4091: To be deprecated
const uint8_t CREATE_COLUMN_EXTENT_DBROOT = 36; // @bug 4091: To be deprecated
const uint8_t BULK_SET_HWM = 37;
const uint8_t ROLLBACK_COLUMN_EXTENTS_DBROOT = 38;
const uint8_t ROLLBACK_DICT_STORE_EXTENTS_DBROOT = 39;
@ -541,7 +536,7 @@ const uint8_t CHANGE_TABLE_LOCK_OWNER = 73;
const uint8_t GET_ALL_TABLE_LOCKS = 74;
const uint8_t RELEASE_ALL_TABLE_LOCKS = 75;
const uint8_t GET_TABLE_LOCK_INFO = 76;
const uint8_t OWNER_CHECK = 77; // the msg from the controller to worker
const uint8_t OWNER_CHECK = 77; // the msg from the controller to worker
/* Autoincrement interface (WIP) */
const uint8_t START_AI_SEQUENCE = 80;
@ -560,7 +555,6 @@ const uint8_t BULK_UPDATE_DBROOT = 100;
const uint8_t GET_SYSTEM_CATALOG = 101;
const uint8_t BULK_WRITE_VB_ENTRY = 102;
/* Error codes returned by the DBRM functions. */
/// The operation was successful
const int8_t ERR_OK = 0;
@ -568,22 +562,28 @@ const int8_t ERR_OK = 0;
/// There was some unspecific failure and if the operation was a "write", no change was made
const int8_t ERR_FAILURE = 1;
/// The operation failed because at least one slave has a different image than the others. No change was made.
/// The operation failed because at least one slave has a different image than the others. No change was
/// made.
const int8_t ERR_SLAVE_INCONSISTENCY = 2;
/// The operation failed because of a communication problem.
const int8_t ERR_NETWORK = 3;
/// The operation failed because one slave did not send a response within 10 seconds. The administrator should look into it.
/// The operation failed because one slave did not send a response within 10 seconds. The administrator
/// should look into it.
const int8_t ERR_TIMEOUT = 4;
/// The operation failed because the Master is in read-only mode. Either it detected an serious error (ie ERR_SLAVE_INCONSISTENCY), or the administrator set it using dbrmctl. The system needs the administrator to fix the problem and enable read-write mode.
/// The operation failed because the Master is in read-only mode. Either it detected an serious error (ie
/// ERR_SLAVE_INCONSISTENCY), or the administrator set it using dbrmctl. The system needs the administrator
/// to fix the problem and enable read-write mode.
const int8_t ERR_READONLY = 5;
/// beginVBCopy was attempted, but deadlocked and was cancelled. The transaction must be rolled back after receiving this error code.
/// beginVBCopy was attempted, but deadlocked and was cancelled. The transaction must be rolled back after
/// receiving this error code.
const int8_t ERR_DEADLOCK = 6;
/// While waiting for beginVBCopy to allocate the requested LBIDs, the transaction was killed by another thread. The caller must roll back after receiving this error code.
/// While waiting for beginVBCopy to allocate the requested LBIDs, the transaction was killed by another
/// thread. The caller must roll back after receiving this error code.
const int8_t ERR_KILLED = 7;
/// version buffer overflow error
@ -600,62 +600,62 @@ const int8_t ERR_TABLE_NOT_LOCKED = 14;
const int8_t ERR_SNAPSHOT_TOO_OLD = 15;
const int8_t ERR_NO_PARTITION_PERFORMED = 16;
/// This error code is returned by writeVBEntry when a session with a low txnid attempts to write to a block with a higher verid
/// This error code is returned by writeVBEntry when a session with a low txnid attempts to write to a block
/// with a higher verid
const int8_t ERR_OLDTXN_OVERWRITING_NEWTXN = 17;
// structure used to hold the information to identify a partition for shared-nothing
struct PartitionInfo
{
LogicalPartition lp;
OID_t oid;
LogicalPartition lp;
OID_t oid;
void serialize (messageqcpp::ByteStream& b) const
{
lp.serialize(b);
b << (uint32_t)oid;
}
void serialize(messageqcpp::ByteStream& b) const
{
lp.serialize(b);
b << (uint32_t)oid;
}
void unserialize (messageqcpp::ByteStream& b)
{
lp.unserialize(b);
b >> (uint32_t&)oid;
}
void unserialize(messageqcpp::ByteStream& b)
{
lp.unserialize(b);
b >> (uint32_t&)oid;
}
};
// Note: Copies share the currentTxns array
class QueryContext : public messageqcpp::Serializeable
{
public:
explicit QueryContext(VER_t scn = 0)
: currentScn(scn)
{
currentTxns.reset(new std::vector<VER_t>());
}
public:
explicit QueryContext(VER_t scn = 0) : currentScn(scn)
{
currentTxns.reset(new std::vector<VER_t>());
}
void serialize(messageqcpp::ByteStream& bs) const
{
bs << currentScn;
serializeInlineVector(bs, *currentTxns);
}
void serialize(messageqcpp::ByteStream& bs) const
{
bs << currentScn;
serializeInlineVector(bs, *currentTxns);
}
void deserialize(messageqcpp::ByteStream& bs)
{
bs >> currentScn;
deserializeInlineVector(bs, *currentTxns);
}
void deserialize(messageqcpp::ByteStream& bs)
{
bs >> currentScn;
deserializeInlineVector(bs, *currentTxns);
}
execplan::CalpontSystemCatalog::SCN currentScn;
boost::shared_ptr<std::vector<execplan::CalpontSystemCatalog::SCN> > currentTxns;
execplan::CalpontSystemCatalog::SCN currentScn;
boost::shared_ptr<std::vector<execplan::CalpontSystemCatalog::SCN> > currentTxns;
private:
//defaults okay?
//QueryContext(const QueryContext& rhs);
//QueryContext& operator=(const QueryContext& rhs);
private:
// defaults okay?
// QueryContext(const QueryContext& rhs);
// QueryContext& operator=(const QueryContext& rhs);
};
std::ostream& operator<<(std::ostream&, const QueryContext&);
}
} // namespace BRM
#undef EXPORT

View File

@ -48,16 +48,16 @@ namespace bi = boost::interprocess;
#define CL_MAGIC_V1 0x789ba6c1
#ifndef O_BINARY
# define O_BINARY 0
#define O_BINARY 0
#endif
#ifndef O_DIRECT
# define O_DIRECT 0
#define O_DIRECT 0
#endif
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#define O_LARGEFILE 0
#endif
#ifndef O_NOATIME
# define O_NOATIME 0
#define O_NOATIME 0
#endif
using namespace std;
@ -70,12 +70,11 @@ using namespace idbdatafile;
namespace BRM
{
CopyLockEntry::CopyLockEntry()
{
start = 0;
size = 0;
txnID = 0;
start = 0;
size = 0;
txnID = 0;
}
/*static*/
@ -88,37 +87,36 @@ CopyLocksImpl* CopyLocksImpl::fInstance = 0;
/*static*/
CopyLocksImpl* CopyLocksImpl::makeCopyLocksImpl(unsigned key, off_t size, bool readOnly)
{
boost::mutex::scoped_lock lk(fInstanceMutex);
boost::mutex::scoped_lock lk(fInstanceMutex);
if (fInstance)
if (fInstance)
{
if (key != fInstance->fCopyLocks.key())
{
if (key != fInstance->fCopyLocks.key())
{
BRMShmImpl newShm(key, size, readOnly);
fInstance->swapout(newShm);
}
idbassert(key == fInstance->fCopyLocks.key());
return fInstance;
BRMShmImpl newShm(key, size, readOnly);
fInstance->swapout(newShm);
}
fInstance = new CopyLocksImpl(key, size, readOnly);
idbassert(key == fInstance->fCopyLocks.key());
return fInstance;
}
fInstance = new CopyLocksImpl(key, size, readOnly);
return fInstance;
}
CopyLocksImpl::CopyLocksImpl(unsigned key, off_t size, bool readOnly) :
fCopyLocks(key, size, readOnly)
CopyLocksImpl::CopyLocksImpl(unsigned key, off_t size, bool readOnly) : fCopyLocks(key, size, readOnly)
{
}
CopyLocks::CopyLocks()
{
entries = NULL;
currentShmkey = shmid = 0;
shminfo = NULL;
r_only = false;
fCopyLocksImpl = 0;
entries = NULL;
currentShmkey = shmid = 0;
shminfo = NULL;
r_only = false;
fCopyLocksImpl = 0;
}
CopyLocks::~CopyLocks()
@ -127,182 +125,183 @@ CopyLocks::~CopyLocks()
void CopyLocks::setReadOnly()
{
r_only = true;
r_only = true;
}
/* always returns holding the specified lock type, and with the EM seg mapped */
void CopyLocks::lock(OPS op)
{
boost::mutex::scoped_lock lk(mutex);
boost::mutex::scoped_lock lk(mutex);
if (op == READ)
shminfo = mst.getTable_read(MasterSegmentTable::CLSegment);
else
shminfo = mst.getTable_write(MasterSegmentTable::CLSegment);
if (op == READ)
shminfo = mst.getTable_read(MasterSegmentTable::CLSegment);
else
shminfo = mst.getTable_write(MasterSegmentTable::CLSegment);
if (currentShmkey != shminfo->tableShmkey)
{
if (entries != NULL)
entries = NULL;
if (currentShmkey != shminfo->tableShmkey)
{
if (entries != NULL)
entries = NULL;
if (shminfo->allocdSize == 0)
if (op == READ)
{
mst.getTable_upgrade(MasterSegmentTable::CLSegment);
if (shminfo->allocdSize == 0)
if (op == READ)
{
mst.getTable_upgrade(MasterSegmentTable::CLSegment);
growCL();
if (shminfo->allocdSize == 0)
growCL();
mst.getTable_downgrade(MasterSegmentTable::CLSegment);
}
else
growCL();
else
{
currentShmkey = shminfo->tableShmkey;
fCopyLocksImpl = CopyLocksImpl::makeCopyLocksImpl(currentShmkey, 0, r_only);
entries = fCopyLocksImpl->get();
mst.getTable_downgrade(MasterSegmentTable::CLSegment);
}
else
growCL();
else
{
currentShmkey = shminfo->tableShmkey;
fCopyLocksImpl = CopyLocksImpl::makeCopyLocksImpl(currentShmkey, 0, r_only);
entries = fCopyLocksImpl->get();
if (entries == NULL)
{
log_errno(string("CopyLocks::lock(): shmat failed"));
throw std::runtime_error("CopyLocks::lock(): shmat failed. Check the error log.");
}
}
if (entries == NULL)
{
log_errno(string("CopyLocks::lock(): shmat failed"));
throw std::runtime_error("CopyLocks::lock(): shmat failed. Check the error log.");
}
}
}
}
void CopyLocks::release(OPS op)
{
if (op == READ)
mst.releaseTable_read(MasterSegmentTable::CLSegment);
else
mst.releaseTable_write(MasterSegmentTable::CLSegment);
if (op == READ)
mst.releaseTable_read(MasterSegmentTable::CLSegment);
else
mst.releaseTable_write(MasterSegmentTable::CLSegment);
}
key_t CopyLocks::chooseShmkey()
{
int fixedKeys = 1;
key_t ret;
int fixedKeys = 1;
key_t ret;
if (shminfo->tableShmkey + 1 == (key_t) (fShmKeys.KEYRANGE_CL_BASE +
fShmKeys.KEYRANGE_SIZE - 1) || (unsigned)shminfo->tableShmkey < fShmKeys.KEYRANGE_CL_BASE)
ret = fShmKeys.KEYRANGE_CL_BASE + fixedKeys;
else
ret = shminfo->tableShmkey + 1;
if (shminfo->tableShmkey + 1 == (key_t)(fShmKeys.KEYRANGE_CL_BASE + fShmKeys.KEYRANGE_SIZE - 1) ||
(unsigned)shminfo->tableShmkey < fShmKeys.KEYRANGE_CL_BASE)
ret = fShmKeys.KEYRANGE_CL_BASE + fixedKeys;
else
ret = shminfo->tableShmkey + 1;
return ret;
return ret;
}
void CopyLocks::growCL()
{
int allocSize;
key_t newshmkey;
int allocSize;
key_t newshmkey;
if (shminfo->allocdSize == 0)
allocSize = CL_INITIAL_SIZE;
else
allocSize = shminfo->allocdSize + CL_INCREMENT;
if (shminfo->allocdSize == 0)
allocSize = CL_INITIAL_SIZE;
else
allocSize = shminfo->allocdSize + CL_INCREMENT;
newshmkey = chooseShmkey();
idbassert((allocSize == CL_INITIAL_SIZE && !fCopyLocksImpl) || fCopyLocksImpl);
newshmkey = chooseShmkey();
idbassert((allocSize == CL_INITIAL_SIZE && !fCopyLocksImpl) || fCopyLocksImpl);
if (!fCopyLocksImpl)
fCopyLocksImpl = CopyLocksImpl::makeCopyLocksImpl(newshmkey, allocSize, r_only);
else
fCopyLocksImpl->grow(newshmkey, allocSize);
if (!fCopyLocksImpl)
fCopyLocksImpl = CopyLocksImpl::makeCopyLocksImpl(newshmkey, allocSize, r_only);
else
fCopyLocksImpl->grow(newshmkey, allocSize);
shminfo->tableShmkey = currentShmkey = newshmkey;
shminfo->allocdSize = allocSize;
shminfo->tableShmkey = currentShmkey = newshmkey;
shminfo->allocdSize = allocSize;
if (r_only)
fCopyLocksImpl->makeReadOnly();
if (r_only)
fCopyLocksImpl->makeReadOnly();
entries = fCopyLocksImpl->get();
// Temporary fix. Get rid of the old undo records that now point to nothing.
// Would be nice to be able to carry them forward.
confirmChanges();
entries = fCopyLocksImpl->get();
// Temporary fix. Get rid of the old undo records that now point to nothing.
// Would be nice to be able to carry them forward.
confirmChanges();
}
// this fcn is dumb; relies on external check on whether it's safe or not
// also relies on external write lock grab
void CopyLocks::lockRange(const LBIDRange& l, VER_t txnID)
{
int i, numEntries;
int i, numEntries;
// grow if necessary
if (shminfo->currentSize == shminfo->allocdSize)
growCL();
// grow if necessary
if (shminfo->currentSize == shminfo->allocdSize)
growCL();
/* debugging code, check for an existing lock */
//assert(!isLocked(l));
/* debugging code, check for an existing lock */
// assert(!isLocked(l));
//ostringstream os;
//os << "Copylocks locking <" << l.start << ", " << l.size << "> txnID = " << txnID;
//log(os.str());
// ostringstream os;
// os << "Copylocks locking <" << l.start << ", " << l.size << "> txnID = " << txnID;
// log(os.str());
// scan for an empty entry
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
// scan for an empty entry
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
for (i = 0; i < numEntries; i++)
{
if (entries[i].size == 0)
{
if (entries[i].size == 0)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
entries[i].start = l.start;
entries[i].size = l.size;
entries[i].txnID = txnID;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize += sizeof(CopyLockEntry);
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
entries[i].start = l.start;
entries[i].size = l.size;
entries[i].txnID = txnID;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize += sizeof(CopyLockEntry);
// make sure isLocked() now sees the lock
//assert(isLocked(l));
return;
}
// make sure isLocked() now sees the lock
// assert(isLocked(l));
return;
}
}
log(string("CopyLocks::lockRange(): shm metadata problem: could not find an empty copylock entry"));
throw std::logic_error("CopyLocks::lockRange(): shm metadata problem: could not find an empty copylock entry");
log(string("CopyLocks::lockRange(): shm metadata problem: could not find an empty copylock entry"));
throw std::logic_error(
"CopyLocks::lockRange(): shm metadata problem: could not find an empty copylock entry");
}
// this fcn is dumb; relies on external check on whether it's safe or not
// also relies on external write lock grab
void CopyLocks::releaseRange(const LBIDRange& l)
{
int i, numEntries;
LBID_t lastBlock = l.start + l.size - 1;
LBID_t eLastBlock;
int i, numEntries;
LBID_t lastBlock = l.start + l.size - 1;
LBID_t eLastBlock;
#ifdef BRM_DEBUG
// debatable whether this should be included or not given the timers
// that automatically release locks
idbassert(isLocked(l));
// debatable whether this should be included or not given the timers
// that automatically release locks
idbassert(isLocked(l));
#endif
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
for (i = 0; i < numEntries; i++)
{
CopyLockEntry& e = entries[i];
if (e.size != 0)
{
CopyLockEntry& e = entries[i];
eLastBlock = e.start + e.size - 1;
if (e.size != 0)
{
eLastBlock = e.start + e.size - 1;
if (l.start <= eLastBlock && lastBlock >= e.start)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
e.size = 0;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize -= sizeof(CopyLockEntry);
}
}
if (l.start <= eLastBlock && lastBlock >= e.start)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
e.size = 0;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize -= sizeof(CopyLockEntry);
}
}
}
#ifdef BRM_DEBUG
idbassert(!isLocked(l));
//log(string("CopyLocks::releaseRange(): that range isn't locked", LOG_TYPE_WARNING));
//throw std::invalid_argument("CopyLocks::releaseRange(): that range isn't locked");
idbassert(!isLocked(l));
// log(string("CopyLocks::releaseRange(): that range isn't locked", LOG_TYPE_WARNING));
// throw std::invalid_argument("CopyLocks::releaseRange(): that range isn't locked");
#endif
}
@ -310,89 +309,86 @@ void CopyLocks::releaseRange(const LBIDRange& l)
* shouldn't use makeUndoRecord() */
void CopyLocks::forceRelease(const LBIDRange& l)
{
int i, numEntries;
LBID_t lastBlock = l.start + l.size - 1;
LBID_t eLastBlock;
int i, numEntries;
LBID_t lastBlock = l.start + l.size - 1;
LBID_t eLastBlock;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
//ostringstream os;
//os << "Copylocks force-releasing <" << l.start << ", " << l.size << ">";
//log(os.str());
// ostringstream os;
// os << "Copylocks force-releasing <" << l.start << ", " << l.size << ">";
// log(os.str());
/* If a range intersects l, get rid of it. */
for (i = 0; i < numEntries; i++)
{
CopyLockEntry& e = entries[i];
/* If a range intersects l, get rid of it. */
for (i = 0; i < numEntries; i++)
if (e.size != 0)
{
CopyLockEntry& e = entries[i];
eLastBlock = e.start + e.size - 1;
if (e.size != 0)
{
eLastBlock = e.start + e.size - 1;
if (l.start <= eLastBlock && lastBlock >= e.start)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
e.size = 0;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize -= sizeof(CopyLockEntry);
}
}
if (l.start <= eLastBlock && lastBlock >= e.start)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
e.size = 0;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize -= sizeof(CopyLockEntry);
}
}
}
//assert(!isLocked(l));
// assert(!isLocked(l));
}
//assumes read lock
// assumes read lock
bool CopyLocks::isLocked(const LBIDRange& l) const
{
int i, numEntries;
LBID_t lLastBlock, lastBlock;
int i, numEntries;
LBID_t lLastBlock, lastBlock;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
lLastBlock = l.start + l.size - 1;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
lLastBlock = l.start + l.size - 1;
for (i = 0; i < numEntries; i++)
for (i = 0; i < numEntries; i++)
{
if (entries[i].size != 0)
{
if (entries[i].size != 0)
{
lastBlock = entries[i].start + entries[i].size - 1;
lastBlock = entries[i].start + entries[i].size - 1;
if (lLastBlock >= entries[i].start && l.start <= lastBlock)
return true;
}
if (lLastBlock >= entries[i].start && l.start <= lastBlock)
return true;
}
}
return false;
return false;
}
void CopyLocks::rollback(VER_t txnID)
{
int i, numEntries;
int i, numEntries;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
if (entries[i].size != 0 && entries[i].txnID == txnID)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
entries[i].size = 0;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize -= sizeof(CopyLockEntry);
}
for (i = 0; i < numEntries; i++)
if (entries[i].size != 0 && entries[i].txnID == txnID)
{
makeUndoRecord(&entries[i], sizeof(CopyLockEntry));
entries[i].size = 0;
makeUndoRecord(shminfo, sizeof(MSTEntry));
shminfo->currentSize -= sizeof(CopyLockEntry);
}
}
void CopyLocks::getCurrentTxnIDs(std::set<VER_t>& list) const
{
int i, numEntries;
int i, numEntries;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
if (entries[i].size != 0)
list.insert(entries[i].txnID);
for (i = 0; i < numEntries; i++)
if (entries[i].size != 0)
list.insert(entries[i].txnID);
}
} // namespace
} // namespace BRM

View File

@ -45,8 +45,8 @@
#include "brmshmimpl.h"
/* Should load these from a config file */
#define CL_INITIAL_SIZE (50*sizeof(CopyLockEntry))
#define CL_INCREMENT (50*sizeof(CopyLockEntry))
#define CL_INITIAL_SIZE (50 * sizeof(CopyLockEntry))
#define CL_INCREMENT (50 * sizeof(CopyLockEntry))
#if defined(_MSC_VER) && defined(xxxCOPYLOCKS_DLLEXPORT)
#define EXPORT __declspec(dllexport)
@ -54,7 +54,6 @@
#define EXPORT
#endif
namespace idbdatafile
{
class IDBDataFile;
@ -62,112 +61,110 @@ class IDBDataFile;
namespace BRM
{
struct CopyLockEntry
{
LBID_t start;
int size;
VER_t txnID;
EXPORT CopyLockEntry();
LBID_t start;
int size;
VER_t txnID;
EXPORT CopyLockEntry();
};
class CopyLocksImpl
{
public:
static CopyLocksImpl* makeCopyLocksImpl(unsigned key, off_t size, bool readOnly = false);
public:
static CopyLocksImpl* makeCopyLocksImpl(unsigned key, off_t size, bool readOnly = false);
inline void grow(unsigned key, off_t size)
inline void grow(unsigned key, off_t size)
#ifdef NDEBUG
{
fCopyLocks.grow(key, size);
}
{
fCopyLocks.grow(key, size);
}
#else
{
int rc = fCopyLocks.grow(key, size);
idbassert(rc == 0);
}
{
int rc = fCopyLocks.grow(key, size);
idbassert(rc == 0);
}
#endif
inline void makeReadOnly()
{
fCopyLocks.setReadOnly();
}
inline void clear(unsigned key, off_t size)
{
fCopyLocks.clear(key, size);
}
inline void swapout(BRMShmImpl& rhs)
{
fCopyLocks.swap(rhs);
rhs.destroy();
}
inline unsigned key() const
{
return fCopyLocks.key();
}
inline void makeReadOnly()
{
fCopyLocks.setReadOnly();
}
inline void clear(unsigned key, off_t size)
{
fCopyLocks.clear(key, size);
}
inline void swapout(BRMShmImpl& rhs)
{
fCopyLocks.swap(rhs);
rhs.destroy();
}
inline unsigned key() const
{
return fCopyLocks.key();
}
inline CopyLockEntry* get() const
{
return reinterpret_cast<CopyLockEntry*>(fCopyLocks.fMapreg.get_address());
}
inline CopyLockEntry* get() const
{
return reinterpret_cast<CopyLockEntry*>(fCopyLocks.fMapreg.get_address());
}
private:
CopyLocksImpl(unsigned key, off_t size, bool readOnly = false);
~CopyLocksImpl();
CopyLocksImpl(const CopyLocksImpl& rhs);
CopyLocksImpl& operator=(const CopyLocksImpl& rhs);
private:
CopyLocksImpl(unsigned key, off_t size, bool readOnly = false);
~CopyLocksImpl();
CopyLocksImpl(const CopyLocksImpl& rhs);
CopyLocksImpl& operator=(const CopyLocksImpl& rhs);
BRMShmImpl fCopyLocks;
BRMShmImpl fCopyLocks;
static boost::mutex fInstanceMutex;
static CopyLocksImpl* fInstance;
static boost::mutex fInstanceMutex;
static CopyLocksImpl* fInstance;
};
class CopyLocks : public Undoable
{
public:
public:
enum OPS
{
NONE,
READ,
WRITE
};
enum OPS
{
NONE,
READ,
WRITE
};
EXPORT CopyLocks();
EXPORT ~CopyLocks();
EXPORT CopyLocks();
EXPORT ~CopyLocks();
EXPORT void lockRange(const LBIDRange& range, VER_t txnID);
EXPORT void releaseRange(const LBIDRange& range);
EXPORT bool isLocked(const LBIDRange& range) const;
EXPORT void rollback(VER_t txnID);
EXPORT void lockRange(const LBIDRange& range, VER_t txnID);
EXPORT void releaseRange(const LBIDRange& range);
EXPORT bool isLocked(const LBIDRange& range) const;
EXPORT void rollback(VER_t txnID);
EXPORT void lock(OPS op);
EXPORT void release(OPS op);
EXPORT void setReadOnly();
EXPORT void getCurrentTxnIDs(std::set<VER_t>& txnList) const;
EXPORT void lock(OPS op);
EXPORT void release(OPS op);
EXPORT void setReadOnly();
EXPORT void getCurrentTxnIDs(std::set<VER_t>& txnList) const;
EXPORT void forceRelease(const LBIDRange& range);
EXPORT void forceRelease(const LBIDRange& range);
private:
CopyLocks(const CopyLocks&);
CopyLocks& operator=(const CopyLocks&);
private:
CopyLocks(const CopyLocks&);
CopyLocks& operator=(const CopyLocks&);
key_t chooseShmkey();
void growCL();
key_t chooseShmkey();
void growCL();
CopyLockEntry* entries;
key_t currentShmkey;
int shmid; //shmid's necessary?
MSTEntry* shminfo;
MasterSegmentTable mst;
bool r_only;
static boost::mutex mutex;
static const int MAX_IO_RETRIES = 10;
ShmKeys fShmKeys;
CopyLocksImpl* fCopyLocksImpl;
CopyLockEntry* entries;
key_t currentShmkey;
int shmid; // shmid's necessary?
MSTEntry* shminfo;
MasterSegmentTable mst;
bool r_only;
static boost::mutex mutex;
static const int MAX_IO_RETRIES = 10;
ShmKeys fShmKeys;
CopyLocksImpl* fCopyLocksImpl;
};
}
} // namespace BRM
#undef EXPORT

View File

@ -10,105 +10,92 @@ DBRM dbrm;
void lockRange()
{
LBIDRange r;
r.start = 12345;
r.size = 5;
copylocks.lock(CopyLocks::WRITE);
LBIDRange r;
r.start = 12345;
r.size = 5;
copylocks.lock(CopyLocks::WRITE);
if (copylocks.isLocked(r))
cout << "already locked\n";
else
{
copylocks.lockRange(r, -1);
cout << "got the 1st lock\n";
}
if (copylocks.isLocked(r))
cout << "already locked\n";
else
{
copylocks.lockRange(r, -1);
cout << "got the 1st lock\n";
}
r.start = 12349;
r.start = 12349;
if (copylocks.isLocked(r))
cout << "2nd range is locked\n";
else
cout << "2nd range is NOT locked\n";
if (copylocks.isLocked(r))
cout << "2nd range is locked\n";
else
cout << "2nd range is NOT locked\n";
r.start = 12350;
r.start = 12350;
if (copylocks.isLocked(r))
cout << "3rd range is locked\n";
else
{
copylocks.lockRange(r, -1);
cout << "got the 3rd lock\n";
}
if (copylocks.isLocked(r))
cout << "3rd range is locked\n";
else
{
copylocks.lockRange(r, -1);
cout << "got the 3rd lock\n";
}
copylocks.release(CopyLocks::WRITE);
copylocks.release(CopyLocks::WRITE);
}
void dbrmLockRange()
{
dbrm.lockLBIDRange(12345, 5);
cout << "OK\n";
dbrm.lockLBIDRange(12345, 5);
cout << "OK\n";
}
void dbrmReleaseRange()
{
dbrm.releaseLBIDRange(12345, 5);
cout << "OK\n";
dbrm.releaseLBIDRange(12345, 5);
cout << "OK\n";
}
void releaseRange()
{
LBIDRange r;
r.start = 12345;
r.size = 5;
copylocks.lock(CopyLocks::WRITE);
copylocks.releaseRange(r);
LBIDRange r;
r.start = 12345;
r.size = 5;
copylocks.lock(CopyLocks::WRITE);
copylocks.releaseRange(r);
r.start = 12350;
copylocks.releaseRange(r);
copylocks.release(CopyLocks::WRITE);
r.start = 12350;
copylocks.releaseRange(r);
copylocks.release(CopyLocks::WRITE);
cout << "OK\n";
cout << "OK\n";
}
int main(int argc, char** argv)
{
char cmd;
char cmd;
if (argc < 2)
goto usage;
if (argc < 2)
goto usage;
cmd = argv[1][0];
cmd = argv[1][0];
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
switch (cmd)
{
case 'l':
lockRange();
break;
switch (cmd)
{
case 'l': lockRange(); break;
case 'r':
releaseRange();
break;
case 'r': releaseRange(); break;
case 'L':
dbrmLockRange();
break;
case 'L': dbrmLockRange(); break;
case 'R':
dbrmReleaseRange();
break;
case 'R': dbrmReleaseRange(); break;
default:
goto usage;
}
default: goto usage;
}
exit(0);
exit(0);
usage:
cout << "Usage: " << argv[0] << " l | r | L | R. lock/release. Check the code for specifics. :P" << endl;
exit(1);
cout << "Usage: " << argv[0] << " l | r | L | R. lock/release. Check the code for specifics. :P" << endl;
exit(1);
}

View File

@ -37,200 +37,202 @@ namespace
{
void usage(char* name)
{
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
} // namespace
namespace BRM
{
class ExtentMapConverter
{
public:
ExtentMapConverter() {};
public:
ExtentMapConverter(){};
int doCvt(unsigned oldExtentSize, unsigned newExtentSize, const string& filename);
int doCvt(unsigned oldExtentSize, unsigned newExtentSize, const string& filename);
private:
ExtentMapConverter(const ExtentMapConverter& rhs);
ExtentMapConverter& operator=(const ExtentMapConverter& rhs);
private:
ExtentMapConverter(const ExtentMapConverter& rhs);
ExtentMapConverter& operator=(const ExtentMapConverter& rhs);
ExtentMap em;
ExtentMap em;
};
int ExtentMapConverter::doCvt(unsigned oldExtentSize, unsigned newExtentSize, const string& filename)
{
int currentSize, loadSize[3];
ifstream in;
int currentSize, loadSize[3];
ifstream in;
em.grabEMEntryTable(ExtentMap::WRITE);
em.grabEMEntryTable(ExtentMap::WRITE);
try
{
em.grabFreeList(ExtentMap::WRITE);
}
catch (...)
{
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
try
{
em.grabFreeList(ExtentMap::WRITE);
}
catch (...)
{
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
div_t d = div((int)oldExtentSize, (int)newExtentSize);
idbassert(d.quot > 1);
idbassert(d.rem == 0);
div_t d = div((int)oldExtentSize, (int)newExtentSize);
idbassert(d.quot > 1);
idbassert(d.rem == 0);
const unsigned mult = d.quot;
const unsigned mult = d.quot;
in.open(filename.c_str());
in.open(filename.c_str());
if (!in)
{
log_errno("ExtentMap::load(): open");
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw std::ios_base::failure("ExtentMap::load(): open failed. Check the error log.");
}
if (!in)
{
log_errno("ExtentMap::load(): open");
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw std::ios_base::failure("ExtentMap::load(): open failed. Check the error log.");
}
in.exceptions(ios_base::badbit | ios_base::failbit);
in.exceptions(ios_base::badbit | ios_base::failbit);
try
{
in.read((char*) &loadSize, 3 * sizeof(int));
}
catch (...)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
try
{
in.read((char*)&loadSize, 3 * sizeof(int));
}
catch (...)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
const int emVersion = loadSize[0];
const int emNumElements = loadSize[1];
const int flNumElements = loadSize[2];
/* What's a safe upper limit on the # of EM and FL entries? */
const int emVersion = loadSize[0];
const int emNumElements = loadSize[1];
const int flNumElements = loadSize[2];
/* What's a safe upper limit on the # of EM and FL entries? */
#define EM_MAGIC_V3 0x76f78b1e
if ( emVersion != EM_MAGIC_V3 || emNumElements < 0 || flNumElements < 0)
if (emVersion != EM_MAGIC_V3 || emNumElements < 0 || flNumElements < 0)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
log("ExtentMap::load64(): That file is not a valid 64-bit ExtentMap image");
throw std::runtime_error("ExtentMap::load64(): That file is not a valid 64-bit ExtentMap image");
}
memset(em.fExtentMap, 0, em.fEMShminfo->allocdSize);
memset(em.fFreeList, 0, em.fFLShminfo->allocdSize);
em.fEMShminfo->currentSize = 0;
em.fFLShminfo->currentSize = 0;
int j = 0;
int maxLoops = (emNumElements * (signed)mult - em.fEMShminfo->allocdSize / sizeof(EMEntry)) / 100 + 1;
int target = (int)(maxLoops * .02);
if (maxLoops < 50)
target = 1;
// allocate shared memory for extent data
for (currentSize = em.fEMShminfo->allocdSize / sizeof(EMEntry);
currentSize < (emNumElements * (signed)mult);
currentSize = em.fEMShminfo->allocdSize / sizeof(EMEntry))
{
em.growEMShmseg();
if ((j % target) == 0)
cout << '.' << flush;
j++;
}
cout << endl;
// allocate shared memory for freelist
for (currentSize = em.fFLShminfo->allocdSize / sizeof(InlineLBIDRange); currentSize < flNumElements;
currentSize = em.fFLShminfo->allocdSize / sizeof(InlineLBIDRange))
{
em.growFLShmseg();
}
try
{
typedef map<int, vector<int> > OIDMap_t;
OIDMap_t OIDMap;
uint8_t buf[emNumElements * sizeof(EMEntry)];
uint8_t buf2[flNumElements * sizeof(InlineLBIDRange)];
in.read((char*)buf, emNumElements * sizeof(EMEntry));
// memcpy(fExtentMap, buf, emNumElements * sizeof(EMEntry));
EMEntry* emSrc = reinterpret_cast<EMEntry*>(&buf[0]);
j = 0;
for (int i = 0; i < emNumElements; i++)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
log("ExtentMap::load64(): That file is not a valid 64-bit ExtentMap image");
throw std::runtime_error("ExtentMap::load64(): That file is not a valid 64-bit ExtentMap image");
}
memset(em.fExtentMap, 0, em.fEMShminfo->allocdSize);
memset(em.fFreeList, 0, em.fFLShminfo->allocdSize);
em.fEMShminfo->currentSize = 0;
em.fFLShminfo->currentSize = 0;
int j = 0;
int maxLoops = (emNumElements * (signed)mult - em.fEMShminfo->allocdSize / sizeof(EMEntry)) / 100 + 1;
int target = (int)(maxLoops * .02);
if (maxLoops < 50) target = 1;
// allocate shared memory for extent data
for (currentSize = em.fEMShminfo->allocdSize / sizeof(EMEntry);
currentSize < (emNumElements * (signed)mult);
currentSize = em.fEMShminfo->allocdSize / sizeof(EMEntry))
{
em.growEMShmseg();
if ((j % target) == 0) cout << '.' << flush;
vector<int>& oidv = OIDMap[emSrc[i].fileID];
for (unsigned k = 0; k < mult; k++)
{
oidv.push_back(j);
// em.fExtentMap[j].range.start = emSrc[i].range.start;
em.fExtentMap[j].range.start = emSrc[i].range.start + (k * newExtentSize);
// em.fExtentMap[j].range.size = emSrc[i].range.size;
em.fExtentMap[j].range.size = newExtentSize / 1024;
em.fExtentMap[j].fileID = emSrc[i].fileID;
em.fExtentMap[j].blockOffset = emSrc[i].blockOffset + (k * newExtentSize);
em.fExtentMap[j].HWM = emSrc[i].HWM;
em.fExtentMap[j].txnID = emSrc[i].txnID;
em.fExtentMap[j].secondHWM = emSrc[i].secondHWM;
em.fExtentMap[j].nextHeader = emSrc[i].nextHeader;
em.fExtentMap[j].partition.type = emSrc[i].partition.type;
// em.fExtentMap[j].partition.cprange.hi_val = emSrc[i].partition.cprange.hi_val;
em.fExtentMap[j].partition.cprange.hi_val = numeric_limits<int64_t>::min();
// em.fExtentMap[j].partition.cprange.lo_val = emSrc[i].partition.cprange.lo_val;
em.fExtentMap[j].partition.cprange.lo_val = numeric_limits<int64_t>::max();
// em.fExtentMap[j].partition.cprange.sequenceNum = emSrc[i].partition.cprange.sequenceNum;
em.fExtentMap[j].partition.cprange.sequenceNum = 0;
// em.fExtentMap[j].partition.cprange.isValid = emSrc[i].partition.cprange.isValid;
em.fExtentMap[j].partition.cprange.isValid = CP_INVALID;
j++;
}
}
cout << endl;
em.fEMShminfo->currentSize = j * sizeof(EMEntry);
// allocate shared memory for freelist
for (currentSize = em.fFLShminfo->allocdSize / sizeof(InlineLBIDRange);
currentSize < flNumElements;
currentSize = em.fFLShminfo->allocdSize / sizeof(InlineLBIDRange))
cout << j << " total new em entries from " << emNumElements << " file entries" << endl;
cout << OIDMap.size() << " OIDs added to em" << endl;
OIDMap_t::const_iterator iter = OIDMap.begin();
OIDMap_t::const_iterator end = OIDMap.end();
int l = 0;
while (iter != end)
{
em.growFLShmseg();
const vector<int>& oidv = iter->second;
vector<int>::const_reverse_iterator riter = oidv.rbegin();
vector<int>::const_reverse_iterator rend = oidv.rend();
HWM_t hwm = em.fExtentMap[*riter].HWM;
while (riter != rend)
{
if (em.fExtentMap[*riter].blockOffset > hwm)
{
em.fExtentMap[*riter].fileID = numeric_limits<int>::max();
em.fExtentMap[*riter].blockOffset = 0;
em.fExtentMap[*riter].HWM = 0;
l++;
}
else
break;
++riter;
}
++iter;
}
try
{
typedef map<int, vector<int> > OIDMap_t;
OIDMap_t OIDMap;
uint8_t buf[emNumElements * sizeof(EMEntry)];
uint8_t buf2[flNumElements * sizeof(InlineLBIDRange)];
in.read((char*) buf, emNumElements * sizeof(EMEntry));
//memcpy(fExtentMap, buf, emNumElements * sizeof(EMEntry));
EMEntry* emSrc = reinterpret_cast<EMEntry*>(&buf[0]);
j = 0;
for (int i = 0; i < emNumElements; i++)
{
vector<int>& oidv = OIDMap[emSrc[i].fileID];
for (unsigned k = 0; k < mult; k++)
{
oidv.push_back(j);
//em.fExtentMap[j].range.start = emSrc[i].range.start;
em.fExtentMap[j].range.start = emSrc[i].range.start + (k * newExtentSize);
//em.fExtentMap[j].range.size = emSrc[i].range.size;
em.fExtentMap[j].range.size = newExtentSize / 1024;
em.fExtentMap[j].fileID = emSrc[i].fileID;
em.fExtentMap[j].blockOffset = emSrc[i].blockOffset + (k * newExtentSize);
em.fExtentMap[j].HWM = emSrc[i].HWM;
em.fExtentMap[j].txnID = emSrc[i].txnID;
em.fExtentMap[j].secondHWM = emSrc[i].secondHWM;
em.fExtentMap[j].nextHeader = emSrc[i].nextHeader;
em.fExtentMap[j].partition.type = emSrc[i].partition.type;
//em.fExtentMap[j].partition.cprange.hi_val = emSrc[i].partition.cprange.hi_val;
em.fExtentMap[j].partition.cprange.hi_val = numeric_limits<int64_t>::min();
//em.fExtentMap[j].partition.cprange.lo_val = emSrc[i].partition.cprange.lo_val;
em.fExtentMap[j].partition.cprange.lo_val = numeric_limits<int64_t>::max();
//em.fExtentMap[j].partition.cprange.sequenceNum = emSrc[i].partition.cprange.sequenceNum;
em.fExtentMap[j].partition.cprange.sequenceNum = 0;
//em.fExtentMap[j].partition.cprange.isValid = emSrc[i].partition.cprange.isValid;
em.fExtentMap[j].partition.cprange.isValid = CP_INVALID;
j++;
}
}
em.fEMShminfo->currentSize = j * sizeof(EMEntry);
cout << j << " total new em entries from " << emNumElements << " file entries" << endl;
cout << OIDMap.size() << " OIDs added to em" << endl;
OIDMap_t::const_iterator iter = OIDMap.begin();
OIDMap_t::const_iterator end = OIDMap.end();
int l = 0;
while (iter != end)
{
const vector<int>& oidv = iter->second;
vector<int>::const_reverse_iterator riter = oidv.rbegin();
vector<int>::const_reverse_iterator rend = oidv.rend();
HWM_t hwm = em.fExtentMap[*riter].HWM;
while (riter != rend)
{
if (em.fExtentMap[*riter].blockOffset > hwm)
{
em.fExtentMap[*riter].fileID = numeric_limits<int>::max();
em.fExtentMap[*riter].blockOffset = 0;
em.fExtentMap[*riter].HWM = 0;
l++;
}
else break;
++riter;
}
++iter;
}
cout << l << " entries moved to OID " << numeric_limits<int>::max() << endl;
cout << l << " entries moved to OID " << numeric_limits<int>::max() << endl;
#if 0
int k = j;
@ -241,53 +243,52 @@ int ExtentMapConverter::doCvt(unsigned oldExtentSize, unsigned newExtentSize, co
em.fExtentMap[j].txnID << '\t' << em.fExtentMap[j].secondHWM << '\t' << em.fExtentMap[j].nextHeader << endl;
#endif
in.read((char*) buf2, flNumElements * sizeof(InlineLBIDRange));
in.read((char*)buf2, flNumElements * sizeof(InlineLBIDRange));
//memcpy(fFreeList, buf2, flNumElements * sizeof(InlineLBIDRange));
InlineLBIDRange* lrSrc = reinterpret_cast<InlineLBIDRange*>(&buf2[0]);
j = 0;
// memcpy(fFreeList, buf2, flNumElements * sizeof(InlineLBIDRange));
InlineLBIDRange* lrSrc = reinterpret_cast<InlineLBIDRange*>(&buf2[0]);
j = 0;
for (int i = 0; i < flNumElements; i++)
{
em.fFreeList[j].start = lrSrc[i].start;
em.fFreeList[j].size = lrSrc[i].size;
j++;
}
em.fFLShminfo->currentSize = j * sizeof(InlineLBIDRange);
cout << j << " total new fl entries from " << flNumElements << " file entries" << endl;
}
catch (...)
for (int i = 0; i < flNumElements; i++)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
em.fFreeList[j].start = lrSrc[i].start;
em.fFreeList[j].size = lrSrc[i].size;
j++;
}
em.fFLShminfo->currentSize = j * sizeof(InlineLBIDRange);
cout << j << " total new fl entries from " << flNumElements << " file entries" << endl;
}
catch (...)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
return 0;
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
return 0;
}
}
} // namespace BRM
int main(int argc, char** argv)
{
ExtentMapConverter emc;
ExtentMapConverter emc;
if (emc.doCvt(8192, 1024, "BRM_saves_em") != 0)
{
cerr << "Conversion failed." << endl;
return 1;
}
else
{
cout << "OK" << endl;
return 0;
}
if (emc.doCvt(8192, 1024, "BRM_saves_em") != 0)
{
cerr << "Conversion failed." << endl;
return 1;
}
else
{
cout << "OK" << endl;
return 0;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,6 @@
*
****************************************************************************/
#include <unistd.h>
#include <iostream>
using namespace std;
@ -40,157 +39,143 @@ bool vflg;
void usage(char* c)
{
cerr << "Usage: " << c << " [-vh] status | halt | resume | readonly | readwrite | reload" << endl;
exit(1);
cerr << "Usage: " << c << " [-vh] status | halt | resume | readonly | readwrite | reload" << endl;
exit(1);
}
void errMsg(int err)
{
switch (err)
{
case ERR_OK:
cout << "OK.";
switch (err)
{
case ERR_OK:
cout << "OK.";
if (vflg)
{
if (dbrm.getSystemReady() > 0)
cout << " (and the system is ready)";
else
cout << " (but the system is not ready)";
}
if (vflg)
{
if (dbrm.getSystemReady() > 0)
cout << " (and the system is ready)";
else
cout << " (but the system is not ready)";
}
cout << endl;
break;
cout << endl;
break;
case ERR_NETWORK:
cout << "Failure: an unspecific communication error." << endl;
break;
case ERR_NETWORK: cout << "Failure: an unspecific communication error." << endl; break;
case ERR_TIMEOUT:
cout << "Failure: controller node timed out." << endl;
break;
case ERR_TIMEOUT: cout << "Failure: controller node timed out." << endl; break;
case ERR_READONLY:
cout << "DBRM is currently Read Only!" << endl;
break;
case ERR_READONLY: cout << "DBRM is currently Read Only!" << endl; break;
case 20:
cout << "System is ready" << endl;
break;
case 20: cout << "System is ready" << endl; break;
case 21:
cout << "System is not ready" << endl;
break;
case 21: cout << "System is not ready" << endl; break;
default:
cout << "Failure: an unexpected error (" << err << ")" << endl;
break;
}
default: cout << "Failure: an unexpected error (" << err << ")" << endl; break;
}
}
void do_halt()
{
int err;
int err;
err = dbrm.halt();
errMsg(err);
err = dbrm.halt();
errMsg(err);
}
void do_resume()
{
int err;
int err;
err = dbrm.resume();
errMsg(err);
err = dbrm.resume();
errMsg(err);
}
void do_reload()
{
int err;
int err;
err = dbrm.forceReload();
errMsg(err);
err = dbrm.forceReload();
errMsg(err);
}
void set_readonly(bool b)
{
int err;
int err;
err = dbrm.setReadOnly(b);
errMsg(err);
err = dbrm.setReadOnly(b);
errMsg(err);
}
void do_status()
{
int err;
int err;
err = dbrm.isReadWrite();
errMsg(err);
err = dbrm.isReadWrite();
errMsg(err);
}
void do_sysstatus()
{
int err;
int err;
bool ready = dbrm.getSystemReady() > 0 ? true : false;
bool ready = dbrm.getSystemReady() > 0 ? true : false;
if (ready)
err = 20;
else
err = 21;
if (ready)
err = 20;
else
err = 21;
errMsg(err);
errMsg(err);
}
}
} // namespace
int main(int argc, char** argv)
{
int c;
vflg = false;
int c;
vflg = false;
opterr = 0;
opterr = 0;
while ((c = getopt(argc, argv, "vh")) != EOF)
switch (c)
{
case 'v':
vflg = true;
break;
while ((c = getopt(argc, argv, "vh")) != EOF)
switch (c)
{
case 'v': vflg = true; break;
case 'h':
case '?':
default:
usage(argv[0]);
return (c == 'h' ? 0 : 1);
break;
}
string cmd;
if ((argc - optind) < 1)
case 'h':
case '?':
default:
usage(argv[0]);
return (c == 'h' ? 0 : 1);
break;
}
idbdatafile::IDBPolicy::configIDBPolicy();
string cmd;
cmd = argv[optind++];
if ((argc - optind) < 1)
usage(argv[0]);
if (cmd == "status")
do_status();
else if (cmd == "halt")
do_halt();
else if (cmd == "resume")
do_resume();
else if (cmd == "readonly")
set_readonly(true);
else if (cmd == "readwrite")
set_readonly(false);
else if (cmd == "reload")
do_reload();
else if (cmd == "sysstatus")
do_sysstatus();
else
usage(argv[0]);
idbdatafile::IDBPolicy::configIDBPolicy();
return 0;
cmd = argv[optind++];
if (cmd == "status")
do_status();
else if (cmd == "halt")
do_halt();
else if (cmd == "resume")
do_resume();
else if (cmd == "readonly")
set_readonly(true);
else if (cmd == "readwrite")
set_readonly(false);
else if (cmd == "reload")
do_reload();
else if (cmd == "sysstatus")
do_sysstatus();
else
usage(argv[0]);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -31,58 +31,56 @@ using namespace std;
namespace BRM
{
LBIDResourceGraph::LBIDResourceGraph() : color(0)
{
}
LBIDResourceGraph::LBIDResourceGraph(const LBIDResourceGraph& r)
{
throw logic_error("Don't do that");
throw logic_error("Don't do that");
}
LBIDResourceGraph::~LBIDResourceGraph()
{
std::map<VER_t, TransactionNode*>::iterator tnit;
RNodes_t::iterator rit;
TransactionNode* txnNode;
std::map<VER_t, TransactionNode*>::iterator tnit;
RNodes_t::iterator rit;
TransactionNode* txnNode;
for (tnit = txns.begin(); tnit != txns.end(); )
for (tnit = txns.begin(); tnit != txns.end();)
{
txnNode = (*tnit).second;
if (txnNode->sleeping())
{
txnNode = (*tnit).second;
if (txnNode->sleeping())
{
txnNode->die();
txnNode->wake();
++tnit;
}
else
{
txns.erase(tnit++);
delete txnNode;
}
txnNode->die();
txnNode->wake();
++tnit;
}
for (rit = resources.begin(); rit != resources.end(); )
else
{
delete *rit;
resources.erase(rit++);
txns.erase(tnit++);
delete txnNode;
}
}
for (rit = resources.begin(); rit != resources.end();)
{
delete *rit;
resources.erase(rit++);
}
}
LBIDResourceGraph& LBIDResourceGraph::operator=(const LBIDResourceGraph& r)
{
throw logic_error("Don't do that");
throw logic_error("Don't do that");
}
void LBIDResourceGraph::connectResources(LBID_t start, LBID_t end,
TransactionNode* txnNode)
void LBIDResourceGraph::connectResources(LBID_t start, LBID_t end, TransactionNode* txnNode)
{
vector<ResourceNode*> intersection, reserveList;
RNodes_t::iterator sit;
vector<ResourceNode*>::iterator it;
LBID_t i;
vector<ResourceNode*> intersection, reserveList;
RNodes_t::iterator sit;
vector<ResourceNode*>::iterator it;
LBID_t i;
#if 0
/* This version creates ResourceNodes that span a range of LBIDs.
@ -133,239 +131,237 @@ void LBIDResourceGraph::connectResources(LBID_t start, LBID_t end,
#endif
/* This version creates one ResourceNode per LBID requested */
/* This version creates one ResourceNode per LBID requested */
/*
Search for each LBID in the range
if it exists, put the node in intersections
else, put a new node in the reserve list
continue...
*/
/*
Search for each LBID in the range
if it exists, put the node in intersections
else, put a new node in the reserve list
continue...
*/
for (i = start; i <= end; i++)
for (i = start; i <= end; i++)
{
ResourceNode rn(i);
sit = resources.find(&rn);
if (sit == resources.end())
{
ResourceNode rn(i);
sit = resources.find(&rn);
if (sit == resources.end())
{
ResourceNode* tmp = new ResourceNode(i);
resources.insert(tmp);
reserveList.push_back(tmp);
}
else
intersection.push_back(*sit);
}
// at this point, reserveList and intersection compose a contiguous range
// including [start, end]. reserveList has newly created ranges, intersection
// has the previously existing ones.
// of the previously existing resources; if it's not already owned (existing in edge),
// then it's one this transaction has to wait on (new out edge).
// (the set class takes care of duplicates in the out edges)
for (it = intersection.begin(); it != intersection.end(); it++)
{
if (txnNode->in.find(*it) == txnNode->in.end())
txnNode->addOutEdge(*it);
}
// reserve the new resources
for (it = reserveList.begin(); it != reserveList.end(); it++)
txnNode->addInEdge(*it);
// at this point, txnNode is adjacent to a set of ResourcesNodes s.t.
// [start, end] is contained within it.
}
/*
0 = OK
1 = transaction node was not found on wake
-1 = deadlock detected, transaction node destroyed and resources released
mutex should be slavelock
*/
int LBIDResourceGraph::reserveRange(LBID_t start, LBID_t end, VER_t txn,
boost::mutex& mutex)
{
TransactionNode* txnNode;
map<VER_t, TransactionNode*>::iterator it;
/*
look for existing transaction node T
- make one if necessary
connectResources();
checkDeadlock();
while (txnNode.out.size() > 0)
block on T's condvar
connectResources();
checkDeadlock();
}
*/
it = txns.find(txn);
if (it == txns.end())
{
txnNode = new TransactionNode(txn);
txns[txn] = txnNode;
ResourceNode* tmp = new ResourceNode(i);
resources.insert(tmp);
reserveList.push_back(tmp);
}
else
txnNode = (*it).second;
intersection.push_back(*sit);
}
connectResources(start, end, txnNode);
// at this point, reserveList and intersection compose a contiguous range
// including [start, end]. reserveList has newly created ranges, intersection
// has the previously existing ones.
// "If txnNode is waiting on at least one LBID range..."
while (txnNode->out.size() > 0)
// of the previously existing resources; if it's not already owned (existing in edge),
// then it's one this transaction has to wait on (new out edge).
// (the set class takes care of duplicates in the out edges)
for (it = intersection.begin(); it != intersection.end(); it++)
{
if (txnNode->in.find(*it) == txnNode->in.end())
txnNode->addOutEdge(*it);
}
// reserve the new resources
for (it = reserveList.begin(); it != reserveList.end(); it++)
txnNode->addInEdge(*it);
// at this point, txnNode is adjacent to a set of ResourcesNodes s.t.
// [start, end] is contained within it.
}
/*
0 = OK
1 = transaction node was not found on wake
-1 = deadlock detected, transaction node destroyed and resources released
mutex should be slavelock
*/
int LBIDResourceGraph::reserveRange(LBID_t start, LBID_t end, VER_t txn, boost::mutex& mutex)
{
TransactionNode* txnNode;
map<VER_t, TransactionNode*>::iterator it;
/*
look for existing transaction node T
- make one if necessary
connectResources();
checkDeadlock();
while (txnNode.out.size() > 0)
block on T's condvar
connectResources();
checkDeadlock();
}
*/
it = txns.find(txn);
if (it == txns.end())
{
txnNode = new TransactionNode(txn);
txns[txn] = txnNode;
}
else
txnNode = (*it).second;
connectResources(start, end, txnNode);
// "If txnNode is waiting on at least one LBID range..."
while (txnNode->out.size() > 0)
{
// make sure there's no deadlock before blocking
if (checkDeadlock(*txnNode))
{
// make sure there's no deadlock before blocking
if (checkDeadlock(*txnNode))
{
// releaseResources(txn);
return ERR_DEADLOCK;
}
#ifdef BRM_VERBOSE
cerr << " RG: sleeping transaction " << txn << endl;
set<RGNode*>::iterator sit;
cerr << " waiting on: " << endl;
for (sit = txnNode->out.begin(); sit != txnNode->out.end(); sit++)
{
ResourceNode* rn = dynamic_cast<ResourceNode*>(*sit);
cerr << hex << rn << dec << " " << rn->lbid() << endl;
}
#endif
txnNode->sleep(mutex);
#ifdef BRM_VERBOSE
cerr << " RG: txn " << txn << " is awake" << endl;
#endif
if (txnNode->dead())
{
txns.erase(txn);
delete txnNode;
return ERR_KILLED;
}
// attempt to grab remaining resources
connectResources(start, end, txnNode);
// releaseResources(txn);
return ERR_DEADLOCK;
}
// txn has all requested LBID ranges
return ERR_OK;
#ifdef BRM_VERBOSE
cerr << " RG: sleeping transaction " << txn << endl;
set<RGNode*>::iterator sit;
cerr << " waiting on: " << endl;
for (sit = txnNode->out.begin(); sit != txnNode->out.end(); sit++)
{
ResourceNode* rn = dynamic_cast<ResourceNode*>(*sit);
cerr << hex << rn << dec << " " << rn->lbid() << endl;
}
#endif
txnNode->sleep(mutex);
#ifdef BRM_VERBOSE
cerr << " RG: txn " << txn << " is awake" << endl;
#endif
if (txnNode->dead())
{
txns.erase(txn);
delete txnNode;
return ERR_KILLED;
}
// attempt to grab remaining resources
connectResources(start, end, txnNode);
}
// txn has all requested LBID ranges
return ERR_OK;
}
void LBIDResourceGraph::releaseResources(VER_t txn)
{
/*
get transaction node
get all inbound nodes
detach them and wake all txns on the in-edges
delete the resource nodes
get all outbound nodes (this can happen if a rollback comes in while blocked)
detach them
if txnNode isn't sleeping,
delete the transaction node
else
mark it dead and wake it
*/
/*
get transaction node
get all inbound nodes
detach them and wake all txns on the in-edges
delete the resource nodes
get all outbound nodes (this can happen if a rollback comes in while blocked)
detach them
if txnNode isn't sleeping,
delete the transaction node
else
mark it dead and wake it
*/
TransactionNode* txnNode;
ResourceNode* rNode;
map<VER_t, TransactionNode*>::iterator it;
set<RGNode*>::iterator sit;
set<RGNode*>::iterator dummy_sit;
TransactionNode* txnNode;
ResourceNode* rNode;
map<VER_t, TransactionNode*>::iterator it;
set<RGNode*>::iterator sit;
set<RGNode*>::iterator dummy_sit;
it = txns.find(txn);
it = txns.find(txn);
if (it == txns.end())
return;
if (it == txns.end())
return;
txnNode = (*it).second;
txnNode = (*it).second;
for (sit = txnNode->in.begin(); sit != txnNode->in.end(); )
{
rNode = dynamic_cast<ResourceNode*>(*sit);
dummy_sit = ++sit;
rNode->wakeAndDetach();
txnNode->removeInEdge(rNode);
resources.erase(rNode);
delete rNode;
sit = dummy_sit;
}
for (sit = txnNode->in.begin(); sit != txnNode->in.end();)
{
rNode = dynamic_cast<ResourceNode*>(*sit);
dummy_sit = ++sit;
rNode->wakeAndDetach();
txnNode->removeInEdge(rNode);
resources.erase(rNode);
delete rNode;
sit = dummy_sit;
}
for (sit = txnNode->out.begin(); sit != txnNode->out.end(); )
{
rNode = dynamic_cast<ResourceNode*>(*sit);
dummy_sit = ++sit;
txnNode->removeOutEdge(rNode);
sit = dummy_sit;
}
for (sit = txnNode->out.begin(); sit != txnNode->out.end();)
{
rNode = dynamic_cast<ResourceNode*>(*sit);
dummy_sit = ++sit;
txnNode->removeOutEdge(rNode);
sit = dummy_sit;
}
if (txnNode->sleeping())
{
txnNode->die();
txnNode->wake();
}
else
{
txns.erase(txn);
delete txnNode;
}
if (txnNode->sleeping())
{
txnNode->die();
txnNode->wake();
}
else
{
txns.erase(txn);
delete txnNode;
}
}
void LBIDResourceGraph::releaseResource(LBID_t lbid)
{
RNodes_t::iterator sit;
TransactionNode* txnNode;
RNodes_t::iterator sit;
TransactionNode* txnNode;
for (sit = resources.begin(); sit != resources.end(); sit++)
if (**sit == lbid)
break;
for (sit = resources.begin(); sit != resources.end(); sit++)
if (**sit == lbid)
break;
if (sit != resources.end())
{
(*sit)->wakeAndDetach();
if (sit != resources.end())
{
(*sit)->wakeAndDetach();
//should only be one out edge of any resource node
txnNode = dynamic_cast<TransactionNode*>(*(*sit)->out.begin());
(*sit)->removeOutEdge(txnNode);
resources.erase(*sit);
delete *sit;
}
// should only be one out edge of any resource node
txnNode = dynamic_cast<TransactionNode*>(*(*sit)->out.begin());
(*sit)->removeOutEdge(txnNode);
resources.erase(*sit);
delete *sit;
}
}
bool LBIDResourceGraph::DFSStep(RGNode* curNode, uint64_t gray, uint64_t black) const
{
set<RGNode*>::iterator it;
set<RGNode*>::iterator it;
if (curNode->color() == gray)
if (curNode->color() == gray)
return true;
curNode->color(gray);
for (it = curNode->out.begin(); it != curNode->out.end(); it++)
{
if ((*it)->color() != black)
if (DFSStep(*it, gray, black))
return true;
}
curNode->color(gray);
curNode->color(black);
for (it = curNode->out.begin(); it != curNode->out.end(); it++)
{
if ((*it)->color() != black)
if (DFSStep(*it, gray, black))
return true;
}
curNode->color(black);
return false;
return false;
}
bool LBIDResourceGraph::checkDeadlock(TransactionNode& start)
{
uint64_t gray = ++color, black = ++color;
uint64_t gray = ++color, black = ++color;
return DFSStep(&start, gray, black);
return DFSStep(&start, gray, black);
}
}
} // namespace BRM

View File

@ -48,40 +48,37 @@
namespace BRM
{
class LBIDResourceGraph
{
public:
typedef std::tr1::unordered_set<ResourceNode*, RNHasher, RNEquals> RNodes_t;
public:
typedef std::tr1::unordered_set<ResourceNode*, RNHasher, RNEquals> RNodes_t;
EXPORT LBIDResourceGraph();
EXPORT ~LBIDResourceGraph();
EXPORT LBIDResourceGraph();
EXPORT ~LBIDResourceGraph();
EXPORT int reserveRange(LBID_t start, LBID_t end, VER_t txn, boost::mutex& mutex);
EXPORT int reserveRange(LBID_t start, LBID_t end, VER_t txn, boost::mutex& mutex);
/// releases all resources held by txn
EXPORT void releaseResources(VER_t txn);
/// releases all resources held by txn
EXPORT void releaseResources(VER_t txn);
/// releases one resource
EXPORT void releaseResource(LBID_t start);
/// releases one resource
EXPORT void releaseResource(LBID_t start);
private:
uint64_t color;
private:
uint64_t color;
LBIDResourceGraph(const LBIDResourceGraph&);
LBIDResourceGraph& operator=(const LBIDResourceGraph&);
LBIDResourceGraph(const LBIDResourceGraph&);
LBIDResourceGraph& operator=(const LBIDResourceGraph&);
void connectResources(LBID_t start, LBID_t end, TransactionNode* txnNode);
bool checkDeadlock(TransactionNode&);
bool DFSStep(RGNode*, uint64_t, uint64_t) const;
std::map<VER_t, TransactionNode*> txns;
RNodes_t resources;
void connectResources(LBID_t start, LBID_t end, TransactionNode* txnNode);
bool checkDeadlock(TransactionNode&);
bool DFSStep(RGNode*, uint64_t, uint64_t) const;
std::map<VER_t, TransactionNode*> txns;
RNodes_t resources;
};
}
} // namespace BRM
#undef EXPORT

View File

@ -38,97 +38,93 @@ using namespace BRM;
namespace
{
void usage()
{
cout << "usage: load_brm [-fh] prefix" << endl << endl;
cout << " -h display this help" << endl;
cout << " -f possibly fix a corrupted Free List" << endl;
cout << "usage: load_brm [-fh] prefix" << endl << endl;
cout << " -h display this help" << endl;
cout << " -f possibly fix a corrupted Free List" << endl;
}
struct CtlShmImage
{
bi::interprocess_mutex controlFifoMutex;
bi::interprocess_mutex controlFifoMutex;
};
}
} // namespace
int main(int argc, char** argv)
{
opterr = 0;
bool fflg = false;
opterr = 0;
bool fflg = false;
int c;
int c;
while ((c = getopt(argc, argv, "fh")) != EOF)
switch (c)
{
case 'f':
fflg = true;
break;
case 'h':
case '?':
default:
usage();
return (c == 'h' ? 0 : 1);
break;
}
if ((argc - optind) != 1)
while ((c = getopt(argc, argv, "fh")) != EOF)
switch (c)
{
case 'f': fflg = true; break;
case 'h':
case '?':
default:
usage();
return 1;
return (c == 'h' ? 0 : 1);
break;
}
idbdatafile::IDBPolicy::configIDBPolicy();
if ((argc - optind) != 1)
{
usage();
return 1;
}
BlockResolutionManager brm;
int err;
string prefix;
idbdatafile::IDBPolicy::configIDBPolicy();
prefix = argv[optind];
err = brm.loadState(prefix, fflg);
BlockResolutionManager brm;
int err;
string prefix;
if (err != 0)
{
cout << "Loading BRM snapshot failed (" << prefix << ")\n";
return 1;
}
prefix = argv[optind];
err = brm.loadState(prefix, fflg);
err = brm.replayJournal(prefix);
if (err != 0)
{
cout << "Loading BRM snapshot failed (" << prefix << ")\n";
return 1;
}
if (err < 0)
{
cout << "Could not load BRM journal file\n";
return 1;
}
err = brm.replayJournal(prefix);
ShmKeys shmkeys;
string key_name = ShmKeys::keyToName(shmkeys.DECOMSVRMUTEX_SYSVKEY);
bi::shared_memory_object::remove(key_name.c_str());
bi::permissions perms;
perms.set_unrestricted();
if (err < 0)
{
cout << "Could not load BRM journal file\n";
return 1;
}
try
{
bi::shared_memory_object shm(bi::create_only, key_name.c_str(), bi::read_write, perms);
shm.truncate(sizeof(CtlShmImage));
bi::mapped_region region(shm, bi::read_write);
(void)new (region.get_address()) CtlShmImage;
}
catch (...)
{
//Hmm...we just deleted it above, but the create failed...just bail out
throw runtime_error("couldn't create DecomSvr shm");
}
ShmKeys shmkeys;
string key_name = ShmKeys::keyToName(shmkeys.DECOMSVRMUTEX_SYSVKEY);
bi::shared_memory_object::remove(key_name.c_str());
bi::permissions perms;
perms.set_unrestricted();
/* An OAM friendly success msg */
cout << "OK.\n";
cout << "Successfully loaded BRM snapshot\n";
cout << "Successfully replayed " << err << " BRM transactions\n";
try
{
bi::shared_memory_object shm(bi::create_only, key_name.c_str(), bi::read_write, perms);
shm.truncate(sizeof(CtlShmImage));
bi::mapped_region region(shm, bi::read_write);
(void)new (region.get_address()) CtlShmImage;
}
catch (...)
{
// Hmm...we just deleted it above, but the create failed...just bail out
throw runtime_error("couldn't create DecomSvr shm");
}
return 0;
/* An OAM friendly success msg */
cout << "OK.\n";
cout << "Successfully loaded BRM snapshot\n";
cout << "Successfully replayed " << err << " BRM transactions\n";
return 0;
}
// vim:ts=4 sw=4:

View File

@ -42,40 +42,40 @@ using namespace std;
void usage(char* name)
{
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
int main(int argc, char** argv)
{
#if __WORDSIZE <= 32
//This code is OBE now that the structs are padded correctly
BlockResolutionManager brm;
int err;
string prefix;
// This code is OBE now that the structs are padded correctly
BlockResolutionManager brm;
int err;
string prefix;
if (argc > 2)
usage(argv[0]);
else if (argc == 2)
prefix = argv[1];
else
prefix = "BRM_state";
if (argc > 2)
usage(argv[0]);
else if (argc == 2)
prefix = argv[1];
else
prefix = "BRM_state";
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
err = brm.loadState(prefix);
err = brm.loadState(prefix);
if (err == 0)
cout << "OK." << endl;
else
{
cout << "Load failed" << endl;
return 1;
}
return 0;
#else
cerr << "This tool does not work on 64-bit arch!" << endl;
if (err == 0)
cout << "OK." << endl;
else
{
cout << "Load failed" << endl;
return 1;
}
return 0;
#else
cerr << "This tool does not work on 64-bit arch!" << endl;
return 1;
#endif
}

View File

@ -22,9 +22,10 @@
* this tool to create a binary BRM_saves_em file.
*
* compile with
* g++ -g -Wall -o load_brm_from_file -I$HOME/genii/export/include -I/usr/include/libxml2 load_brm_from_file.cpp
* g++ -g -Wall -o load_brm_from_file -I$HOME/genii/export/include -I/usr/include/libxml2
* load_brm_from_file.cpp
*
*/
*/
#include <iostream>
#include <stdint.h>
#include <fstream>
@ -48,99 +49,99 @@ namespace BRM
{
EMEntry::EMEntry()
{
fileID = 0;
blockOffset = 0;
HWM = 0;
partitionNum = 0;
segmentNum = 0;
dbRoot = 0;
colWid = 0;
status = 0;
fileID = 0;
blockOffset = 0;
HWM = 0;
partitionNum = 0;
segmentNum = 0;
dbRoot = 0;
colWid = 0;
status = 0;
}
EMCasualPartition_struct::EMCasualPartition_struct()
{
lo_val = numeric_limits<int64_t>::min();
hi_val = numeric_limits<int64_t>::max();
sequenceNum = 0;
isValid = CP_INVALID;
}
lo_val = numeric_limits<int64_t>::min();
hi_val = numeric_limits<int64_t>::max();
sequenceNum = 0;
isValid = CP_INVALID;
}
} // namespace BRM
int main(int argc, char** argv)
{
int e;
int e;
int loadSize[3];
int loadSize[3];
if (argc < 2)
{
cerr << "filename arg needed" << endl;
return 1;
}
if (argc < 2)
{
cerr << "filename arg needed" << endl;
return 1;
}
ifstream in(argv[1]);
e = errno;
ifstream in(argv[1]);
e = errno;
if (!in)
{
cerr << "file read error: " << strerror(e) << endl;
return 1;
}
if (!in)
{
cerr << "file read error: " << strerror(e) << endl;
return 1;
}
//Brute force count the number of lines
int numEMEntries = 0;
// Brute force count the number of lines
int numEMEntries = 0;
string line;
string line;
getline(in, line);
while (!in.eof())
{
numEMEntries++;
getline(in, line);
}
while (!in.eof())
{
numEMEntries++;
getline(in, line);
}
// start at the beginning again...
in.clear();
in.seekg(0, ios_base::beg);
//start at the beginning again...
in.clear();
in.seekg(0, ios_base::beg);
idbassert(in.good());
idbassert(in.tellg() == static_cast<streampos>(0));
idbassert(in.good());
idbassert(in.tellg() == static_cast<streampos>(0));
string outname(argv[1]);
outname += ".out";
string outname(argv[1]);
outname += ".out";
ofstream out(outname.c_str());
e = errno;
ofstream out(outname.c_str());
e = errno;
if (!out)
{
cerr << "file write error: " << strerror(e) << endl;
return 1;
}
if (!out)
{
cerr << "file write error: " << strerror(e) << endl;
return 1;
}
loadSize[0] = EM_MAGIC_V4;
loadSize[1] = numEMEntries;
loadSize[2] = 1; // one free list entry
out.write((char*)&loadSize, (3 * sizeof(int)));
loadSize[0] = EM_MAGIC_V4;
loadSize[1] = numEMEntries;
loadSize[2] = 1; //one free list entry
out.write((char*)&loadSize, (3 * sizeof(int)));
InlineLBIDRange fl;
fl.start = 0;
// the max lbid is 2^54-1, the size is in units of 1k
fl.size = numeric_limits<uint32_t>::max();
InlineLBIDRange fl;
fl.start = 0;
//the max lbid is 2^54-1, the size is in units of 1k
fl.size = numeric_limits<uint32_t>::max();
InlineLBIDRange maxLBIDinUse;
maxLBIDinUse.start = 0;
maxLBIDinUse.size = 0;
InlineLBIDRange maxLBIDinUse;
maxLBIDinUse.start = 0;
maxLBIDinUse.size = 0;
getline(in, line);
getline(in, line);
while (!in.eof())
{
EMEntry em;
int64_t v;
tokenizer<> tok(line);
tokenizer<>::iterator beg = tok.begin();
while (!in.eof())
{
EMEntry em;
int64_t v;
tokenizer<> tok(line);
tokenizer<>::iterator beg = tok.begin();
#if 0
emSrc[i].range.start
<< '\t' << emSrc[i].range.size
@ -157,81 +158,80 @@ int main(int argc, char** argv)
<< '\t' << emSrc[i].partition.cprange.sequenceNum
<< '\t' << (int)(emSrc[i].partition.cprange.isValid)
#endif
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.range.start = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.range.start = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.range.size = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.range.size = v;
if (em.range.start > maxLBIDinUse.start)
{
maxLBIDinUse.start = em.range.start;
maxLBIDinUse.size = em.range.size;
}
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.fileID = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.blockOffset = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.HWM = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partitionNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.segmentNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.dbRoot = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.colWid = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.status = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.hi_val = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.lo_val = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.sequenceNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.isValid = v;
out.write((char*)&em, sizeof(em));
getline(in, line);
if (em.range.start > maxLBIDinUse.start)
{
maxLBIDinUse.start = em.range.start;
maxLBIDinUse.size = em.range.size;
}
fl.start = maxLBIDinUse.start + maxLBIDinUse.size * 1024;
fl.size -= fl.start / 1024;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.fileID = v;
out.write((char*)&fl, sizeof(fl));
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.blockOffset = v;
out.close();
in.close();
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.HWM = v;
return 0;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partitionNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.segmentNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.dbRoot = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.colWid = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.status = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.hi_val = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.lo_val = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.sequenceNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.isValid = v;
out.write((char*)&em, sizeof(em));
getline(in, line);
}
fl.start = maxLBIDinUse.start + maxLBIDinUse.size * 1024;
fl.size -= fl.start / 1024;
out.write((char*)&fl, sizeof(fl));
out.close();
in.close();
return 0;
}

View File

@ -39,34 +39,34 @@ using namespace std;
void usage(char* name)
{
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
int main(int argc, char** argv)
{
ExtentMap em;
string prefix;
ExtentMap em;
string prefix;
if (argc > 2)
usage(argv[0]);
else if (argc == 2)
prefix = argv[1];
else
prefix = "BRM_state";
if (argc > 2)
usage(argv[0]);
else if (argc == 2)
prefix = argv[1];
else
prefix = "BRM_state";
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
try
{
em.load(prefix);
cout << "OK." << endl;
}
catch (exception& e)
{
cout << "Load failed." << endl;
return 1;
}
try
{
em.load(prefix);
cout << "OK." << endl;
}
catch (exception& e)
{
cout << "Load failed." << endl;
return 1;
}
return 0;
return 0;
}

View File

@ -32,58 +32,58 @@ char* name;
void usage()
{
cout << "Usage " << name << " which_lock_to_use which_side_to_use lock_or_unlock\n" <<
" which_lock_to_use: 1=VSS 2=ExtentMap 3=FreeList 4=VBBM 5=CopyLocks\n" <<
" which_side_to_use: r|w (read or write)\n" <<
" lock_or_unlock: l|u (lock or unlock)\n";
exit(1);
cout << "Usage " << name << " which_lock_to_use which_side_to_use lock_or_unlock\n"
<< " which_lock_to_use: 1=VSS 2=ExtentMap 3=FreeList 4=VBBM 5=CopyLocks\n"
<< " which_side_to_use: r|w (read or write)\n"
<< " lock_or_unlock: l|u (lock or unlock)\n";
exit(1);
}
int main(int argc, char** argv)
{
uint32_t which_lock; // 1-5
uint32_t which_side; // 0 or 1
uint32_t lock_unlock; // 0 or 1
RWLock* rwlock;
uint32_t which_lock; // 1-5
uint32_t which_side; // 0 or 1
uint32_t lock_unlock; // 0 or 1
RWLock* rwlock;
name = argv[0];
name = argv[0];
if (argc != 4)
usage();
if (argc != 4)
usage();
if (strlen(argv[1]) != 1 || strlen(argv[2]) != 1 || strlen(argv[3]) != 1)
usage();
if (strlen(argv[1]) != 1 || strlen(argv[2]) != 1 || strlen(argv[3]) != 1)
usage();
which_lock = atoi(argv[1]);
which_lock = atoi(argv[1]);
if (which_lock < 1 || which_lock > 5)
usage();
if (which_lock < 1 || which_lock > 5)
usage();
if (argv[2][0] == 'r')
which_side = 0;
else if (argv[2][0] == 'w')
which_side = 1;
if (argv[2][0] == 'r')
which_side = 0;
else if (argv[2][0] == 'w')
which_side = 1;
else
usage();
if (argv[3][0] == 'l')
lock_unlock = 0;
else if (argv[3][0] == 'u')
lock_unlock = 1;
else
usage();
rwlock = new RWLock(0x10000 * which_lock);
if (which_side == 0)
if (lock_unlock == 0)
rwlock->read_lock();
else
usage();
rwlock->read_unlock();
else if (lock_unlock == 0)
rwlock->write_lock();
else
rwlock->write_unlock();
if (argv[3][0] == 'l')
lock_unlock = 0;
else if (argv[3][0] == 'u')
lock_unlock = 1;
else
usage();
rwlock = new RWLock(0x10000 * which_lock);
if (which_side == 0)
if (lock_unlock == 0)
rwlock->read_lock();
else
rwlock->read_unlock();
else if (lock_unlock == 0)
rwlock->write_lock();
else
rwlock->write_unlock();
return 0;
return 0;
}

View File

@ -32,37 +32,37 @@ char* name;
void usage()
{
cout << "Usage " << name << " which_lock_to_use which_side_to_use lock_or_unlock\n" <<
" which_lock_to_use: 1=VSS 2=ExtentMap 3=FreeList 4=VBBM 5=CopyLocks\n";
exit(1);
cout << "Usage " << name << " which_lock_to_use which_side_to_use lock_or_unlock\n"
<< " which_lock_to_use: 1=VSS 2=ExtentMap 3=FreeList 4=VBBM 5=CopyLocks\n";
exit(1);
}
int main(int argc, char** argv)
{
uint32_t which_lock; // 1-5
RWLock* rwlock;
LockState state;
uint32_t which_lock; // 1-5
RWLock* rwlock;
LockState state;
name = argv[0];
name = argv[0];
if (argc != 2)
usage();
if (argc != 2)
usage();
if (strlen(argv[1]) != 1)
usage();
if (strlen(argv[1]) != 1)
usage();
which_lock = atoi(argv[1]);
which_lock = atoi(argv[1]);
if (which_lock < 1 || which_lock > 5)
usage();
if (which_lock < 1 || which_lock > 5)
usage();
rwlock = new RWLock(0x10000 * which_lock);
state = rwlock->getLockState();
cout << "readers = " << state.reading << endl
<< "writers = " << state.writing << endl
<< "readers waiting = " << state.readerswaiting << endl
<< "writers waiting = " << state.writerswaiting << endl
<< "mutex locked = " << (int) state.mutexLocked << endl;
rwlock = new RWLock(0x10000 * which_lock);
state = rwlock->getLockState();
cout << "readers = " << state.reading << endl
<< "writers = " << state.writing << endl
<< "readers waiting = " << state.readerswaiting << endl
<< "writers waiting = " << state.writerswaiting << endl
<< "mutex locked = " << (int)state.mutexLocked << endl;
return 0;
return 0;
}

View File

@ -34,9 +34,9 @@ namespace BRM
{
std::string LogicalPartition::toString() const
{
char buf[256] = {0};
std::sprintf(buf, "%d.%d.%d", pp, seg, dbroot);
return std::string(buf);
char buf[256] = {0};
std::sprintf(buf, "%d.%d.%d", pp, seg, dbroot);
return std::string(buf);
}
/**
@ -44,18 +44,18 @@ std::string LogicalPartition::toString() const
*/
std::ostream& operator<<(std::ostream& output, const LogicalPartition& rhs)
{
output << rhs.pp << "." << rhs.seg << "." << rhs.dbroot;
return output;
output << rhs.pp << "." << rhs.seg << "." << rhs.dbroot;
return output;
}
std::istream& operator>>(std::istream& input, LogicalPartition& rhs)
{
input >> rhs.pp;
input.ignore();
input >> rhs.seg;
input.ignore();
input >> rhs.dbroot;
return input;
input >> rhs.pp;
input.ignore();
input >> rhs.seg;
input.ignore();
input >> rhs.dbroot;
return input;
}
/**
@ -63,14 +63,14 @@ std::istream& operator>>(std::istream& input, LogicalPartition& rhs)
*/
messageqcpp::ByteStream& operator<<(messageqcpp::ByteStream& bs, const LogicalPartition& rhs)
{
rhs.serialize(bs);
return bs;
rhs.serialize(bs);
return bs;
}
messageqcpp::ByteStream& operator>>(messageqcpp::ByteStream& bs, LogicalPartition& rhs)
{
rhs.unserialize(bs);
return bs;
rhs.unserialize(bs);
return bs;
}
}
} // namespace BRM

View File

@ -35,42 +35,39 @@ namespace BRM
// Logical partition number descriptor
struct LogicalPartition
{
uint16_t dbroot; // dbroot #
uint32_t pp; // physical partition #
uint16_t seg; // segment #
uint16_t dbroot; // dbroot #
uint32_t pp; // physical partition #
uint16_t seg; // segment #
LogicalPartition() : dbroot ((uint16_t) - 1),
pp ((uint32_t) - 1),
seg ((uint16_t) - 1) {}
LogicalPartition() : dbroot((uint16_t)-1), pp((uint32_t)-1), seg((uint16_t)-1)
{
}
LogicalPartition(uint16_t d, uint32_t p, uint16_t s) : dbroot(d),
pp(p),
seg(s)
{}
LogicalPartition(uint16_t d, uint32_t p, uint16_t s) : dbroot(d), pp(p), seg(s)
{
}
bool operator<( const LogicalPartition& n ) const
{
return ((pp < n.pp) ||
(pp == n.pp && seg < n.seg) ||
(pp == n.pp && seg == n.seg && dbroot < n.dbroot));
}
bool operator<(const LogicalPartition& n) const
{
return ((pp < n.pp) || (pp == n.pp && seg < n.seg) || (pp == n.pp && seg == n.seg && dbroot < n.dbroot));
}
void serialize(messageqcpp::ByteStream& b) const
{
b << (uint16_t)dbroot;
b << (uint32_t)pp;
b << (uint16_t)seg;
}
void serialize(messageqcpp::ByteStream& b) const
{
b << (uint16_t)dbroot;
b << (uint32_t)pp;
b << (uint16_t)seg;
}
void unserialize(messageqcpp::ByteStream& b)
{
b >> (uint16_t&)dbroot;
b >> (uint32_t&)pp;
b >> (uint16_t&)seg;
}
void unserialize(messageqcpp::ByteStream& b)
{
b >> (uint16_t&)dbroot;
b >> (uint32_t&)pp;
b >> (uint16_t&)seg;
}
/** @bug4816. For output to user purpose */
std::string toString() const;
/** @bug4816. For output to user purpose */
std::string toString() const;
};
/**
@ -86,5 +83,5 @@ messageqcpp::ByteStream& operator<<(messageqcpp::ByteStream& bs, const LogicalPa
messageqcpp::ByteStream& operator>>(messageqcpp::ByteStream& bs, LogicalPartition& rhs);
}
} // namespace BRM
#endif

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,6 @@
namespace BRM
{
/** @brief The Master node of the DBRM system.
*
* There are 3 components of the Distributed BRM (DBRM).
@ -85,182 +84,178 @@ constexpr size_t connectTimeoutStep = 50000;
class MasterDBRMNode
{
public:
MasterDBRMNode();
~MasterDBRMNode();
public:
MasterDBRMNode();
~MasterDBRMNode();
/** @brief The primary function of the class.
*
* The main loop of the master node. It accepts connections from the DBRM
* class, receives commands, and distributes them to each slave. It returns
* only after stop() or the destructor is called by another thread.
*/
void run();
/** @brief The primary function of the class.
*
* The main loop of the master node. It accepts connections from the DBRM
* class, receives commands, and distributes them to each slave. It returns
* only after stop() or the destructor is called by another thread.
*/
void run();
/** @brief Tells the Master to shut down cleanly.
*
* Tells the Master to shut down cleanly.
*/
void stop();
/** @brief Tells the Master to shut down cleanly.
*
* Tells the Master to shut down cleanly.
*/
void stop();
/** @brief Effectively makes the whole DBRM system stop.
*
* Grabs a lock that effectively halts all further BRM data changes.
* @warning Use with care. It's basically an accessor to a raw pthread_mutex.
*/
void lock();
/** @brief Effectively makes the whole DBRM system stop.
*
* Grabs a lock that effectively halts all further BRM data changes.
* @warning Use with care. It's basically an accessor to a raw pthread_mutex.
*/
void lock();
/** @brief Resumes DBRM functionality.
*
* Releases a lock that allows the DBRM to continue processing changes.
* @warning Use with care. It's basically an accessor to a raw pthread_mutex.
*/
void unlock();
/** @brief Resumes DBRM functionality.
*
* Releases a lock that allows the DBRM to continue processing changes.
* @warning Use with care. It's basically an accessor to a raw pthread_mutex.
*/
void unlock();
/** @brief Reload the config file and reconnect to all slaves.
*
* Drops all existing connections, reloads the config file and
* reconnects with all slaves.
* @note Doesn't work yet. Redundant anyway.
*/
void reload();
/** @brief Reload the config file and reconnect to all slaves.
*
* Drops all existing connections, reloads the config file and
* reconnects with all slaves.
* @note Doesn't work yet. Redundant anyway.
*/
void reload();
/** @brief Sets either read/write or read-only mode
*
* Sets either read/write or read-only mode. When in read-only mode
* all BRM change requests will return ERR_READONLY immediately.
* @param ro true specifies read-only, false specifies read/write
*/
void setReadOnly(bool ro);
/** @brief Sets either read/write or read-only mode
*
* Sets either read/write or read-only mode. When in read-only mode
* all BRM change requests will return ERR_READONLY immediately.
* @param ro true specifies read-only, false specifies read/write
*/
void setReadOnly(bool ro);
/** @brief Returns true if the Master is in read-only mode, false if in RW mode.
*
* @returns true if the Master is in read-only mode, false if in read-write
* mode
*/
bool isReadOnly() const
{
return readOnly;
}
/** @brief Connects to the all workers */
void connectToWorkers(const size_t connectTimeoutSecs);
/** @brief Returns true if the Master is in read-only mode, false if in RW mode.
*
* @returns true if the Master is in read-only mode, false if in read-write
* mode
*/
bool isReadOnly() const
{
return readOnly;
}
/** @brief Connects to the all workers */
void connectToWorkers(const size_t connectTimeoutSecs);
/** @brief Extracts number of workers and connection timeout from the config */
void getNumWorkersAndTimeout(size_t& connectTimeoutSecs,
const std::string& methodName,
config::Config* config);
/** @brief Extracts number of workers and connection timeout from the config */
void getNumWorkersAndTimeout(size_t& connectTimeoutSecs, const std::string& methodName,
config::Config* config);
private:
private:
class MsgProcessor
{
public:
MsgProcessor(MasterDBRMNode* master);
~MsgProcessor();
void operator()();
class MsgProcessor
{
public:
MsgProcessor(MasterDBRMNode* master);
~MsgProcessor();
void operator()();
private:
MasterDBRMNode* m;
};
private:
MasterDBRMNode* m;
};
struct ThreadParams
{
messageqcpp::IOSocket* sock;
boost::thread* t;
};
struct ThreadParams
{
messageqcpp::IOSocket* sock;
boost::thread* t;
};
MasterDBRMNode(const MasterDBRMNode& m);
MasterDBRMNode& operator=(const MasterDBRMNode& m);
MasterDBRMNode(const MasterDBRMNode& m);
MasterDBRMNode& operator=(const MasterDBRMNode& m);
void initMsgQueues(config::Config* config);
void msgProcessor();
void distribute(messageqcpp::ByteStream* msg);
void undo() throw();
void confirm();
void sendError(messageqcpp::IOSocket* dest, uint8_t err) const throw();
int gatherResponses(uint8_t cmd, uint32_t msgCmdLength, std::vector<messageqcpp::ByteStream*>* responses,
bool& readErrFlag) throw();
int compareResponses(uint8_t cmd, uint32_t msgCmdLength,
const std::vector<messageqcpp::ByteStream*>& responses) const;
void finalCleanup();
void initMsgQueues(config::Config* config);
void msgProcessor();
void distribute(messageqcpp::ByteStream* msg);
void undo() throw();
void confirm();
void sendError(messageqcpp::IOSocket* dest, uint8_t err) const throw();
int gatherResponses(uint8_t cmd, uint32_t msgCmdLength,
std::vector<messageqcpp::ByteStream*>* responses,
bool& readErrFlag) throw();
int compareResponses(uint8_t cmd, uint32_t msgCmdLength,
const std::vector <messageqcpp::ByteStream*>& responses) const;
void finalCleanup();
/* Commands the master executes */
void doHalt(messageqcpp::IOSocket* sock);
void doResume(messageqcpp::IOSocket* sock);
void doReload(messageqcpp::IOSocket* sock);
void doSetReadOnly(messageqcpp::IOSocket* sock, bool b);
void doGetReadOnly(messageqcpp::IOSocket* sock);
/* Commands the master executes */
void doHalt(messageqcpp::IOSocket* sock);
void doResume(messageqcpp::IOSocket* sock);
void doReload(messageqcpp::IOSocket* sock);
void doSetReadOnly(messageqcpp::IOSocket* sock, bool b);
void doGetReadOnly(messageqcpp::IOSocket* sock);
/* SessionManager interface */
SessionManagerServer sm;
void doVerID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetSystemCatalog(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSysCatVerID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doNewTxnID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doCommitted(messageqcpp::ByteStream& msg, ThreadParams* p);
void doRolledBack(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetTxnID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSIDTIDMap(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetShmContents(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetUniqueUint32(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetUniqueUint64(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetSystemState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSetSystemState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doClearSystemState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSessionManagerReset(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetUncommittedLbids(messageqcpp::ByteStream& msg, ThreadParams* p);
/* SessionManager interface */
SessionManagerServer sm;
void doVerID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetSystemCatalog(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSysCatVerID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doNewTxnID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doCommitted(messageqcpp::ByteStream& msg, ThreadParams* p);
void doRolledBack(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetTxnID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSIDTIDMap(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetShmContents(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetUniqueUint32(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetUniqueUint64(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetSystemState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSetSystemState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doClearSystemState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doSessionManagerReset(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetUncommittedLbids(messageqcpp::ByteStream& msg, ThreadParams* p);
/* OID Manager interface */
OIDServer oids;
boost::mutex oidsMutex;
void doAllocOIDs(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReturnOIDs(messageqcpp::ByteStream& msg, ThreadParams* p);
void doOidmSize(messageqcpp::ByteStream& msg, ThreadParams* p);
void doAllocVBOID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetDBRootOfVBOID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetVBOIDToDBRootMap(messageqcpp::ByteStream& msg, ThreadParams* p);
/* Table lock interface */
boost::scoped_ptr<TableLockServer> tableLockServer;
void doGetTableLock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReleaseTableLock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doChangeTableLockState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doChangeTableLockOwner(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetAllTableLocks(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReleaseAllTableLocks(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetTableLockInfo(messageqcpp::ByteStream& msg, ThreadParams* p);
void doOwnerCheck(messageqcpp::ByteStream& msg, ThreadParams* p);
/* OID Manager interface */
OIDServer oids;
boost::mutex oidsMutex;
void doAllocOIDs(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReturnOIDs(messageqcpp::ByteStream& msg, ThreadParams* p);
void doOidmSize(messageqcpp::ByteStream& msg, ThreadParams* p);
void doAllocVBOID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetDBRootOfVBOID(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetVBOIDToDBRootMap(messageqcpp::ByteStream& msg, ThreadParams* p);
/* Autoincrement interface */
AutoincrementManager aiManager;
void doStartAISequence(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetAIRange(messageqcpp::ByteStream& msg, ThreadParams* p);
void doResetAISequence(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetAILock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReleaseAILock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doDeleteAISequence(messageqcpp::ByteStream& msg, ThreadParams* p);
/* Table lock interface */
boost::scoped_ptr<TableLockServer> tableLockServer;
void doGetTableLock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReleaseTableLock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doChangeTableLockState(messageqcpp::ByteStream& msg, ThreadParams* p);
void doChangeTableLockOwner(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetAllTableLocks(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReleaseAllTableLocks(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetTableLockInfo(messageqcpp::ByteStream& msg, ThreadParams* p);
void doOwnerCheck(messageqcpp::ByteStream& msg, ThreadParams* p);
messageqcpp::MessageQueueServer* dbrmServer;
std::vector<messageqcpp::MessageQueueClient*> slaves;
std::vector<messageqcpp::MessageQueueClient*>::iterator iSlave;
std::vector<messageqcpp::IOSocket*> activeSessions;
/* Autoincrement interface */
AutoincrementManager aiManager;
void doStartAISequence(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetAIRange(messageqcpp::ByteStream& msg, ThreadParams* p);
void doResetAISequence(messageqcpp::ByteStream& msg, ThreadParams* p);
void doGetAILock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doReleaseAILock(messageqcpp::ByteStream& msg, ThreadParams* p);
void doDeleteAISequence(messageqcpp::ByteStream& msg, ThreadParams* p);
LBIDResourceGraph* rg;
messageqcpp::MessageQueueServer* dbrmServer;
std::vector<messageqcpp::MessageQueueClient*> slaves;
std::vector<messageqcpp::MessageQueueClient*>::iterator iSlave;
std::vector<messageqcpp::IOSocket*> activeSessions;
LBIDResourceGraph* rg;
boost::mutex mutex;
boost::mutex mutex2; // protects params and the hand-off TODO: simplify
boost::mutex slaveLock; // syncs communication with the slaves
boost::mutex serverLock; // kludge to synchronize reloading
int runners, NumWorkers;
ThreadParams* params;
volatile bool die, halting;
bool reloadCmd;
mutable bool readOnly;
struct timespec MSG_TIMEOUT;
boost::mutex mutex;
boost::mutex mutex2; // protects params and the hand-off TODO: simplify
boost::mutex slaveLock; // syncs communication with the slaves
boost::mutex serverLock; // kludge to synchronize reloading
int runners, NumWorkers;
ThreadParams* params;
volatile bool die, halting;
bool reloadCmd;
mutable bool readOnly;
struct timespec MSG_TIMEOUT;
};
}
} // namespace BRM
#endif

View File

@ -24,7 +24,6 @@
* The executable source that runs a Master DBRM Node.
*/
#include "masterdbrmnode.h"
#include "liboamcpp.h"
#include <unistd.h>
@ -42,180 +41,174 @@
#define MAX_RETRIES 10
BRM::MasterDBRMNode* m;
bool die= false;
bool die = false;
using namespace std;
using namespace BRM;
class Opt
{
protected:
const char *m_progname;
bool m_fg;
public:
Opt(int argc, char **argv)
:m_progname(argv[0]),
m_fg(argc >= 2 && string(argv[1]) == "fg")
{ }
protected:
const char* m_progname;
bool m_fg;
public:
Opt(int argc, char** argv) : m_progname(argv[0]), m_fg(argc >= 2 && string(argv[1]) == "fg")
{
}
};
class ServiceControllerNode: public Service, public Opt
class ServiceControllerNode : public Service, public Opt
{
protected:
void setupChildSignalHandlers();
protected:
void setupChildSignalHandlers();
public:
ServiceControllerNode(const Opt &opt)
:Service("ControllerNode"), Opt(opt)
{ }
void LogErrno() override
{
perror(m_progname);
log_errno(std::string(m_progname));
}
void ParentLogChildMessage(const std::string &str) override
{
log(str, logging::LOG_TYPE_INFO);
}
int Child() override;
int Run()
{
return m_fg ? Child() : RunForking();
}
public:
ServiceControllerNode(const Opt& opt) : Service("ControllerNode"), Opt(opt)
{
}
void LogErrno() override
{
perror(m_progname);
log_errno(std::string(m_progname));
}
void ParentLogChildMessage(const std::string& str) override
{
log(str, logging::LOG_TYPE_INFO);
}
int Child() override;
int Run()
{
return m_fg ? Child() : RunForking();
}
};
void stop(int num)
{
#ifdef BRM_VERBOSE
std::cerr << "stopping..." << std::endl;
std::cerr << "stopping..." << std::endl;
#endif
die = true;
die = true;
if (m != NULL)
m->stop();
if (m != NULL)
m->stop();
}
void restart(int num)
{
#ifdef BRM_VERBOSE
std::cerr << "stopping this instance..." << std::endl;
std::cerr << "stopping this instance..." << std::endl;
#endif
if (m != NULL)
m->stop();
if (m != NULL)
m->stop();
}
/* doesn't quite work yet...
void reload(int num)
{
#ifdef BRM_VERBOSE
std::cerr << "reloading the config file" << std::endl;
std::cerr << "reloading the config file" << std::endl;
#endif
m->lock();
try {
m->reload();
}
catch (std::exception &e) {
m->setReadOnly(true);
std::cerr << "Reload failed. Check the config file. Reverting to read-only mode."
<< std::endl;
}
m->unlock();
m->lock();
try {
m->reload();
}
catch (std::exception &e) {
m->setReadOnly(true);
std::cerr << "Reload failed. Check the config file. Reverting to read-only mode."
<< std::endl;
}
m->unlock();
}
*/
void ServiceControllerNode::setupChildSignalHandlers()
{
/* XXXPAT: we might want to install signal handlers for every signal */
/* XXXPAT: we might want to install signal handlers for every signal */
signal(SIGINT, stop);
signal(SIGTERM, stop);
signal(SIGINT, stop);
signal(SIGTERM, stop);
#ifndef _MSC_VER
signal(SIGHUP, SIG_IGN);
signal(SIGUSR1, restart);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGUSR1, restart);
signal(SIGPIPE, SIG_IGN);
#endif
struct sigaction ign;
struct sigaction ign;
memset(&ign, 0, sizeof(ign));
ign.sa_handler = fatalHandler;
sigaction(SIGSEGV, &ign, 0);
sigaction(SIGABRT, &ign, 0);
sigaction(SIGFPE, &ign, 0);
memset(&ign, 0, sizeof(ign));
ign.sa_handler = fatalHandler;
sigaction(SIGSEGV, &ign, 0);
sigaction(SIGABRT, &ign, 0);
sigaction(SIGFPE, &ign, 0);
}
int ServiceControllerNode::Child()
{
int retries = 0;
int retries = 0;
(void)config::Config::makeConfig();
(void)config::Config::makeConfig();
setupChildSignalHandlers();
setupChildSignalHandlers();
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
m = NULL;
m = NULL;
while (retries < MAX_RETRIES && !die)
while (retries < MAX_RETRIES && !die)
{
try
{
try
{
if (m != NULL)
delete m;
if (m != NULL)
delete m;
m = new BRM::MasterDBRMNode();
m = new BRM::MasterDBRMNode();
NotifyServiceStarted();
NotifyServiceStarted();
m->run();
retries = 0;
delete m;
m = NULL;
}
catch (std::exception& e)
{
ostringstream os;
os << e.what();
os << "... attempt #" << retries + 1 << "/" << MAX_RETRIES << " to restart the DBRM controller node";
cerr << os.str() << endl;
log(os.str());
sleep(5);
}
retries++;
m->run();
retries = 0;
delete m;
m = NULL;
}
catch (std::exception& e)
{
ostringstream os;
os << e.what();
os << "... attempt #" << retries + 1 << "/" << MAX_RETRIES << " to restart the DBRM controller node";
cerr << os.str() << endl;
log(os.str());
sleep(5);
}
if (retries == MAX_RETRIES)
{
NotifyServiceInitializationFailed();
log(string("Exiting after too many errors"));
return 1;
}
retries++;
}
std::cerr << "Exiting..." << std::endl;
return 0;
if (retries == MAX_RETRIES)
{
NotifyServiceInitializationFailed();
log(string("Exiting after too many errors"));
return 1;
}
std::cerr << "Exiting..." << std::endl;
return 0;
}
int main(int argc, char** argv)
{
Opt opt(argc, argv);
// Set locale language
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
Opt opt(argc, argv);
// Set locale language
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
BRM::logInit ( BRM::SubSystemLogId_controllerNode );
BRM::logInit(BRM::SubSystemLogId_controllerNode);
/*
Need to shutdown TheadPool before fork(),
otherwise it would get stuck when trying to join fPruneThread.
*/
joblist::JobStep::jobstepThreadPool.stop();
/*
Need to shutdown TheadPool before fork(),
otherwise it would get stuck when trying to join fPruneThread.
*/
joblist::JobStep::jobstepThreadPool.stop();
return ServiceControllerNode(opt).Run();
return ServiceControllerNode(opt).Run();
}

View File

@ -51,7 +51,6 @@ using namespace BRM;
namespace BRM
{
/*static*/
boost::mutex MasterSegmentTableImpl::fInstanceMutex;
@ -61,208 +60,209 @@ MasterSegmentTableImpl* MasterSegmentTableImpl::fInstance = 0;
/*static*/
MasterSegmentTableImpl* MasterSegmentTableImpl::makeMasterSegmentTableImpl(int key, int size)
{
boost::mutex::scoped_lock lk(fInstanceMutex);
if (fInstance)
return fInstance;
fInstance = new MasterSegmentTableImpl(key, size);
boost::mutex::scoped_lock lk(fInstanceMutex);
if (fInstance)
return fInstance;
fInstance = new MasterSegmentTableImpl(key, size);
return fInstance;
}
MasterSegmentTableImpl::MasterSegmentTableImpl(int key, int size)
{
string keyName = ShmKeys::keyToName(key);
string keyName = ShmKeys::keyToName(key);
try
try
{
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
shm.truncate(size);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception& biex)
{
if (biex.get_error_code() == bi::already_exists_error)
{
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
shm.truncate(size);
try
{
bi::shared_memory_object shm(bi::open_only, keyName.c_str(), bi::read_write);
fShmobj.swap(shm);
}
catch (exception& e)
{
ostringstream o;
o << "BRM caught an exception attaching to a shared memory segment (" << keyName << "): " << e.what();
log(o.str());
throw;
}
}
catch (bi::interprocess_exception& biex)
else
{
if (biex.get_error_code() == bi::already_exists_error) {
try {
bi::shared_memory_object shm(bi::open_only, keyName.c_str(), bi::read_write);
fShmobj.swap(shm);
}
catch (exception &e) {
ostringstream o;
o << "BRM caught an exception attaching to a shared memory segment (" << keyName << "): " << e.what();
log(o.str());
throw;
}
}
else {
ostringstream o;
o << "BRM caught an exception creating a shared memory segment (" << keyName << "): " << biex.what();
log(o.str());
throw;
}
ostringstream o;
o << "BRM caught an exception creating a shared memory segment (" << keyName << "): " << biex.what();
log(o.str());
throw;
}
bi::mapped_region region(fShmobj, bi::read_write);
fMapreg.swap(region);
}
bi::mapped_region region(fShmobj, bi::read_write);
fMapreg.swap(region);
}
MSTEntry::MSTEntry() :
tableShmkey(-1),
allocdSize(0),
currentSize(0)
MSTEntry::MSTEntry() : tableShmkey(-1), allocdSize(0), currentSize(0)
{
}
MasterSegmentTable::MasterSegmentTable()
{
#ifdef _MSC_VER
const char* envp = getenv("SystemRoot");
string SystemRoot;
const char* envp = getenv("SystemRoot");
string SystemRoot;
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
#endif
int i;
bool initializer = false;
int i;
bool initializer = false;
RWLockKeys[0] = fShmKeys.KEYRANGE_EXTENTMAP_BASE;
RWLockKeys[1] = fShmKeys.KEYRANGE_EMFREELIST_BASE;
RWLockKeys[2] = fShmKeys.KEYRANGE_VBBM_BASE;
RWLockKeys[3] = fShmKeys.KEYRANGE_VSS_BASE;
RWLockKeys[4] = fShmKeys.KEYRANGE_CL_BASE;
RWLockKeys[0] = fShmKeys.KEYRANGE_EXTENTMAP_BASE;
RWLockKeys[1] = fShmKeys.KEYRANGE_EMFREELIST_BASE;
RWLockKeys[2] = fShmKeys.KEYRANGE_VBBM_BASE;
RWLockKeys[3] = fShmKeys.KEYRANGE_VSS_BASE;
RWLockKeys[4] = fShmKeys.KEYRANGE_CL_BASE;
try
{
// if initializer is returned false, then this is not the first time for this key.
rwlock[0].reset(new RWLock(RWLockKeys[0], &initializer));
}
catch (exception& e)
{
cerr << "ControllerSegmentTable: RWLock() threw: " << e.what() << endl;
throw;
}
try
{
// if initializer is returned false, then this is not the first time for this key.
rwlock[0].reset(new RWLock(RWLockKeys[0], &initializer));
}
catch (exception& e)
{
cerr << "ControllerSegmentTable: RWLock() threw: " << e.what() << endl;
throw;
}
if (rwlock[0] == NULL)
{
cerr << "ControllerSegmentTable(): RWLock() failed..?" << endl;
throw runtime_error("ControllerSegmentTable(): RWLock() failed..?");
}
if (rwlock[0] == NULL)
{
cerr << "ControllerSegmentTable(): RWLock() failed..?" << endl;
throw runtime_error("ControllerSegmentTable(): RWLock() failed..?");
}
for (i = 1; i < nTables; i++)
rwlock[i].reset(new RWLock(RWLockKeys[i]));
for (i = 1; i < nTables; i++)
rwlock[i].reset(new RWLock(RWLockKeys[i]));
makeMSTSegment();
makeMSTSegment();
if (initializer)
{
initMSTData();
rwlock[0]->write_unlock();
}
else
{
rwlock[0]->read_lock_priority(); // this is to synch with the initializer
rwlock[0]->read_unlock();
}
if (initializer)
{
initMSTData();
rwlock[0]->write_unlock();
}
else
{
rwlock[0]->read_lock_priority(); // this is to synch with the initializer
rwlock[0]->read_unlock();
}
}
MasterSegmentTable::~MasterSegmentTable()
{
// int i;
// int i;
// for (i = 0; i < nTables; i++)
// delete rwlock[i];
// for (i = 0; i < nTables; i++)
// delete rwlock[i];
}
void MasterSegmentTable::makeMSTSegment()
{
fPImpl = MasterSegmentTableImpl::makeMasterSegmentTableImpl(fShmKeys.MST_SYSVKEY, MSTshmsize);
fShmDescriptors = static_cast<MSTEntry*>(fPImpl->fMapreg.get_address());
fPImpl = MasterSegmentTableImpl::makeMasterSegmentTableImpl(fShmKeys.MST_SYSVKEY, MSTshmsize);
fShmDescriptors = static_cast<MSTEntry*>(fPImpl->fMapreg.get_address());
}
void MasterSegmentTable::initMSTData()
{
void *dp = static_cast<void*>(&fShmDescriptors);
memset(dp, 0, MSTshmsize);
void* dp = static_cast<void*>(&fShmDescriptors);
memset(dp, 0, MSTshmsize);
}
MSTEntry* MasterSegmentTable::getTable_read(int num, bool block) const
{
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_read()");
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_read()");
if (!block)
try
{
rwlock[num]->read_lock(false);
}
catch (rwlock::wouldblock& e)
{
return NULL;
}
else
rwlock[num]->read_lock();
if (!block)
try
{
rwlock[num]->read_lock(false);
}
catch (rwlock::wouldblock& e)
{
return NULL;
}
else
rwlock[num]->read_lock();
return &fShmDescriptors[num];
return &fShmDescriptors[num];
}
MSTEntry* MasterSegmentTable::getTable_write(int num, bool block) const
{
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_write()");
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_write()");
if (!block)
try
{
rwlock[num]->write_lock(false);
}
catch (rwlock::wouldblock& e)
{
return NULL;
}
else
rwlock[num]->write_lock();
if (!block)
try
{
rwlock[num]->write_lock(false);
}
catch (rwlock::wouldblock& e)
{
return NULL;
}
else
rwlock[num]->write_lock();
return &fShmDescriptors[num];
return &fShmDescriptors[num];
}
void MasterSegmentTable::getTable_upgrade(int num) const
{
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_upgrade()");
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_upgrade()");
rwlock[num]->upgrade_to_write();
rwlock[num]->upgrade_to_write();
}
void MasterSegmentTable::getTable_downgrade(int num) const
{
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_downgrade()");
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_downgrade()");
rwlock[num]->downgrade_to_read();
rwlock[num]->downgrade_to_read();
}
void MasterSegmentTable::releaseTable_read(int num) const
{
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
rwlock[num]->read_unlock();
rwlock[num]->read_unlock();
}
void MasterSegmentTable::releaseTable_write(int num) const
{
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
rwlock[num]->write_unlock();
rwlock[num]->write_unlock();
}
} //namespace
} // namespace BRM

View File

@ -52,40 +52,39 @@
namespace BRM
{
struct MSTEntry
{
key_t tableShmkey;
int allocdSize;
int currentSize;
EXPORT MSTEntry();
key_t tableShmkey;
int allocdSize;
int currentSize;
EXPORT MSTEntry();
};
class MasterSegmentTableImpl
{
public:
~MasterSegmentTableImpl(){};
static MasterSegmentTableImpl* makeMasterSegmentTableImpl(int key, int size);
public:
~MasterSegmentTableImpl(){};
static MasterSegmentTableImpl* makeMasterSegmentTableImpl(int key, int size);
static void refreshShm()
static void refreshShm()
{
if (fInstance)
{
if (fInstance)
{
delete fInstance;
fInstance = NULL;
}
delete fInstance;
fInstance = NULL;
}
boost::interprocess::shared_memory_object fShmobj;
boost::interprocess::mapped_region fMapreg;
private:
MasterSegmentTableImpl(int key, int size);
MasterSegmentTableImpl(const MasterSegmentTableImpl& rhs);
MasterSegmentTableImpl& operator=(const MasterSegmentTableImpl& rhs);
}
static boost::mutex fInstanceMutex;
static MasterSegmentTableImpl* fInstance;
boost::interprocess::shared_memory_object fShmobj;
boost::interprocess::mapped_region fMapreg;
private:
MasterSegmentTableImpl(int key, int size);
MasterSegmentTableImpl(const MasterSegmentTableImpl& rhs);
MasterSegmentTableImpl& operator=(const MasterSegmentTableImpl& rhs);
static boost::mutex fInstanceMutex;
static MasterSegmentTableImpl* fInstance;
};
/** @brief This class regulates access to the BRM tables in shared memory
@ -94,122 +93,122 @@ private:
*/
class MasterSegmentTable
{
public:
/** @brief Constructor.
* @note Throws runtime_error on a semaphore-related error.
*/
EXPORT MasterSegmentTable();
EXPORT ~MasterSegmentTable();
public:
/** @brief Constructor.
* @note Throws runtime_error on a semaphore-related error.
*/
EXPORT MasterSegmentTable();
EXPORT ~MasterSegmentTable();
/// specifies the Extent Map table
static const int EMTable = 0;
/// specifies the Extent Map's Freelist table
static const int EMFreeList = 1;
/// specifies the Version Buffer Block Map segment
static const int VBBMSegment = 2;
/// specifies the Version Substitution Structure segment
static const int VSSSegment = 3;
/// specifies the copy lock segment
static const int CLSegment = 4;
/// the number of tables currently defined
static const int nTables = 5;
/// specifies the Extent Map table
static const int EMTable = 0;
/// specifies the Extent Map's Freelist table
static const int EMFreeList = 1;
/// specifies the Version Buffer Block Map segment
static const int VBBMSegment = 2;
/// specifies the Version Substitution Structure segment
static const int VSSSegment = 3;
/// specifies the copy lock segment
static const int CLSegment = 4;
/// the number of tables currently defined
static const int nTables = 5;
/** @brief This function gets the specified table.
*
* This function gets the specified table and grabs the
* associated read lock.
* @param num EMTable, EMFreeList, or VBBMTable
* @param block If false, it won't block.
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
* @return If block == true, it always returns the specified MSTEntry;
* if block == false, it can also return NULL if it could not grab
* the table's lock.
*/
EXPORT MSTEntry* getTable_read(int num, bool block = true) const;
/** @brief This function gets the specified table.
*
* This function gets the specified table and grabs the
* associated read lock.
* @param num EMTable, EMFreeList, or VBBMTable
* @param block If false, it won't block.
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
* @return If block == true, it always returns the specified MSTEntry;
* if block == false, it can also return NULL if it could not grab
* the table's lock.
*/
EXPORT MSTEntry* getTable_read(int num, bool block = true) const;
/** @brief This function gets the specified table.
*
* This function gets the specified table and grabs the
* associated write lock.
* @param num EMTable, EMFreeList, or VBBMTable
* @param block If false, it won't block.
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
* @return If block == true, it always returns the specified MSTEntry;
* if block == false, it can also return NULL if it could not grab
* the table's lock.
*/
EXPORT MSTEntry* getTable_write(int num, bool block = true) const;
/** @brief This function gets the specified table.
*
* This function gets the specified table and grabs the
* associated write lock.
* @param num EMTable, EMFreeList, or VBBMTable
* @param block If false, it won't block.
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
* @return If block == true, it always returns the specified MSTEntry;
* if block == false, it can also return NULL if it could not grab
* the table's lock.
*/
EXPORT MSTEntry* getTable_write(int num, bool block = true) const;
/** @brief Upgrade a read lock to a write lock.
*
* Upgrade a read lock to a write lock. This is not an atomic
* operation.
* @param num The table the caller holds the read lock to.
*/
EXPORT void getTable_upgrade(int num) const;
/** @brief Upgrade a read lock to a write lock.
*
* Upgrade a read lock to a write lock. This is not an atomic
* operation.
* @param num The table the caller holds the read lock to.
*/
EXPORT void getTable_upgrade(int num) const;
/** @brief Downgrade a write lock to a read lock.
*
* Downgrade a write lock to a read lock. This is an atomic
* operation.
* @param num The table the caller holds the write lock to.
*/
EXPORT void getTable_downgrade(int num) const;
/** @brief Downgrade a write lock to a read lock.
*
* Downgrade a write lock to a read lock. This is an atomic
* operation.
* @param num The table the caller holds the write lock to.
*/
EXPORT void getTable_downgrade(int num) const;
/** @brief This function unlocks the specified table.
*
* This function unlocks the specified table.
*
* @param num EMTable, EMFreeList, or VBBMTable
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
*/
EXPORT void releaseTable_read(int num) const;
/** @brief This function unlocks the specified table.
*
* This function unlocks the specified table.
*
* @param num EMTable, EMFreeList, or VBBMTable
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
*/
EXPORT void releaseTable_read(int num) const;
/** @brief This function unlocks the specified table.
*
* This function unlocks the specified table.
*
* @param num EMTable, EMFreeList, or VBBMTable
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
*/
EXPORT void releaseTable_write(int num) const;
/** @brief This function unlocks the specified table.
*
* This function unlocks the specified table.
*
* @param num EMTable, EMFreeList, or VBBMTable
* @note throws invalid_argument if num is outside the valid range
* and runtime_error on a semaphore-related error.
*/
EXPORT void releaseTable_write(int num) const;
/** @brief This function gets the current VSS key out of shared memory without locking
*
* This function gets the current VSS key out of shared memory without any locking. It is used
* (eventually) by DBRM::vssLookup() to try and correctly & efficiently short-circuit a vss
* lookup when there are no locked blocks in the vss. This read should be atomic. Even if it's
* not, we should still be okay.
*/
inline key_t getVSSShmkey() const
{
return fShmDescriptors[VSSSegment].tableShmkey;
}
/** @brief This function gets the current VSS key out of shared memory without locking
*
* This function gets the current VSS key out of shared memory without any locking. It is used
* (eventually) by DBRM::vssLookup() to try and correctly & efficiently short-circuit a vss
* lookup when there are no locked blocks in the vss. This read should be atomic. Even if it's
* not, we should still be okay.
*/
inline key_t getVSSShmkey() const
{
return fShmDescriptors[VSSSegment].tableShmkey;
}
private:
MasterSegmentTable(const MasterSegmentTable& mst);
MasterSegmentTable& operator=(const MasterSegmentTable& mst);
private:
MasterSegmentTable(const MasterSegmentTable& mst);
MasterSegmentTable& operator=(const MasterSegmentTable& mst);
int shmid;
mutable boost::scoped_ptr<rwlock::RWLock> rwlock[nTables];
int shmid;
mutable boost::scoped_ptr<rwlock::RWLock> rwlock[nTables];
static const int MSTshmsize = nTables * sizeof(MSTEntry);
int RWLockKeys[nTables];
static const int MSTshmsize = nTables * sizeof(MSTEntry);
int RWLockKeys[nTables];
/// indexed by EMTable, EMFreeList, and VBBMTable
MSTEntry* fShmDescriptors;
/// indexed by EMTable, EMFreeList, and VBBMTable
MSTEntry* fShmDescriptors;
void makeMSTSegment();
void initMSTData();
ShmKeys fShmKeys;
MasterSegmentTableImpl* fPImpl;
void makeMSTSegment();
void initMSTData();
ShmKeys fShmKeys;
MasterSegmentTableImpl* fPImpl;
};
} //namespace
} // namespace BRM
#undef EXPORT

File diff suppressed because it is too large Load Diff

View File

@ -45,10 +45,8 @@ namespace idbdatafile
class IDBDataFile;
}
namespace BRM
{
/** @brief The class that manages the Object ID space
*
* The class that manages the allocation and deallocation of IDs
@ -56,159 +54,158 @@ namespace BRM
*/
class OIDServer
{
private:
struct FEntry
{
int begin, end;
};
private:
struct FEntry
{
int begin, end;
};
public:
/** @brief Default constructor
*
* @note Throws ios::failure on a file IO error
*/
EXPORT OIDServer();
EXPORT virtual ~OIDServer();
public:
/** @brief Default constructor
*
* @note Throws ios::failure on a file IO error
*/
EXPORT OIDServer();
EXPORT virtual ~OIDServer();
/** @brief Allocate a contiguous range of Object IDs
*
* @param num The number of contiguous Object IDs to allocate
* @return The first OID allocated on success, -1 on failure
*/
EXPORT int allocOIDs(int num);
/** @brief Allocate a contiguous range of Object IDs
*
* @param num The number of contiguous Object IDs to allocate
* @return The first OID allocated on success, -1 on failure
*/
EXPORT int allocOIDs(int num);
/** @brief Allocates a single OID for a version buffer file, given its dbroot
*
* A new requirement in the shared nothing implementation is for version buffer
* files to be anchored to a specific dbroot. This association is stored on disk as
* an array of uint16s. Version buffer OIDs use 0-999, so the 0th offset in the
* array is the dbroot of the OID 0, and so on.
*/
EXPORT int allocVBOID(uint16_t dbroot);
/** @brief Allocates a single OID for a version buffer file, given its dbroot
*
* A new requirement in the shared nothing implementation is for version buffer
* files to be anchored to a specific dbroot. This association is stored on disk as
* an array of uint16s. Version buffer OIDs use 0-999, so the 0th offset in the
* array is the dbroot of the OID 0, and so on.
*/
EXPORT int allocVBOID(uint16_t dbroot);
/** @brief Returns the DBRoot of the given version buffer file.
*
*/
EXPORT int getDBRootOfVBOID(uint32_t vbOID);
/** @brief Returns the DBRoot of the given version buffer file.
*
*/
EXPORT int getDBRootOfVBOID(uint32_t vbOID);
/** @brief Returns the VB OID of the given DB root.
*
*/
EXPORT int getVBOIDOfDBRoot(uint32_t vbOID);
/** @brief Returns the VB OID of the given DB root.
*
*/
EXPORT int getVBOIDOfDBRoot(uint32_t vbOID);
/** @brief Returns the whole VB OID -> DBRoot mapping. The returned vector is indexed by VB OID.
*
*/
EXPORT const std::vector<uint16_t>& getVBOIDToDBRootMap();
/** @brief Returns the whole VB OID -> DBRoot mapping. The returned vector is indexed by VB OID.
*
*/
EXPORT const std::vector<uint16_t>& getVBOIDToDBRootMap();
/** @brief Return a list of OIDs to the pool
*
* @param start The first OID to return
* @param end The last OID to return
*/
EXPORT void returnOIDs(int start, int end) const;
/** @brief Return a list of OIDs to the pool
*
* @param start The first OID to return
* @param end The last OID to return
*/
EXPORT void returnOIDs(int start, int end) const;
/** @brief Counts the number of allocated OIDs
*
* @note This currently assumes the bitmap length is a multiple of 4096
* @return The number of allocated OIDs
*/
EXPORT int size() const;
/** @brief Counts the number of allocated OIDs
*
* @note This currently assumes the bitmap length is a multiple of 4096
* @return The number of allocated OIDs
*/
EXPORT int size() const;
/** @brief Get the OID bitmap filename
*/
const std::string getFilename() const;
/** @brief Get the OID bitmap filename
*/
const std::string getFilename() const;
private:
std::string fFilename;
static const int FreeListEntries = 256;
static const int HeaderSize = FreeListEntries * sizeof(FEntry);
static const int StartOfVBOidSection = HeaderSize + 2097152; // (2^24/8)
static const int MaxRetries = 10; /// max number of retries on file operations
static boost::mutex fMutex;
idbdatafile::IDBDataFile* fFp;
int fFd; /// file descriptor referencing the bitmap file
std::vector<uint16_t> vbOidDBRootMap;
private:
std::string fFilename;
static const int FreeListEntries = 256;
static const int HeaderSize = FreeListEntries * sizeof(FEntry);
static const int StartOfVBOidSection = HeaderSize + 2097152; // (2^24/8)
static const int MaxRetries = 10; /// max number of retries on file operations
static boost::mutex fMutex;
idbdatafile::IDBDataFile* fFp;
int fFd; /// file descriptor referencing the bitmap file
std::vector<uint16_t> vbOidDBRootMap;
/** @brief Grab the file lock
*
* Grab the file lock.
* @note Throws ios::failure after MaxRetries hard errors
*/
// void lockFile() const;
/** @brief Grab the file lock
*
* Grab the file lock.
* @note Throws ios::failure after MaxRetries hard errors
*/
//void lockFile() const;
/** @brief Reliably reads data from the bitmap file
*
* Reliably reads data from the bitmap file.
* @note Throws ios::failure after MaxRetries hard errors
* @note Caller is responsible for locking & unlocking
* @param buf the buffer to read into
* @param offset the offset to start reading at
* @param size the number of bytes to read into buf
*/
void readData(uint8_t* buf, off_t offset, int size) const;
/** @brief Reliably reads data from the bitmap file
*
* Reliably reads data from the bitmap file.
* @note Throws ios::failure after MaxRetries hard errors
* @note Caller is responsible for locking & unlocking
* @param buf the buffer to read into
* @param offset the offset to start reading at
* @param size the number of bytes to read into buf
*/
void readData(uint8_t* buf, off_t offset, int size) const;
/** @brief Reliably writes data to the bitmap file
*
* Reliably write data to the bitmap file.
* @note Throws ios::failure after MaxRetries hard errors
* @note Caller is responsible for locking & unlocking
* @param buf the data to write
* @param offset the offset to start writing at
* @param size the number of bytes to write
*/
void writeData(uint8_t* buf, off_t offset, int size) const;
/** @brief Reliably writes data to the bitmap file
*
* Reliably write data to the bitmap file.
* @note Throws ios::failure after MaxRetries hard errors
* @note Caller is responsible for locking & unlocking
* @param buf the data to write
* @param offset the offset to start writing at
* @param size the number of bytes to write
*/
void writeData(uint8_t* buf, off_t offset, int size) const;
/** @brief If there is no bitmap file yet, this is used to make one
*
* If there is no bitmap file yet, this is used to make one.
* @note It assumes no OIDs are allocated, we may want
* to fully rebuild it from actual DB contents instead.
*/
void initializeBitmap() const;
/** @brief If there is no bitmap file yet, this is used to make one
*
* If there is no bitmap file yet, this is used to make one.
* @note It assumes no OIDs are allocated, we may want
* to fully rebuild it from actual DB contents instead.
*/
void initializeBitmap() const;
/** @brief Allocates OIDs using a designated freelist entry
*
* Allocates OIDs using a designated freelist entry
* @param fe The freelist entry to use.
* @param num The number of OIDs to allocate from that block
*/
void useFreeListEntry(struct FEntry& fe, int num);
/** @brief Allocates OIDs using a designated freelist entry
*
* Allocates OIDs using a designated freelist entry
* @param fe The freelist entry to use.
* @param num The number of OIDs to allocate from that block
*/
void useFreeListEntry(struct FEntry& fe, int num);
/** @brief This allocates or deallocates a block of OIDs
*
* This allocates or deallocates a block of OIDs
* @param start The first OID to alloc/dealloc
* @param end The number of OIDs to flip
* @param mode mode = 0 means 'allocate', mode = 1 means 'deallocate'
*/
void flipOIDBlock(int start, int num, int mode) const;
/** @brief This allocates or deallocates a block of OIDs
*
* This allocates or deallocates a block of OIDs
* @param start The first OID to alloc/dealloc
* @param end The number of OIDs to flip
* @param mode mode = 0 means 'allocate', mode = 1 means 'deallocate'
*/
void flipOIDBlock(int start, int num, int mode) const;
/** @brief This scans the whole bitmap for a block of free OIDs
*
* This scans the whole bitmap for a block of free OIDs
* @param num the size of the block to locate
* @param freelist the freelist
* @return The first OID of the block allocated, or -1 if there is no match
*/
int fullScan(int num, struct FEntry* freelist) const;
/** @brief This scans the whole bitmap for a block of free OIDs
*
* This scans the whole bitmap for a block of free OIDs
* @param num the size of the block to locate
* @param freelist the freelist
* @return The first OID of the block allocated, or -1 if there is no match
*/
int fullScan(int num, struct FEntry* freelist) const;
/** @brief This is used by allocOIDs to fix the freelist after a full scan
*
* This is used by fullScan to fix the freelist before an allocation
* @param freelist The freelist
* @param start The first OID of the block allocated by fullScan
* @param num The number of OIDs allocated
* @note At the moment it throws logic_error if it detects a specific error in
* fullscan
*/
void patchFreelist(struct FEntry* freelist, int start, int num) const;
/** @brief This is used by allocOIDs to fix the freelist after a full scan
*
* This is used by fullScan to fix the freelist before an allocation
* @param freelist The freelist
* @param start The first OID of the block allocated by fullScan
* @param num The number of OIDs allocated
* @note At the moment it throws logic_error if it detects a specific error in
* fullscan
*/
void patchFreelist(struct FEntry* freelist, int start, int num) const;
void loadVBOIDs();
void loadVBOIDs();
};
} // namespace
} // namespace BRM
#undef EXPORT

View File

@ -18,7 +18,6 @@
// $Id: reset_locks.cpp 1823 2013-01-21 14:13:09Z rdempsey $
//
#include <unistd.h>
#include <iostream>
using namespace std;
@ -34,15 +33,21 @@ using namespace rwlock;
using namespace BRM;
#define RESET(str, i) \
do { cout << " - checking " << str << " semaphore" << endl; \
rwlock[i]->reset(); } while (0)
#define RESET(str, i) \
do \
{ \
cout << " - checking " << str << " semaphore" << endl; \
rwlock[i]->reset(); \
} while (0)
#define PRINT(str, i) \
do { cout << " - checking " << str << " semaphore" << endl \
<< " - r: " << rwlock[i]->getReading() << " w: " \
<< rwlock[i]->getWriting() << " rwt: " << rwlock[i]->getReadersWaiting() \
<< " wwt: " << rwlock[i]->getWritersWaiting() << endl; } while (0)
#define PRINT(str, i) \
do \
{ \
cout << " - checking " << str << " semaphore" << endl \
<< " - r: " << rwlock[i]->getReading() << " w: " << rwlock[i]->getWriting() \
<< " rwt: " << rwlock[i]->getReadersWaiting() << " wwt: " << rwlock[i]->getWritersWaiting() \
<< endl; \
} while (0)
namespace
{
@ -52,126 +57,119 @@ bool sFlg;
void usage()
{
cout << "usage: reset_locks [-vnh]" << endl;
cout << " reset all ColumnStore shared memory locks" << endl;
cout << " -h display this help" << endl;
cout << " -v verbose output" << endl;
cout << " -s skip session mgr resets" << endl;
cout << " -n don't actually reset anything (implies -v)" << endl;
}
cout << "usage: reset_locks [-vnh]" << endl;
cout << " reset all ColumnStore shared memory locks" << endl;
cout << " -h display this help" << endl;
cout << " -v verbose output" << endl;
cout << " -s skip session mgr resets" << endl;
cout << " -n don't actually reset anything (implies -v)" << endl;
}
} // namespace
int main(int argc, char** argv)
{
#ifdef _MSC_VER
const char* envp = getenv("SystemRoot");
string SystemRoot;
const char* envp = getenv("SystemRoot");
string SystemRoot;
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
#endif
BRM::DBRM dbrm;
BRM::DBRM dbrm;
int c;
opterr = 0;
vFlg = false;
nFlg = false;
sFlg = false;
int c;
opterr = 0;
vFlg = false;
nFlg = false;
sFlg = false;
while ((c = getopt(argc, argv, "vnh")) != EOF)
switch (c)
while ((c = getopt(argc, argv, "vnh")) != EOF)
switch (c)
{
case 'v': vFlg = true; break;
case 'n': nFlg = true; break;
case 's': sFlg = true; break;
case 'h':
default:
usage();
return (c == 'h' ? 0 : 1);
break;
}
if (nFlg)
vFlg = true;
ShmKeys keys;
cerr << "(Exception msgs are probably OK)" << std::endl;
RWLock* rwlock[MasterSegmentTable::nTables];
int RWLockKeys[MasterSegmentTable::nTables];
int i;
if (MasterSegmentTable::nTables != 5)
{
cout << "There are more locks than reset_locks knows of. Time for an update." << endl;
exit(1);
}
RWLockKeys[0] = keys.KEYRANGE_EXTENTMAP_BASE;
RWLockKeys[1] = keys.KEYRANGE_EMFREELIST_BASE;
RWLockKeys[2] = keys.KEYRANGE_VBBM_BASE;
RWLockKeys[3] = keys.KEYRANGE_VSS_BASE;
RWLockKeys[4] = keys.KEYRANGE_CL_BASE;
for (i = 0; i < MasterSegmentTable::nTables; i++)
rwlock[i] = new RWLock(RWLockKeys[i]);
if (vFlg)
{
PRINT("Extent Map", 0);
PRINT("Extent Map free list", 1);
PRINT("VBBM", 2);
PRINT("VSS", 3);
PRINT("CL", 4);
}
if (!nFlg)
{
RESET("Extent Map", 0);
RESET("Extent Map free list", 1);
RESET("VBBM", 2);
RESET("VSS", 3);
RESET("CL", 4);
if (!sFlg)
{
if (dbrm.isDBRMReady())
{
cout << " - resetting SessionManager semaphore" << endl;
try
{
case 'v':
vFlg = true;
break;
case 'n':
nFlg = true;
break;
case 's':
sFlg = true;
break;
case 'h':
default:
usage();
return (c == 'h' ? 0 : 1);
break;
execplan::SessionManager sm;
sm.reset();
}
if (nFlg)
vFlg = true;
ShmKeys keys;
cerr << "(Exception msgs are probably OK)" << std::endl;
RWLock* rwlock[MasterSegmentTable::nTables];
int RWLockKeys[MasterSegmentTable::nTables];
int i;
if (MasterSegmentTable::nTables != 5)
{
cout << "There are more locks than reset_locks knows of. Time for an update." << endl;
exit(1);
}
RWLockKeys[0] = keys.KEYRANGE_EXTENTMAP_BASE;
RWLockKeys[1] = keys.KEYRANGE_EMFREELIST_BASE;
RWLockKeys[2] = keys.KEYRANGE_VBBM_BASE;
RWLockKeys[3] = keys.KEYRANGE_VSS_BASE;
RWLockKeys[4] = keys.KEYRANGE_CL_BASE;
for (i = 0; i < MasterSegmentTable::nTables; i++)
rwlock[i] = new RWLock(RWLockKeys[i]);
if (vFlg)
{
PRINT("Extent Map", 0);
PRINT("Extent Map free list", 1);
PRINT("VBBM", 2);
PRINT("VSS", 3);
PRINT("CL", 4);
}
if (!nFlg)
{
RESET("Extent Map", 0);
RESET("Extent Map free list", 1);
RESET("VBBM", 2);
RESET("VSS", 3);
RESET("CL", 4);
if (!sFlg)
catch (std::exception& e)
{
if (dbrm.isDBRMReady())
{
cout << " - resetting SessionManager semaphore" << endl;
try
{
execplan::SessionManager sm;
sm.reset();
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
}
std::cout << e.what() << std::endl;
}
}
}
}
for (i = 0; i < MasterSegmentTable::nTables; i++)
delete rwlock[i];
for (i = 0; i < MasterSegmentTable::nTables; i++)
delete rwlock[i];
std::cout << "OK." << std::endl;
return 0;
std::cout << "OK." << std::endl;
return 0;
}

View File

@ -6,9 +6,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -29,7 +29,6 @@ using namespace std;
namespace BRM
{
ResourceNode::ResourceNode() : _lbid(0)
{
}
@ -48,48 +47,47 @@ ResourceNode::~ResourceNode()
ResourceNode& ResourceNode::operator=(const ResourceNode& n)
{
static_cast<RGNode&>(*this) = static_cast<const RGNode&>(n);
_lbid = n._lbid;
return *this;
static_cast<RGNode&>(*this) = static_cast<const RGNode&>(n);
_lbid = n._lbid;
return *this;
}
bool ResourceNode::operator==(const ResourceNode& n) const
{
return (_lbid == n._lbid);
return (_lbid == n._lbid);
}
bool ResourceNode::operator==(LBID_t l) const
{
return (_lbid == l);
return (_lbid == l);
}
bool ResourceNode::operator<(const ResourceNode& n) const
{
return (_lbid < n._lbid);
return (_lbid < n._lbid);
}
LBID_t ResourceNode::lbid() const
{
return _lbid;
return _lbid;
}
void ResourceNode::wakeAndDetach()
{
TransactionNode* txn;
set<RGNode*>::iterator sit;
set<RGNode*>::iterator dummy_sit;
TransactionNode* txn;
set<RGNode*>::iterator sit;
set<RGNode*>::iterator dummy_sit;
for (sit = in.begin(); sit != in.end(); )
{
txn = dynamic_cast<TransactionNode*>(*sit);
txn->wake();
dummy_sit = ++sit;
removeInEdge(txn);
sit = dummy_sit;
}
in.clear();
}
for (sit = in.begin(); sit != in.end();)
{
txn = dynamic_cast<TransactionNode*>(*sit);
txn->wake();
dummy_sit = ++sit;
removeInEdge(txn);
sit = dummy_sit;
}
in.clear();
}
} // namespace BRM

View File

@ -37,53 +37,53 @@
namespace BRM
{
class ResourceNode : public RGNode
{
public:
EXPORT ResourceNode();
EXPORT ResourceNode(const ResourceNode&);
EXPORT ResourceNode(LBID_t);
EXPORT virtual ~ResourceNode();
public:
EXPORT ResourceNode();
EXPORT ResourceNode(const ResourceNode&);
EXPORT ResourceNode(LBID_t);
EXPORT virtual ~ResourceNode();
EXPORT ResourceNode& operator=(const ResourceNode&);
EXPORT bool operator==(const ResourceNode&) const;
EXPORT bool operator==(LBID_t) const;
EXPORT bool operator<(const ResourceNode&) const;
EXPORT ResourceNode& operator=(const ResourceNode&);
EXPORT bool operator==(const ResourceNode&) const;
EXPORT bool operator==(LBID_t) const;
EXPORT bool operator<(const ResourceNode&) const;
EXPORT void wakeAndDetach();
EXPORT void wakeAndDetach();
EXPORT LBID_t lbid() const;
private:
LBID_t _lbid;
EXPORT LBID_t lbid() const;
private:
LBID_t _lbid;
};
template<typename T>
template <typename T>
struct RNLess
{
bool operator()(const T& x, const T& y) const
{
return *x < *y;
}
bool operator()(const T& x, const T& y) const
{
return *x < *y;
}
};
struct RNHasher
{
size_t operator()(const ResourceNode* x) const
{
return x->lbid();
}
size_t operator()(const ResourceNode* x) const
{
return x->lbid();
}
};
struct RNEquals
{
bool operator()(const ResourceNode* x, const ResourceNode* y) const
{
return *x == *y;
}
bool operator()(const ResourceNode* x, const ResourceNode* y) const
{
return *x == *y;
}
};
}
} // namespace BRM
#undef EXPORT

View File

@ -28,7 +28,6 @@ using namespace std;
namespace BRM
{
RGNode::RGNode() : _color(0)
{
}
@ -39,62 +38,61 @@ RGNode::RGNode(const RGNode& n) : out(n.out), in(n.in), _color(n._color)
RGNode::~RGNode()
{
set<RGNode*>::iterator it;
set<RGNode*>::iterator it;
for (it = in.begin(); it != in.end(); )
{
(*it)->out.erase(this);
in.erase(it++);
}
for (it = out.begin(); it != out.end(); )
{
(*it)->in.erase(this);
out.erase(it++);
}
for (it = in.begin(); it != in.end();)
{
(*it)->out.erase(this);
in.erase(it++);
}
for (it = out.begin(); it != out.end();)
{
(*it)->in.erase(this);
out.erase(it++);
}
}
RGNode& RGNode::operator=(const RGNode& n)
{
_color = n._color;
in = n.in;
out = n.out;
return *this;
_color = n._color;
in = n.in;
out = n.out;
return *this;
}
uint64_t RGNode::color() const
{
return _color;
return _color;
}
void RGNode::color(uint64_t c)
{
_color = c;
_color = c;
}
void RGNode::addOutEdge(RGNode* n)
{
out.insert(n);
n->in.insert(this);
out.insert(n);
n->in.insert(this);
}
void RGNode::addInEdge(RGNode* n)
{
in.insert(n);
n->out.insert(this);
in.insert(n);
n->out.insert(this);
}
void RGNode::removeOutEdge(RGNode* n)
{
out.erase(n);
n->in.erase(this);
out.erase(n);
n->in.erase(this);
}
void RGNode::removeInEdge(RGNode* n)
{
in.erase(n);
n->out.erase(this);
in.erase(n);
n->out.erase(this);
}
} // namespace
} // namespace BRM

View File

@ -39,38 +39,37 @@
namespace BRM
{
class RGNode;
class RGNode
{
public:
EXPORT RGNode();
EXPORT RGNode(const RGNode&);
EXPORT virtual ~RGNode();
public:
EXPORT RGNode();
EXPORT RGNode(const RGNode&);
EXPORT virtual ~RGNode();
EXPORT RGNode& operator=(const RGNode&);
EXPORT RGNode& operator=(const RGNode&);
EXPORT uint64_t color() const;
EXPORT void color(uint64_t);
EXPORT void addOutEdge(RGNode*);
EXPORT void addInEdge(RGNode*);
EXPORT void removeOutEdge(RGNode*);
EXPORT void removeInEdge(RGNode*);
EXPORT uint64_t color() const;
EXPORT void color(uint64_t);
EXPORT void addOutEdge(RGNode*);
EXPORT void addInEdge(RGNode*);
EXPORT void removeOutEdge(RGNode*);
EXPORT void removeInEdge(RGNode*);
friend class LBIDResourceGraph;
friend class LBIDResourceGraph;
protected:
// adjacency lists. Technically these should be private, but ResourceNode
// currently uses them to wake connected transactions. TBD...
std::set<RGNode*> out;
std::set<RGNode*> in;
protected:
// adjacency lists. Technically these should be private, but ResourceNode
// currently uses them to wake connected transactions. TBD...
std::set<RGNode*> out;
std::set<RGNode*> in;
private:
uint64_t _color;
private:
uint64_t _color;
};
}
} // namespace BRM
#undef EXPORT

View File

@ -29,7 +29,6 @@
* rollback -r transID (for each one to roll them back)
*/
#include "dbrm.h"
#include <iostream>
@ -42,84 +41,76 @@ using namespace BRM;
void help(string name)
{
cout << "Usage: " << endl << name << " -r txnID" << endl;
cout << name << " -p" << endl << endl;
cout << "Options:" << endl;
cout << " -r -- rollback a transaction in the BRM data structures" << endl;
cout << " -p -- print current transactions according to the BRM" << endl;
cout << "Usage: " << endl << name << " -r txnID" << endl;
cout << name << " -p" << endl << endl;
cout << "Options:" << endl;
cout << " -r -- rollback a transaction in the BRM data structures" << endl;
cout << " -p -- print current transactions according to the BRM" << endl;
}
void printTxnIDs()
{
DBRM brm;
set<VER_t> txnList;
set<VER_t>::iterator it;
int err;
DBRM brm;
set<VER_t> txnList;
set<VER_t>::iterator it;
int err;
err = brm.getCurrentTxnIDs(txnList);
err = brm.getCurrentTxnIDs(txnList);
if (err != 0)
return;
if (err != 0)
return;
for (it = txnList.begin(); it != txnList.end(); it++)
cout << *it << endl;
for (it = txnList.begin(); it != txnList.end(); it++)
cout << *it << endl;
}
void rollbackTxn(VER_t txnID)
{
DBRM brm;
vector<LBID_t> lbidList;
int err;
DBRM brm;
vector<LBID_t> lbidList;
int err;
err = brm.getUncommittedLBIDs(txnID, lbidList);
err = brm.getUncommittedLBIDs(txnID, lbidList);
if (err != 0)
return;
if (err != 0)
return;
err = brm.vbRollback(txnID, lbidList);
err = brm.vbRollback(txnID, lbidList);
if (err != 0)
return;
if (err != 0)
return;
cout << "OK." << endl;
cout << "OK." << endl;
}
int main(int argc, char** argv)
{
int opt;
char options[] = "pr:";
VER_t txnID = -1;
string progname(argv[0]);
int opt;
char options[] = "pr:";
VER_t txnID = -1;
string progname(argv[0]);
while ((opt = getopt (argc, argv, options)) != -1)
while ((opt = getopt(argc, argv, options)) != -1)
{
switch (opt)
{
switch (opt)
case 'r':
txnID = atoi(optarg);
if (txnID < 1)
{
case 'r':
txnID = atoi (optarg);
if (txnID < 1)
{
help(progname);
exit(0);
}
idbdatafile::IDBPolicy::configIDBPolicy();
rollbackTxn(txnID);
exit(0);
case 'p':
printTxnIDs();
exit(0);
help(progname);
exit(0);
}
idbdatafile::IDBPolicy::configIDBPolicy();
rollbackTxn(txnID);
exit(0);
case 'p': printTxnIDs(); exit(0);
}
}
help(progname);
exit(0);
help(progname);
exit(0);
}

View File

@ -35,14 +35,12 @@ using namespace logging;
namespace BRM
{
RWLockMonitor::RWLockMonitor(const bool* d, const bool* ls, const uint32_t k) :
die(d), lockStatus(ls), key(k)
RWLockMonitor::RWLockMonitor(const bool* d, const bool* ls, const uint32_t k) : die(d), lockStatus(ls), key(k)
{
ts.tv_sec = 210; // 3:30 timer
ts.tv_nsec = 0;
secsBetweenAttempts = 30;
lock.reset(new RWLock(key));
ts.tv_sec = 210; // 3:30 timer
ts.tv_nsec = 0;
secsBetweenAttempts = 30;
lock.reset(new RWLock(key));
}
RWLockMonitor::~RWLockMonitor()
@ -51,106 +49,105 @@ RWLockMonitor::~RWLockMonitor()
void RWLockMonitor::operator()()
{
/*
* Grab a timed write lock.
* on failure
* if there's an active reader, do read_unlock()
* log everything else.
* *** write lock fixing is being postponed for now.
*/
/*
* Grab a timed write lock.
* on failure
* if there's an active reader, do read_unlock()
* log everything else.
* *** write lock fixing is being postponed for now.
*/
LockState state;
bool gotTheLock;
bool reportedProblem = false;
Logger logger(30);
LockState state;
bool gotTheLock;
bool reportedProblem = false;
Logger logger(30);
while (!(*die))
{
gotTheLock = lock->timed_write_lock(ts, &state);
while (!(*die))
if (*die)
break;
if (!gotTheLock)
{
gotTheLock = lock->timed_write_lock(ts, &state);
if (*die)
break;
if (!gotTheLock)
if (state.mutexLocked)
{
if (!reportedProblem)
{
if (state.mutexLocked)
{
if (!reportedProblem)
{
//Message msg(ERR_BRM_MUTEX);
Message msg(M0092);
logger.logMessage(LOG_TYPE_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
}
else if (state.reading > 0)
{
if (!reportedProblem)
{
//Message msg(ERR_RECOVERABLE_LOCK_STATE);
Message msg(M0094);
Message::Args args;
args.add(state.reading);
args.add(state.readerswaiting);
args.add(state.writing);
args.add(state.writerswaiting);
msg.format(args);
logger.logMessage(LOG_TYPE_WARNING, msg, LoggingID());
reportedProblem = true;
}
for (int i = 0; i < state.reading; i++)
lock->read_unlock();
}
// the write lock is held but not by this process, not good.
// there's a slight race here between these two vars but it's miniscule,
// and the worst thing that happens is a false positive error msg.
else if (state.writing > 0 && !(*lockStatus))
{
if (!reportedProblem)
{
//Message msg(ERR_UNRECOVERABLE_LOCK_STATE);
Message msg(M0093);
Message::Args args;
args.add(state.reading);
args.add(state.readerswaiting);
args.add(state.writing);
args.add(state.writerswaiting);
msg.format(args);
logger.logMessage(LOG_TYPE_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
/* put write lock recovery code here */
}
else
{
// the workernode is legitmately taking a long time
//cout << "holds the lock. " << " r=" << state.reading << " rwt=" << state.readerswaiting <<
// " w=" << state.writing << " wwt=" << state.writerswaiting << endl;
}
// Message msg(ERR_BRM_MUTEX);
Message msg(M0092);
logger.logMessage(LOG_TYPE_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
else
}
else if (state.reading > 0)
{
if (!reportedProblem)
{
/* got the write lock. If there was a problem before it's been fixed. */
lock->write_unlock();
// Message msg(ERR_RECOVERABLE_LOCK_STATE);
Message msg(M0094);
Message::Args args;
if (reportedProblem)
{
//Message msg(ERR_SUCCESSFUL_RECOVERY);
Message msg(M0095);
logger.logMessage(LOG_TYPE_WARNING, msg, LoggingID());
reportedProblem = false;
}
sleep(secsBetweenAttempts);
args.add(state.reading);
args.add(state.readerswaiting);
args.add(state.writing);
args.add(state.writerswaiting);
msg.format(args);
logger.logMessage(LOG_TYPE_WARNING, msg, LoggingID());
reportedProblem = true;
}
for (int i = 0; i < state.reading; i++)
lock->read_unlock();
}
// the write lock is held but not by this process, not good.
// there's a slight race here between these two vars but it's miniscule,
// and the worst thing that happens is a false positive error msg.
else if (state.writing > 0 && !(*lockStatus))
{
if (!reportedProblem)
{
// Message msg(ERR_UNRECOVERABLE_LOCK_STATE);
Message msg(M0093);
Message::Args args;
args.add(state.reading);
args.add(state.readerswaiting);
args.add(state.writing);
args.add(state.writerswaiting);
msg.format(args);
logger.logMessage(LOG_TYPE_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
/* put write lock recovery code here */
}
else
{
// the workernode is legitmately taking a long time
// cout << "holds the lock. " << " r=" << state.reading << " rwt=" << state.readerswaiting <<
// " w=" << state.writing << " wwt=" << state.writerswaiting << endl;
}
}
else
{
/* got the write lock. If there was a problem before it's been fixed. */
lock->write_unlock();
if (reportedProblem)
{
// Message msg(ERR_SUCCESSFUL_RECOVERY);
Message msg(M0095);
logger.logMessage(LOG_TYPE_WARNING, msg, LoggingID());
reportedProblem = false;
}
sleep(secsBetweenAttempts);
}
}
}
} /* namespace BRM */

View File

@ -38,30 +38,29 @@
namespace BRM
{
class RWLockMonitor
{
public:
// d = die, ls = lock status, k = key
EXPORT RWLockMonitor(const bool* d, const bool* ls, const uint32_t k);
public:
// d = die, ls = lock status, k = key
EXPORT RWLockMonitor(const bool* d, const bool* ls, const uint32_t k);
EXPORT virtual ~RWLockMonitor();
EXPORT virtual ~RWLockMonitor();
EXPORT void operator()();
EXPORT void operator()();
private:
//Are these defaults okay?
//RWLockMonitor(const RWLockMonitor&rhs);
//RWLockMonitor& operator=(const RWLockMonitor&rhs);
private:
// Are these defaults okay?
// RWLockMonitor(const RWLockMonitor&rhs);
// RWLockMonitor& operator=(const RWLockMonitor&rhs);
/* Some of these vars are only useful once we implement write_lock checking. */
const bool* die;
const bool* lockStatus;
uint32_t key;
boost::shared_ptr<rwlock::RWLock> lock;
/* Some of these vars are only useful once we implement write_lock checking. */
const bool* die;
const bool* lockStatus;
uint32_t key;
boost::shared_ptr<rwlock::RWLock> lock;
struct timespec ts; // 3:30 timer
uint32_t secsBetweenAttempts; // :30
struct timespec ts; // 3:30 timer
uint32_t secsBetweenAttempts; // :30
};
} /* namespace BRM */
@ -69,4 +68,3 @@ private:
#undef EXPORT
#endif /* RWLOCKMONITOR_H_ */

View File

@ -26,7 +26,6 @@
* More detailed description
*/
#include <unistd.h>
#include <iostream>
#include <sys/types.h>
@ -48,79 +47,76 @@ using namespace BRM;
#include "configcpp.h"
int main (int argc, char** argv)
int main(int argc, char** argv)
{
BlockResolutionManager brm;
config::Config* config = config::Config::makeConfig();
int err;
string prefix, currentFilename;
IDBDataFile* currentFile = NULL;
BlockResolutionManager brm;
config::Config* config = config::Config::makeConfig();
int err;
string prefix, currentFilename;
IDBDataFile* currentFile = NULL;
if (argc > 1)
prefix = argv[1];
else
if (argc > 1)
prefix = argv[1];
else
{
prefix = config->getConfig("SystemConfig", "DBRMRoot");
if (prefix.length() == 0)
{
prefix = config->getConfig("SystemConfig", "DBRMRoot");
if (prefix.length() == 0)
{
cerr << "Error: Need a valid Calpont configuation file" << endl;
exit(1);
}
cerr << "Error: Need a valid Calpont configuation file" << endl;
exit(1);
}
}
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
err = brm.saveState(prefix);
err = brm.saveState(prefix);
if (err == 0)
cout << "Saved to " << prefix << endl;
else
{
cout << "Save failed" << endl;
exit(1);
}
if (err == 0)
cout << "Saved to " << prefix << endl;
else
{
cout << "Save failed" << endl;
exit(1);
}
(void)::umask(0);
(void)::umask(0);
currentFilename = prefix + "_current";
currentFile = IDBDataFile::open(IDBPolicy::getType(currentFilename.c_str(),
IDBPolicy::WRITEENG),
currentFilename.c_str(),
"wb",
0);
currentFilename = prefix + "_current";
currentFile = IDBDataFile::open(IDBPolicy::getType(currentFilename.c_str(), IDBPolicy::WRITEENG),
currentFilename.c_str(), "wb", 0);
if (!currentFile)
{
cerr << "Error: could not open " << currentFilename << "for writing" << endl;
exit(1);
}
if (!currentFile)
{
cerr << "Error: could not open " << currentFilename << "for writing" << endl;
exit(1);
}
try
{
try
{
#ifndef _MSC_VER
prefix += '\n';
prefix += '\n';
#endif
// for MCOL-1558. Make the _current file relative to DBRMRoot
string relative = prefix.substr(prefix.find_last_of('/') + 1);
currentFile->write(relative.c_str(), relative.length());
}
catch (exception& e)
{
cerr << "Error: failed to write to " << currentFilename << ": " << e.what() << endl;
exit(1);
}
// for MCOL-1558. Make the _current file relative to DBRMRoot
string relative = prefix.substr(prefix.find_last_of('/') + 1);
currentFile->write(relative.c_str(), relative.length());
}
catch (exception& e)
{
cerr << "Error: failed to write to " << currentFilename << ": " << e.what() << endl;
exit(1);
}
try
{
delete currentFile;
currentFile = NULL;
}
catch (exception& e)
{
cerr << "Error: failed to close " << currentFilename << ": " << e.what() << endl;
exit(1);
}
try
{
delete currentFile;
currentFile = NULL;
}
catch (exception& e)
{
cerr << "Error: failed to close " << currentFilename << ": " << e.what() << endl;
exit(1);
}
return 0;
return 0;
}

View File

@ -56,82 +56,85 @@ using namespace execplan;
#undef SESSIONMANAGERSERVER_DLLEXPORT
#ifndef O_BINARY
# define O_BINARY 0
#define O_BINARY 0
#endif
#ifndef O_DIRECT
# define O_DIRECT 0
#define O_DIRECT 0
#endif
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#define O_LARGEFILE 0
#endif
#ifndef O_NOATIME
# define O_NOATIME 0
#define O_NOATIME 0
#endif
#include "IDBDataFile.h"
#include "IDBPolicy.h"
using namespace idbdatafile;
namespace BRM
{
const uint32_t SessionManagerServer::SS_READY = 1 << 0; // Set by dmlProc one time when dmlProc is ready
const uint32_t SessionManagerServer::SS_SUSPENDED = 1 << 1; // Set by console when the system has been suspended by user.
const uint32_t SessionManagerServer::SS_SUSPEND_PENDING = 1 << 2; // Set by console when user wants to suspend, but writing is occuring.
const uint32_t SessionManagerServer::SS_SHUTDOWN_PENDING = 1 << 3; // Set by console when user wants to shutdown, but writing is occuring.
const uint32_t SessionManagerServer::SS_ROLLBACK = 1 << 4; // In combination with a PENDING flag, force a rollback as soom as possible.
const uint32_t SessionManagerServer::SS_FORCE = 1 << 5; // In combination with a PENDING flag, force a shutdown without rollback.
const uint32_t SessionManagerServer::SS_QUERY_READY = 1 << 6; // Set by ProcManager when system is ready for queries
const uint32_t SessionManagerServer::SS_READY = 1 << 0; // Set by dmlProc one time when dmlProc is ready
const uint32_t SessionManagerServer::SS_SUSPENDED =
1 << 1; // Set by console when the system has been suspended by user.
const uint32_t SessionManagerServer::SS_SUSPEND_PENDING =
1 << 2; // Set by console when user wants to suspend, but writing is occuring.
const uint32_t SessionManagerServer::SS_SHUTDOWN_PENDING =
1 << 3; // Set by console when user wants to shutdown, but writing is occuring.
const uint32_t SessionManagerServer::SS_ROLLBACK =
1 << 4; // In combination with a PENDING flag, force a rollback as soom as possible.
const uint32_t SessionManagerServer::SS_FORCE =
1 << 5; // In combination with a PENDING flag, force a shutdown without rollback.
const uint32_t SessionManagerServer::SS_QUERY_READY =
1 << 6; // Set by ProcManager when system is ready for queries
SessionManagerServer::SessionManagerServer() : unique32(0), unique64(0)
{
config::Config* conf;
string stmp;
const char* ctmp;
config::Config* conf;
string stmp;
const char* ctmp;
conf = config::Config::makeConfig();
conf = config::Config::makeConfig();
try
{
stmp = conf->getConfig("SessionManager", "MaxConcurrentTransactions");
}
catch (const std::exception& e)
{
cout << e.what() << endl;
stmp.clear();
}
try
{
stmp = conf->getConfig("SessionManager", "MaxConcurrentTransactions");
}
catch (const std::exception& e)
{
cout << e.what() << endl;
stmp.clear();
}
if (stmp != "")
{
int64_t tmp;
ctmp = stmp.c_str();
tmp = config::Config::fromText(ctmp);
if (stmp != "")
{
int64_t tmp;
ctmp = stmp.c_str();
tmp = config::Config::fromText(ctmp);
if (tmp < 1)
maxTxns = 1;
else
maxTxns = static_cast<int>(tmp);
}
if (tmp < 1)
maxTxns = 1;
else
maxTxns = 1;
maxTxns = static_cast<int>(tmp);
}
else
maxTxns = 1;
txnidFilename = conf->getConfig("SessionManager", "TxnIDFile");
txnidFilename = conf->getConfig("SessionManager", "TxnIDFile");
semValue = maxTxns;
_verID = 0;
_sysCatVerID = 0;
systemState = 0;
semValue = maxTxns;
_verID = 0;
_sysCatVerID = 0;
systemState = 0;
try
{
loadState();
}
catch (...)
{
// first-time run most likely, ignore the error
}
try
{
loadState();
}
catch (...)
{
// first-time run most likely, ignore the error
}
}
SessionManagerServer::~SessionManagerServer()
@ -139,295 +142,293 @@ SessionManagerServer::~SessionManagerServer()
}
void SessionManagerServer::reset()
{
mutex.try_lock();
semValue = maxTxns;
condvar.notify_all();
activeTxns.clear();
mutex.unlock();
mutex.try_lock();
semValue = maxTxns;
condvar.notify_all();
activeTxns.clear();
mutex.unlock();
}
void SessionManagerServer::loadState()
{
int lastTxnID;
int err;
int lastSysCatVerId;
int lastTxnID;
int err;
int lastSysCatVerId;
again:
// There are now 3 pieces of info stored in the txnidfd file: last
// transaction id, last system catalog version id, and the
// system state flags. All these values are stored in shared, an
// instance of struct Overlay.
// If we fail to read a full four bytes for any value, then the
// value isn't in the file, and we start with the default.
// There are now 3 pieces of info stored in the txnidfd file: last
// transaction id, last system catalog version id, and the
// system state flags. All these values are stored in shared, an
// instance of struct Overlay.
// If we fail to read a full four bytes for any value, then the
// value isn't in the file, and we start with the default.
if (IDBPolicy::exists(txnidFilename.c_str()))
if (IDBPolicy::exists(txnidFilename.c_str()))
{
scoped_ptr<IDBDataFile> txnidfp(IDBDataFile::open(
IDBPolicy::getType(txnidFilename.c_str(), IDBPolicy::WRITEENG), txnidFilename.c_str(), "rb", 0));
if (!txnidfp)
{
scoped_ptr<IDBDataFile> txnidfp(IDBDataFile::open(
IDBPolicy::getType(txnidFilename.c_str(),
IDBPolicy::WRITEENG),
txnidFilename.c_str(), "rb", 0));
if (!txnidfp)
{
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
// Last transaction id
txnidfp->seek(0, SEEK_SET);
err = txnidfp->read(&lastTxnID, 4);
if (err < 0 && errno != EINTR)
{
perror("Sessionmanager::initSegment(): read");
throw runtime_error("SessionManagerServer: read failed, aborting");
}
else if (err < 0)
goto again;
else if (err == sizeof(int))
_verID = lastTxnID;
// last system catalog version id
err = txnidfp->read(&lastSysCatVerId, 4);
if (err < 0 && errno != EINTR)
{
perror("Sessionmanager::initSegment(): read");
throw runtime_error("SessionManagerServer: read failed, aborting");
}
else if (err < 0)
goto again;
else if (err == sizeof(int))
_sysCatVerID = lastSysCatVerId;
// System state. Contains flags regarding the suspend state of the system.
err = txnidfp->read(&systemState, 4);
if (err < 0 && errno == EINTR)
{
goto again;
}
else if (err == sizeof(int))
{
// Turn off the pending and force flags. They make no sense for a clean start.
// Turn off the ready flag. DMLProc will set it back on when
// initialized.
systemState &=
~(SS_READY | SS_QUERY_READY | SS_SUSPEND_PENDING | SS_SHUTDOWN_PENDING | SS_ROLLBACK | SS_FORCE);
}
else
{
// else no problem. System state wasn't saved. Might be an upgraded system.
systemState = 0;
}
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
// Last transaction id
txnidfp->seek(0, SEEK_SET);
err = txnidfp->read(&lastTxnID, 4);
if (err < 0 && errno != EINTR)
{
perror("Sessionmanager::initSegment(): read");
throw runtime_error("SessionManagerServer: read failed, aborting");
}
else if (err < 0)
goto again;
else if (err == sizeof(int))
_verID = lastTxnID;
// last system catalog version id
err = txnidfp->read(&lastSysCatVerId, 4);
if (err < 0 && errno != EINTR)
{
perror("Sessionmanager::initSegment(): read");
throw runtime_error("SessionManagerServer: read failed, aborting");
}
else if (err < 0)
goto again;
else if (err == sizeof(int))
_sysCatVerID = lastSysCatVerId;
// System state. Contains flags regarding the suspend state of the system.
err = txnidfp->read(&systemState, 4);
if (err < 0 && errno == EINTR)
{
goto again;
}
else if (err == sizeof(int))
{
// Turn off the pending and force flags. They make no sense for a clean start.
// Turn off the ready flag. DMLProc will set it back on when
// initialized.
systemState &=
~(SS_READY | SS_QUERY_READY | SS_SUSPEND_PENDING | SS_SHUTDOWN_PENDING | SS_ROLLBACK | SS_FORCE);
}
else
{
// else no problem. System state wasn't saved. Might be an upgraded system.
systemState = 0;
}
}
}
/* Save the systemState flags of the Overlay
* segment. This is saved in the third
* word of txnid File
*/
*/
void SessionManagerServer::saveSystemState()
{
saveSMTxnIDAndState();
saveSMTxnIDAndState();
}
const QueryContext SessionManagerServer::verID()
{
QueryContext ret;
QueryContext ret;
boost::mutex::scoped_lock lk(mutex);
ret.currentScn = _verID;
boost::mutex::scoped_lock lk(mutex);
ret.currentScn = _verID;
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
return ret;
return ret;
}
const QueryContext SessionManagerServer::sysCatVerID()
{
QueryContext ret;
QueryContext ret;
boost::mutex::scoped_lock lk(mutex);
ret.currentScn = _sysCatVerID;
boost::mutex::scoped_lock lk(mutex);
ret.currentScn = _sysCatVerID;
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
return ret;
return ret;
}
const TxnID SessionManagerServer::newTxnID(const SID session, bool block, bool isDDL)
{
TxnID ret; //ctor must set valid = false
iterator it;
TxnID ret; // ctor must set valid = false
iterator it;
boost::mutex::scoped_lock lk(mutex);
boost::mutex::scoped_lock lk(mutex);
// if it already has a txn...
it = activeTxns.find(session);
// if it already has a txn...
it = activeTxns.find(session);
if (it != activeTxns.end())
{
ret.id = it->second;
ret.valid = true;
return ret;
}
if (!block && semValue == 0)
return ret;
else while (semValue == 0)
condvar.wait(lk);
semValue--;
idbassert(semValue <= (uint32_t)maxTxns);
ret.id = ++_verID;
if (it != activeTxns.end())
{
ret.id = it->second;
ret.valid = true;
activeTxns[session] = ret.id;
if (isDDL)
++_sysCatVerID;
saveSMTxnIDAndState();
return ret;
}
if (!block && semValue == 0)
return ret;
else
while (semValue == 0)
condvar.wait(lk);
semValue--;
idbassert(semValue <= (uint32_t)maxTxns);
ret.id = ++_verID;
ret.valid = true;
activeTxns[session] = ret.id;
if (isDDL)
++_sysCatVerID;
saveSMTxnIDAndState();
return ret;
}
void SessionManagerServer::finishTransaction(TxnID& txn)
{
iterator it;
boost::mutex::scoped_lock lk(mutex);
bool found = false;
iterator it;
boost::mutex::scoped_lock lk(mutex);
bool found = false;
if (!txn.valid)
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction is invalid");
if (!txn.valid)
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction is invalid");
for (it = activeTxns.begin(); it != activeTxns.end(); )
for (it = activeTxns.begin(); it != activeTxns.end();)
{
if (it->second == txn.id)
{
if (it->second == txn.id)
{
activeTxns.erase(it++);
txn.valid = false;
found = true;
//we could probably break at this point, but there won't be that many active txns, and,
// even though it'd be an error to have multiple entries for the same txn, we might
// well just get rid of them...
}
else
++it;
}
if (found)
{
semValue++;
idbassert(semValue <= (uint32_t)maxTxns);
condvar.notify_one();
activeTxns.erase(it++);
txn.valid = false;
found = true;
// we could probably break at this point, but there won't be that many active txns, and,
// even though it'd be an error to have multiple entries for the same txn, we might
// well just get rid of them...
}
else
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction doesn't exist");
++it;
}
if (found)
{
semValue++;
idbassert(semValue <= (uint32_t)maxTxns);
condvar.notify_one();
}
else
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction doesn't exist");
}
const TxnID SessionManagerServer::getTxnID(const SID session)
{
TxnID ret;
iterator it;
TxnID ret;
iterator it;
boost::mutex::scoped_lock lk(mutex);
boost::mutex::scoped_lock lk(mutex);
it = activeTxns.find(session);
it = activeTxns.find(session);
if (it != activeTxns.end())
{
ret.id = it->second;
ret.valid = true;
}
if (it != activeTxns.end())
{
ret.id = it->second;
ret.valid = true;
}
return ret;
return ret;
}
shared_array<SIDTIDEntry> SessionManagerServer::SIDTIDMap(int& len)
{
int j;
shared_array<SIDTIDEntry> ret;
boost::mutex::scoped_lock lk(mutex);
iterator it;
int j;
shared_array<SIDTIDEntry> ret;
boost::mutex::scoped_lock lk(mutex);
iterator it;
ret.reset(new SIDTIDEntry[activeTxns.size()]);
ret.reset(new SIDTIDEntry[activeTxns.size()]);
len = activeTxns.size();
len = activeTxns.size();
for (it = activeTxns.begin(), j = 0; it != activeTxns.end(); ++it, ++j)
{
ret[j].sessionid = it->first;
ret[j].txnid.id = it->second;
ret[j].txnid.valid = true;
}
for (it = activeTxns.begin(), j = 0; it != activeTxns.end(); ++it, ++j)
{
ret[j].sessionid = it->first;
ret[j].txnid.id = it->second;
ret[j].txnid.valid = true;
}
return ret;
return ret;
}
void SessionManagerServer::setSystemState(uint32_t state)
{
boost::mutex::scoped_lock lk(mutex);
boost::mutex::scoped_lock lk(mutex);
systemState |= state;
saveSystemState();
systemState |= state;
saveSystemState();
}
void SessionManagerServer::clearSystemState(uint32_t state)
{
boost::mutex::scoped_lock lk(mutex);
boost::mutex::scoped_lock lk(mutex);
systemState &= ~state;
saveSystemState();
systemState &= ~state;
saveSystemState();
}
uint32_t SessionManagerServer::getTxnCount()
{
boost::mutex::scoped_lock lk(mutex);
return activeTxns.size();
boost::mutex::scoped_lock lk(mutex);
return activeTxns.size();
}
void SessionManagerServer::saveSMTxnIDAndState()
{
// caller holds the lock
scoped_ptr<IDBDataFile> txnidfp(IDBDataFile::open(
IDBPolicy::getType(txnidFilename.c_str(), IDBPolicy::WRITEENG),
txnidFilename.c_str(), "wb", 0));
// caller holds the lock
scoped_ptr<IDBDataFile> txnidfp(IDBDataFile::open(
IDBPolicy::getType(txnidFilename.c_str(), IDBPolicy::WRITEENG), txnidFilename.c_str(), "wb", 0));
if (!txnidfp)
{
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
if (!txnidfp)
{
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
int filedata[2];
filedata[0] = _verID;
filedata[1] = _sysCatVerID;
int filedata[2];
filedata[0] = _verID;
filedata[1] = _sysCatVerID;
int err = txnidfp->write(filedata, 8);
int err = txnidfp->write(filedata, 8);
if (err < 0)
{
perror("SessionManagerServer::newTxnID(): write(verid)");
throw runtime_error("SessionManagerServer::newTxnID(): write(verid) failed");
}
if (err < 0)
{
perror("SessionManagerServer::newTxnID(): write(verid)");
throw runtime_error("SessionManagerServer::newTxnID(): write(verid) failed");
}
uint32_t lSystemState = systemState;
// We don't save the pending flags, the force flag or the ready flags.
lSystemState &= ~(SS_READY | SS_QUERY_READY | SS_SUSPEND_PENDING | SS_SHUTDOWN_PENDING | SS_FORCE);
err = txnidfp->write(&lSystemState, sizeof(int));
uint32_t lSystemState = systemState;
// We don't save the pending flags, the force flag or the ready flags.
lSystemState &= ~(SS_READY | SS_QUERY_READY | SS_SUSPEND_PENDING | SS_SHUTDOWN_PENDING | SS_FORCE);
err = txnidfp->write(&lSystemState, sizeof(int));
if (err < 0)
{
perror("SessionManagerServer::saveSystemState(): write(systemState)");
throw runtime_error("SessionManagerServer::saveSystemState(): write(systemState) failed");
}
if (err < 0)
{
perror("SessionManagerServer::saveSystemState(): write(systemState)");
throw runtime_error("SessionManagerServer::saveSystemState(): write(systemState) failed");
}
txnidfp->flush();
txnidfp->flush();
}
} //namespace
} // namespace BRM

View File

@ -45,17 +45,16 @@
#endif
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4200)
#pragma warning(push)
#pragma warning(disable : 4200)
#endif
namespace BRM
{
/** @brief Issues transaction IDs and keeps track of the current system-wide version ID.
*
* This class's primary purpose is to keep track of the current system-wide version ID and issue transaction IDs.
* It can be used simultaneously by multiple threads and processes.
* This class's primary purpose is to keep track of the current system-wide version ID and issue transaction
* IDs. It can be used simultaneously by multiple threads and processes.
*
* It uses system-wide semaphores and shared memory segments for IPC.
* It allocates both if they don't already exist, but it only deallocates
@ -92,203 +91,207 @@ namespace BRM
class SessionManagerServer
{
public:
/** @brief SID = Session ID */
typedef uint32_t SID;
public:
/** @brief SID = Session ID */
typedef uint32_t SID;
// State flags. These bit values are stored in Overlay::state and reflect the current state of the system
static const uint32_t SS_READY; /// bit 0 => Set by dmlProc one time when dmlProc is ready
static const uint32_t SS_SUSPENDED; /// bit 1 => Set by console when the system has been suspended by user.
static const uint32_t SS_SUSPEND_PENDING; /// bit 2 => Set by console when user wants to suspend, but writing is occuring.
static const uint32_t SS_SHUTDOWN_PENDING; /// bit 3 => Set by console when user wants to shutdown, but writing is occuring.
static const uint32_t SS_ROLLBACK; /// bit 4 => In combination with a PENDING flag, force a rollback as soom as possible.
static const uint32_t SS_FORCE; /// bit 5 => In combination with a PENDING flag, force a shutdown without rollback.
static const uint32_t SS_QUERY_READY; /// bit 6 => Set by ProcManager when system is ready for queries
// State flags. These bit values are stored in Overlay::state and reflect the current state of the system
static const uint32_t SS_READY; /// bit 0 => Set by dmlProc one time when dmlProc is ready
static const uint32_t SS_SUSPENDED; /// bit 1 => Set by console when the system has been suspended by user.
static const uint32_t
SS_SUSPEND_PENDING; /// bit 2 => Set by console when user wants to suspend, but writing is occuring.
static const uint32_t
SS_SHUTDOWN_PENDING; /// bit 3 => Set by console when user wants to shutdown, but writing is occuring.
static const uint32_t
SS_ROLLBACK; /// bit 4 => In combination with a PENDING flag, force a rollback as soom as possible.
static const uint32_t
SS_FORCE; /// bit 5 => In combination with a PENDING flag, force a shutdown without rollback.
static const uint32_t SS_QUERY_READY; /// bit 6 => Set by ProcManager when system is ready for queries
/** @brief Constructor
*
* This sets up the shared memory segment & semaphores used by this
* instance. No additional set-up calls are necessary.
* @note throws ios_base::failure on file IO error, runtime_error for
* other types of errors. It might be worthwhile to define additional
* exceptions for all the different types of failures that can happen
* here.
*/
EXPORT SessionManagerServer();
/** @brief Constructor
*
* This sets up the shared memory segment & semaphores used by this
* instance. No additional set-up calls are necessary.
* @note throws ios_base::failure on file IO error, runtime_error for
* other types of errors. It might be worthwhile to define additional
* exceptions for all the different types of failures that can happen
* here.
*/
EXPORT SessionManagerServer();
/** @brief Destructor
*
* This detaches the shared memory segment. If DESTROYSHMSEG is defined and this
* is the last reference to it, it will be saved to disk and destroyed.
* It does not destroy the semaphores. Those persist until the system
* is shut down.
*/
virtual ~SessionManagerServer();
/** @brief Destructor
*
* This detaches the shared memory segment. If DESTROYSHMSEG is defined and this
* is the last reference to it, it will be saved to disk and destroyed.
* It does not destroy the semaphores. Those persist until the system
* is shut down.
*/
virtual ~SessionManagerServer();
/** @brief Gets the current version ID
*
* Gets the current version ID.
*/
EXPORT const QueryContext verID();
/** @brief Gets the current version ID
*
* Gets the current version ID.
*/
EXPORT const QueryContext verID();
/** @brief Gets the current version ID
*
* Gets the current version ID.
*/
EXPORT const QueryContext sysCatVerID();
/** @brief Gets the current version ID
*
* Gets the current version ID.
*/
EXPORT const QueryContext sysCatVerID();
/** @brief Gets a new Transaction ID
*
* Makes a new Transaction ID, associates it with the given session
* and increments the system-wide version ID
* @note This blocks until (# active transactions) \< MaxTxns unless block == false
* @note Throws runtime_error on semaphore-related error
* @note This will always return a valid TxnID unless block == false, in which case
* it will return a valid TxnID iff it doesn't have to block.
* @param session The session ID to associate with the transaction ID
* @param block If true, this will block until there is an available slot, otherwise
* it will return a TxnID marked invalid, signifying that it could not start a new transaction
* @return The new transaction ID.
*/
EXPORT const TxnID newTxnID(const SID session, bool block = true, bool isDDL = false);
/** @brief Gets a new Transaction ID
*
* Makes a new Transaction ID, associates it with the given session
* and increments the system-wide version ID
* @note This blocks until (# active transactions) \< MaxTxns unless block == false
* @note Throws runtime_error on semaphore-related error
* @note This will always return a valid TxnID unless block == false, in which case
* it will return a valid TxnID iff it doesn't have to block.
* @param session The session ID to associate with the transaction ID
* @param block If true, this will block until there is an available slot, otherwise
* it will return a TxnID marked invalid, signifying that it could not start a new transaction
* @return The new transaction ID.
*/
EXPORT const TxnID newTxnID(const SID session, bool block = true, bool isDDL = false);
/** @brief Record that a transaction has been committed
*
* Record that a transaction has been committed.
* @note Throws runtime_error on a semaphore-related error, invalid_argument
* when txnid can't be found
* @param txnid The committed transaction ID. This is marked invalid
* on return.
*/
void committed(TxnID& txn)
{
finishTransaction(txn);
}
/** @brief Record that a transaction has been committed
*
* Record that a transaction has been committed.
* @note Throws runtime_error on a semaphore-related error, invalid_argument
* when txnid can't be found
* @param txnid The committed transaction ID. This is marked invalid
* on return.
*/
void committed(TxnID& txn)
{
finishTransaction(txn);
}
/** @brief Record that a transaction has been rolled back
*
* Record that a transaction has been rolled back.
* @note Throws runtime_error on a semaphore-related error, invalid_argument
* when txnid can't be found
* @param txnid The rolled back transaction ID. This is marked invalid
* on return.
*/
void rolledback(TxnID& txn)
{
finishTransaction(txn);
}
/** @brief Record that a transaction has been rolled back
*
* Record that a transaction has been rolled back.
* @note Throws runtime_error on a semaphore-related error, invalid_argument
* when txnid can't be found
* @param txnid The rolled back transaction ID. This is marked invalid
* on return.
*/
void rolledback(TxnID& txn)
{
finishTransaction(txn);
}
/** @brief Gets the transaction ID associated with a given session ID
*
* Gets the transaction ID associated with a given session ID.
* @note Throws runtime_error on a semaphore-related error
* @param session The session ID
* @return A valid transaction ID if there's an association; an invalid
* one if there isn't.
*/
EXPORT const TxnID getTxnID(const SID session);
/** @brief Gets the transaction ID associated with a given session ID
*
* Gets the transaction ID associated with a given session ID.
* @note Throws runtime_error on a semaphore-related error
* @param session The session ID
* @return A valid transaction ID if there's an association; an invalid
* one if there isn't.
*/
EXPORT const TxnID getTxnID(const SID session);
/** @brief Gets an array containing all active SID-TID associations
*
* Gets an array containing the SID-TID associations of all active
* transactions. This is intended to be used by another object
* that can determine which sessions are still live and which
* transactions need to go away.
* @note Throws runtime_error on a semaphore-related error
* @param len (out) the length of the array
* @return A pointer to the array. Note: The caller is responsible for
* deallocating it. Use delete[].
*/
EXPORT boost::shared_array<SIDTIDEntry> SIDTIDMap(int& len);
/** @brief Gets an array containing all active SID-TID associations
*
* Gets an array containing the SID-TID associations of all active
* transactions. This is intended to be used by another object
* that can determine which sessions are still live and which
* transactions need to go away.
* @note Throws runtime_error on a semaphore-related error
* @param len (out) the length of the array
* @return A pointer to the array. Note: The caller is responsible for
* deallocating it. Use delete[].
*/
EXPORT boost::shared_array<SIDTIDEntry> SIDTIDMap(int& len);
/**
* get a unique 32-bit number
*/
uint32_t getUnique32()
{
return atomicops::atomicInc(&unique32);
}
/**
* get a unique 32-bit number
*/
uint32_t getUnique32()
{
return atomicops::atomicInc(&unique32);
}
/**
* get a unique 64-bit number
*/
uint64_t getUnique64()
{
return atomicops::atomicInc(&unique64);
}
/**
* get a unique 64-bit number
*/
uint64_t getUnique64()
{
return atomicops::atomicInc(&unique64);
}
/** @brief Resets the semaphores to their original state. For testing only.
*
* Resets the semaphores to their original state. For testing only.
*/
EXPORT void reset();
/** @brief Resets the semaphores to their original state. For testing only.
*
* Resets the semaphores to their original state. For testing only.
*/
EXPORT void reset();
/**
* get the Txn ID filename
*/
std::string getTxnIDFilename() const
{
return txnidFilename;
}
/**
* get the Txn ID filename
*/
std::string getTxnIDFilename() const
{
return txnidFilename;
}
/** @brief set system state info
*
* Sets the bits on in Overlay::systemState that are found on in
* state. That is Overlay::systemState | state.
*/
EXPORT void setSystemState(uint32_t state);
/** @brief set system state info
*
* Sets the bits on in Overlay::systemState that are found on in
* state. That is Overlay::systemState | state.
*/
EXPORT void setSystemState(uint32_t state);
/** @brief set system state info
*
* Clears the bits on in Overlay::systemState that are found on
* in state. That is Overlay::systemState & ~state.
*/
EXPORT void clearSystemState(uint32_t state);
/** @brief set system state info
*
* Clears the bits on in Overlay::systemState that are found on
* in state. That is Overlay::systemState & ~state.
*/
EXPORT void clearSystemState(uint32_t state);
/** @brief get system state info
*
* Returns the Overlay::systemState flags
*/
void getSystemState(uint32_t& state)
{
state = systemState;
}
/** @brief get system state info
*
* Returns the Overlay::systemState flags
*/
void getSystemState(uint32_t& state)
{
state = systemState;
}
/**
* get the number of active txn's
*/
EXPORT uint32_t getTxnCount();
/**
* get the number of active txn's
*/
EXPORT uint32_t getTxnCount();
private:
SessionManagerServer(const SessionManagerServer&);
SessionManagerServer& operator=(const SessionManagerServer&);
private:
SessionManagerServer(const SessionManagerServer&);
SessionManagerServer& operator=(const SessionManagerServer&);
void loadState();
void saveSystemState();
void finishTransaction(TxnID& txn);
void saveSMTxnIDAndState();
void loadState();
void saveSystemState();
void finishTransaction(TxnID& txn);
void saveSMTxnIDAndState();
volatile uint32_t unique32;
volatile uint64_t unique64;
volatile uint32_t unique32;
volatile uint64_t unique64;
int maxTxns; // the maximum number of concurrent transactions
std::string txnidFilename;
execplan::CalpontSystemCatalog::SCN _verID;
execplan::CalpontSystemCatalog::SCN _sysCatVerID;
uint32_t systemState;
int maxTxns; // the maximum number of concurrent transactions
std::string txnidFilename;
execplan::CalpontSystemCatalog::SCN _verID;
execplan::CalpontSystemCatalog::SCN _sysCatVerID;
uint32_t systemState;
std::map<SID, execplan::CalpontSystemCatalog::SCN> activeTxns;
typedef std::map<SID, execplan::CalpontSystemCatalog::SCN>::iterator iterator;
std::map<SID, execplan::CalpontSystemCatalog::SCN> activeTxns;
typedef std::map<SID, execplan::CalpontSystemCatalog::SCN>::iterator iterator;
boost::mutex mutex;
boost::condition_variable condvar; // used to synthesize a semaphore
uint32_t semValue;
boost::mutex mutex;
boost::condition_variable condvar; // used to synthesize a semaphore
uint32_t semValue;
};
} //namespace
} // namespace BRM
#ifdef _MSC_VER
#pragma warning (pop)
#pragma warning(pop)
#endif
#undef EXPORT

View File

@ -32,41 +32,39 @@ using namespace std;
namespace BRM
{
ShmKeys::ShmKeys()
{
uint32_t BRM_UID = 0x0;
uint32_t BRM_UID = 0x0;
#ifdef WANT_EM_BRM_UID
config::Config* cf = config::Config::makeConfig();
string brm_str = cf->getConfig("ExtentMap", "BRM_UID");
config::Config* cf = config::Config::makeConfig();
string brm_str = cf->getConfig("ExtentMap", "BRM_UID");
if (brm_str.length() > 0)
BRM_UID = static_cast<uint32_t>(config::Config::uFromText(brm_str));
if (brm_str.length() > 0)
BRM_UID = static_cast<uint32_t>(config::Config::uFromText(brm_str));
#endif
KEYRANGE_VSS_BASE = 0x10000 | (BRM_UID << 20);
KEYRANGE_EXTENTMAP_BASE = 0x20000 | (BRM_UID << 20);
KEYRANGE_EMFREELIST_BASE = 0x30000 | (BRM_UID << 20);
KEYRANGE_VBBM_BASE = 0x40000 | (BRM_UID << 20);
KEYRANGE_CL_BASE = 0x50000 | (BRM_UID << 20);
MST_SYSVKEY = 0xff000000 | BRM_UID;
PROCESSSTATUS_SYSVKEY = 0xfd000000 | BRM_UID;
SYSTEMSTATUS_SYSVKEY = 0xfc000000 | BRM_UID;
SWITCHSTATUS_SYSVKEY = 0xfb000000 | BRM_UID;
NICSTATUS_SYSVKEY = 0xf9000000 | BRM_UID;
DBROOTSTATUS_SYSVKEY = 0xf8000000 | BRM_UID;
DECOMSVRMUTEX_SYSVKEY = 0xf7000000 | BRM_UID;
KEYRANGE_VSS_BASE = 0x10000 | (BRM_UID << 20);
KEYRANGE_EXTENTMAP_BASE = 0x20000 | (BRM_UID << 20);
KEYRANGE_EMFREELIST_BASE = 0x30000 | (BRM_UID << 20);
KEYRANGE_VBBM_BASE = 0x40000 | (BRM_UID << 20);
KEYRANGE_CL_BASE = 0x50000 | (BRM_UID << 20);
MST_SYSVKEY = 0xff000000 | BRM_UID;
PROCESSSTATUS_SYSVKEY = 0xfd000000 | BRM_UID;
SYSTEMSTATUS_SYSVKEY = 0xfc000000 | BRM_UID;
SWITCHSTATUS_SYSVKEY = 0xfb000000 | BRM_UID;
NICSTATUS_SYSVKEY = 0xf9000000 | BRM_UID;
DBROOTSTATUS_SYSVKEY = 0xf8000000 | BRM_UID;
DECOMSVRMUTEX_SYSVKEY = 0xf7000000 | BRM_UID;
}
string ShmKeys::keyToName(unsigned key)
{
ostringstream oss;
oss << "InfiniDB-shm-";
oss << setw(8) << setfill('0') << hex << key;
return oss.str();
}
ostringstream oss;
oss << "InfiniDB-shm-";
oss << setw(8) << setfill('0') << hex << key;
return oss.str();
}
} // namespace BRM

View File

@ -31,51 +31,51 @@
namespace BRM
{
/** A struct to hold shared memory keys
*
* A struct to hold shared memory keys that can be tuned via the config file
*/
struct ShmKeys
{
public:
EXPORT ShmKeys();
~ShmKeys() { }
public:
EXPORT ShmKeys();
~ShmKeys()
{
}
/******** The shmseg/sem key range assigments *******/
/******** The shmseg/sem key range assigments *******/
#if defined(COMMUNITY_KEYRANGE)
const static uint32_t KEYRANGE_SIZE = 0x1000;
const static uint32_t KEYRANGE_SIZE = 0x1000;
#elif defined(_MSC_VER)
const static uint32_t KEYRANGE_SIZE = 0x3800;
const static uint32_t KEYRANGE_SIZE = 0x3800;
#else
const static uint32_t KEYRANGE_SIZE = 0x10000;
const static uint32_t KEYRANGE_SIZE = 0x10000;
#endif
uint32_t KEYRANGE_CL_BASE;
uint32_t KEYRANGE_EXTENTMAP_BASE;
uint32_t KEYRANGE_EMFREELIST_BASE;
uint32_t KEYRANGE_VBBM_BASE;
uint32_t KEYRANGE_VSS_BASE;
uint32_t KEYRANGE_CL_BASE;
uint32_t KEYRANGE_EXTENTMAP_BASE;
uint32_t KEYRANGE_EMFREELIST_BASE;
uint32_t KEYRANGE_VBBM_BASE;
uint32_t KEYRANGE_VSS_BASE;
/****** Fixed location assignments *******/
uint32_t MST_SYSVKEY;
uint32_t PROCESSSTATUS_SYSVKEY;
uint32_t SYSTEMSTATUS_SYSVKEY;
uint32_t SWITCHSTATUS_SYSVKEY;
uint32_t NICSTATUS_SYSVKEY;
uint32_t DBROOTSTATUS_SYSVKEY;
uint32_t DECOMSVRMUTEX_SYSVKEY;
/****** Fixed location assignments *******/
uint32_t MST_SYSVKEY;
uint32_t PROCESSSTATUS_SYSVKEY;
uint32_t SYSTEMSTATUS_SYSVKEY;
uint32_t SWITCHSTATUS_SYSVKEY;
uint32_t NICSTATUS_SYSVKEY;
uint32_t DBROOTSTATUS_SYSVKEY;
uint32_t DECOMSVRMUTEX_SYSVKEY;
EXPORT static std::string keyToName(unsigned key);
EXPORT static std::string keyToName(unsigned key);
private:
//defaults okay
//ShmKeys(const ShmKeys& rhs);
//ShmKeys operator=(const ShmKeys& rhs);
private:
// defaults okay
// ShmKeys(const ShmKeys& rhs);
// ShmKeys operator=(const ShmKeys& rhs);
};
}
} // namespace BRM
#undef EXPORT
#endif

File diff suppressed because it is too large Load Diff

View File

@ -49,96 +49,93 @@ namespace idbdatafile
class IDBDataFile;
}
namespace BRM
{
class SlaveComm
{
public:
/** Use this ctor to instantiate a standalone SlaveComm ie, for replaying
the journal. Should be used only by load_brm. */
EXPORT SlaveComm();
public:
/** Use this ctor to instantiate a standalone SlaveComm ie, for replaying
the journal. Should be used only by load_brm. */
EXPORT SlaveComm();
/** Use this ctor to have it connected to the rest of the DBRM system */
EXPORT SlaveComm(std::string hostname, SlaveDBRMNode* s); //hostname = 'DBRM_WorkerN'
EXPORT ~SlaveComm();
/** Use this ctor to have it connected to the rest of the DBRM system */
EXPORT SlaveComm(std::string hostname, SlaveDBRMNode* s); // hostname = 'DBRM_WorkerN'
EXPORT ~SlaveComm();
EXPORT void run();
EXPORT void stop();
EXPORT void reset();
EXPORT void run();
EXPORT void stop();
EXPORT void reset();
EXPORT int replayJournal(std::string prefix);
EXPORT int printJournal(std::string prefix);
EXPORT int replayJournal(std::string prefix);
EXPORT int printJournal(std::string prefix);
private:
private:
SlaveComm& operator=(const SlaveComm& s);
SlaveComm& operator=(const SlaveComm& s);
void processCommand(messageqcpp::ByteStream& msg);
void processCommand(messageqcpp::ByteStream& msg);
void do_createStripeColumnExtents(messageqcpp::ByteStream& msg);
void do_createColumnExtent_DBroot(messageqcpp::ByteStream& msg);
void do_createColumnExtentExactFile(messageqcpp::ByteStream& msg);
void do_createDictStoreExtent(messageqcpp::ByteStream& msg);
void do_rollbackColumnExtents_DBroot(messageqcpp::ByteStream& msg);
void do_deleteEmptyColExtents(messageqcpp::ByteStream& msg);
void do_deleteEmptyDictStoreExtents(messageqcpp::ByteStream& msg);
void do_rollbackDictStoreExtents_DBroot(messageqcpp::ByteStream& msg);
void do_deleteOID(messageqcpp::ByteStream& msg);
void do_deleteOIDs(messageqcpp::ByteStream& msg);
void do_setLocalHWM(messageqcpp::ByteStream& msg);
void do_bulkSetHWM(messageqcpp::ByteStream& msg);
void do_bulkSetHWMAndCP(messageqcpp::ByteStream& msg);
void do_writeVBEntry(messageqcpp::ByteStream& msg);
void do_bulkWriteVBEntry(messageqcpp::ByteStream& msg);
void do_beginVBCopy(messageqcpp::ByteStream& msg);
void do_endVBCopy(messageqcpp::ByteStream& msg);
void do_vbRollback1(messageqcpp::ByteStream& msg);
void do_vbRollback2(messageqcpp::ByteStream& msg);
void do_vbCommit(messageqcpp::ByteStream& msg);
void do_markInvalid(messageqcpp::ByteStream& msg);
void do_markManyExtentsInvalid(messageqcpp::ByteStream& msg);
void do_mergeExtentsMaxMin(messageqcpp::ByteStream& msg);
void do_setExtentMaxMin(messageqcpp::ByteStream& msg);
void do_setExtentsMaxMin(messageqcpp::ByteStream& msg); // bug 1970
void do_deletePartition(messageqcpp::ByteStream& msg);
void do_markPartitionForDeletion(messageqcpp::ByteStream& msg);
void do_markAllPartitionForDeletion(messageqcpp::ByteStream& msg);
void do_restorePartition(messageqcpp::ByteStream& msg);
void do_dmlLockLBIDRanges(messageqcpp::ByteStream& msg);
void do_dmlReleaseLBIDRanges(messageqcpp::ByteStream& msg);
void do_deleteDBRoot(messageqcpp::ByteStream& msg);
void do_bulkUpdateDBRoot(messageqcpp::ByteStream& msg);
void do_createStripeColumnExtents(messageqcpp::ByteStream& msg);
void do_createColumnExtent_DBroot(messageqcpp::ByteStream& msg);
void do_createColumnExtentExactFile(messageqcpp::ByteStream& msg);
void do_createDictStoreExtent(messageqcpp::ByteStream& msg);
void do_rollbackColumnExtents_DBroot(messageqcpp::ByteStream& msg);
void do_deleteEmptyColExtents(messageqcpp::ByteStream& msg);
void do_deleteEmptyDictStoreExtents(messageqcpp::ByteStream& msg);
void do_rollbackDictStoreExtents_DBroot(messageqcpp::ByteStream& msg);
void do_deleteOID(messageqcpp::ByteStream& msg);
void do_deleteOIDs(messageqcpp::ByteStream& msg);
void do_setLocalHWM(messageqcpp::ByteStream& msg);
void do_bulkSetHWM(messageqcpp::ByteStream& msg);
void do_bulkSetHWMAndCP(messageqcpp::ByteStream& msg);
void do_writeVBEntry(messageqcpp::ByteStream& msg);
void do_bulkWriteVBEntry(messageqcpp::ByteStream& msg);
void do_beginVBCopy(messageqcpp::ByteStream& msg);
void do_endVBCopy(messageqcpp::ByteStream& msg);
void do_vbRollback1(messageqcpp::ByteStream& msg);
void do_vbRollback2(messageqcpp::ByteStream& msg);
void do_vbCommit(messageqcpp::ByteStream& msg);
void do_markInvalid(messageqcpp::ByteStream& msg);
void do_markManyExtentsInvalid(messageqcpp::ByteStream& msg);
void do_mergeExtentsMaxMin(messageqcpp::ByteStream& msg);
void do_setExtentMaxMin(messageqcpp::ByteStream& msg);
void do_setExtentsMaxMin(messageqcpp::ByteStream& msg); // bug 1970
void do_deletePartition(messageqcpp::ByteStream& msg);
void do_markPartitionForDeletion(messageqcpp::ByteStream& msg);
void do_markAllPartitionForDeletion(messageqcpp::ByteStream& msg);
void do_restorePartition(messageqcpp::ByteStream& msg);
void do_dmlLockLBIDRanges(messageqcpp::ByteStream& msg);
void do_dmlReleaseLBIDRanges(messageqcpp::ByteStream& msg);
void do_deleteDBRoot(messageqcpp::ByteStream& msg);
void do_bulkUpdateDBRoot(messageqcpp::ByteStream& msg);
void do_undo();
void do_confirm();
void do_flushInodeCache();
void do_clear();
void do_ownerCheck(messageqcpp::ByteStream& msg);
void do_takeSnapshot();
void saveDelta();
bool processExists(const uint32_t pid, const std::string& pname);
void do_undo();
void do_confirm();
void do_flushInodeCache();
void do_clear();
void do_ownerCheck(messageqcpp::ByteStream& msg);
void do_takeSnapshot();
void saveDelta();
bool processExists(const uint32_t pid, const std::string& pname);
messageqcpp::MessageQueueServer* server;
messageqcpp::IOSocket master;
SlaveDBRMNode* slave;
std::string savefile;
bool release, die, firstSlave, saveFileToggle, takeSnapshot, doSaveDelta, standalone, printOnly;
messageqcpp::ByteStream delta;
idbdatafile::IDBDataFile* currentSaveFile;
std::string journalName;
idbdatafile::IDBDataFile* journalh;
int64_t snapshotInterval, journalCount;
struct timespec MSG_TIMEOUT;
messageqcpp::MessageQueueServer* server;
messageqcpp::IOSocket master;
SlaveDBRMNode* slave;
std::string savefile;
bool release, die, firstSlave, saveFileToggle, takeSnapshot, doSaveDelta, standalone, printOnly;
messageqcpp::ByteStream delta;
idbdatafile::IDBDataFile* currentSaveFile;
std::string journalName;
idbdatafile::IDBDataFile* journalh;
int64_t snapshotInterval, journalCount;
struct timespec MSG_TIMEOUT;
#ifdef _MSC_VER
boost::mutex fPidMemLock;
DWORD* fPids;
DWORD fMaxPids;
boost::mutex fPidMemLock;
DWORD* fPids;
DWORD fMaxPids;
#endif
};
}
} // namespace BRM
#undef EXPORT

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,6 @@
namespace BRM
{
/** @brief The Slave node of the DBRM system
*
* There are 3 components of the Distributed BRM (DBRM).
@ -90,432 +89,396 @@ namespace BRM
class SlaveDBRMNode
{
public:
EXPORT SlaveDBRMNode() throw();
EXPORT ~SlaveDBRMNode() throw();
public:
EXPORT SlaveDBRMNode() throw();
EXPORT ~SlaveDBRMNode() throw();
/** @brief Allocate a "stripe" of extents for columns in a table.
*
* Allocate a "stripe" of extents for the specified columns and DBRoot
* @param cols (in) List of column OIDs and column widths
* @param dbRoot (in) DBRoot for requested extents.
* @param partitionNum (in/out) Partition number in file path.
* If allocating OID's first extent for this DBRoot, then
* partitionNum is input, else it is an output arg.
* @param segmentNum (out) Segment number selected for new extents.
* @param extents (out) list of lbids, numBlks, and fbo for new extents
* @return 0 on success, -1 on error
*/
EXPORT int createStripeColumnExtents(
const std::vector<CreateStripeColumnExtentsArgIn>& cols,
uint16_t dbRoot,
uint32_t& partitionNum,
uint16_t& segmentNum,
std::vector<CreateStripeColumnExtentsArgOut>& extents) throw();
/** @brief Allocate a "stripe" of extents for columns in a table.
*
* Allocate a "stripe" of extents for the specified columns and DBRoot
* @param cols (in) List of column OIDs and column widths
* @param dbRoot (in) DBRoot for requested extents.
* @param partitionNum (in/out) Partition number in file path.
* If allocating OID's first extent for this DBRoot, then
* partitionNum is input, else it is an output arg.
* @param segmentNum (out) Segment number selected for new extents.
* @param extents (out) list of lbids, numBlks, and fbo for new extents
* @return 0 on success, -1 on error
*/
EXPORT int createStripeColumnExtents(const std::vector<CreateStripeColumnExtentsArgIn>& cols,
uint16_t dbRoot, uint32_t& partitionNum, uint16_t& segmentNum,
std::vector<CreateStripeColumnExtentsArgOut>& extents) throw();
/** @brief Allocate extent in the specified segment file
*
* Allocate column extent for the exact segment file specified by the
* requested OID,DBRoot, partition, and segment.
* @param OID (in) The OID requesting the extent.
* @param colWidth (in) Column width of the OID.
* @param dbRoot (in) DBRoot where extent is to be added.
* @param partitionNum (in) Partition number in file path.
* @param segmentNum (in) Segment number in file path.
* @param colDataType (in) the column type
* @param lbid (out) The first LBID of the extent created.
* @param allocdSize (out) The total number of LBIDs allocated.
* @param startBlockOffset (out) The first block of the extent created.
* @return 0 on success, -1 on error
*/
EXPORT int createColumnExtentExactFile(OID_t oid,
uint32_t colWidth,
uint16_t dbRoot,
uint32_t partitionNum,
uint16_t segmentNum,
execplan::CalpontSystemCatalog::ColDataType colDataType,
LBID_t& lbid,
int& allocdSize,
uint32_t& startBlockOffset) throw();
/** @brief Allocate an extent for a column file
*
* Allocate a column extent for the specified OID and DBRoot.
* @param OID (in) The OID requesting the extent.
* @param colWidth (in) Column width of the OID.
* @param dbRoot (in) DBRoot where extent is to be added.
* @param colDataType (in) the column type
* @param partitionNum (in/out) Partition number in file path.
* If allocating OID's first extent for this DBRoot, then
* partitionNum is input, else it is an output arg.
* @param segmentNum (in/out) Segment number in file path.
* If allocating OID's first extent for this DBRoot, then
* segmentNum is input, else it is an output arg.
* @param lbid (out) The first LBID of the extent created.
* @param allocdSize (out) The total number of LBIDs allocated.
* @param startBlockOffset (out) The first block of the extent created.
* @return 0 on success, -1 on error
*/
EXPORT int createColumnExtent_DBroot(OID_t oid,
uint32_t colWidth,
uint16_t dbRoot,
/** @brief Allocate extent in the specified segment file
*
* Allocate column extent for the exact segment file specified by the
* requested OID,DBRoot, partition, and segment.
* @param OID (in) The OID requesting the extent.
* @param colWidth (in) Column width of the OID.
* @param dbRoot (in) DBRoot where extent is to be added.
* @param partitionNum (in) Partition number in file path.
* @param segmentNum (in) Segment number in file path.
* @param colDataType (in) the column type
* @param lbid (out) The first LBID of the extent created.
* @param allocdSize (out) The total number of LBIDs allocated.
* @param startBlockOffset (out) The first block of the extent created.
* @return 0 on success, -1 on error
*/
EXPORT int createColumnExtentExactFile(OID_t oid, uint32_t colWidth, uint16_t dbRoot, uint32_t partitionNum,
uint16_t segmentNum,
execplan::CalpontSystemCatalog::ColDataType colDataType,
uint32_t& partitionNum,
uint16_t& segmentNum,
LBID_t& lbid,
int& allocdSize,
uint32_t& startBlockOffset) throw();
LBID_t& lbid, int& allocdSize, uint32_t& startBlockOffset) throw();
/** @brief Allocate an extent for a dictionary store file
*
* Allocate a dictionary store extent for the specified OID, dbRoot,
* partition number, and segment number.
* @param OID (in) The OID requesting the extent.
* @param dbRoot (in) DBRoot to assign to the extent.
* @param partitionNum (in) Partition number to assign to the extent.
* @param segmentNum (in) Segment number to assign to the extent.
* @param lbid (out) The first LBID of the extent created.
* @param allocdSize (out) The total number of LBIDs allocated.
* @return 0 on success, -1 on error
*/
EXPORT int createDictStoreExtent(OID_t oid,
uint16_t dbRoot,
uint32_t partitionNum,
uint16_t segmentNum,
LBID_t& lbid,
int& allocdSize) throw();
/** @brief Allocate an extent for a column file
*
* Allocate a column extent for the specified OID and DBRoot.
* @param OID (in) The OID requesting the extent.
* @param colWidth (in) Column width of the OID.
* @param dbRoot (in) DBRoot where extent is to be added.
* @param colDataType (in) the column type
* @param partitionNum (in/out) Partition number in file path.
* If allocating OID's first extent for this DBRoot, then
* partitionNum is input, else it is an output arg.
* @param segmentNum (in/out) Segment number in file path.
* If allocating OID's first extent for this DBRoot, then
* segmentNum is input, else it is an output arg.
* @param lbid (out) The first LBID of the extent created.
* @param allocdSize (out) The total number of LBIDs allocated.
* @param startBlockOffset (out) The first block of the extent created.
* @return 0 on success, -1 on error
*/
EXPORT int createColumnExtent_DBroot(OID_t oid, uint32_t colWidth, uint16_t dbRoot,
execplan::CalpontSystemCatalog::ColDataType colDataType,
uint32_t& partitionNum, uint16_t& segmentNum, LBID_t& lbid,
int& allocdSize, uint32_t& startBlockOffset) throw();
/** @brief Rollback (delete) a set of extents for the specified OID.
*
* Deletes all the extents that logically follow the specified
* column extent; and sets the HWM for the specified extent.
* @param oid OID of the extents to be deleted.
* @param partitionNum Last partition to be kept.
* @param segmentNum Last segment in partitionNum to be kept.
* @param hwm HWM to be assigned to the last extent that is kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackColumnExtents(OID_t oid,
uint32_t partitionNum,
uint16_t segmentNum,
HWM_t hwm) throw();
/** @brief Allocate an extent for a dictionary store file
*
* Allocate a dictionary store extent for the specified OID, dbRoot,
* partition number, and segment number.
* @param OID (in) The OID requesting the extent.
* @param dbRoot (in) DBRoot to assign to the extent.
* @param partitionNum (in) Partition number to assign to the extent.
* @param segmentNum (in) Segment number to assign to the extent.
* @param lbid (out) The first LBID of the extent created.
* @param allocdSize (out) The total number of LBIDs allocated.
* @return 0 on success, -1 on error
*/
EXPORT int createDictStoreExtent(OID_t oid, uint16_t dbRoot, uint32_t partitionNum, uint16_t segmentNum,
LBID_t& lbid, int& allocdSize) throw();
/** @brief Rollback (delete) set of extents for specified OID & DBRoot.
*
* Deletes all the extents that logically follow the specified
* column extent; and sets the HWM for the specified extent.
* @param oid OID of the extents to be deleted.
* @param bDeleteAll Indicates if all extents in oid and dbroot are to
* be deleted; else part#, seg#, and hwm are used.
* @param dbRoot DBRoot of the extents to be deleted.
* @param partitionNum Last partition to be kept.
* @param segmentNum Last segment in partitionNum to be kept.
* @param hwm HWM to be assigned to the last extent that is kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackColumnExtents_DBroot(OID_t oid,
bool bDeleteAll,
uint16_t dbRoot,
uint32_t partitionNum,
uint16_t segmentNum,
HWM_t hwm) throw();
/** @brief Rollback (delete) a set of extents for the specified OID.
*
* Deletes all the extents that logically follow the specified
* column extent; and sets the HWM for the specified extent.
* @param oid OID of the extents to be deleted.
* @param partitionNum Last partition to be kept.
* @param segmentNum Last segment in partitionNum to be kept.
* @param hwm HWM to be assigned to the last extent that is kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackColumnExtents(OID_t oid, uint32_t partitionNum, uint16_t segmentNum, HWM_t hwm) throw();
/** @brief Rollback (delete) a set of dict store extents for an OID.
*
* Arguments specify the last stripe. Any extents after this are
* deleted. The hwm's of the extents in the last stripe are updated
* based on the contents of the hwm vector. If hwms is a partial list,
* (as in the first stripe of a partition), then any extents in sub-
* sequent segment files for that partition are deleted.
* @param oid OID of the extents to be deleted or updated.
* @param partitionNum Last partition to be kept.
* @param hwms Vector of hwms for the last partition to be kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackDictStoreExtents(OID_t oid,
uint32_t partitionNum,
const std::vector<HWM_t>& hwms) throw ();
/** @brief Rollback (delete) set of extents for specified OID & DBRoot.
*
* Deletes all the extents that logically follow the specified
* column extent; and sets the HWM for the specified extent.
* @param oid OID of the extents to be deleted.
* @param bDeleteAll Indicates if all extents in oid and dbroot are to
* be deleted; else part#, seg#, and hwm are used.
* @param dbRoot DBRoot of the extents to be deleted.
* @param partitionNum Last partition to be kept.
* @param segmentNum Last segment in partitionNum to be kept.
* @param hwm HWM to be assigned to the last extent that is kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackColumnExtents_DBroot(OID_t oid, bool bDeleteAll, uint16_t dbRoot, uint32_t partitionNum,
uint16_t segmentNum, HWM_t hwm) throw();
/** @brief Rollback (delete) a set of dict store extents for an OID &
* DBRoot.
*
* Arguments specify the last stripe. Any extents after this are
* deleted. The hwm's of the extents in the last stripe are updated
* based on the contents of the hwm vector. If hwms is a partial list,
* (as in the first stripe of a partition), then any extents in sub-
* sequent segment files for that partition are deleted. If hwms is
* empty then all the extents in dbRoot are deleted.
* @param oid OID of the extents to be deleted or updated.
* @param dbRoot DBRoot of the extents to be deleted.
* @param partitionNum Last partition to be kept.
* @param hwms Vector of hwms for the last partition to be kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackDictStoreExtents_DBroot(OID_t oid,
uint16_t dbRoot,
uint32_t partitionNum,
const std::vector<uint16_t>& segNums,
const std::vector<HWM_t>& hwms) throw ();
/** @brief Rollback (delete) a set of dict store extents for an OID.
*
* Arguments specify the last stripe. Any extents after this are
* deleted. The hwm's of the extents in the last stripe are updated
* based on the contents of the hwm vector. If hwms is a partial list,
* (as in the first stripe of a partition), then any extents in sub-
* sequent segment files for that partition are deleted.
* @param oid OID of the extents to be deleted or updated.
* @param partitionNum Last partition to be kept.
* @param hwms Vector of hwms for the last partition to be kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackDictStoreExtents(OID_t oid, uint32_t partitionNum,
const std::vector<HWM_t>& hwms) throw();
/** @brief delete of column extents for the specified extents.
*
* Deletes the extents from extent map
* @param extentInfo the information for extents
*/
EXPORT int deleteEmptyColExtents(const ExtentsInfoMap_t& extentsInfo) throw();
/** @brief Rollback (delete) a set of dict store extents for an OID &
* DBRoot.
*
* Arguments specify the last stripe. Any extents after this are
* deleted. The hwm's of the extents in the last stripe are updated
* based on the contents of the hwm vector. If hwms is a partial list,
* (as in the first stripe of a partition), then any extents in sub-
* sequent segment files for that partition are deleted. If hwms is
* empty then all the extents in dbRoot are deleted.
* @param oid OID of the extents to be deleted or updated.
* @param dbRoot DBRoot of the extents to be deleted.
* @param partitionNum Last partition to be kept.
* @param hwms Vector of hwms for the last partition to be kept.
* @return 0 on success, -1 on error
*/
EXPORT int rollbackDictStoreExtents_DBroot(OID_t oid, uint16_t dbRoot, uint32_t partitionNum,
const std::vector<uint16_t>& segNums,
const std::vector<HWM_t>& hwms) throw();
/** @brief delete of dictionary extents for the specified extents.
*
* Deletes the extents from extent map
* @param extentInfo the information for extents
*/
EXPORT int deleteEmptyDictStoreExtents(const ExtentsInfoMap_t& extentsInfo) throw();
/** @brief delete of column extents for the specified extents.
*
* Deletes the extents from extent map
* @param extentInfo the information for extents
*/
EXPORT int deleteEmptyColExtents(const ExtentsInfoMap_t& extentsInfo) throw();
/** @brief Delete the extents of an OID and invalidate VSS references to them
*
* Delete the extents assigned to an OID and deletes entries in the VSS
* that refer to the LBIDs used by it.
* @note The old version of this function deliberately did not delete the entries
* in the version buffer.
* @note This function is ridiculously slow right now.
* @param OID The OID of the object being deleted
* @return 0 on success, -1 on error
*/
EXPORT int deleteOID(OID_t oid) throw();
/** @brief delete of dictionary extents for the specified extents.
*
* Deletes the extents from extent map
* @param extentInfo the information for extents
*/
EXPORT int deleteEmptyDictStoreExtents(const ExtentsInfoMap_t& extentsInfo) throw();
/** @brief Delete the extents of OIDs and invalidate VSS references to them
*
* Delete the extents assigned to OIDs and deletes entries in the VSS
* that refer to the LBIDs used by it.
* @note The old version of this function deliberately did not delete the entries
* in the version buffer.
* @param OIDs The OIDs of the object being deleted
* @return 0 on success, -1 on error
*/
EXPORT int deleteOIDs(const OidsMap_t& oids) throw();
/** @brief Delete the extents of an OID and invalidate VSS references to them
*
* Delete the extents assigned to an OID and deletes entries in the VSS
* that refer to the LBIDs used by it.
* @note The old version of this function deliberately did not delete the entries
* in the version buffer.
* @note This function is ridiculously slow right now.
* @param OID The OID of the object being deleted
* @return 0 on success, -1 on error
*/
EXPORT int deleteOID(OID_t oid) throw();
/** @brief Set the "high water mark" of an OID, partition, segment
*
* Set the high water mark (aka, the highest numbered written
* block offset) for a specific OID, partition, segment file.
* @param oid (in) The OID
* @param partitionNum (in) The relevant partition number
* @param segmentNum (in) The relevant segment number
* @param hwm (in) The high water mark of oid
* @return 0 on success, -1 on error
*/
EXPORT int setLocalHWM(OID_t, uint32_t partitionNum, uint16_t segmentNum,
HWM_t hwm, bool firstNode) throw();
/** @brief Delete the extents of OIDs and invalidate VSS references to them
*
* Delete the extents assigned to OIDs and deletes entries in the VSS
* that refer to the LBIDs used by it.
* @note The old version of this function deliberately did not delete the entries
* in the version buffer.
* @param OIDs The OIDs of the object being deleted
* @return 0 on success, -1 on error
*/
EXPORT int deleteOIDs(const OidsMap_t& oids) throw();
EXPORT int bulkSetHWM(const std::vector<BulkSetHWMArg>&, VER_t transID,
bool firstNode) throw();
/** @brief Set the "high water mark" of an OID, partition, segment
*
* Set the high water mark (aka, the highest numbered written
* block offset) for a specific OID, partition, segment file.
* @param oid (in) The OID
* @param partitionNum (in) The relevant partition number
* @param segmentNum (in) The relevant segment number
* @param hwm (in) The high water mark of oid
* @return 0 on success, -1 on error
*/
EXPORT int setLocalHWM(OID_t, uint32_t partitionNum, uint16_t segmentNum, HWM_t hwm,
bool firstNode) throw();
EXPORT int bulkSetHWMAndCP(const std::vector<BulkSetHWMArg>& hwmArgs,
const std::vector<CPInfo>& setCPDataArgs,
const std::vector<CPInfoMerge>& mergeCPDataArgs,
VER_t transID, bool firstNode) throw();
EXPORT int bulkSetHWM(const std::vector<BulkSetHWMArg>&, VER_t transID, bool firstNode) throw();
EXPORT int bulkUpdateDBRoot(const std::vector<BulkUpdateDBRootArg>&) throw();
EXPORT int bulkSetHWMAndCP(const std::vector<BulkSetHWMArg>& hwmArgs,
const std::vector<CPInfo>& setCPDataArgs,
const std::vector<CPInfoMerge>& mergeCPDataArgs, VER_t transID,
bool firstNode) throw();
/** @brief Delete a Partition for the specified OID(s).
*
* @param OID (in) the OID of interest.
* @param partitionNums (in) the set of partitions to be deleted.
*/
EXPORT int deletePartition(const std::set<OID_t>& oids,
std::set<LogicalPartition>& partitionNums, std::string& emsg) throw();
EXPORT int bulkUpdateDBRoot(const std::vector<BulkUpdateDBRootArg>&) throw();
/** @brief Mark a Partition for the specified OID(s) as out of service.
*
* @param OID (in) the OID of interest.
* @param partitionNums (in) the set of partitions to be marked out of service.
*/
EXPORT int markPartitionForDeletion(const std::set<OID_t>& oids,
std::set<LogicalPartition>& partitionNums, std::string& emsg) throw();
/** @brief Delete a Partition for the specified OID(s).
*
* @param OID (in) the OID of interest.
* @param partitionNums (in) the set of partitions to be deleted.
*/
EXPORT int deletePartition(const std::set<OID_t>& oids, std::set<LogicalPartition>& partitionNums,
std::string& emsg) throw();
/** @brief Mark all Partitions for the specified OID(s) as out of service.
*
* @param OID (in) the OID of interest.
*/
EXPORT int markAllPartitionForDeletion(const std::set<OID_t>& oids) throw();
/** @brief Mark a Partition for the specified OID(s) as out of service.
*
* @param OID (in) the OID of interest.
* @param partitionNums (in) the set of partitions to be marked out of service.
*/
EXPORT int markPartitionForDeletion(const std::set<OID_t>& oids, std::set<LogicalPartition>& partitionNums,
std::string& emsg) throw();
/** @brief Restore a Partition for the specified OID(s).
*
* @param OID (in) the OID of interest.
* @param partitionNums (in) the set of partitions to be restored.
*/
EXPORT int restorePartition(const std::set<OID_t>& oids,
std::set<LogicalPartition>& partitionNum, std::string& emsg) throw();
/** @brief Mark all Partitions for the specified OID(s) as out of service.
*
* @param OID (in) the OID of interest.
*/
EXPORT int markAllPartitionForDeletion(const std::set<OID_t>& oids) throw();
/** @brief Delete all extent map rows for the specified dbroot
*
* @param dbroot (in) the dbroot
*/
EXPORT int deleteDBRoot(uint16_t dbroot) throw();
/** @brief Restore a Partition for the specified OID(s).
*
* @param OID (in) the OID of interest.
* @param partitionNums (in) the set of partitions to be restored.
*/
EXPORT int restorePartition(const std::set<OID_t>& oids, std::set<LogicalPartition>& partitionNum,
std::string& emsg) throw();
/** @brief Registers a version buffer entry.
*
* Registers a version buffer entry at <vbOID, vbFBO> with
* values of <transID, lbid>.
* @note The version buffer locations must hold the 'copy' lock
* first.
* @return 0 on success, -1 on error
*/
EXPORT int writeVBEntry(VER_t transID, LBID_t lbid, OID_t vbOID,
uint32_t vbFBO) throw();
/** @brief Delete all extent map rows for the specified dbroot
*
* @param dbroot (in) the dbroot
*/
EXPORT int deleteDBRoot(uint16_t dbroot) throw();
/** @brief Bulk registers a version buffer entry.
*
* Similar to writeVBEntry, but registers the version buffer
* entries in bulk for a list of lbids and vbFBOs, for a given
* transID and vbOID.
* @note The version buffer locations must hold the 'copy' lock
* first.
* @return 0 on success, -1 on error
*/
EXPORT int bulkWriteVBEntry(VER_t transID,
const std::vector<BRM::LBID_t>& lbids,
OID_t vbOID,
const std::vector<uint32_t>& vbFBOs) throw();
/** @brief Registers a version buffer entry.
*
* Registers a version buffer entry at <vbOID, vbFBO> with
* values of <transID, lbid>.
* @note The version buffer locations must hold the 'copy' lock
* first.
* @return 0 on success, -1 on error
*/
EXPORT int writeVBEntry(VER_t transID, LBID_t lbid, OID_t vbOID, uint32_t vbFBO) throw();
/** @brief Atomically prepare to copy data to the version buffer
*
* Atomically sets the copy flag on the specified LBID ranges
* and allocate blocks in the version buffer to copy them to.
* If any LBID in the range cannot be locked, none will be
* and this will return -1.
* @param transID The transaction ID doing the operation
* @param ranges (in) A list of LBID ranges that will be copied
* @param freeList (out) On success, a list of ranges of the version
* buffer blocks to copy the LBID range to.
* @return 0 on success, -1 on error.
*/
/** @brief Bulk registers a version buffer entry.
*
* Similar to writeVBEntry, but registers the version buffer
* entries in bulk for a list of lbids and vbFBOs, for a given
* transID and vbOID.
* @note The version buffer locations must hold the 'copy' lock
* first.
* @return 0 on success, -1 on error
*/
EXPORT int bulkWriteVBEntry(VER_t transID, const std::vector<BRM::LBID_t>& lbids, OID_t vbOID,
const std::vector<uint32_t>& vbFBOs) throw();
/* Note, the params to the analogous DBRM class fcn are slightly different.
* It takes a DBRoot param instead of a VB OID. The conversion is
* done in the controllernode b/c the OID server is housed there.
*/
EXPORT int beginVBCopy(VER_t transID, uint16_t vbOID,
const LBIDRange_v& ranges, VBRange_v& freeList, bool flushPMCache) throw();
/** @brief Atomically prepare to copy data to the version buffer
*
* Atomically sets the copy flag on the specified LBID ranges
* and allocate blocks in the version buffer to copy them to.
* If any LBID in the range cannot be locked, none will be
* and this will return -1.
* @param transID The transaction ID doing the operation
* @param ranges (in) A list of LBID ranges that will be copied
* @param freeList (out) On success, a list of ranges of the version
* buffer blocks to copy the LBID range to.
* @return 0 on success, -1 on error.
*/
/** @brief Atomically unset the copy lock & update the VSS. Beware! Read the warning!
*
* Atomically unset the copy lock for the specified LBID ranges
* and add a new locked VSS entry for each LBID in the range.
* @note The elements of the ranges parameter <b>MUST</b> be the
* same elements passed to beginVBCopy(). The number and order of the
* elements can be different, but every element in ranges must also
* have been an element in beginVBCopy's ranges.
* @return 0 on success, -1 on error.
*/
EXPORT int endVBCopy(VER_t transID, const LBIDRange_v& ranges)
throw();
/* Note, the params to the analogous DBRM class fcn are slightly different.
* It takes a DBRoot param instead of a VB OID. The conversion is
* done in the controllernode b/c the OID server is housed there.
*/
EXPORT int beginVBCopy(VER_t transID, uint16_t vbOID, const LBIDRange_v& ranges, VBRange_v& freeList,
bool flushPMCache) throw();
/** @brief Commit the changes made for the given transaction.
*
* This unlocks the VSS entries with VerID = transID.
* @return 0 on success, -1 on error.
*/
EXPORT int vbCommit(VER_t transID) throw();
/** @brief Atomically unset the copy lock & update the VSS. Beware! Read the warning!
*
* Atomically unset the copy lock for the specified LBID ranges
* and add a new locked VSS entry for each LBID in the range.
* @note The elements of the ranges parameter <b>MUST</b> be the
* same elements passed to beginVBCopy(). The number and order of the
* elements can be different, but every element in ranges must also
* have been an element in beginVBCopy's ranges.
* @return 0 on success, -1 on error.
*/
EXPORT int endVBCopy(VER_t transID, const LBIDRange_v& ranges) throw();
/** @brief Reverse the changes made during the given transaction.
*
* Record that the given LBID was reverted to version verID.
* @warning This removes the copy locks held on all ranges by transID.
* @param transID The transaction ID
* @param lbidList The list of ranges to rollback.
* @param verID The version of the block now in the database.
* @return 0 on success, -1 on error.
*/
EXPORT int vbRollback(VER_t transID, const LBIDRange_v& lbidList,
bool flushPMCache) throw();
/** @brief Commit the changes made for the given transaction.
*
* This unlocks the VSS entries with VerID = transID.
* @return 0 on success, -1 on error.
*/
EXPORT int vbCommit(VER_t transID) throw();
/** @brief Reverse the changes made during the given transaction.
*
* Record that the given LBID was reverted to version verID.
* @warning This removes the copy locks held on all ranges by transID.
* @param transID The transaction ID
* @param lbidList The list of singular LBIDs to rollback.
* @param verID The version of the block now in the database.
* @return 0 on success, -1 on error.
*/
EXPORT int vbRollback(VER_t transID, const std::vector<LBID_t>& lbidList,
bool flushPMCache) throw();
/** @brief Reverse the changes made during the given transaction.
*
* Record that the given LBID was reverted to version verID.
* @warning This removes the copy locks held on all ranges by transID.
* @param transID The transaction ID
* @param lbidList The list of ranges to rollback.
* @param verID The version of the block now in the database.
* @return 0 on success, -1 on error.
*/
EXPORT int vbRollback(VER_t transID, const LBIDRange_v& lbidList, bool flushPMCache) throw();
EXPORT int clear() throw();
/** @brief Reverse the changes made during the given transaction.
*
* Record that the given LBID was reverted to version verID.
* @warning This removes the copy locks held on all ranges by transID.
* @param transID The transaction ID
* @param lbidList The list of singular LBIDs to rollback.
* @param verID The version of the block now in the database.
* @return 0 on success, -1 on error.
*/
EXPORT int vbRollback(VER_t transID, const std::vector<LBID_t>& lbidList, bool flushPMCache) throw();
/** @brief Check the consistency of each data structure
*
* Check the consistency of each data structure
* @return 0 on success, -1 on error.
*/
EXPORT int checkConsistency() throw();
EXPORT int clear() throw();
EXPORT void confirmChanges() throw();
EXPORT void undoChanges() throw();
/** @brief Check the consistency of each data structure
*
* Check the consistency of each data structure
* @return 0 on success, -1 on error.
*/
EXPORT int checkConsistency() throw();
EXPORT int loadExtentMap(const std::string& filename);
EXPORT int saveExtentMap(const std::string& filename);
EXPORT void confirmChanges() throw();
EXPORT void undoChanges() throw();
// Casual partitioning support
//
/** @brief mark the extent containing the lbid as not having valid max and min values
*
**/
EXPORT int markExtentInvalid(const LBID_t lbid,
execplan::CalpontSystemCatalog::ColDataType colDataType);
EXPORT int markExtentsInvalid(const std::vector<LBID_t>& lbids,
const std::vector<execplan::CalpontSystemCatalog::ColDataType>& colDataTypes);
EXPORT int loadExtentMap(const std::string& filename);
EXPORT int saveExtentMap(const std::string& filename);
/** @brief update the extent with the lbidRange with max, min, & seqNum values
*
**/
EXPORT int setExtentMaxMin(const LBID_t lbid, const int64_t max, const int64_t min,
const int32_t seqNum, bool firstNode);
// Casual partitioning support
//
/** @brief mark the extent containing the lbid as not having valid max and min values
*
**/
EXPORT int markExtentInvalid(const LBID_t lbid, execplan::CalpontSystemCatalog::ColDataType colDataType);
EXPORT int markExtentsInvalid(const std::vector<LBID_t>& lbids,
const std::vector<execplan::CalpontSystemCatalog::ColDataType>& colDataTypes);
// Casual partitioning support
//
/** @brief Sets min and max values from the information in the passed map.
*
* @param cpMaxMinMap - Map with cp info. The key must be the starting LBID.
*
**/
// @bug 1970. Added setExtentsMaxMin.
EXPORT int setExtentsMaxMin(const CPMaxMinMap_t& cpMaxMinMap, bool firstNode);
/** @brief update the extent with the lbidRange with max, min, & seqNum values
*
**/
EXPORT int setExtentMaxMin(const LBID_t lbid, const int64_t max, const int64_t min, const int32_t seqNum,
bool firstNode);
/** @brief Merges list of min/max values with current CP min/max info
*
* @param cpMaxMinMap - Map with CP info. The key is the starting LBID
*/
EXPORT int mergeExtentsMaxMin(CPMaxMinMergeMap_t& cpMaxMinMap);
// Casual partitioning support
//
/** @brief Sets min and max values from the information in the passed map.
*
* @param cpMaxMinMap - Map with cp info. The key must be the starting LBID.
*
**/
// @bug 1970. Added setExtentsMaxMin.
EXPORT int setExtentsMaxMin(const CPMaxMinMap_t& cpMaxMinMap, bool firstNode);
/* Write-side copylocks interface */
EXPORT int dmlLockLBIDRanges(const std::vector<LBIDRange>& ranges, int txnID);
EXPORT int dmlReleaseLBIDRanges(const std::vector<LBIDRange>& ranges);
/** @brief Merges list of min/max values with current CP min/max info
*
* @param cpMaxMinMap - Map with CP info. The key is the starting LBID
*/
EXPORT int mergeExtentsMaxMin(CPMaxMinMergeMap_t& cpMaxMinMap);
EXPORT int loadState(std::string filename) throw();
EXPORT int saveState(std::string filename) throw();
/* Write-side copylocks interface */
EXPORT int dmlLockLBIDRanges(const std::vector<LBIDRange>& ranges, int txnID);
EXPORT int dmlReleaseLBIDRanges(const std::vector<LBIDRange>& ranges);
EXPORT const bool* getEMFLLockStatus();
EXPORT const bool* getEMLockStatus();
EXPORT const bool* getVBBMLockStatus();
EXPORT const bool* getVSSLockStatus();
EXPORT int loadState(std::string filename) throw();
EXPORT int saveState(std::string filename) throw();
private:
explicit SlaveDBRMNode(const SlaveDBRMNode& brm);
SlaveDBRMNode& operator=(const SlaveDBRMNode& brm);
int lookup(OID_t oid, LBIDRange_v& lbidList) throw();
EXPORT const bool* getEMFLLockStatus();
EXPORT const bool* getEMLockStatus();
EXPORT const bool* getVBBMLockStatus();
EXPORT const bool* getVSSLockStatus();
MasterSegmentTable mst;
ExtentMap em;
VBBM vbbm;
VSS vss;
CopyLocks copylocks;
bool locked[3]; // 0 = VBBM, 1 = VSS, 2 = CopyLocks
private:
explicit SlaveDBRMNode(const SlaveDBRMNode& brm);
SlaveDBRMNode& operator=(const SlaveDBRMNode& brm);
int lookup(OID_t oid, LBIDRange_v& lbidList) throw();
MasterSegmentTable mst;
ExtentMap em;
VBBM vbbm;
VSS vss;
CopyLocks copylocks;
bool locked[3]; // 0 = VBBM, 1 = VSS, 2 = CopyLocks
};
}
} // namespace BRM
#undef EXPORT

View File

@ -20,7 +20,6 @@
*
****************************************************************************/
#include <iostream>
#include <signal.h>
#include <string>
@ -45,161 +44,152 @@ using namespace BRM;
using namespace std;
SlaveComm* comm;
bool die= false;
bool die = false;
boost::thread_group monitorThreads;
class Opt
{
protected:
const char *m_progname;
const char *m_nodename;
bool m_fg;
public:
Opt(int argc, char **argv)
:m_progname(argv[0]),
m_nodename(argc > 1 ? argv[1] : nullptr),
m_fg(argc > 2 && string(argv[2]) == "fg")
{ }
protected:
const char* m_progname;
const char* m_nodename;
bool m_fg;
public:
Opt(int argc, char** argv)
: m_progname(argv[0]), m_nodename(argc > 1 ? argv[1] : nullptr), m_fg(argc > 2 && string(argv[2]) == "fg")
{
}
};
class ServiceWorkerNode: public Service, public Opt
class ServiceWorkerNode : public Service, public Opt
{
protected:
void setupChildSignalHandlers();
protected:
void setupChildSignalHandlers();
public:
ServiceWorkerNode(const Opt &opt)
:Service("WorkerNode"), Opt(opt)
{ }
void LogErrno() override
{
perror(m_progname);
log_errno(std::string(m_progname));
}
void ParentLogChildMessage(const std::string &str) override
{
log(str, logging::LOG_TYPE_INFO);
}
int Child() override;
int Run()
{
return m_fg ? Child() : RunForking();
}
public:
ServiceWorkerNode(const Opt& opt) : Service("WorkerNode"), Opt(opt)
{
}
void LogErrno() override
{
perror(m_progname);
log_errno(std::string(m_progname));
}
void ParentLogChildMessage(const std::string& str) override
{
log(str, logging::LOG_TYPE_INFO);
}
int Child() override;
int Run()
{
return m_fg ? Child() : RunForking();
}
};
void stop(int sig)
{
if (!die)
{
die = true;
comm->stop();
monitorThreads.interrupt_all();
}
if (!die)
{
die = true;
comm->stop();
monitorThreads.interrupt_all();
}
}
void reset(int sig)
{
comm->reset();
comm->reset();
}
void ServiceWorkerNode::setupChildSignalHandlers()
{
#ifdef SIGHUP
signal(SIGHUP, reset);
signal(SIGHUP, reset);
#endif
signal(SIGINT, stop);
signal(SIGTERM, stop);
signal(SIGINT, stop);
signal(SIGTERM, stop);
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
#endif
struct sigaction ign;
memset(&ign, 0, sizeof(ign));
ign.sa_handler = fatalHandler;
sigaction(SIGSEGV, &ign, 0);
sigaction(SIGABRT, &ign, 0);
sigaction(SIGFPE, &ign, 0);
struct sigaction ign;
memset(&ign, 0, sizeof(ign));
ign.sa_handler = fatalHandler;
sigaction(SIGSEGV, &ign, 0);
sigaction(SIGABRT, &ign, 0);
sigaction(SIGFPE, &ign, 0);
}
int ServiceWorkerNode::Child()
{
setupChildSignalHandlers();
setupChildSignalHandlers();
SlaveDBRMNode slave;
ShmKeys keys;
SlaveDBRMNode slave;
ShmKeys keys;
try
{
comm = new SlaveComm(std::string(m_nodename), &slave);
NotifyServiceStarted();
}
catch (exception& e)
{
ostringstream os;
os << "An error occured: " << e.what();
cerr << os.str() << endl;
log(os.str());
NotifyServiceInitializationFailed();
return 1;
}
try
{
comm = new SlaveComm(std::string(m_nodename), &slave);
NotifyServiceStarted();
}
catch (exception& e)
{
ostringstream os;
os << "An error occured: " << e.what();
cerr << os.str() << endl;
log(os.str());
NotifyServiceInitializationFailed();
return 1;
}
/* Start 4 threads to monitor write lock state */
monitorThreads.create_thread(RWLockMonitor
(&die, slave.getEMFLLockStatus(), keys.KEYRANGE_EMFREELIST_BASE));
monitorThreads.create_thread(RWLockMonitor
(&die, slave.getEMLockStatus(), keys.KEYRANGE_EXTENTMAP_BASE));
monitorThreads.create_thread(RWLockMonitor
(&die, slave.getVBBMLockStatus(), keys.KEYRANGE_VBBM_BASE));
monitorThreads.create_thread(RWLockMonitor
(&die, slave.getVSSLockStatus(), keys.KEYRANGE_VSS_BASE));
/* Start 4 threads to monitor write lock state */
monitorThreads.create_thread(RWLockMonitor(&die, slave.getEMFLLockStatus(), keys.KEYRANGE_EMFREELIST_BASE));
monitorThreads.create_thread(RWLockMonitor(&die, slave.getEMLockStatus(), keys.KEYRANGE_EXTENTMAP_BASE));
monitorThreads.create_thread(RWLockMonitor(&die, slave.getVBBMLockStatus(), keys.KEYRANGE_VBBM_BASE));
monitorThreads.create_thread(RWLockMonitor(&die, slave.getVSSLockStatus(), keys.KEYRANGE_VSS_BASE));
try
{
comm->run();
}
catch (exception& e)
{
ostringstream os;
os << "An error occurred: " << e.what();
cerr << os.str() << endl;
log(os.str());
return 1;
}
return 0;
try
{
comm->run();
}
catch (exception& e)
{
ostringstream os;
os << "An error occurred: " << e.what();
cerr << os.str() << endl;
log(os.str());
return 1;
}
return 0;
}
int main(int argc, char** argv)
{
Opt opt(argc, argv);
Opt opt(argc, argv);
// Set locale language
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
// Set locale language
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
BRM::logInit ( BRM::SubSystemLogId_workerNode );
BRM::logInit(BRM::SubSystemLogId_workerNode);
/*
Need to shutdown TheadPool before fork(),
otherwise it would get stuck when trying to join fPruneThread.
*/
joblist::JobStep::jobstepThreadPool.stop();
/*
Need to shutdown TheadPool before fork(),
otherwise it would get stuck when trying to join fPruneThread.
*/
joblist::JobStep::jobstepThreadPool.stop();
if (argc < 2)
{
ostringstream os;
os << "Usage: " << argv[0] << " DBRM_WorkerN";
cerr << os.str() << endl;
log(os.str());
exit(1);
}
if (argc < 2)
{
ostringstream os;
os << "Usage: " << argv[0] << " DBRM_WorkerN";
cerr << os.str() << endl;
log(os.str());
exit(1);
}
// TODO: this should move to child() probably, like in masternode.cpp
idbdatafile::IDBPolicy::configIDBPolicy();
// TODO: this should move to child() probably, like in masternode.cpp
idbdatafile::IDBPolicy::configIDBPolicy();
return ServiceWorkerNode(opt).Run();
return ServiceWorkerNode(opt).Run();
}

View File

@ -37,18 +37,19 @@ using namespace idbdatafile;
namespace BRM
{
TableLockServer::TableLockServer(SessionManagerServer* sm) : sms(sm)
{
boost::mutex::scoped_lock lk(mutex);
config::Config* config = config::Config::makeConfig();
boost::mutex::scoped_lock lk(mutex);
config::Config* config = config::Config::makeConfig();
filename = config->getConfig("SystemConfig", "TableLockSaveFile");
filename = config->getConfig("SystemConfig", "TableLockSaveFile");
if (filename == "")
throw invalid_argument("TableLockServer: Need to define SystemConfig/TableLockSaveFile in config file"); // todo, replace this
if (filename == "")
throw invalid_argument(
"TableLockServer: Need to define SystemConfig/TableLockSaveFile in config file"); // todo, replace
// this
load();
load();
}
TableLockServer::~TableLockServer()
@ -58,264 +59,259 @@ TableLockServer::~TableLockServer()
// call with lock held
void TableLockServer::save()
{
lit_t it;
uint32_t count = locks.size();
lit_t it;
uint32_t count = locks.size();
const char* filename_p = filename.c_str();
const char* filename_p = filename.c_str();
scoped_ptr<IDBDataFile> out(IDBDataFile::open(
IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG),
filename_p, "wb", 0));
scoped_ptr<IDBDataFile> out(
IDBDataFile::open(IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG), filename_p, "wb", 0));
if (!out)
throw runtime_error("TableLockServer::save(): could not open save file");
out->write((char*)&count, 4);
for (it = locks.begin(); it != locks.end(); ++it)
{
if (!out)
throw runtime_error("TableLockServer::save(): could not open save file");
throw runtime_error("TableLockServer::save(): could not write save file");
out->write((char*) &count, 4);
for (it = locks.begin(); it != locks.end(); ++it)
{
if (!out)
throw runtime_error("TableLockServer::save(): could not write save file");
it->second.serialize(out.get());
}
it->second.serialize(out.get());
}
}
// call with lock held
void TableLockServer::load()
{
uint32_t size;
uint32_t i = 0;
TableLockInfo tli;
uint32_t size;
uint32_t i = 0;
TableLockInfo tli;
/* Need to standardize the file error handling */
const char* filename_p = filename.c_str();
scoped_ptr<IDBDataFile> in(IDBDataFile::open(
IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG),
filename_p, "rb", 0));
/* Need to standardize the file error handling */
const char* filename_p = filename.c_str();
scoped_ptr<IDBDataFile> in(
IDBDataFile::open(IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG), filename_p, "rb", 0));
if (!in)
if (!in)
{
ostringstream os;
os << "TableLockServer::load(): could not open the save file" << filename;
log(os.str(), logging::LOG_TYPE_DEBUG);
return;
}
try
{
in->read((char*)&size, 4);
for (i = 0; i < size; i++)
{
ostringstream os;
os << "TableLockServer::load(): could not open the save file"
<< filename;
log(os.str(), logging::LOG_TYPE_DEBUG);
return;
}
try
{
in->read((char*) &size, 4);
for (i = 0; i < size; i++)
{
tli.deserialize(in.get());
tli.id = sms->getUnique64(); // Need new #s...
if (tli.id == 0) // 0 is an error code
tli.id = sms->getUnique64();
locks[tli.id] = tli;
}
}
catch (std::exception& e)
{
ostringstream os;
os << "TableLockServer::load(): could not load save file " << filename <<
" loaded " << i << "/" << size << " entries\n";
log(os.str(), logging::LOG_TYPE_DEBUG);
throw;
tli.deserialize(in.get());
tli.id = sms->getUnique64(); // Need new #s...
if (tli.id == 0) // 0 is an error code
tli.id = sms->getUnique64();
locks[tli.id] = tli;
}
}
catch (std::exception& e)
{
ostringstream os;
os << "TableLockServer::load(): could not load save file " << filename << " loaded " << i << "/" << size
<< " entries\n";
log(os.str(), logging::LOG_TYPE_DEBUG);
throw;
}
}
// throws on a failed save()
uint64_t TableLockServer::lock(TableLockInfo* tli)
{
set<uint32_t> dbroots;
lit_t it;
uint32_t i;
boost::mutex::scoped_lock lk(mutex);
set<uint32_t> dbroots;
lit_t it;
uint32_t i;
boost::mutex::scoped_lock lk(mutex);
for (i = 0; i < tli->dbrootList.size(); i++)
dbroots.insert(tli->dbrootList[i]);
for (i = 0; i < tli->dbrootList.size(); i++)
dbroots.insert(tli->dbrootList[i]);
for (it = locks.begin(); it != locks.end(); ++it)
for (it = locks.begin(); it != locks.end(); ++it)
{
if (it->second.overlaps(*tli, dbroots))
{
if (it->second.overlaps(*tli, dbroots))
{
tli->ownerName = it->second.ownerName;
tli->ownerPID = it->second.ownerPID;
tli->ownerSessionID = it->second.ownerSessionID;
tli->ownerTxnID = it->second.ownerTxnID;
return false;
}
tli->ownerName = it->second.ownerName;
tli->ownerPID = it->second.ownerPID;
tli->ownerSessionID = it->second.ownerSessionID;
tli->ownerTxnID = it->second.ownerTxnID;
return false;
}
}
tli->id = sms->getUnique64();
if (tli->id == 0) // 0 is an error code
tli->id = sms->getUnique64();
if (tli->id == 0) // 0 is an error code
tli->id = sms->getUnique64();
locks[tli->id] = *tli;
locks[tli->id] = *tli;
try
{
save();
}
catch (...)
{
locks.erase(tli->id);
throw;
}
try
{
save();
}
catch (...)
{
locks.erase(tli->id);
throw;
}
return tli->id;
return tli->id;
}
bool TableLockServer::unlock(uint64_t id)
{
std::map<uint64_t, TableLockInfo>::iterator it;
TableLockInfo tli;
std::map<uint64_t, TableLockInfo>::iterator it;
TableLockInfo tli;
boost::mutex::scoped_lock lk(mutex);
it = locks.find(id);
boost::mutex::scoped_lock lk(mutex);
it = locks.find(id);
if (it != locks.end())
if (it != locks.end())
{
tli = it->second;
locks.erase(it);
try
{
tli = it->second;
locks.erase(it);
try
{
save();
}
catch (...)
{
locks[tli.id] = tli;
throw;
}
return true;
save();
}
catch (...)
{
locks[tli.id] = tli;
throw;
}
return false;
return true;
}
return false;
}
bool TableLockServer::changeState(uint64_t id, LockState state)
{
lit_t it;
boost::mutex::scoped_lock lk(mutex);
LockState old;
lit_t it;
boost::mutex::scoped_lock lk(mutex);
LockState old;
it = locks.find(id);
it = locks.find(id);
if (it == locks.end())
return false;
if (it == locks.end())
return false;
old = it->second.state;
it->second.state = state;
old = it->second.state;
it->second.state = state;
try
{
save();
}
catch (...)
{
it->second.state = old;
throw;
}
try
{
save();
}
catch (...)
{
it->second.state = old;
throw;
}
return true;
return true;
}
bool TableLockServer::changeOwner(uint64_t id, const string& ownerName, uint32_t pid, int32_t session,
int32_t txnID)
{
lit_t it;
boost::mutex::scoped_lock lk(mutex);
string oldName;
uint32_t oldPID;
int32_t oldSession;
int32_t oldTxnID;
lit_t it;
boost::mutex::scoped_lock lk(mutex);
string oldName;
uint32_t oldPID;
int32_t oldSession;
int32_t oldTxnID;
it = locks.find(id);
it = locks.find(id);
if (it == locks.end())
return false;
if (it == locks.end())
return false;
oldName = it->second.ownerName;
oldPID = it->second.ownerPID;
oldSession = it->second.ownerSessionID;
oldTxnID = it->second.ownerTxnID;
it->second.ownerName = ownerName;
it->second.ownerPID = pid;
it->second.ownerSessionID = session;
it->second.ownerTxnID = txnID;
oldName = it->second.ownerName;
oldPID = it->second.ownerPID;
oldSession = it->second.ownerSessionID;
oldTxnID = it->second.ownerTxnID;
it->second.ownerName = ownerName;
it->second.ownerPID = pid;
it->second.ownerSessionID = session;
it->second.ownerTxnID = txnID;
try
{
save();
}
catch (...)
{
it->second.ownerName = oldName;
it->second.ownerPID = oldPID;
it->second.ownerSessionID = oldSession;
it->second.ownerTxnID = oldTxnID;
throw;
}
try
{
save();
}
catch (...)
{
it->second.ownerName = oldName;
it->second.ownerPID = oldPID;
it->second.ownerSessionID = oldSession;
it->second.ownerTxnID = oldTxnID;
throw;
}
return true;
return true;
}
vector<TableLockInfo> TableLockServer::getAllLocks() const
{
vector<TableLockInfo> ret;
boost::mutex::scoped_lock lk(mutex);
constlit_t it;
vector<TableLockInfo> ret;
boost::mutex::scoped_lock lk(mutex);
constlit_t it;
for (it = locks.begin(); it != locks.end(); ++it)
ret.push_back(it->second);
for (it = locks.begin(); it != locks.end(); ++it)
ret.push_back(it->second);
return ret;
return ret;
}
void TableLockServer::releaseAllLocks()
{
std::map<uint64_t, TableLockInfo> tmp;
std::map<uint64_t, TableLockInfo> tmp;
boost::mutex::scoped_lock lk(mutex);
boost::mutex::scoped_lock lk(mutex);
tmp.swap(locks);
try
{
save();
}
catch (...)
{
tmp.swap(locks);
try
{
save();
}
catch (...)
{
tmp.swap(locks);
throw;
}
throw;
}
}
bool TableLockServer::getLockInfo(uint64_t id, TableLockInfo* out) const
{
constlit_t it;
boost::mutex::scoped_lock lk(mutex);
constlit_t it;
boost::mutex::scoped_lock lk(mutex);
it = locks.find(id);
it = locks.find(id);
if (out == NULL)
return (it != locks.end());
if (out == NULL)
return (it != locks.end());
if (it != locks.end())
{
*out = it->second;
return true;
}
return false;
}
if (it != locks.end())
{
*out = it->second;
return true;
}
return false;
}
} // namespace BRM

View File

@ -36,35 +36,34 @@
namespace BRM
{
class TableLockServer
{
public:
EXPORT TableLockServer(SessionManagerServer*);
virtual ~TableLockServer();
public:
EXPORT TableLockServer(SessionManagerServer*);
virtual ~TableLockServer();
EXPORT uint64_t lock(TableLockInfo*);
EXPORT bool unlock(uint64_t id);
EXPORT bool changeState(uint64_t id, LockState state);
EXPORT bool changeOwner(uint64_t id, const std::string& ownerName, uint32_t pid, int32_t sessionID,
int32_t txnID);
EXPORT std::vector<TableLockInfo> getAllLocks() const;
EXPORT void releaseAllLocks();
EXPORT bool getLockInfo(uint64_t id, TableLockInfo* out) const;
EXPORT uint64_t lock(TableLockInfo*);
EXPORT bool unlock(uint64_t id);
EXPORT bool changeState(uint64_t id, LockState state);
EXPORT bool changeOwner(uint64_t id, const std::string& ownerName, uint32_t pid, int32_t sessionID,
int32_t txnID);
EXPORT std::vector<TableLockInfo> getAllLocks() const;
EXPORT void releaseAllLocks();
EXPORT bool getLockInfo(uint64_t id, TableLockInfo* out) const;
private:
void load();
void save();
private:
void load();
void save();
mutable boost::mutex mutex;
std::map<uint64_t, TableLockInfo> locks;
typedef std::map<uint64_t, TableLockInfo>::iterator lit_t;
typedef std::map<uint64_t, TableLockInfo>::const_iterator constlit_t;
std::string filename;
SessionManagerServer* sms;
mutable boost::mutex mutex;
std::map<uint64_t, TableLockInfo> locks;
typedef std::map<uint64_t, TableLockInfo>::iterator lit_t;
typedef std::map<uint64_t, TableLockInfo>::const_iterator constlit_t;
std::string filename;
SessionManagerServer* sms;
};
}
} // namespace BRM
#undef EXPORT

View File

@ -2,236 +2,228 @@
#include "dbrm.h"
using namespace std;
using namespace BRM;
void grabLock()
{
DBRM dbrm;
uint64_t id;
vector<uint32_t> pmlist;
DBRM dbrm;
uint64_t id;
vector<uint32_t> pmlist;
string name = "init";
uint32_t pid = 1;
int32_t sid = 5678;
string name = "init";
uint32_t pid = 1;
int32_t sid = 5678;
pmlist.push_back(1);
pmlist.push_back(1);
try
{
id = dbrm.getTableLock(pmlist, 1234, &name, &pid, &sid, &sid, LOADING);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
id = dbrm.getTableLock(pmlist, 1234, &name, &pid, &sid, &sid, LOADING);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
cout << "lock ID = " << id << endl;
if (id == 0)
cout << " existing owner name = " << name << " pid = " << pid << " session = " << sid << endl;
cout << "lock ID = " << id << endl;
if (id == 0)
cout << " existing owner name = " << name << " pid = " << pid << " session = " << sid << endl;
}
void releaseLock(uint64_t id)
{
DBRM dbrm;
bool ret;
DBRM dbrm;
bool ret;
cout << "releasing lock " << id << endl;
cout << "releasing lock " << id << endl;
try
{
ret = dbrm.releaseTableLock(id);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
ret = dbrm.releaseTableLock(id);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
if (ret)
cout << "success\n";
else
cout << "failed\n";
if (ret)
cout << "success\n";
else
cout << "failed\n";
}
void changeState(uint64_t id)
{
DBRM dbrm;
bool ret;
DBRM dbrm;
bool ret;
cout << "changing state of lock " << id << endl;
cout << "changing state of lock " << id << endl;
try
{
ret = dbrm.changeState(id, CLEANUP);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
ret = dbrm.changeState(id, CLEANUP);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
if (ret)
cout << "success\n";
else
cout << "failed\n";
if (ret)
cout << "success\n";
else
cout << "failed\n";
}
void changeOwner(uint64_t id)
{
DBRM dbrm;
bool ret;
DBRM dbrm;
bool ret;
cout << "changing owner of lock " << id << endl;
cout << "changing owner of lock " << id << endl;
try
{
ret = dbrm.changeOwner(id, "blah blah", 5678, 1234, 9999);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
ret = dbrm.changeOwner(id, "blah blah", 5678, 1234, 9999);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
if (ret)
cout << "success\n";
else
cout << "failed\n";
if (ret)
cout << "success\n";
else
cout << "failed\n";
}
void printAllLocks()
{
DBRM dbrm;
vector<TableLockInfo> locks;
uint32_t i;
DBRM dbrm;
vector<TableLockInfo> locks;
uint32_t i;
try
{
locks = dbrm.getAllTableLocks();
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
locks = dbrm.getAllTableLocks();
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
cout << "got " << locks.size() << " locks\n";
cout << "got " << locks.size() << " locks\n";
for (i = 0; i < locks.size(); i++)
cout << " lock[" << i << "] id=" << locks[i].id << " tableOID=" << locks[i].tableOID <<
" owner: " << locks[i].ownerName << ":" << locks[i].ownerPID << ":" <<
locks[i].ownerSessionID << " " << ctime(&locks[i].creationTime) << endl;
for (i = 0; i < locks.size(); i++)
cout << " lock[" << i << "] id=" << locks[i].id << " tableOID=" << locks[i].tableOID
<< " owner: " << locks[i].ownerName << ":" << locks[i].ownerPID << ":" << locks[i].ownerSessionID
<< " " << ctime(&locks[i].creationTime) << endl;
}
void releaseAllLocks()
{
DBRM dbrm;
DBRM dbrm;
try
{
dbrm.releaseAllTableLocks();
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
dbrm.releaseAllTableLocks();
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
cout << "OK\n";
cout << "OK\n";
}
void getLockInfo(uint64_t id)
{
DBRM dbrm;
bool ret;
TableLockInfo tli;
DBRM dbrm;
bool ret;
TableLockInfo tli;
try
{
ret = dbrm.getTableLockInfo(id, &tli);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
try
{
ret = dbrm.getTableLockInfo(id, &tli);
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
if (ret)
cout << "id=" << tli.id << " tableOID=" << tli.tableOID <<
" owner: " << tli.ownerName << ":" << tli.ownerPID << ":" <<
tli.ownerSessionID << endl;
else
cout << "failed\n";
if (ret)
cout << "id=" << tli.id << " tableOID=" << tli.tableOID << " owner: " << tli.ownerName << ":"
<< tli.ownerPID << ":" << tli.ownerSessionID << endl;
else
cout << "failed\n";
}
int main(int argc, char** argv)
{
if (argc < 2)
{
cout << "Usage: " << argv[0] << " g | r | s | o | p | R | z. Check the code to see what they do. :P\n";
exit(1);
}
if (argc < 2)
char cmd = argv[1][0];
if (cmd == 'g')
grabLock();
else if (cmd == 'r')
{
if (argc < 3)
{
cout << "Usage: " << argv[0] << " g | r | s | o | p | R | z. Check the code to see what they do. :P\n";
exit(1);
cout << "need an ID\n";
exit(1);
}
char cmd = argv[1][0];
if (cmd == 'g')
grabLock();
else if (cmd == 'r')
releaseLock(atoi(argv[2]));
}
else if (cmd == 's')
{
if (argc < 3)
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
releaseLock(atoi(argv[2]));
cout << "need an ID\n";
exit(1);
}
else if (cmd == 's')
changeState(atoi(argv[2]));
}
else if (cmd == 'o')
{
if (argc < 3)
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
changeState(atoi(argv[2]));
cout << "need an ID\n";
exit(1);
}
else if (cmd == 'o')
changeOwner(atoi(argv[2]));
}
else if (cmd == 'p')
printAllLocks();
else if (cmd == 'R')
releaseAllLocks();
else if (cmd == 'z')
{
if (argc < 3)
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
changeOwner(atoi(argv[2]));
cout << "need an ID\n";
exit(1);
}
else if (cmd == 'p')
printAllLocks();
else if (cmd == 'R')
releaseAllLocks();
else if (cmd == 'z')
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
getLockInfo(atoi(argv[2]));
}
else
cout << "bad command, need g | r | s | o | p\n";
getLockInfo(atoi(argv[2]));
}
else
cout << "bad command, need g | r | s | o | p\n";
exit(0);
exit(0);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -45,153 +45,148 @@ namespace BRM
#ifdef BRM_INFO
std::ofstream brmlog(string(MCSLOGDIR) + "/brm.log", std::ios::app);
Tracer::Tracer(const std::string& file, int line, const std::string& msg, bool debug, bool writeNow): fFileName(file), fLine(line), fMsg(msg), fDebug(debug), fpid(getpid())
Tracer::Tracer(const std::string& file, int line, const std::string& msg, bool debug, bool writeNow)
: fFileName(file), fLine(line), fMsg(msg), fDebug(debug), fpid(getpid())
{
if (writeNow)
writeBegin();
if (writeNow)
writeBegin();
}
Tracer::~Tracer()
{
writeEnd();
writeEnd();
}
void printIntVec(const pair<string, const int*>& p)
{
brmlog << p.first << ": (" << *p.second << ") ";
brmlog << p.first << ": (" << *p.second << ") ";
}
void printBoolVec(const pair<string, const bool*>& p)
void printBoolVec(const pair<string, const bool*>& p)
{
brmlog << p.first << ": (" << *p.second << ") ";
brmlog << p.first << ": (" << *p.second << ") ";
}
void printStrVec(const pair<string, const string*>& p)
{
brmlog << p.first << ": (" << *p.second << ") ";
brmlog << p.first << ": (" << *p.second << ") ";
}
void printShortVec(const pair<string, const short*>& p)
{
brmlog << p.first << ": (" << *p.second << ") ";
brmlog << p.first << ": (" << *p.second << ") ";
}
void printInt64Vec(const pair<string, const int64_t*>& p)
{
brmlog << p.first << ": (" << *p.second << ") ";
brmlog << p.first << ": (" << *p.second << ") ";
}
void Tracer::writeBegin()
{
brmlog << timeStamp() << fpid << ":" << fFileName << "@" << fLine << " " << fMsg << " begin - ";
for_each(fInputs.begin(), fInputs.end(), printIntVec);
for_each(fBoolInputs.begin(), fBoolInputs.end(), printBoolVec);
for_each(fStrInputs.begin(), fStrInputs.end(), printStrVec);
for_each(fShortInputs.begin(), fShortInputs.end(), printShortVec);
for_each(fInt64Inputs.begin(), fInt64Inputs.end(), printInt64Vec);
brmlog << endl << flush;
brmlog << timeStamp() << fpid << ":" << fFileName << "@" << fLine << " " << fMsg << " begin - ";
for_each(fInputs.begin(), fInputs.end(), printIntVec);
for_each(fBoolInputs.begin(), fBoolInputs.end(), printBoolVec);
for_each(fStrInputs.begin(), fStrInputs.end(), printStrVec);
for_each(fShortInputs.begin(), fShortInputs.end(), printShortVec);
for_each(fInt64Inputs.begin(), fInt64Inputs.end(), printInt64Vec);
brmlog << endl << flush;
}
void Tracer::writeEnd()
{
brmlog << timeStamp() << fpid << ":" << fFileName << " " << fMsg << " end ";
brmlog << timeStamp() << fpid << ":" << fFileName << " " << fMsg << " end ";
if (! fOutputs.empty() || ! fBoolOutputs.empty())
brmlog << "- ";
for_each(fOutputs.begin(), fOutputs.end(), printIntVec);
for_each(fBoolOutputs.begin(), fBoolOutputs.end(), printBoolVec);
for_each(fShortOutputs.begin(), fShortOutputs.end(), printShortVec);
for_each(fInt64Outputs.begin(), fInt64Outputs.end(), printInt64Vec);
brmlog << endl << flush;
if (!fOutputs.empty() || !fBoolOutputs.empty())
brmlog << "- ";
for_each(fOutputs.begin(), fOutputs.end(), printIntVec);
for_each(fBoolOutputs.begin(), fBoolOutputs.end(), printBoolVec);
for_each(fShortOutputs.begin(), fShortOutputs.end(), printShortVec);
for_each(fInt64Outputs.begin(), fInt64Outputs.end(), printInt64Vec);
brmlog << endl << flush;
}
void Tracer::writeDirect(const std::string& msg)
{
brmlog << msg << endl;
brmlog << msg << endl;
}
string Tracer::timeStamp()
{
time_t outputTime;
time(&outputTime);
string datestr(ctime(&outputTime));
time_t outputTime;
time(&outputTime);
string datestr(ctime(&outputTime));
try
try
{
// replace newline
return datestr.replace(datestr.length() - 1, 1, string(":"));
}
catch (exception& ex)
{
size_t tries = 3;
while (!datestr.length() && tries--)
datestr = ctime(&outputTime);
if (datestr.length())
return datestr.replace(datestr.length() - 1, 1, string(":"));
else
{
//replace newline
return datestr.replace(datestr.length() - 1, 1, string(":"));
}
catch (exception& ex)
{
size_t tries = 3;
while (!datestr.length() && tries--)
datestr = ctime(&outputTime);
if (datestr.length())
return datestr.replace(datestr.length() - 1, 1, string(":"));
else
{
std::cerr << __FILE__ << "@" << __LINE__ << " " << ex.what() << " ";
cerr << datestr << " length " << datestr.length() << " Source: ";
cerr << fFileName << "@" << fLine << " " << fMsg << endl;
return string("timestamp error:");
}
std::cerr << __FILE__ << "@" << __LINE__ << " " << ex.what() << " ";
cerr << datestr << " length " << datestr.length() << " Source: ";
cerr << fFileName << "@" << fLine << " " << fMsg << endl;
return string("timestamp error:");
}
}
}
void Tracer::addInput(const string& name, const int* value)
{
fInputs.push_back(make_pair(name, value));
fInputs.push_back(make_pair(name, value));
}
void Tracer::addInput(const string& name, const string* value)
{
fStrInputs.push_back(make_pair(name, value));
fStrInputs.push_back(make_pair(name, value));
}
void Tracer::addInput(const string& name, const bool* value)
{
fBoolInputs.push_back(make_pair(name, value));
fBoolInputs.push_back(make_pair(name, value));
}
void Tracer::addInput(const string& name, const short* value)
{
fShortInputs.push_back(make_pair(name, value));
fShortInputs.push_back(make_pair(name, value));
}
void Tracer::addInput(const string& name, const int64_t* value)
{
fInt64Inputs.push_back(make_pair(name, value));
fInt64Inputs.push_back(make_pair(name, value));
}
void Tracer::addOutput(const string& name, const int* value)
{
fOutputs.push_back(make_pair(name, value));
fOutputs.push_back(make_pair(name, value));
}
void Tracer::addOutput(const string& name, const bool* value)
{
fBoolOutputs.push_back(make_pair(name, value));
fBoolOutputs.push_back(make_pair(name, value));
}
void Tracer::addOutput(const string& name, const short* value)
{
fShortOutputs.push_back(make_pair(name, value));
fShortOutputs.push_back(make_pair(name, value));
}
void Tracer::addOutput(const string& name, const int64_t* value)
{
fInt64Outputs.push_back(make_pair(name, value));
fInt64Outputs.push_back(make_pair(name, value));
}
#endif
} //namespace
} // namespace BRM

View File

@ -40,155 +40,139 @@
namespace BRM
{
/** @brief Trace beginning and end of a call.
*
* When turned on, fDebug is true, Tracer writes informational messages to /var/log/mariadb/columnstore/brm.log.
* It keeps track of integral, string and boolean inputs, and integral and boolean outputs.
* If it should print a message immediately from the constructor, call it with the final parameter,
* writeNow, true (default). If input and output parameters need to be added, call it with
* writeNow false. Then writeBegin() must be called explicitely.
*
* Input parameters are added with addInput, output with addOutput.
*
* On end, if debug is set, an end message is printed with the output parameters.
*/
*
* When turned on, fDebug is true, Tracer writes informational messages to
* /var/log/mariadb/columnstore/brm.log. It keeps track of integral, string and boolean inputs, and integral
* and boolean outputs. If it should print a message immediately from the constructor, call it with the final
* parameter, writeNow, true (default). If input and output parameters need to be added, call it with
* writeNow false. Then writeBegin() must be called explicitely.
*
* Input parameters are added with addInput, output with addOutput.
*
* On end, if debug is set, an end message is printed with the output parameters.
*/
class Tracer
{
public:
/** @brief Tracer Constructor
*
* @param file (in string) the file name.
* @param line (in int ) the line number.
* @param msg (in string) the message that will be printed at the begin and end.
* @param debug (in bool) if information should be printed
* @param writeNow (in bool) whether to print the begin message from the constructor
* (printed if debug is true.)
*/
EXPORT Tracer(const std::string& file, int line, const std::string& msg, bool debug, bool writeNow = true);
public:
/** @brief Tracer Constructor
*
* @param file (in string) the file name.
* @param line (in int ) the line number.
* @param msg (in string) the message that will be printed at the begin and end.
* @param debug (in bool) if information should be printed
* @param writeNow (in bool) whether to print the begin message from the constructor
* (printed if debug is true.)
*/
EXPORT Tracer(const std::string& file, int line, const std::string& msg, bool debug, bool writeNow = true);
/** @brief Tracer destructor
*
* Prints the output message if debug is true.
*/
EXPORT ~Tracer();
/** @brief Tracer destructor
*
* Prints the output message if debug is true.
*/
EXPORT ~Tracer();
/** @brief writeBegin
*
* Prints the begin message in form:
* file@line number begin - followed by the input parameters:
* name: (value)
*/
EXPORT void writeBegin();
/** @brief writeBegin
*
* Prints the begin message in form:
* file@line number begin - followed by the input parameters:
* name: (value)
*/
EXPORT void writeBegin();
/** @brief writeEnd
*
* Prints the end message in form:
* file@line number begin - followed by the output parameters:
* name: (value)
*/
EXPORT void writeEnd();
/** @brief writeEnd
*
* Prints the end message in form:
* file@line number begin - followed by the output parameters:
* name: (value)
*/
EXPORT void writeEnd();
/** @brief writeDirect
*
* Prints specified string immediately (directly) to the brm log.
* Different than the addInput and addOutput functions that
* accumulate the data for later printing to the brm log.
* @param msg String to be printed to the brm log
*/
void writeDirect(const std::string& msg);
/** @brief writeDirect
*
* Prints specified string immediately (directly) to the brm log.
* Different than the addInput and addOutput functions that
* accumulate the data for later printing to the brm log.
* @param msg String to be printed to the brm log
*/
void writeDirect(const std::string& msg);
/** @brief addInput
*
* @param name (in string) the variable name.
* @param value (in int* or string* or bool* ) the variable
*/
EXPORT void addInput(const std::string& name, const int* value);
EXPORT void addInput(const std::string& name, const std::string* value);
EXPORT void addInput(const std::string& name, const bool* value);
EXPORT void addInput(const std::string& name, const short* value);
EXPORT void addInput(const std::string& name, const int64_t* value);
/** @brief addInput
*
* @param name (in string) the variable name.
* @param value (in int* or string* or bool* ) the variable
*/
EXPORT void addInput(const std::string& name, const int* value);
EXPORT void addInput(const std::string& name, const std::string* value);
EXPORT void addInput(const std::string& name, const bool* value);
EXPORT void addInput(const std::string& name, const short* value);
EXPORT void addInput(const std::string& name, const int64_t* value);
/** @brief addOutput
*
* @param name (in string) the variable name.
* @param value (in int* or bool* ) the variable
*/
EXPORT void addOutput(const std::string& name, const int* value);
EXPORT void addOutput(const std::string& name, const bool* value);
EXPORT void addOutput(const std::string& name, const short* value);
EXPORT void addOutput(const std::string& name, const int64_t* value);
/** @brief addOutput
*
* @param name (in string) the variable name.
* @param value (in int* or bool* ) the variable
*/
EXPORT void addOutput(const std::string& name, const int* value);
EXPORT void addOutput(const std::string& name, const bool* value);
EXPORT void addOutput(const std::string& name, const short* value);
EXPORT void addOutput(const std::string& name, const int64_t* value);
private:
std::string timeStamp();
typedef std::vector<std::pair <std::string, const int*> > ValuesVec;
typedef std::vector<std::pair <std::string, const std::string*> > ValuesStrVec;
typedef std::vector<std::pair <std::string, const bool*> > ValuesBoolVec;
typedef std::vector<std::pair <std::string, const short*> > ValuesShortVec;
typedef std::vector<std::pair <std::string, const int64_t*> > ValuesInt64Vec;
std::string fFileName;
int fLine;
std::string fMsg;
bool fDebug;
ValuesVec fInputs;
ValuesStrVec fStrInputs;
ValuesBoolVec fBoolInputs;
ValuesShortVec fShortInputs;
ValuesInt64Vec fInt64Inputs;
ValuesVec fOutputs;
ValuesBoolVec fBoolOutputs;
ValuesShortVec fShortOutputs;
ValuesInt64Vec fInt64Outputs;
pid_t fpid;
private:
std::string timeStamp();
typedef std::vector<std::pair<std::string, const int*> > ValuesVec;
typedef std::vector<std::pair<std::string, const std::string*> > ValuesStrVec;
typedef std::vector<std::pair<std::string, const bool*> > ValuesBoolVec;
typedef std::vector<std::pair<std::string, const short*> > ValuesShortVec;
typedef std::vector<std::pair<std::string, const int64_t*> > ValuesInt64Vec;
std::string fFileName;
int fLine;
std::string fMsg;
bool fDebug;
ValuesVec fInputs;
ValuesStrVec fStrInputs;
ValuesBoolVec fBoolInputs;
ValuesShortVec fShortInputs;
ValuesInt64Vec fInt64Inputs;
ValuesVec fOutputs;
ValuesBoolVec fBoolOutputs;
ValuesShortVec fShortOutputs;
ValuesInt64Vec fInt64Outputs;
pid_t fpid;
};
/** @brief tracer macros
*
* Use the contructors if there is a bool fDebug in scope.
*/
*
* Use the contructors if there is a bool fDebug in scope.
*/
#define TRACER_WRITENOW(a) Tracer tracer(__FILE__, __LINE__, a, fDebug);
#define TRACER_WRITENOW(a)\
Tracer tracer(__FILE__, __LINE__, a, fDebug);
#define TRACER_WRITELATER(a) Tracer tracer(__FILE__, __LINE__, a, fDebug, false);
#define TRACER_WRITELATER(a)\
Tracer tracer(__FILE__, __LINE__, a, fDebug, false);
#define TRACER_ADDINPUT(a) tracer.addInput((std::string) #a, (int*)&a);
#define TRACER_ADDINPUT(a)\
tracer.addInput((std::string)#a, (int*)&a);
#define TRACER_ADDSTRINPUT(a) tracer.addInput((std::string) #a, &a);
#define TRACER_ADDSTRINPUT(a)\
tracer.addInput((std::string)#a, &a);
#define TRACER_ADDBOOLINPUT(a) tracer.addInput((std::string) #a, &a);
#define TRACER_ADDBOOLINPUT(a)\
tracer.addInput((std::string)#a, &a);
#define TRACER_ADDSHORTINPUT(a) tracer.addInput((std::string) #a, (short*)&a);
#define TRACER_ADDSHORTINPUT(a)\
tracer.addInput((std::string)#a, (short*)&a);
#define TRACER_ADDINT64INPUT(a) tracer.addInput((std::string) #a, (int64_t*)&a);
#define TRACER_ADDINT64INPUT(a)\
tracer.addInput((std::string)#a, (int64_t*)&a);
#define TRACER_ADDOUTPUT(a) tracer.addOutput((std::string) #a, (int*)&a);
#define TRACER_ADDOUTPUT(a)\
tracer.addOutput((std::string)#a, (int*)&a);
#define TRACER_ADDBOOLOUTPUT(a) tracer.addOutput((std::string) #a, &a);
#define TRACER_ADDBOOLOUTPUT(a)\
tracer.addOutput((std::string)#a, &a);
#define TRACER_ADDSHORTOUTPUT(a) tracer.addOutput((std::string) #a, (short*)&a);
#define TRACER_ADDSHORTOUTPUT(a)\
tracer.addOutput((std::string)#a, (short*)&a);
#define TRACER_ADDINT64OUTPUT(a) tracer.addOutput((std::string) #a, (int64_t*)&a);
#define TRACER_ADDINT64OUTPUT(a)\
tracer.addOutput((std::string)#a, (int64_t*)&a);
#define TRACER_WRITE tracer.writeBegin();
#define TRACER_WRITE\
tracer.writeBegin();
#define TRACER_WRITEDIRECT(msg)\
tracer.writeDirect(msg);
}
#define TRACER_WRITEDIRECT(msg) tracer.writeDirect(msg);
} // namespace BRM
#undef EXPORT
#endif

View File

@ -29,7 +29,6 @@
namespace BRM
{
TransactionNode::TransactionNode(int txn) : txnID(txn), _die(false), _sleeping(false)
{
}
@ -40,39 +39,39 @@ TransactionNode::~TransactionNode()
void TransactionNode::setTxnID(VER_t txn)
{
txnID = txn;
txnID = txn;
}
int TransactionNode::getTxnID() const
{
return txnID;
return txnID;
}
void TransactionNode::sleep(boost::mutex& mutex)
{
_sleeping = true;
condVar.wait(mutex);
_sleeping = true;
condVar.wait(mutex);
}
void TransactionNode::wake()
{
condVar.notify_one();
_sleeping = false;
condVar.notify_one();
_sleeping = false;
}
void TransactionNode::die()
{
_die = true;
_die = true;
}
bool TransactionNode::dead()
{
return _die;
return _die;
}
bool TransactionNode::sleeping()
{
return _sleeping;
return _sleeping;
}
} // namespace
} // namespace BRM

View File

@ -41,33 +41,32 @@
namespace BRM
{
class TransactionNode : public RGNode
{
public:
EXPORT explicit TransactionNode(int txnid = 0);
EXPORT virtual ~TransactionNode();
public:
EXPORT explicit TransactionNode(int txnid = 0);
EXPORT virtual ~TransactionNode();
EXPORT void setTxnID(VER_t);
EXPORT int getTxnID() const;
EXPORT void setTxnID(VER_t);
EXPORT int getTxnID() const;
EXPORT void sleep(boost::mutex& mutex);
EXPORT void wake();
EXPORT void die();
EXPORT bool dead();
EXPORT bool sleeping();
EXPORT void sleep(boost::mutex& mutex);
EXPORT void wake();
EXPORT void die();
EXPORT bool dead();
EXPORT bool sleeping();
private:
TransactionNode(const TransactionNode&);
TransactionNode& operator=(const TransactionNode&);
private:
TransactionNode(const TransactionNode&);
TransactionNode& operator=(const TransactionNode&);
boost::condition condVar;
VER_t txnID;
bool _die, _sleeping;
boost::condition condVar;
VER_t txnID;
bool _die, _sleeping;
};
#undef EXPORT
} // namespace
} // namespace BRM
#endif // TRANSACTIONNODE_H_
#endif // TRANSACTIONNODE_H_

View File

@ -30,7 +30,6 @@ using namespace std;
namespace BRM
{
Undoable::Undoable()
{
}
@ -41,30 +40,30 @@ Undoable::~Undoable()
inline void Undoable::makeUndoRecord(void* start, int size)
{
ImageDelta d;
ImageDelta d;
if (size > ID_MAXSIZE)
throw overflow_error("Undoable::makeUndoRecord(): size > max");
if (size > ID_MAXSIZE)
throw overflow_error("Undoable::makeUndoRecord(): size > max");
d.start = start;
d.size = size;
memcpy(d.data, start, size);
undoRecords.push_back(d);
d.start = start;
d.size = size;
memcpy(d.data, start, size);
undoRecords.push_back(d);
}
void Undoable::undoChanges()
{
vector<ImageDelta>::reverse_iterator it;
vector<ImageDelta>::reverse_iterator it;
for (it = undoRecords.rbegin(); it != undoRecords.rend(); it++)
memcpy((*it).start, (*it).data, (*it).size);
for (it = undoRecords.rbegin(); it != undoRecords.rend(); it++)
memcpy((*it).start, (*it).data, (*it).size);
undoRecords.clear();
undoRecords.clear();
}
void Undoable::confirmChanges()
{
undoRecords.clear();
undoRecords.clear();
}
}
} // namespace BRM

View File

@ -40,23 +40,22 @@
namespace BRM
{
class Undoable
{
public:
EXPORT Undoable();
EXPORT virtual ~Undoable();
public:
EXPORT Undoable();
EXPORT virtual ~Undoable();
EXPORT virtual void confirmChanges();
EXPORT virtual void undoChanges();
EXPORT virtual void confirmChanges();
EXPORT virtual void undoChanges();
protected:
virtual void makeUndoRecord(void* start, int size);
std::vector<ImageDelta> undoRecords;
protected:
virtual void makeUndoRecord(void* start, int size);
std::vector<ImageDelta> undoRecords;
};
#undef EXPORT
}
} // namespace BRM
#endif

File diff suppressed because it is too large Load Diff

View File

@ -41,22 +41,21 @@
// These config parameters need to be loaded
//will get a small hash function performance boost by using powers of 2
// will get a small hash function performance boost by using powers of 2
#define VBSTORAGE_INITIAL_COUNT 100000
#define VBSTORAGE_INITIAL_SIZE (VBSTORAGE_INITIAL_COUNT*sizeof(VBBMEntry))
#define VBSTORAGE_INITIAL_SIZE (VBSTORAGE_INITIAL_COUNT * sizeof(VBBMEntry))
#define VBSTORAGE_INCREMENT_COUNT 10000
#define VBSTORAGE_INCREMENT (VBSTORAGE_INCREMENT_COUNT*sizeof(VBBMEntry))
#define VBSTORAGE_INCREMENT (VBSTORAGE_INCREMENT_COUNT * sizeof(VBBMEntry))
// (average list length = 4)
#define VBTABLE_INITIAL_SIZE (25000*sizeof(int))
#define VBTABLE_INCREMENT (2500*sizeof(int))
#define VBTABLE_INITIAL_SIZE (25000 * sizeof(int))
#define VBTABLE_INCREMENT (2500 * sizeof(int))
#define VBBM_INCREMENT (VBTABLE_INCREMENT + VBSTORAGE_INCREMENT)
#define VBBM_SIZE(files, entries) \
((entries * sizeof(VBBMEntry)) + (entries/4 * sizeof(int)) \
+ (files * sizeof(VBFileMetadata)) + sizeof(VBShmsegHeader))
#define VBBM_SIZE(files, entries) \
((entries * sizeof(VBBMEntry)) + (entries / 4 * sizeof(int)) + (files * sizeof(VBFileMetadata)) + \
sizeof(VBShmsegHeader))
#if defined(_MSC_VER) && defined(xxxVBBM_DLLEXPORT)
#define EXPORT __declspec(dllexport)
@ -64,7 +63,6 @@
#define EXPORT
#endif
namespace idbdatafile
{
class IDBDataFile;
@ -72,89 +70,88 @@ class IDBDataFile;
namespace BRM
{
class VSS;
struct VBFileMetadata
{
OID_t OID;
uint64_t fileSize;
uint64_t nextOffset;
OID_t OID;
uint64_t fileSize;
uint64_t nextOffset;
};
struct VBBMEntry
{
LBID_t lbid;
VER_t verID;
OID_t vbOID;
uint32_t vbFBO;
int next;
EXPORT VBBMEntry();
LBID_t lbid;
VER_t verID;
OID_t vbOID;
uint32_t vbFBO;
int next;
EXPORT VBBMEntry();
};
struct VBShmsegHeader
{
int nFiles;
int vbCapacity;
int vbCurrentSize;
int vbLWM;
int numHashBuckets;
int nFiles;
int vbCapacity;
int vbCurrentSize;
int vbLWM;
int numHashBuckets;
// the rest of the overlay looks like this
// VBFileMetadata files[nFiles];
// int hashBuckets[numHashBuckets];
// VBBMEntry storage[vbCapacity];
// the rest of the overlay looks like this
// VBFileMetadata files[nFiles];
// int hashBuckets[numHashBuckets];
// VBBMEntry storage[vbCapacity];
};
class VBBMImpl
{
public:
static VBBMImpl* makeVBBMImpl(unsigned key, off_t size, bool readOnly = false);
public:
static VBBMImpl* makeVBBMImpl(unsigned key, off_t size, bool readOnly = false);
inline void grow(unsigned key, off_t size)
inline void grow(unsigned key, off_t size)
#ifdef NDEBUG
{
fVBBM.grow(key, size);
}
{
fVBBM.grow(key, size);
}
#else
{
int rc = fVBBM.grow(key, size);
idbassert(rc == 0);
}
{
int rc = fVBBM.grow(key, size);
idbassert(rc == 0);
}
#endif
inline void makeReadOnly()
{
fVBBM.setReadOnly();
}
inline void clear(unsigned key, off_t size)
{
fVBBM.clear(key, size);
}
inline void swapout(BRMShmImpl& rhs)
{
fVBBM.swap(rhs);
rhs.destroy();
}
inline unsigned key() const
{
return fVBBM.key();
}
inline void makeReadOnly()
{
fVBBM.setReadOnly();
}
inline void clear(unsigned key, off_t size)
{
fVBBM.clear(key, size);
}
inline void swapout(BRMShmImpl& rhs)
{
fVBBM.swap(rhs);
rhs.destroy();
}
inline unsigned key() const
{
return fVBBM.key();
}
inline VBShmsegHeader* get() const
{
return reinterpret_cast<VBShmsegHeader*>(fVBBM.fMapreg.get_address());
}
inline VBShmsegHeader* get() const
{
return reinterpret_cast<VBShmsegHeader*>(fVBBM.fMapreg.get_address());
}
private:
VBBMImpl(unsigned key, off_t size, bool readOnly = false);
~VBBMImpl();
VBBMImpl(const VBBMImpl& rhs);
VBBMImpl& operator=(const VBBMImpl& rhs);
private:
VBBMImpl(unsigned key, off_t size, bool readOnly = false);
~VBBMImpl();
VBBMImpl(const VBBMImpl& rhs);
VBBMImpl& operator=(const VBBMImpl& rhs);
BRMShmImpl fVBBM;
BRMShmImpl fVBBM;
static boost::mutex fInstanceMutex;
static VBBMImpl* fInstance;
static boost::mutex fInstanceMutex;
static VBBMImpl* fInstance;
};
/** @brief The Version Buffer Block Map (VBBM)
@ -187,78 +184,75 @@ private:
class VBBM : public Undoable
{
public:
enum OPS
{
NONE,
READ,
WRITE
};
public:
enum OPS
{
NONE,
READ,
WRITE
};
EXPORT VBBM();
EXPORT ~VBBM();
EXPORT VBBM();
EXPORT ~VBBM();
EXPORT void lock(OPS op);
EXPORT void release(OPS op);
EXPORT int lookup(LBID_t lbid, VER_t ver, OID_t& oid, uint32_t& fbo) const;
EXPORT void insert(LBID_t lbid, VER_t ver, OID_t oid, uint32_t fbo, bool loading = false);
EXPORT void getBlocks(int num, OID_t vbOID, std::vector<VBRange>& vbRanges, VSS& vss, bool flushPMCache);
EXPORT void removeEntry(LBID_t, VER_t ver);
EXPORT void lock(OPS op);
EXPORT void release(OPS op);
EXPORT int lookup(LBID_t lbid, VER_t ver, OID_t& oid, uint32_t& fbo) const;
EXPORT void insert(LBID_t lbid, VER_t ver, OID_t oid, uint32_t fbo, bool loading = false);
EXPORT void getBlocks(int num, OID_t vbOID, std::vector<VBRange>& vbRanges, VSS& vss,
bool flushPMCache);
EXPORT void removeEntry(LBID_t, VER_t ver);
EXPORT int size() const;
EXPORT bool hashEmpty() const;
EXPORT int checkConsistency() const;
EXPORT void setReadOnly();
EXPORT int size() const;
EXPORT bool hashEmpty() const;
EXPORT int checkConsistency() const;
EXPORT void setReadOnly();
EXPORT void clear();
EXPORT void load(std::string filename);
EXPORT void loadVersion2(idbdatafile::IDBDataFile* in);
EXPORT void save(std::string filename);
EXPORT void clear();
EXPORT void load(std::string filename);
EXPORT void loadVersion2(idbdatafile::IDBDataFile* in);
EXPORT void save(std::string filename);
#ifdef BRM_DEBUG
EXPORT int getShmid() const;
EXPORT int getShmid() const;
#endif
private:
VBBM(const VBBM&);
VBBM& operator=(const VBBM&);
private:
VBBM(const VBBM&);
VBBM& operator=(const VBBM&);
VBShmsegHeader* vbbm;
VBFileMetadata* files;
int* hashBuckets;
VBBMEntry* storage;
VBShmsegHeader* vbbm;
VBFileMetadata* files;
int* hashBuckets;
VBBMEntry* storage;
key_t currentVBBMShmkey;
int vbbmShmid;
bool r_only;
MSTEntry* vbbmShminfo;
MasterSegmentTable mst;
static boost::mutex mutex; // @bug5355 - made mutex static
static const int MAX_IO_RETRIES = 10;
key_t currentVBBMShmkey;
int vbbmShmid;
bool r_only;
MSTEntry* vbbmShminfo;
MasterSegmentTable mst;
static boost::mutex mutex; // @bug5355 - made mutex static
static const int MAX_IO_RETRIES = 10;
key_t chooseShmkey() const;
void growVBBM(bool addAFile = false);
void growForLoad(int count);
void copyVBBM(VBShmsegHeader* dest);
void initShmseg(int nFiles);
key_t chooseShmkey() const;
void growVBBM(bool addAFile = false);
void growForLoad(int count);
void copyVBBM(VBShmsegHeader* dest);
void initShmseg(int nFiles);
void _insert(VBBMEntry& e, VBShmsegHeader* dest, int* destTable, VBBMEntry*
destStorage, bool loading = false);
int getIndex(LBID_t lbid, VER_t verID, int& prev, int& bucket) const;
ShmKeys fShmKeys;
VBBMImpl* fPVBBMImpl;
void _insert(VBBMEntry& e, VBShmsegHeader* dest, int* destTable, VBBMEntry* destStorage,
bool loading = false);
int getIndex(LBID_t lbid, VER_t verID, int& prev, int& bucket) const;
ShmKeys fShmKeys;
VBBMImpl* fPVBBMImpl;
/* Shared nothing mods */
uint64_t currentFileSize;
void setCurrentFileSize();
uint32_t addVBFileIfNotExists(OID_t vbOID);
/* Shared nothing mods */
uint64_t currentFileSize;
void setCurrentFileSize();
uint32_t addVBFileIfNotExists(OID_t vbOID);
};
}
} // namespace BRM
#undef EXPORT
#endif // _VBBM_H_
#endif // _VBBM_H_

File diff suppressed because it is too large Load Diff

View File

@ -52,23 +52,22 @@
// These config parameters need to be loaded
//will get a small hash function performance boost by using powers of 2
// will get a small hash function performance boost by using powers of 2
#define VSSSTORAGE_INITIAL_COUNT 200000
#define VSSSTORAGE_INITIAL_SIZE (VSSSTORAGE_INITIAL_COUNT*sizeof(VSSEntry))
#define VSSSTORAGE_INITIAL_SIZE (VSSSTORAGE_INITIAL_COUNT * sizeof(VSSEntry))
#define VSSSTORAGE_INCREMENT_COUNT 20000
#define VSSSTORAGE_INCREMENT (VSSSTORAGE_INCREMENT_COUNT*sizeof(VSSEntry))
#define VSSSTORAGE_INCREMENT (VSSSTORAGE_INCREMENT_COUNT * sizeof(VSSEntry))
// (average list length = 4)
#define VSSTABLE_INITIAL_SIZE (50000*sizeof(int))
#define VSSTABLE_INCREMENT (5000*sizeof(int))
#define VSSTABLE_INITIAL_SIZE (50000 * sizeof(int))
#define VSSTABLE_INCREMENT (5000 * sizeof(int))
#define VSS_INITIAL_SIZE (sizeof(VSSShmsegHeader) + \
VSSSTORAGE_INITIAL_SIZE + VSSTABLE_INITIAL_SIZE)
#define VSS_INITIAL_SIZE (sizeof(VSSShmsegHeader) + VSSSTORAGE_INITIAL_SIZE + VSSTABLE_INITIAL_SIZE)
#define VSS_INCREMENT (VSSTABLE_INCREMENT + VSSSTORAGE_INCREMENT)
#define VSS_SIZE(entries) \
((entries*sizeof(VSSEntry)) + (entries/4 * sizeof(int)) + sizeof(VSSShmsegHeader))
((entries * sizeof(VSSEntry)) + (entries / 4 * sizeof(int)) + sizeof(VSSShmsegHeader))
#if defined(_MSC_VER) && defined(xxxVSS_DLLEXPORT)
#define EXPORT __declspec(dllexport)
@ -78,94 +77,93 @@
namespace BRM
{
struct VSSEntry
{
LBID_t lbid;
VER_t verID;
bool vbFlag;
bool locked;
int next;
LBID_t lbid;
VER_t verID;
bool vbFlag;
bool locked;
int next;
#ifndef __LP64__
uint32_t pad1;
uint32_t pad1;
#endif
EXPORT VSSEntry();
EXPORT VSSEntry();
};
struct VSSShmsegHeader
{
int capacity;
int currentSize;
int LWM;
int numHashBuckets;
int lockedEntryCount;
int capacity;
int currentSize;
int LWM;
int numHashBuckets;
int lockedEntryCount;
// the rest of the overlay looks like this
// int hashBuckets[numHashBuckets];
// VSSEntry storage[capacity];
// the rest of the overlay looks like this
// int hashBuckets[numHashBuckets];
// VSSEntry storage[capacity];
};
class QueryContext_vss
{
public:
QueryContext_vss() : currentScn(0)
{
txns.reset(new std::set<VER_t>());
}
QueryContext_vss(const QueryContext& qc);
VER_t currentScn;
boost::shared_ptr<std::set<VER_t> > txns;
public:
QueryContext_vss() : currentScn(0)
{
txns.reset(new std::set<VER_t>());
}
QueryContext_vss(const QueryContext& qc);
VER_t currentScn;
boost::shared_ptr<std::set<VER_t> > txns;
};
class VSSImpl
{
public:
static VSSImpl* makeVSSImpl(unsigned key, off_t size, bool readOnly = false);
public:
static VSSImpl* makeVSSImpl(unsigned key, off_t size, bool readOnly = false);
inline void grow(unsigned key, off_t size)
inline void grow(unsigned key, off_t size)
#ifndef NDBUG
{
fVSS.grow(key, size);
}
{
fVSS.grow(key, size);
}
#else
{
int rc = fVSS.grow(key, size);
idbassert(rc == 0);
}
{
int rc = fVSS.grow(key, size);
idbassert(rc == 0);
}
#endif
inline void makeReadOnly()
{
fVSS.setReadOnly();
}
inline void clear(unsigned key, off_t size)
{
fVSS.clear(key, size);
}
inline void swapout(BRMShmImpl& rhs)
{
fVSS.swap(rhs);
rhs.destroy();
}
inline unsigned key() const
{
return fVSS.key();
}
inline void makeReadOnly()
{
fVSS.setReadOnly();
}
inline void clear(unsigned key, off_t size)
{
fVSS.clear(key, size);
}
inline void swapout(BRMShmImpl& rhs)
{
fVSS.swap(rhs);
rhs.destroy();
}
inline unsigned key() const
{
return fVSS.key();
}
inline VSSShmsegHeader* get() const
{
return reinterpret_cast<VSSShmsegHeader*>(fVSS.fMapreg.get_address());
}
inline VSSShmsegHeader* get() const
{
return reinterpret_cast<VSSShmsegHeader*>(fVSS.fMapreg.get_address());
}
private:
VSSImpl(unsigned key, off_t size, bool readOnly = false);
~VSSImpl();
VSSImpl(const VSSImpl& rhs);
VSSImpl& operator=(const VSSImpl& rhs);
private:
VSSImpl(unsigned key, off_t size, bool readOnly = false);
~VSSImpl();
VSSImpl(const VSSImpl& rhs);
VSSImpl& operator=(const VSSImpl& rhs);
BRMShmImpl fVSS;
BRMShmImpl fVSS;
static boost::mutex fInstanceMutex;
static VSSImpl* fInstance;
static boost::mutex fInstanceMutex;
static VSSImpl* fInstance;
};
class VBBM;
@ -204,99 +202,97 @@ class ExtentMap;
class VSS : public Undoable
{
public:
public:
enum OPS
{
NONE,
READ,
WRITE
};
enum OPS
{
NONE,
READ,
WRITE
};
EXPORT VSS();
EXPORT ~VSS();
EXPORT VSS();
EXPORT ~VSS();
EXPORT bool isLocked(const LBIDRange& l, VER_t txnID = -1) const;
EXPORT void removeEntry(LBID_t lbid, VER_t verID, std::vector<LBID_t>* flushList);
EXPORT bool isLocked(const LBIDRange& l, VER_t txnID = -1) const;
EXPORT void removeEntry(LBID_t lbid, VER_t verID, std::vector<LBID_t>* flushList);
// Note, the use_vbbm switch should be used for unit testing the VSS only
EXPORT void removeEntriesFromDB(const LBIDRange& range, VBBM& vbbm, bool use_vbbm = true);
EXPORT int lookup(LBID_t lbid, const QueryContext_vss&, VER_t txnID, VER_t* outVer, bool* vbFlag,
bool vbOnly = false) const;
// Note, the use_vbbm switch should be used for unit testing the VSS only
EXPORT void removeEntriesFromDB(const LBIDRange& range, VBBM& vbbm, bool use_vbbm = true);
EXPORT int lookup(LBID_t lbid, const QueryContext_vss&, VER_t txnID, VER_t* outVer,
bool* vbFlag, bool vbOnly = false) const;
/// Returns the version in the main DB files
EXPORT VER_t getCurrentVersion(LBID_t lbid, bool* isLocked) const; // returns the ver in the main DB files
/// Returns the version in the main DB files
EXPORT VER_t getCurrentVersion(LBID_t lbid, bool* isLocked) const; // returns the ver in the main DB files
/// Returns the highest version in the version buffer, less than max
EXPORT VER_t getHighestVerInVB(LBID_t lbid, VER_t max) const;
/// Returns the highest version in the version buffer, less than max
EXPORT VER_t getHighestVerInVB(LBID_t lbid, VER_t max) const;
/// returns true if that block is in the version buffer, false otherwise
EXPORT bool isVersioned(LBID_t lbid, VER_t version) const;
/// returns true if that block is in the version buffer, false otherwise
EXPORT bool isVersioned(LBID_t lbid, VER_t version) const;
EXPORT void setVBFlag(LBID_t lbid, VER_t verID, bool vbFlag);
EXPORT void insert(LBID_t, VER_t, bool vbFlag, bool locked, bool loading = false);
EXPORT void commit(VER_t txnID);
EXPORT void getUncommittedLBIDs(VER_t txnID, std::vector<LBID_t>& lbids);
EXPORT void getUnlockedLBIDs(BlockList_t& lbids);
EXPORT void getLockedLBIDs(BlockList_t& lbids);
EXPORT void lock(OPS op);
EXPORT void release(OPS op);
EXPORT void setReadOnly();
EXPORT void setVBFlag(LBID_t lbid, VER_t verID, bool vbFlag);
EXPORT void insert(LBID_t, VER_t, bool vbFlag, bool locked, bool loading = false);
EXPORT void commit(VER_t txnID);
EXPORT void getUncommittedLBIDs(VER_t txnID, std::vector<LBID_t>& lbids);
EXPORT void getUnlockedLBIDs(BlockList_t& lbids);
EXPORT void getLockedLBIDs(BlockList_t& lbids);
EXPORT void lock(OPS op);
EXPORT void release(OPS op);
EXPORT void setReadOnly();
EXPORT int checkConsistency(const VBBM& vbbm, ExtentMap& em) const;
EXPORT int size() const;
EXPORT bool hashEmpty() const;
EXPORT void getCurrentTxnIDs(std::set<VER_t>& txnList) const;
EXPORT int checkConsistency(const VBBM& vbbm, ExtentMap& em) const;
EXPORT int size() const;
EXPORT bool hashEmpty() const;
EXPORT void getCurrentTxnIDs(std::set<VER_t>& txnList) const;
EXPORT void clear();
EXPORT void load(std::string filename);
EXPORT void save(std::string filename);
EXPORT void clear();
EXPORT void load(std::string filename);
EXPORT void save(std::string filename);
#ifdef BRM_DEBUG
EXPORT int getShmid() const;
EXPORT int getShmid() const;
#endif
EXPORT bool isEmpty(bool doLock = true);
EXPORT bool isEmpty(bool doLock = true);
/* Bug 2293. VBBM will use this fcn to determine whether a block is
* currently in use. */
EXPORT bool isEntryLocked(LBID_t lbid, VER_t verID) const;
EXPORT bool isTooOld(LBID_t lbid, VER_t verID) const;
/* Bug 2293. VBBM will use this fcn to determine whether a block is
* currently in use. */
EXPORT bool isEntryLocked(LBID_t lbid, VER_t verID) const;
EXPORT bool isTooOld(LBID_t lbid, VER_t verID) const;
private:
VSS(const VSS&);
VSS& operator=(const VSS&);
private:
VSS(const VSS&);
VSS& operator=(const VSS&);
struct VSSShmsegHeader* vss;
int* hashBuckets;
VSSEntry* storage;
bool r_only;
static boost::mutex mutex; // @bug5355 - made mutex static
struct VSSShmsegHeader* vss;
int* hashBuckets;
VSSEntry* storage;
bool r_only;
static boost::mutex mutex; // @bug5355 - made mutex static
key_t currentVSSShmkey;
int vssShmid;
MSTEntry* vssShminfo;
MasterSegmentTable mst;
static const int MAX_IO_RETRIES = 10;
key_t currentVSSShmkey;
int vssShmid;
MSTEntry* vssShminfo;
MasterSegmentTable mst;
static const int MAX_IO_RETRIES = 10;
key_t chooseShmkey() const;
void growVSS();
void growForLoad(int count);
void initShmseg();
void copyVSS(VSSShmsegHeader* dest);
key_t chooseShmkey() const;
void growVSS();
void growForLoad(int count);
void initShmseg();
void copyVSS(VSSShmsegHeader* dest);
int getIndex(LBID_t lbid, VER_t verID, int& prev, int& bucket) const;
void _insert(VSSEntry& e, VSSShmsegHeader* dest, int* destTable, VSSEntry*
destStorage, bool loading = false);
ShmKeys fShmKeys;
int getIndex(LBID_t lbid, VER_t verID, int& prev, int& bucket) const;
void _insert(VSSEntry& e, VSSShmsegHeader* dest, int* destTable, VSSEntry* destStorage,
bool loading = false);
ShmKeys fShmKeys;
VSSImpl* fPVSSImpl;
utils::Hasher hasher;
VSSImpl* fPVSSImpl;
utils::Hasher hasher;
};
}
} // namespace BRM
#undef EXPORT
#endif // _VSS_H_
#endif // _VSS_H_