1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-08 14:22:09 +03:00

Reformat all code to coding standard

This commit is contained in:
Andrew Hutchings
2017-10-26 17:18:17 +01:00
parent 4985f3456e
commit 01446d1e22
1296 changed files with 403852 additions and 353747 deletions

View File

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

View File

@@ -36,34 +36,42 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
class AutoincrementManager {
class AutoincrementManager
{
public:
EXPORT AutoincrementManager();
EXPORT virtual ~AutoincrementManager();
EXPORT AutoincrementManager();
EXPORT virtual ~AutoincrementManager();
EXPORT void startSequence(uint32_t OID, uint64_t firstNum, uint32_t colWidth,
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 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; // 30 seconds
struct sequence {
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;
};
static const uint32_t lockTime = 30; // 30 seconds
struct sequence
{
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;
};
boost::mutex lock;
std::map<uint64_t, sequence> sequences;
boost::mutex lock;
std::map<uint64_t, sequence> sequences;
};
} /* namespace BRM */

View File

@@ -21,114 +21,152 @@ DBRM dbrm;
void doStartSeq()
{
try {
dbrm.startAISequence(12345, 67890, 1, execplan::CalpontSystemCatalog::INT);
}
catch (exception &e) {
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
try
{
dbrm.startAISequence(12345, 67890, 1, execplan::CalpontSystemCatalog::INT);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
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);
}
if (!ret)
cout << "getAIRange failed\n";
else
cout << "got firstNum " << firstNum << endl;
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;
}
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);
}
if (!ret)
cout << "getAIValue failed\n";
else
cout << "got val " << val << endl;
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;
}
void doReset()
{
try {
dbrm.resetAISequence(12345, 11111);
}
catch (exception &e) {
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
try
{
dbrm.resetAISequence(12345, 11111);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
}
void doLock()
{
try {
dbrm.getAILock(12345);
}
catch (exception &e) {
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
try
{
dbrm.getAILock(12345);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
}
void doUnlock()
{
try {
dbrm.releaseAILock(12345);
}
catch (exception &e) {
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
try
{
dbrm.releaseAILock(12345);
}
catch (exception& e)
{
cout << "got exception: " << e.what() << endl;
exit(1);
}
cout << "OK.\n";
}
int main(int argc, char **argv)
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;
case 'r': doGetRange(); break;
case 'v': doGetValue(); break;
case 'R': doReset(); break;
case 'l': doLock(); 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);
}
switch (cmd)
{
case 's':
doStartSeq();
break;
case 'r':
doGetRange();
break;
case 'v':
doGetValue();
break;
case 'R':
doReset();
break;
case 'l':
doLock();
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);
}
}

View File

@@ -48,21 +48,23 @@ using namespace idbdatafile;
using namespace logging;
using namespace std;
namespace BRM {
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()
@@ -71,118 +73,133 @@ 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)
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)
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 = journalFilename.c_str();
if (IDBPolicy::useHdfs()) {
IDBDataFile* journal = IDBDataFile::open(
IDBPolicy::getType(filename, IDBPolicy::WRITEENG), filename, "wb", 0);
delete journal;
}
else {
ofstream journal;
uint32_t utmp = ::umask(0);
journal.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
journal.close();
::umask(utmp);
}
// truncate teh file if already exists since no truncate in HDFS.
const char* filename = journalFilename.c_str();
vbbm.save(vbbmFilename);
vss.save(vssFilename);
if (IDBPolicy::useHdfs())
{
IDBDataFile* journal = IDBDataFile::open(
IDBPolicy::getType(filename, IDBPolicy::WRITEENG), filename, "wb", 0);
delete journal;
}
else
{
ofstream journal;
uint32_t utmp = ::umask(0);
journal.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
journal.close();
::umask(utmp);
}
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);
cout << e.what() << endl;
return -1;
}
vbbm.save(vbbmFilename);
vss.save(vssFilename);
return 0;
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);
cout << e.what() << endl;
return -1;
}
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);
if (locked[0])
vbbm.release(VBBM::WRITE);
cout << e.what() << endl;
return -1;
}
return 0;
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);
cout << e.what() << endl;
return -1;
}
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();
}
return err;
try
{
err = sc.replayJournal(prefix);
}
catch (exception& e)
{
cout << e.what();
}
return err;
}

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class BlockResolutionManager
*/
@@ -44,7 +44,8 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
/** @brief The BlockResolutionManager manages the Logical Block ID space.
*
@@ -54,75 +55,76 @@ namespace BRM {
*
* @note This class will be used by C code, so it should not throw exceptions.
*/
class BlockResolutionManager {
public:
EXPORT explicit BlockResolutionManager(bool ronly = false) throw();
EXPORT ~BlockResolutionManager() throw();
class BlockResolutionManager
{
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. 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. 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 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 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. 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();
/** @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;
private:
explicit BlockResolutionManager(const BlockResolutionManager& brm);
BlockResolutionManager& operator=(const BlockResolutionManager& brm);
MasterSegmentTable mst;
ExtentMap em;
VBBM vbbm;
VSS vss;
CopyLocks copylocks;
};
}
#undef EXPORT
#endif
#endif

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* This is a unified BRM header file to prevent HFM.
*/

View File

@@ -30,7 +30,7 @@ using namespace std;
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/version.hpp>
namespace bi=boost::interprocess;
namespace bi = boost::interprocess;
#include "shmkeys.h"
#include "brmshmimpl.h"
@@ -40,209 +40,217 @@ namespace BRM
{
BRMShmImpl::BRMShmImpl(unsigned key, off_t size, bool readOnly) :
fKey(key), fSize(size), fReadOnly(readOnly)
fKey(key), fSize(size), fReadOnly(readOnly)
{
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
#if BOOST_VERSION < 104500
bi::interprocess_exception();
#else
bi::interprocess_exception("shm size is zero");
#endif
}
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;
}
}
try
{
#if BOOST_VERSION < 104500
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
#ifdef __linux__
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
#endif
#else
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
#endif
idbassert(fSize > 0);
shm.truncate(fSize);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception&)
{
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
idbassert(curSize > 0);
idbassert(curSize >= fSize);
fShmobj.swap(shm);
fSize = curSize;
}
catch (...)
{
throw;
}
string keyName = ShmKeys::keyToName(fKey);
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);
}
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
#if BOOST_VERSION < 104500
bi::interprocess_exception();
#else
bi::interprocess_exception("shm size is zero");
#endif
}
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;
}
}
try
{
#if BOOST_VERSION < 104500
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
#ifdef __linux__
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
#endif
#else
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
#endif
idbassert(fSize > 0);
shm.truncate(fSize);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception&)
{
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
idbassert(curSize > 0);
idbassert(curSize >= fSize);
fShmobj.swap(shm);
fSize = curSize;
}
catch (...)
{
throw;
}
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);
string keyName = ShmKeys::keyToName(newKey);
#if BOOST_VERSION < 104500
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
#ifdef __linux__
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
#endif
#else
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
#endif
shm.truncate(newSize);
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);
string keyName = ShmKeys::keyToName(newKey);
#if BOOST_VERSION < 104500
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
#ifdef __linux__
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
#endif
#else
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
#endif
shm.truncate(newSize);
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();
if (!oldName.empty()) bi::shared_memory_object::remove(oldName.c_str());
string oldName = fShmobj.get_name();
if (!oldName.empty()) bi::shared_memory_object::remove(oldName.c_str());
}
} //namespace

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class BRMShmImpl
*/
@@ -33,35 +33,45 @@
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
namespace BRM {
namespace BRM
{
class BRMShmImpl
{
public:
BRMShmImpl(unsigned key, off_t size, bool readOnly=false);
~BRMShmImpl() { }
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);
BRMShmImpl(const BRMShmImpl& rhs);
BRMShmImpl& operator=(const BRMShmImpl& rhs);
unsigned fKey;
off_t fSize;
bool fReadOnly;
unsigned fKey;
off_t fSize;
bool fReadOnly;
};
} //namespace

View File

@@ -51,29 +51,31 @@ using namespace logging;
using namespace idbdatafile;
// local unnamed namespace
namespace {
unsigned int subSystemLoggingId =
(unsigned int)BRM::SubSystemLogId_controllerNode;
namespace
{
unsigned int subSystemLoggingId =
(unsigned int)BRM::SubSystemLogId_controllerNode;
}
namespace BRM {
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()
@@ -82,16 +84,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
@@ -103,58 +105,61 @@ 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;
start = tmp;
bs >> size;
}
else {
// version 1
size = (tmp & 0xffffffff00000000ULL) >> 32;
start = (tmp & 0x00000000ffffffffULL);
}
bs >> tmp;
if (tmp == RANGE_V2_MAGIC)
{
bs >> tmp;
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()
@@ -163,97 +168,121 @@ VBRange::~VBRange()
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 )
{
subSystemLoggingId = (unsigned int)subSystemId;
subSystemLoggingId = (unsigned int)subSystemId;
}
void log(const string &msg, logging::LOG_TYPE level)
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;
case logging::LOG_TYPE_INFO:
logger.logInfoMessage(message); break;
case logging::LOG_TYPE_WARNING:
logger.logWarningMessage(message); break;
case logging::LOG_TYPE_ERROR:
logger.logErrorMessage(message); break;
case logging::LOG_TYPE_CRITICAL:
logger.logCriticalMessage(message); break;
default:
logger.logInfoMessage(message);
}
switch (level)
{
case logging::LOG_TYPE_DEBUG:
logger.logDebugMessage(message);
break;
case logging::LOG_TYPE_INFO:
logger.logInfoMessage(message);
break;
case logging::LOG_TYPE_WARNING:
logger.logWarningMessage(message);
break;
case logging::LOG_TYPE_ERROR:
logger.logErrorMessage(message);
break;
case logging::LOG_TYPE_CRITICAL:
logger.logCriticalMessage(message);
break;
default:
logger.logInfoMessage(message);
}
}
void log_errno(const string &msg, logging::LOG_TYPE level)
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);
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));
#endif
message.format(args);
const char* cMsg;
cMsg = strerror_r(tmp, &test[0], 1000);
switch (level) {
case logging::LOG_TYPE_DEBUG:
logger.logDebugMessage(message); break;
case logging::LOG_TYPE_INFO:
logger.logInfoMessage(message); break;
case logging::LOG_TYPE_WARNING:
logger.logWarningMessage(message); break;
case logging::LOG_TYPE_ERROR:
logger.logErrorMessage(message); break;
case logging::LOG_TYPE_CRITICAL:
logger.logCriticalMessage(message); break;
default:
logger.logInfoMessage(message);
}
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));
#endif
message.format(args);
switch (level)
{
case logging::LOG_TYPE_DEBUG:
logger.logDebugMessage(message);
break;
case logging::LOG_TYPE_INFO:
logger.logInfoMessage(message);
break;
case logging::LOG_TYPE_WARNING:
logger.logWarningMessage(message);
break;
case logging::LOG_TYPE_ERROR:
logger.logErrorMessage(message);
break;
case logging::LOG_TYPE_CRITICAL:
logger.logCriticalMessage(message);
break;
default:
logger.logInfoMessage(message);
}
}
//------------------------------------------------------------------------------
@@ -261,222 +290,245 @@ void log_errno(const string &msg, logging::LOG_TYPE level)
//------------------------------------------------------------------------------
void errString(int rc, string& errMsg)
{
switch (rc)
{
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;
}
}
switch (rc)
{
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;
}
}
}
/* Tablelock impl */
bool TableLockInfo::overlaps(const TableLockInfo &t, const std::set<uint32_t> &sDbrootList) const
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;
return false;
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
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)
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
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);
for (uint32_t j = 0; j < dbrootListSize; j++)
o.write((char *) &dbrootList[j], 4);
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);
}
void TableLockInfo::deserialize(istream &i)
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);
for (uint32_t j = 0; j < dbrootListSize; j++)
i.read((char *) &dbrootList[j], 4);
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);
}
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);
for (uint32_t j = 0; j < dbrootListSize; j++)
o->write((char *) &dbrootList[j], 4);
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);
}
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);
for (uint32_t j = 0; j < dbrootListSize; j++)
i->read((char *) &dbrootList[j], 4);
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);
}
bool TableLockInfo::operator<(const TableLockInfo &tli) const
bool TableLockInfo::operator<(const TableLockInfo& tli) const
{
return (id < tli.id);
return (id < tli.id);
}
ostream & operator<<(ostream &os, const QueryContext &qc)
ostream& operator<<(ostream& os, const QueryContext& qc)
{
os << " SCN: " << qc.currentScn << endl;
os << " Txns: ";
for (uint32_t i = 0; i < qc.currentTxns->size(); i++)
os << (*qc.currentTxns)[i] << " ";
return os;
os << " SCN: " << qc.currentScn << endl;
os << " Txns: ";
for (uint32_t i = 0; i < qc.currentTxns->size(); i++)
os << (*qc.currentTxns)[i] << " ";
return os;
}
} //namespace

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
*/
#ifndef BRMTYPES_H_
@@ -46,14 +46,16 @@ namespace std
{
namespace tr1
{
template<>
struct hash<long long int>
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
{
std::size_t
operator()(long long int val) const
{ return static_cast<std::size_t>(val); }
};
return static_cast<std::size_t>(val);
}
};
}
}
#endif //if __GNUC__
@@ -82,14 +84,15 @@ class IDBDataFile;
}
namespace BRM {
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 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.
typedef execplan::CalpontSystemCatalog::OID OID_t;
typedef execplan::CalpontSystemCatalog::OID OID_t;
typedef std::pair<LBID_t, VER_t> LVP_t;
@@ -99,69 +102,75 @@ typedef std::vector<LVP_t> BlockList_t;
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;
struct InlineLBIDRange
{
LBID_t start;
uint32_t size;
#ifndef __LP64__
int32_t pad1;
int32_t pad1;
#endif
};
#define MAX_PROCNAME 16
/** @brief SID = Session ID */
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();
};
/** @brief A type describing a single transaction ID */
typedef struct _TxnID TxnID;
/** @brief A type associating a session with a transaction.
*/
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();
};
/** @brief A type associating a session with a transaction */
typedef struct _SIDTIDEntry SIDTIDEntry;
/** @brief SID = Session ID */
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();
};
/** @brief A type describing a single transaction ID */
typedef struct _TxnID TxnID;
// @bug 1970 - Added CPInfo and CPMaxMin structs used by new interface that allows setting the max and min CP data
/** @brief A type associating a session with a transaction.
*/
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();
};
/** @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.
// Used in vectors.
struct CPInfo {
LBID_t firstLbid;
int64_t max;
int64_t min;
int32_t seqNum;
struct CPInfo
{
LBID_t firstLbid;
int64_t max;
int64_t min;
int32_t seqNum;
};
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;
struct CPMaxMin
{
int64_t max;
int64_t min;
int32_t seqNum;
};
typedef std::tr1::unordered_map<LBID_t, CPMaxMin> CPMaxMinMap_t;
// @bug 2117 - Add second CP struct to use in merging CP info
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)
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;
bool newExtent; // is this to be treated as a new extent
};
@@ -169,12 +178,13 @@ typedef std::vector<CPInfoMerge> CPInfoMergeList_t;
// Used for map where lbid is the key. Data members have same meaning as
// those in CPInfoMerge.
struct CPMaxMinMerge {
int64_t max;
int64_t min;
int32_t seqNum;
execplan::CalpontSystemCatalog::ColDataType type;
bool newExtent;
struct CPMaxMinMerge
{
int64_t max;
int64_t min;
int32_t seqNum;
execplan::CalpontSystemCatalog::ColDataType type;
bool newExtent;
};
typedef std::tr1::unordered_map<LBID_t, CPMaxMinMerge> CPMaxMinMergeMap_t;
@@ -183,161 +193,183 @@ typedef std::tr1::unordered_map<LBID_t, CPMaxMinMerge> CPMaxMinMergeMap_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;
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;
};
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
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
};
typedef std::tr1::unordered_map<execplan::CalpontSystemCatalog::OID, ExtentInfo> ExtentsInfoMap_t;
enum LockState {
LOADING,
CLEANUP
enum LockState
{
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;
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;
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 {
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;
struct VSSData
{
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;
struct BulkSetHWMArg
{
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
struct BulkUpdateDBRootArg
{
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
struct CreateStripeColumnExtentsArgIn
{
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
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
};
/// A container for LBIDRanges
typedef std::vector<LBIDRange> LBIDRange_v;
typedef std::vector<LBIDRange> LBIDRange_v;
/// Describes a contiguous range of blocks in the Version Buffer
class VBRange : public messageqcpp::Serializeable {
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; }
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;
}
};
typedef std::vector<EmDbRootHWMInfo> EmDbRootHWMInfo_v;
typedef std::vector<EmDbRootHWMInfo> EmDbRootHWMInfo_v;
/// A container for VBRanges
typedef std::vector<VBRange> VBRange_v;
typedef std::vector<VBRange> VBRange_v;
/* Definitions to support 'undo' operations */
@@ -350,25 +382,27 @@ typedef std::vector<VBRange> VBRange_v;
* memcpy(ImageDelta.start, ImageDelta.data, ImageDelta.size). The
* shared memory segments should not be unlinked or unlocked since the
* write operation.
*
*
* Right now it is used specifically to record how BRM data is modified.
* Usage can be generalized.
*/
struct ImageDelta {
void *start;
int size;
char data[ID_MAXSIZE]; /// Has to be as large as the largest change
struct ImageDelta
{
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
enum SubSystemLogId
{
SubSystemLogId_controllerNode = 29,
SubSystemLogId_workerNode = 30
};
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 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 );
const struct timespec FIVE_MIN_TIMEOUT = {300, 0};
@@ -378,7 +412,7 @@ const struct timespec FIVE_MIN_TIMEOUT = {300, 0};
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
The format of the messages from the Slaves to Master and Master to DBRM
will look like
<error code, out-params>
*/
@@ -477,7 +511,7 @@ const uint8_t GET_SYSTEM_CATALOG = 101;
/* Error codes returned by the DBRM functions. */
/// The operation was successful
const int8_t ERR_OK = 0;
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;
@@ -518,55 +552,56 @@ const int8_t ERR_NO_PARTITION_PERFORMED = 16;
const int8_t ERR_OLDTXN_OVERWRITING_NEWTXN = 17;
// structure used to hold the information to identify a partition for shared-nothing
struct PartitionInfo
struct PartitionInfo
{
LogicalPartition lp;
OID_t oid;
void serialize (messageqcpp::ByteStream& b) const
{
lp.serialize(b);
b << (uint32_t)oid;
}
LogicalPartition lp;
OID_t oid;
void unserialize (messageqcpp::ByteStream& b)
{
lp.unserialize(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;
}
};
// Note: Copies share the currentTxns array
class QueryContext : public messageqcpp::Serializeable {
class QueryContext : public messageqcpp::Serializeable
{
public:
explicit QueryContext(VER_t scn=0)
: currentScn(scn)
{
currentTxns.reset(new std::vector<VER_t>());
}
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);
//defaults okay?
//QueryContext(const QueryContext& rhs);
//QueryContext& operator=(const QueryContext& rhs);
};
std::ostream & operator<<(std::ostream &, const QueryContext &);
std::ostream& operator<<(std::ostream&, const QueryContext&);
}

View File

@@ -35,7 +35,7 @@
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
namespace bi=boost::interprocess;
namespace bi = boost::interprocess;
#include "shmkeys.h"
#include "brmtypes.h"
@@ -68,13 +68,14 @@ using namespace logging;
#include "IDBPolicy.h"
using namespace idbdatafile;
namespace BRM {
CopyLockEntry::CopyLockEntry()
namespace BRM
{
start = 0;
size = 0;
txnID = 0;
CopyLockEntry::CopyLockEntry()
{
start = 0;
size = 0;
txnID = 0;
}
/*static*/
@@ -82,41 +83,42 @@ boost::mutex CopyLocksImpl::fInstanceMutex;
boost::mutex CopyLocks::mutex;
/*static*/
CopyLocksImpl* CopyLocksImpl::fInstance=0;
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 (key != fInstance->fCopyLocks.key())
{
BRMShmImpl newShm(key, size, readOnly);
fInstance->swapout(newShm);
}
idbassert(key == fInstance->fCopyLocks.key());
return fInstance;
}
if (fInstance)
{
if (key != fInstance->fCopyLocks.key())
{
BRMShmImpl newShm(key, size, readOnly);
fInstance->swapout(newShm);
}
fInstance = new CopyLocksImpl(key, size, readOnly);
idbassert(key == fInstance->fCopyLocks.key());
return fInstance;
}
return fInstance;
fInstance = new CopyLocksImpl(key, size, readOnly);
return fInstance;
}
CopyLocksImpl::CopyLocksImpl(unsigned key, off_t size, bool readOnly) :
fCopyLocks(key, size, readOnly)
fCopyLocks(key, size, readOnly)
{
}
CopyLocks::CopyLocks()
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()
@@ -125,236 +127,270 @@ 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);
if (op == READ)
shminfo = mst.getTable_read(MasterSegmentTable::CLSegment);
else
shminfo = mst.getTable_write(MasterSegmentTable::CLSegment);
{
boost::mutex::scoped_lock lk(mutex);
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)
growCL();
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 (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 (shminfo->allocdSize == 0)
if (op == READ)
{
mst.getTable_upgrade(MasterSegmentTable::CLSegment);
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();
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;
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;
int fixedKeys = 1;
key_t ret;
return 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;
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);
shminfo->tableShmkey = currentShmkey = newshmkey;
shminfo->allocdSize = allocSize;
if (r_only)
fCopyLocksImpl->makeReadOnly();
if (!fCopyLocksImpl)
fCopyLocksImpl = CopyLocksImpl::makeCopyLocksImpl(newshmkey, allocSize, r_only);
else
fCopyLocksImpl->grow(newshmkey, allocSize);
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();
shminfo->tableShmkey = currentShmkey = newshmkey;
shminfo->allocdSize = allocSize;
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();
}
// 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;
// grow if necessary
if (shminfo->currentSize == shminfo->allocdSize)
growCL();
/* debugging code, check for an existing lock */
//assert(!isLocked(l));
int i, numEntries;
//ostringstream os;
//os << "Copylocks locking <" << l.start << ", " << l.size << "> txnID = " << txnID;
//log(os.str());
// grow if necessary
if (shminfo->currentSize == shminfo->allocdSize)
growCL();
// scan for an empty entry
numEntries = shminfo->allocdSize/sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++) {
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);
/* debugging code, check for an existing lock */
//assert(!isLocked(l));
// make sure isLocked() now sees the lock
//assert(isLocked(l));
return;
}
}
//ostringstream os;
//os << "Copylocks locking <" << l.start << ", " << l.size << "> txnID = " << txnID;
//log(os.str());
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");
// scan for an empty entry
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
{
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);
// 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");
}
// 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);
for (i = 0; i < numEntries; i++) {
CopyLockEntry &e = entries[i];
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);
}
}
}
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
{
CopyLockEntry& e = entries[i];
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);
}
}
}
#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
}
/* This doesn't come from the controllernode right now,
* shouldn't use makeUndoRecord() */
void CopyLocks::forceRelease(const LBIDRange &l)
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 (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);
}
}
}
//assert(!isLocked(l));
/* If a range intersects l, get rid of it. */
for (i = 0; i < numEntries; i++)
{
CopyLockEntry& e = entries[i];
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);
}
}
}
//assert(!isLocked(l));
}
//assumes read lock
bool CopyLocks::isLocked(const LBIDRange &l) const
bool CopyLocks::isLocked(const LBIDRange& l) const
{
int i, numEntries;
LBID_t lLastBlock, lastBlock;
numEntries = shminfo->allocdSize/sizeof(CopyLockEntry);
lLastBlock = l.start + l.size - 1;
for (i = 0; i < numEntries; i++) {
if (entries[i].size != 0) {
lastBlock = entries[i].start + entries[i].size - 1;
if (lLastBlock >= entries[i].start && l.start <= lastBlock)
return true;
}
}
return false;
int i, numEntries;
LBID_t lLastBlock, lastBlock;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
lLastBlock = l.start + l.size - 1;
for (i = 0; i < numEntries; i++)
{
if (entries[i].size != 0)
{
lastBlock = entries[i].start + entries[i].size - 1;
if (lLastBlock >= entries[i].start && l.start <= lastBlock)
return true;
}
}
return false;
}
void CopyLocks::rollback(VER_t txnID)
{
int i, numEntries;
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);
}
}
int i, numEntries;
void CopyLocks::getCurrentTxnIDs(std::set<VER_t> &list) const
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);
}
}
void CopyLocks::getCurrentTxnIDs(std::set<VER_t>& list) const
{
int i, numEntries;
numEntries = shminfo->allocdSize/sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
if (entries[i].size != 0)
list.insert(entries[i].txnID);
int i, numEntries;
numEntries = shminfo->allocdSize / sizeof(CopyLockEntry);
for (i = 0; i < numEntries; i++)
if (entries[i].size != 0)
list.insert(entries[i].txnID);
}

View File

@@ -20,10 +20,10 @@
*
*****************************************************************************/
/** @file
/** @file
* class XXX interface
*/
#ifndef COPYLOCKS_H_
#define COPYLOCKS_H_
@@ -55,93 +55,119 @@
#endif
namespace idbdatafile {
namespace idbdatafile
{
class IDBDataFile;
}
namespace BRM {
namespace BRM
{
struct CopyLockEntry {
LBID_t start;
int size;
VER_t txnID;
EXPORT CopyLockEntry();
struct 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);
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);
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:
enum OPS {
NONE,
READ,
WRITE
};
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 lock(OPS op);
EXPORT void release(OPS op);
EXPORT void setReadOnly();
EXPORT void getCurrentTxnIDs(std::set<VER_t> &txnList) const;
class CopyLocks : public Undoable
{
public:
EXPORT void forceRelease(const LBIDRange &range);
enum OPS
{
NONE,
READ,
WRITE
};
private:
CopyLocks(const CopyLocks &);
CopyLocks& operator=(const CopyLocks &);
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;
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 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);
private:
CopyLocks(const CopyLocks&);
CopyLocks& operator=(const CopyLocks&);
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;
};
}
}
#undef EXPORT

View File

@@ -10,86 +10,105 @@ DBRM dbrm;
void lockRange()
{
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";
}
LBIDRange r;
r.start = 12345;
r.size = 5;
copylocks.lock(CopyLocks::WRITE);
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 << "already locked\n";
else
{
copylocks.lockRange(r, -1);
cout << "got the 1st lock\n";
}
r.start = 12349;
if (copylocks.isLocked(r))
cout << "2nd range is locked\n";
else
cout << "2nd range is NOT locked\n";
r.start = 12350;
if (copylocks.isLocked(r))
cout << "3rd range is locked\n";
else {
copylocks.lockRange(r, -1);
cout << "got the 3rd lock\n";
}
r.start = 12350;
copylocks.release(CopyLocks::WRITE);
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);
}
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)
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;
case 'r': releaseRange(); break;
case 'L': dbrmLockRange(); break;
case 'R': dbrmReleaseRange(); break;
default: goto usage;
}
switch (cmd)
{
case 'l':
lockRange();
break;
exit(0);
case 'r':
releaseRange();
break;
case 'L':
dbrmLockRange();
break;
case 'R':
dbrmReleaseRange();
break;
default:
goto usage;
}
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

@@ -35,10 +35,10 @@ using namespace BRM;
namespace
{
void usage(char *name)
void usage(char* name)
{
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
}
@@ -47,219 +47,247 @@ namespace BRM
class ExtentMapConverter
{
public:
ExtentMapConverter() {};
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);
ExtentMapConverter(const ExtentMapConverter& rhs);
ExtentMapConverter& operator=(const ExtentMapConverter& rhs);
ExtentMap em;
ExtentMap em;
};
int ExtentMapConverter::doCvt(unsigned oldExtentSize, unsigned newExtentSize, const string&filename)
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);
try {
em.grabFreeList(ExtentMap::WRITE);
}
catch(...) {
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
em.grabEMEntryTable(ExtentMap::WRITE);
div_t d = div((int)oldExtentSize, (int)newExtentSize);
idbassert(d.quot > 1);
idbassert(d.rem == 0);
try
{
em.grabFreeList(ExtentMap::WRITE);
}
catch (...)
{
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
const unsigned mult = d.quot;
div_t d = div((int)oldExtentSize, (int)newExtentSize);
idbassert(d.quot > 1);
idbassert(d.rem == 0);
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.");
}
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;
}
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 unsigned mult = d.quot;
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.");
}
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;
}
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) {
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;
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");
}
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;
memset(em.fExtentMap, 0, em.fEMShminfo->allocdSize);
memset(em.fFreeList, 0, em.fFLShminfo->allocdSize);
em.fEMShminfo->currentSize = 0;
em.fFLShminfo->currentSize = 0;
// 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)];
int j = 0;
int maxLoops = (emNumElements * (signed)mult - em.fEMShminfo->allocdSize / sizeof(EMEntry)) / 100 + 1;
int target = (int)(maxLoops * .02);
in.read((char *) buf, emNumElements * sizeof(EMEntry));
if (maxLoops < 50) target = 1;
//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++;
}
}
// 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();
em.fEMShminfo->currentSize = j * sizeof(EMEntry);
if ((j % target) == 0) cout << '.' << flush;
cout << j << " total new em entries from " << emNumElements << " file entries" << endl;
cout << OIDMap.size() << " OIDs added to em" << endl;
j++;
}
OIDMap_t::const_iterator iter = OIDMap.begin();
OIDMap_t::const_iterator end = OIDMap.end();
cout << endl;
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;
}
// allocate shared memory for freelist
for (currentSize = em.fFLShminfo->allocdSize / sizeof(InlineLBIDRange);
currentSize < flNumElements;
currentSize = em.fFLShminfo->allocdSize / sizeof(InlineLBIDRange))
{
em.growFLShmseg();
}
cout << l << " entries moved to OID " << numeric_limits<int>::max() << endl;
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;
#if 0
int k = j;
for (int j = 0; j < k; j++)
cout << em.fExtentMap[j].range.start << '\t' << em.fExtentMap[j].range.size << '\t' <<
em.fExtentMap[j].fileID << '\t' << em.fExtentMap[j].blockOffset << '\t' << em.fExtentMap[j].HWM << '\t' <<
em.fExtentMap[j].txnID << '\t' << em.fExtentMap[j].secondHWM << '\t' << em.fExtentMap[j].nextHeader << endl;
int k = j;
for (int j = 0; j < k; j++)
cout << em.fExtentMap[j].range.start << '\t' << em.fExtentMap[j].range.size << '\t' <<
em.fExtentMap[j].fileID << '\t' << em.fExtentMap[j].blockOffset << '\t' << em.fExtentMap[j].HWM << '\t' <<
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;
for (int i = 0; i < flNumElements; i++)
{
em.fFreeList[j].start = lrSrc[i].start;
em.fFreeList[j].size = lrSrc[i].size;
j++;
}
//memcpy(fFreeList, buf2, flNumElements * sizeof(InlineLBIDRange));
InlineLBIDRange* lrSrc = reinterpret_cast<InlineLBIDRange*>(&buf2[0]);
j = 0;
em.fFLShminfo->currentSize = j * sizeof(InlineLBIDRange);
for (int i = 0; i < flNumElements; i++)
{
em.fFreeList[j].start = lrSrc[i].start;
em.fFreeList[j].size = lrSrc[i].size;
j++;
}
cout << j << " total new fl entries from " << flNumElements << " file entries" << endl;
em.fFLShminfo->currentSize = j * sizeof(InlineLBIDRange);
} catch(...) {
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
cout << j << " total new fl entries from " << flNumElements << " file entries" << endl;
return 0;
}
catch (...)
{
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
throw;
}
in.close();
em.releaseFreeList(ExtentMap::WRITE);
em.releaseEMEntryTable(ExtentMap::WRITE);
return 0;
}
}
int main(int argc, char **argv)
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

@@ -37,148 +37,159 @@ namespace
{
bool vflg;
void usage(char *c) {
cerr << "Usage: " << c << " [-vh] status | halt | resume | readonly | readwrite | reload" << endl;
exit(1);
void usage(char* c)
{
cerr << "Usage: " << c << " [-vh] status | halt | resume | readonly | readwrite | reload" << endl;
exit(1);
}
void errMsg(int err)
void errMsg(int err)
{
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)";
}
cout << 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_READONLY:
cout << "DBRM is currently Read Only!" << endl;
break;
case 20:
cout << "System is ready" <<endl;
break;
case 21:
cout << "System is not ready" <<endl;
break;
default:
cout << "Failure: an unexpected error (" << err << ")" << endl;
break;
}
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)";
}
cout << 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_READONLY:
cout << "DBRM is currently Read Only!" << endl;
break;
case 20:
cout << "System is ready" << endl;
break;
case 21:
cout << "System is not ready" << endl;
break;
default:
cout << "Failure: an unexpected error (" << err << ")" << endl;
break;
}
}
void do_halt()
{
int err;
err = dbrm.halt();
errMsg(err);
int err;
err = dbrm.halt();
errMsg(err);
}
void do_resume()
{
int err;
err = dbrm.resume();
errMsg(err);
int 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;
if (ready)
err=20;
else
err = 21;
errMsg(err);
bool ready = dbrm.getSystemReady() > 0 ? true : false;
if (ready)
err = 20;
else
err = 21;
errMsg(err);
}
}
int main(int argc, char **argv)
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;
case 'h':
case '?':
default:
usage(argv[0]);
return (c == 'h' ? 0 : 1);
break;
}
while ((c = getopt(argc, argv, "vh")) != EOF)
switch (c)
{
case 'v':
vflg = true;
break;
string cmd;
case 'h':
case '?':
default:
usage(argv[0]);
return (c == 'h' ? 0 : 1);
break;
}
if ((argc - optind) < 1)
usage(argv[0]);
string cmd;
idbdatafile::IDBPolicy::configIDBPolicy();
if ((argc - optind) < 1)
usage(argv[0]);
cmd = argv[optind++];
idbdatafile::IDBPolicy::configIDBPolicy();
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]);
cmd = argv[optind++];
return 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]);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -36,132 +36,150 @@ LBIDResourceGraph::LBIDResourceGraph() : color(0)
{
}
LBIDResourceGraph::LBIDResourceGraph(const LBIDResourceGraph &r)
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(); ) {
txnNode = (*tnit).second;
if (txnNode->sleeping()) {
txnNode->die();
txnNode->wake();
++tnit;
}
else {
txns.erase(tnit++);
delete txnNode;
}
}
for (rit = resources.begin(); rit != resources.end(); ) {
delete *rit;
resources.erase(rit++);
}
for (tnit = txns.begin(); tnit != txns.end(); )
{
txnNode = (*tnit).second;
if (txnNode->sleeping())
{
txnNode->die();
txnNode->wake();
++tnit;
}
else
{
txns.erase(tnit++);
delete txnNode;
}
}
for (rit = resources.begin(); rit != resources.end(); )
{
delete *rit;
resources.erase(rit++);
}
}
LBIDResourceGraph & LBIDResourceGraph::operator=(const LBIDResourceGraph &r)
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, next;
LBID_t i;
vector<ResourceNode*> intersection, reserveList;
RNodes_t::iterator sit;
vector<ResourceNode*>::iterator it, next;
LBID_t i;
#if 0
/* This version creates ResourceNodes that span a range of LBIDs.
It's deprecated, but worth saving in case we go back to ranges. This is
the most sensitive code in that impl. */
/* This version creates ResourceNodes that span a range of LBIDs.
It's deprecated, but worth saving in case we go back to ranges. This is
the most sensitive code in that impl. */
// get the list of existing resources intersecting the requested range
for (sit = resources.begin(); sit != resources.end() && (*sit)->start() <= end; sit++) {
if ((*sit)->intersects(start, end))
intersection.push_back(*sit);
}
// get the list of existing resources intersecting the requested range
for (sit = resources.begin(); sit != resources.end() && (*sit)->start() <= end; sit++)
{
if ((*sit)->intersects(start, end))
intersection.push_back(*sit);
}
// make a new node for every gap in the requested range and prepare to reserve it
if (intersection.size() == 0)
{
tmp = new ResourceNode(start, end);
resources.insert(tmp);
reserveList.push_back(tmp);
}
else
{
if (intersection[0]->start() > start)
{
tmp = new ResourceNode(start, intersection[0]->start() - 1);
resources.insert(tmp);
reserveList.push_back(tmp);
}
if (intersection.back()->end() < end)
{
tmp = new ResourceNode(intersection.back()->end() + 1, end);
resources.insert(tmp);
reserveList.push_back(tmp);
}
for (it = intersection.begin(), next = it + 1; next != intersection.end();
it = next, next++)
{
if ((*it)->end() != (*next)->start() - 1)
{
tmp = new ResourceNode((*it)->end() + 1, (*next)->start() - 1);
resources.insert(tmp);
reserveList.push_back(tmp);
}
}
}
// make a new node for every gap in the requested range and prepare to reserve it
if (intersection.size() == 0) {
tmp = new ResourceNode(start, end);
resources.insert(tmp);
reserveList.push_back(tmp);
}
else {
if (intersection[0]->start() > start) {
tmp = new ResourceNode(start, intersection[0]->start() - 1);
resources.insert(tmp);
reserveList.push_back(tmp);
}
if (intersection.back()->end() < end) {
tmp = new ResourceNode(intersection.back()->end() + 1, end);
resources.insert(tmp);
reserveList.push_back(tmp);
}
for (it = intersection.begin(), next = it + 1; next != intersection.end();
it = next, next++) {
if ((*it)->end() != (*next)->start() - 1) {
tmp = new ResourceNode((*it)->end() + 1, (*next)->start() - 1);
resources.insert(tmp);
reserveList.push_back(tmp);
}
}
}
#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++) {
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);
}
for (i = start; i <= end; i++)
{
ResourceNode rn(i);
sit = resources.find(&rn);
// 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);
if (sit == resources.end())
{
ResourceNode* tmp = new ResourceNode(i);
resources.insert(tmp);
reserveList.push_back(tmp);
}
else
intersection.push_back(*sit);
}
// at this point, txnNode is adjacent to a set of ResourcesNodes s.t.
// [start, end] is contained within it.
// 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
@@ -169,165 +187,185 @@ void LBIDResourceGraph::connectResources(LBID_t start, LBID_t end,
mutex should be slavelock
*/
int LBIDResourceGraph::reserveRange(LBID_t start, LBID_t end, VER_t txn,
boost::mutex &mutex)
boost::mutex& mutex)
{
TransactionNode *txnNode;
map<VER_t, TransactionNode *>::iterator it;
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();
}
*/
/*
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;
it = txns.find(txn);
connectResources(start, end, txnNode);
if (it == txns.end())
{
txnNode = new TransactionNode(txn);
txns[txn] = txnNode;
}
else
txnNode = (*it).second;
// "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)) {
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))
{
// releaseResources(txn);
return ERR_DEADLOCK;
}
#ifdef BRM_VERBOSE
cerr << " RG: sleeping transaction " << txn << endl;
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;
}
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);
txnNode->sleep(mutex);
#ifdef BRM_VERBOSE
cerr << " RG: txn " << txn << " is awake" << endl;
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);
}
if (txnNode->dead())
{
txns.erase(txn);
delete txnNode;
return ERR_KILLED;
}
// txn has all requested LBID ranges
return ERR_OK;
// 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);
if (it == txns.end())
return;
it = txns.find(txn);
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->out.begin(); sit != txnNode->out.end(); )
{
rNode = dynamic_cast<ResourceNode *>(*sit);
dummy_sit = ++sit;
txnNode->removeOutEdge(rNode);
sit = dummy_sit;
}
if (it == txns.end())
return;
if (txnNode->sleeping()) {
txnNode->die();
txnNode->wake();
}
else {
txns.erase(txn);
delete txnNode;
}
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->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;
}
}
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
bool LBIDResourceGraph::DFSStep(RGNode* curNode, uint64_t gray, uint64_t black) const
{
set<RGNode *>::iterator it;
set<RGNode*>::iterator it;
if (curNode->color() == gray)
return true;
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(black);
curNode->color(gray);
return false;
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;
}
bool LBIDResourceGraph::checkDeadlock(TransactionNode &start)
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);
}
}

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class XXX interface
*/
@@ -52,32 +52,32 @@ 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);
/// releases all resources held by txn
EXPORT void releaseResources(VER_t txn);
EXPORT int reserveRange(LBID_t start, LBID_t end, VER_t txn, boost::mutex& mutex);
/// releases one resource
EXPORT void releaseResource(LBID_t start);
/// releases all resources held by txn
EXPORT void releaseResources(VER_t txn);
private:
uint64_t color;
/// releases one resource
EXPORT void releaseResource(LBID_t start);
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;
private:
uint64_t color;
std::map<VER_t, TransactionNode *> txns;
RNodes_t resources;
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;
};

View File

@@ -28,7 +28,7 @@ using namespace std;
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
namespace bi=boost::interprocess;
namespace bi = boost::interprocess;
#include "IDBPolicy.h"
#include "blockresolutionmanager.h"
@@ -40,84 +40,94 @@ 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;
};
}
int main(int argc, char **argv)
int main(int argc, char** argv)
{
opterr = 0;
bool fflg = false;
opterr = 0;
bool fflg = false;
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;
}
int c;
if ((argc - optind) != 1)
{
usage();
return 1;
}
while ((c = getopt(argc, argv, "fh")) != EOF)
switch (c)
{
case 'f':
fflg = true;
break;
idbdatafile::IDBPolicy::configIDBPolicy();
case 'h':
case '?':
default:
usage();
return (c == 'h' ? 0 : 1);
break;
}
BlockResolutionManager brm;
int err;
string prefix;
if ((argc - optind) != 1)
{
usage();
return 1;
}
prefix = argv[optind];
err = brm.loadState(prefix, fflg);
if (err != 0) {
cout << "Loading BRM snapshot failed (" << prefix << ")\n";
return 1;
}
idbdatafile::IDBPolicy::configIDBPolicy();
err = brm.replayJournal(prefix);
if (err < 0) {
cout << "Could not load BRM journal file\n";
return 1;
}
BlockResolutionManager brm;
int err;
string 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();
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");
}
prefix = argv[optind];
err = brm.loadState(prefix, fflg);
/* An OAM friendly success msg */
cout << "OK.\n";
cout << "Successfully loaded BRM snapshot\n";
cout << "Successfully replayed " << err << " BRM transactions\n";
if (err != 0)
{
cout << "Loading BRM snapshot failed (" << prefix << ")\n";
return 1;
}
return 0;
err = brm.replayJournal(prefix);
if (err < 0)
{
cout << "Could not load BRM journal file\n";
return 1;
}
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();
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");
}
/* 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

@@ -40,40 +40,42 @@
using namespace BRM;
using namespace std;
void usage(char *name)
void usage(char* name)
{
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
int main(int argc, char **argv)
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;
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);
if (err == 0)
cout << "OK." << endl;
else {
cout << "Load failed" << endl;
return 1;
}
err = brm.loadState(prefix);
return 0;
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;
cerr << "This tool does not work on 64-bit arch!" << endl;
return 1;
#endif
}

View File

@@ -48,190 +48,190 @@ 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;
}
}
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);
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
<< '\t' << emSrc[i].fileID
<< '\t' << emSrc[i].blockOffset
<< '\t' << emSrc[i].HWM
<< '\t' << emSrc[i].partitionNum
<< '\t' << emSrc[i].segmentNum
<< '\t' << emSrc[i].dbRoot
<< '\t' << emSrc[i].colWid
<< '\t' << emSrc[i].status
<< '\t' << emSrc[i].partition.cprange.hi_val
<< '\t' << emSrc[i].partition.cprange.lo_val
<< '\t' << emSrc[i].partition.cprange.sequenceNum
<< '\t' << (int)(emSrc[i].partition.cprange.isValid)
emSrc[i].range.start
<< '\t' << emSrc[i].range.size
<< '\t' << emSrc[i].fileID
<< '\t' << emSrc[i].blockOffset
<< '\t' << emSrc[i].HWM
<< '\t' << emSrc[i].partitionNum
<< '\t' << emSrc[i].segmentNum
<< '\t' << emSrc[i].dbRoot
<< '\t' << emSrc[i].colWid
<< '\t' << emSrc[i].status
<< '\t' << emSrc[i].partition.cprange.hi_val
<< '\t' << emSrc[i].partition.cprange.lo_val
<< '\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;
}
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.fileID = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.blockOffset = 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.HWM = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partitionNum = 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.segmentNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.dbRoot = 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.colWid = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.status = 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.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.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.sequenceNum = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.isValid = v;
v = strtoll(beg->c_str(), 0, 0);
++beg;
em.partition.cprange.isValid = v;
out.write((char *)&em, sizeof(em));
out.write((char*)&em, sizeof(em));
getline(in, line);
}
getline(in, line);
}
fl.start = maxLBIDinUse.start + maxLBIDinUse.size * 1024;
fl.size -= fl.start / 1024;
fl.start = maxLBIDinUse.start + maxLBIDinUse.size * 1024;
fl.size -= fl.start / 1024;
out.write((char *)&fl, sizeof(fl));
out.write((char*)&fl, sizeof(fl));
out.close();
in.close();
out.close();
in.close();
return 0;
return 0;
}

View File

@@ -37,34 +37,36 @@
using namespace BRM;
using namespace std;
void usage(char *name)
void usage(char* name)
{
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
cout << "Usage: " << name << " <prefix>" << endl;
exit(1);
}
int main(int argc, char **argv)
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

@@ -28,60 +28,62 @@
using namespace std;
using namespace rwlock;
char *name;
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)
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 (strlen(argv[1]) != 1 || strlen(argv[2]) != 1 || strlen(argv[3]) != 1)
usage();
if (argc != 4)
usage();
which_lock = atoi(argv[1]);
if (which_lock < 1 || which_lock > 5)
usage();
if (strlen(argv[1]) != 1 || strlen(argv[2]) != 1 || strlen(argv[3]) != 1)
usage();
if (argv[2][0] == 'r')
which_side = 0;
else if (argv[2][0] == 'w')
which_side = 1;
else
usage();
which_lock = atoi(argv[1]);
if (argv[3][0] == 'l')
lock_unlock = 0;
else if (argv[3][0] == 'u')
lock_unlock = 1;
else
usage();
if (which_lock < 1 || which_lock > 5)
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();
if (argv[2][0] == 'r')
which_side = 0;
else if (argv[2][0] == 'w')
which_side = 1;
else
usage();
return 0;
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;
}

View File

@@ -28,39 +28,41 @@
using namespace std;
using namespace rwlock;
char *name;
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)
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 (strlen(argv[1]) != 1)
usage();
if (argc != 2)
usage();
which_lock = atoi(argv[1]);
if (which_lock < 1 || which_lock > 5)
usage();
if (strlen(argv[1]) != 1)
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;
which_lock = atoi(argv[1]);
return 0;
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;
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,33 +44,33 @@ 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;
}
/**
* bytestream operator
*/
messageqcpp::ByteStream& operator<<(messageqcpp::ByteStream &bs, const 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)
messageqcpp::ByteStream& operator>>(messageqcpp::ByteStream& bs, LogicalPartition& rhs)
{
rhs.unserialize(bs);
return bs;
rhs.unserialize(bs);
return bs;
}
}

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* Put LogicalPartition define here to avoid header file include confilct.
* This struct will be used in connector, brm and writeengine
*/
@@ -30,47 +30,47 @@
#include "bytestream.h"
namespace BRM
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)
{}
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));
}
LogicalPartition(uint16_t d, uint32_t p, uint16_t s) : dbroot(d),
pp(p),
seg(s)
{}
void serialize(messageqcpp::ByteStream& b) const
{
b << (uint16_t)dbroot;
b << (uint32_t)pp;
b << (uint16_t)seg;
}
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 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;
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;
}
/** @bug4816. For output to user purpose */
std::string toString() const;
};
/**
@@ -82,9 +82,9 @@ std::istream& operator>>(std::istream& input, LogicalPartition& rhs);
/**
* bytestream operator
*/
messageqcpp::ByteStream& operator<<(messageqcpp::ByteStream &bs, const LogicalPartition& rhs);
messageqcpp::ByteStream& operator<<(messageqcpp::ByteStream& bs, const LogicalPartition& rhs);
messageqcpp::ByteStream& operator>>(messageqcpp::ByteStream &bs, LogicalPartition& rhs);
messageqcpp::ByteStream& operator>>(messageqcpp::ByteStream& bs, LogicalPartition& rhs);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class MasterDBRMNode interface
*/
@@ -41,7 +41,8 @@
#include "tablelockserver.h"
#include "autoincrementmanager.h"
namespace BRM {
namespace BRM
{
/** @brief The Master node of the DBRM system.
*
@@ -78,172 +79,177 @@ namespace BRM {
* <Port>
* </DBRM_WorkerN>
* \endcode
*/
*/
class MasterDBRMNode
{
public:
MasterDBRMNode();
~MasterDBRMNode();
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 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 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 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 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 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 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 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 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;
}
private:
class MsgProcessor {
public:
MsgProcessor(MasterDBRMNode *master);
~MsgProcessor();
void operator()();
private:
MasterDBRMNode *m;
};
class MsgProcessor
{
public:
MsgProcessor(MasterDBRMNode* master);
~MsgProcessor();
void operator()();
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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
messageqcpp::MessageQueueServer *dbrmServer;
std::vector<messageqcpp::MessageQueueClient *> slaves;
std::vector<messageqcpp::MessageQueueClient *>::iterator iSlave;
std::vector<messageqcpp::IOSocket *> activeSessions;
messageqcpp::MessageQueueServer* dbrmServer;
std::vector<messageqcpp::MessageQueueClient*> slaves;
std::vector<messageqcpp::MessageQueueClient*>::iterator iSlave;
std::vector<messageqcpp::IOSocket*> activeSessions;
LBIDResourceGraph *rg;
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;
};
}

View File

@@ -37,7 +37,7 @@
#define MAX_RETRIES 10
BRM::MasterDBRMNode *m;
BRM::MasterDBRMNode* m;
bool die;
using namespace std;
@@ -45,33 +45,37 @@ using namespace BRM;
void fail()
{
try {
oam::Oam oam;
try
{
oam::Oam oam;
oam.processInitFailure();
}
catch (exception&) {
cerr << "failed to notify OAM of server failure" << endl;
}
oam.processInitFailure();
}
catch (exception&)
{
cerr << "failed to notify OAM of server failure" << endl;
}
}
void stop(int num)
{
#ifdef BRM_VERBOSE
std::cerr << "stopping..." << std::endl;
std::cerr << "stopping..." << std::endl;
#endif
die = true;
if (m != NULL)
m->stop();
die = true;
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...
@@ -86,90 +90,106 @@ void reload(int num)
}
catch (std::exception &e) {
m->setReadOnly(true);
std::cerr << "Reload failed. Check the config file. Reverting to read-only mode."
std::cerr << "Reload failed. Check the config file. Reverting to read-only mode."
<< std::endl;
}
m->unlock();
}
*/
int main(int argc, char **argv)
int main(int argc, char** argv)
{
// get and set locale language - BUG 5362
string systemLang = "C";
systemLang = funcexp::utf8::idb_setlocale();
string systemLang = "C";
systemLang = funcexp::utf8::idb_setlocale();
BRM::logInit ( BRM::SubSystemLogId_controllerNode );
BRM::logInit ( BRM::SubSystemLogId_controllerNode );
int retries = 0, err;
std::string arg;
int retries = 0, err;
std::string arg;
die = false;
die = false;
if (!(argc >= 2 && (arg = argv[1]) == "fg")) {
if ((err = fork()) < 0){
perror(argv[0]);
log_errno(string(argv[0]));
fail();
exit(1);
}
if (err > 0)
exit(0);
}
if (!(argc >= 2 && (arg = argv[1]) == "fg"))
{
if ((err = fork()) < 0)
{
perror(argv[0]);
log_errno(string(argv[0]));
fail();
exit(1);
}
(void)config::Config::makeConfig();
if (err > 0)
exit(0);
}
/* XXXPAT: we might want to install signal handlers for every signal */
(void)config::Config::makeConfig();
signal(SIGINT, stop);
signal(SIGTERM, stop);
/* XXXPAT: we might want to install signal handlers for every signal */
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
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
m = NULL;
while (retries < MAX_RETRIES && !die) {
try {
if (m != NULL)
delete m;
m = new BRM::MasterDBRMNode();
try {
oam::Oam oam;
m = NULL;
oam.processInitComplete("DBRMControllerNode");
}
catch (exception &e) {
ostringstream os;
while (retries < MAX_RETRIES && !die)
{
try
{
if (m != NULL)
delete m;
os << "failed to notify OAM: " << e.what();
os << " continuing anyway";
cerr << os.str() << endl;
log(os.str(), logging::LOG_TYPE_WARNING);
}
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++;
}
if (retries == MAX_RETRIES) {
log(string("Exiting after too many errors"));
fail();
}
std::cerr << "Exiting..." << std::endl;
exit(0);
m = new BRM::MasterDBRMNode();
try
{
oam::Oam oam;
oam.processInitComplete("DBRMControllerNode");
}
catch (exception& e)
{
ostringstream os;
os << "failed to notify OAM: " << e.what();
os << " continuing anyway";
cerr << os.str() << endl;
log(os.str(), logging::LOG_TYPE_WARNING);
}
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++;
}
if (retries == MAX_RETRIES)
{
log(string("Exiting after too many errors"));
fail();
}
std::cerr << "Exiting..." << std::endl;
exit(0);
}

View File

@@ -31,7 +31,7 @@ using namespace std;
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/version.hpp>
namespace bi=boost::interprocess;
namespace bi = boost::interprocess;
#include "brmtypes.h"
#include "calpontsystemcatalog.h"
@@ -47,208 +47,224 @@ using namespace BRM;
}
namespace BRM {
namespace BRM
{
/*static*/
boost::mutex MasterSegmentTableImpl::fInstanceMutex;
/*static*/
MasterSegmentTableImpl* MasterSegmentTableImpl::fInstance=0;
MasterSegmentTableImpl* MasterSegmentTableImpl::fInstance = 0;
/*static*/
MasterSegmentTableImpl* MasterSegmentTableImpl::makeMasterSegmentTableImpl(int key, int size)
{
boost::mutex::scoped_lock lk(fInstanceMutex);
boost::mutex::scoped_lock lk(fInstanceMutex);
if (fInstance)
return fInstance;
if (fInstance)
return fInstance;
fInstance = new MasterSegmentTableImpl(key, size);
fInstance = new MasterSegmentTableImpl(key, size);
return fInstance;
return fInstance;
}
MasterSegmentTableImpl::MasterSegmentTableImpl(int key, int size)
{
string keyName = ShmKeys::keyToName(key);
try
{
string keyName = ShmKeys::keyToName(key);
try
{
#if BOOST_VERSION < 104500
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write);
#ifdef __linux__
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
#endif
#else
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
bi::permissions perms;
perms.set_unrestricted();
bi::shared_memory_object shm(bi::create_only, keyName.c_str(), bi::read_write, perms);
#endif
shm.truncate(size);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception& biex)
{
bi::shared_memory_object shm(bi::open_only, keyName.c_str(), bi::read_write);
shm.truncate(size);
fShmobj.swap(shm);
}
catch (bi::interprocess_exception& biex)
{
bi::shared_memory_object shm(bi::open_only, keyName.c_str(), bi::read_write);
#ifdef __linux__
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
{
string pname = "/dev/shm/" + keyName;
chmod(pname.c_str(), 0666);
}
#endif
fShmobj.swap(shm);
}
catch (...)
{
throw;
}
bi::mapped_region region(fShmobj, bi::read_write);
fMapreg.swap(region);
fShmobj.swap(shm);
}
catch (...)
{
throw;
}
bi::mapped_region region(fShmobj, bi::read_write);
fMapreg.swap(region);
}
MSTEntry::MSTEntry() :
tableShmkey(-1),
allocdSize(0),
currentSize(0)
{
tableShmkey(-1),
allocdSize(0),
currentSize(0)
{
}
MasterSegmentTable::MasterSegmentTable()
{
#ifdef _MSC_VER
const char* envp = getenv("SystemRoot");
string SystemRoot;
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
const char* envp = getenv("SystemRoot");
string SystemRoot;
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
#endif
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;
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;
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)
}
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..?");
}
for (i = 1; i < nTables; i++)
rwlock[i].reset(new RWLock(RWLockKeys[i]));
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();
}
cerr << "ControllerSegmentTable: RWLock() threw: " << e.what() << endl;
throw;
}
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]));
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();
}
}
MasterSegmentTable::~MasterSegmentTable()
{
// int 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()
{
memset(fShmDescriptors, 0, MSTshmsize);
memset(fShmDescriptors, 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 (!block)
try {
rwlock[num]->read_lock(false);
}
catch(rwlock::wouldblock& e) {
return NULL;
}
else
rwlock[num]->read_lock();
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_read()");
return &fShmDescriptors[num];
if (!block)
try
{
rwlock[num]->read_lock(false);
}
catch (rwlock::wouldblock& e)
{
return NULL;
}
else
rwlock[num]->read_lock();
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 (!block)
try {
rwlock[num]->write_lock(false);
}
catch(rwlock::wouldblock& e) {
return NULL;
}
else
rwlock[num]->write_lock();
return &fShmDescriptors[num];
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();
return &fShmDescriptors[num];
}
void MasterSegmentTable::getTable_upgrade(int num) const
{
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_upgrade()");
rwlock[num]->upgrade_to_write();
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_upgrade()");
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()");
rwlock[num]->downgrade_to_read();
if (num < 0 || num > nTables - 1)
throw std::invalid_argument("ControllerSegmentTable::getTable_downgrade()");
rwlock[num]->downgrade_to_read();
}
void MasterSegmentTable::releaseTable_read(int num) const
{
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
rwlock[num]->read_unlock();
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
rwlock[num]->read_unlock();
}
void MasterSegmentTable::releaseTable_write(int num) const
{
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
rwlock[num]->write_unlock();
if (num < 0 || num >= nTables)
throw std::invalid_argument("ControllerSegmentTable::releaseTable()");
rwlock[num]->write_unlock();
}
} //namespace

View File

@@ -21,13 +21,13 @@
*****************************************************************************/
/** @file
*
*
* class MasterSegmentTable
*
* The MasterSegmentTable regulates access to the shared memory segments
* The MasterSegmentTable regulates access to the shared memory segments
* used by the BRM classes and provides the means for detecting when to resize
* a segment and when it has been relocated (due to resizing).
*
*
* XXXPAT: We should make a cleanup class here also.
*/
@@ -50,151 +50,157 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
struct MSTEntry {
key_t tableShmkey;
int allocdSize;
int currentSize;
EXPORT MSTEntry();
struct MSTEntry
{
key_t tableShmkey;
int allocdSize;
int currentSize;
EXPORT MSTEntry();
};
class MasterSegmentTableImpl
{
public:
static MasterSegmentTableImpl* makeMasterSegmentTableImpl(int key, int size);
static MasterSegmentTableImpl* makeMasterSegmentTableImpl(int key, int size);
boost::interprocess::shared_memory_object fShmobj;
boost::interprocess::mapped_region fMapreg;
boost::interprocess::shared_memory_object fShmobj;
boost::interprocess::mapped_region fMapreg;
private:
MasterSegmentTableImpl(int key, int size);
~MasterSegmentTableImpl();
MasterSegmentTableImpl(const MasterSegmentTableImpl& rhs);
MasterSegmentTableImpl& operator=(const MasterSegmentTableImpl& rhs);
MasterSegmentTableImpl(int key, int size);
~MasterSegmentTableImpl();
MasterSegmentTableImpl(const MasterSegmentTableImpl& rhs);
MasterSegmentTableImpl& operator=(const MasterSegmentTableImpl& rhs);
static boost::mutex fInstanceMutex;
static MasterSegmentTableImpl* fInstance;
static boost::mutex fInstanceMutex;
static MasterSegmentTableImpl* fInstance;
};
/** @brief This class regulates access to the BRM tables in shared memory
*
*
* This class regulates access to the BRM tables in shared memory
*/
class MasterSegmentTable {
public:
/** @brief Constructor.
* @note Throws runtime_error on a semaphore-related error.
*/
EXPORT MasterSegmentTable();
//MasterSegmentTable(const MasterSegmentTable& mst);
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;
class MasterSegmentTable
{
public:
/** @brief Constructor.
* @note Throws runtime_error on a semaphore-related error.
*/
EXPORT MasterSegmentTable();
//MasterSegmentTable(const MasterSegmentTable& mst);
EXPORT ~MasterSegmentTable();
/** @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 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;
/// 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 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 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 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 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;
private:
MasterSegmentTable(const MasterSegmentTable& mst);
MasterSegmentTable& operator=(const MasterSegmentTable& mst);
/** @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;
int shmid;
mutable boost::scoped_ptr<rwlock::RWLock> rwlock[nTables];
static const int MSTshmsize = nTables * sizeof(MSTEntry);
int RWLockKeys[nTables];
/// indexed by EMTable, EMFreeList, and VBBMTable
MSTEntry* fShmDescriptors;
void makeMSTSegment();
void initMSTData();
ShmKeys fShmKeys;
MasterSegmentTableImpl* fPImpl;
/** @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_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;
}
private:
MasterSegmentTable(const MasterSegmentTable& mst);
MasterSegmentTable& operator=(const MasterSegmentTable& mst);
int shmid;
mutable boost::scoped_ptr<rwlock::RWLock> rwlock[nTables];
static const int MSTshmsize = nTables * sizeof(MSTEntry);
int RWLockKeys[nTables];
/// indexed by EMTable, EMFreeList, and VBBMTable
MSTEntry* fShmDescriptors;
void makeMSTSegment();
void initMSTData();
ShmKeys fShmKeys;
MasterSegmentTableImpl* fPImpl;
};
} //namespace
#undef EXPORT

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class OIDServer interface.
*/
@@ -40,12 +40,14 @@
#define EXPORT
#endif
namespace idbdatafile {
namespace idbdatafile
{
class IDBDataFile;
}
namespace BRM {
namespace BRM
{
/** @brief The class that manages the Object ID space
*
@@ -55,154 +57,155 @@ namespace BRM {
class OIDServer
{
private:
struct FEntry {
int begin, end;
};
struct FEntry
{
int begin, end;
};
public:
/** @brief Default constructor
*
* @note Throws ios::failure on a file IO error
*/
EXPORT OIDServer();
EXPORT virtual ~OIDServer();
/** @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;
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

View File

@@ -50,117 +50,126 @@ bool sFlg;
void usage()
{
cout << "usage: reset_locks [-vnh]" << endl;
cout << " reset all InfiniDB 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 InfiniDB 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;
}
}
int main(int argc, char** argv)
{
#ifdef _MSC_VER
const char* envp = getenv("SystemRoot");
string SystemRoot;
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
string tmpEnv = "TMP=" + SystemRoot + "\\Temp";
_putenv(tmpEnv.c_str());
const char* envp = getenv("SystemRoot");
string SystemRoot;
if (envp && *envp)
SystemRoot = envp;
else
SystemRoot = "C:\\WINDOWS";
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)
{
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;
}
while ((c = getopt(argc, argv, "vnh")) != EOF)
switch (c)
{
case 'v':
vFlg = true;
break;
if (nFlg)
vFlg = true;
case 'n':
nFlg = true;
break;
ShmKeys keys;
case 's':
sFlg = true;
break;
cerr << "(Exception msgs are probably OK)" << std::endl;
case 'h':
default:
usage();
return (c == 'h' ? 0 : 1);
break;
}
RWLock *rwlock[MasterSegmentTable::nTables];
int RWLockKeys[MasterSegmentTable::nTables];
int i;
if (nFlg)
vFlg = true;
if (MasterSegmentTable::nTables != 5) {
cout << "There are more locks than reset_locks knows of. Time for an update." << endl;
exit(1);
}
ShmKeys keys;
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;
cerr << "(Exception msgs are probably OK)" << std::endl;
for (i = 0; i < MasterSegmentTable::nTables; i++)
rwlock[i] = new RWLock(RWLockKeys[i]);
RWLock* rwlock[MasterSegmentTable::nTables];
int RWLockKeys[MasterSegmentTable::nTables];
int i;
if (vFlg)
{
PRINT("Extent Map", 0);
PRINT("Extent Map free list", 1);
PRINT("VBBM", 2);
PRINT("VSS", 3);
PRINT("CL", 4);
}
if (MasterSegmentTable::nTables != 5)
{
cout << "There are more locks than reset_locks knows of. Time for an update." << endl;
exit(1);
}
if (!nFlg)
{
RESET("Extent Map", 0);
RESET("Extent Map free list", 1);
RESET("VBBM", 2);
RESET("VSS", 3);
RESET("CL", 4);
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;
if (!sFlg)
{
if (dbrm.isDBRMReady())
{
cout << " - resetting SessionManager semaphore" << endl;
try {
execplan::SessionManager sm;
sm.reset();
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
}
}
for (i = 0; i < MasterSegmentTable::nTables; i++)
rwlock[i] = new RWLock(RWLockKeys[i]);
for (i = 0; i < MasterSegmentTable::nTables; i++)
delete rwlock[i];
std::cout << "OK." << std::endl;
return 0;
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
{
execplan::SessionManager sm;
sm.reset();
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
}
}
}
for (i = 0; i < MasterSegmentTable::nTables; i++)
delete rwlock[i];
std::cout << "OK." << std::endl;
return 0;
}

View File

@@ -1,14 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by libbrm.rc
// Next default values for new objects
//
#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
#endif
#endif
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by libbrm.rc
// Next default values for new objects
//
#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
#endif
#endif

View File

@@ -34,7 +34,7 @@ ResourceNode::ResourceNode() : _lbid(0)
{
}
ResourceNode::ResourceNode(const ResourceNode &n) : _lbid(n._lbid)
ResourceNode::ResourceNode(const ResourceNode& n) : _lbid(n._lbid)
{
}
@@ -46,47 +46,49 @@ ResourceNode::~ResourceNode()
{
}
ResourceNode & ResourceNode::operator=(const ResourceNode &n)
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
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
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();
}
}

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class XXX interface
*/
@@ -35,48 +35,52 @@
#define EXPORT
#endif
namespace BRM {
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>
struct RNLess {
bool operator()(const T &x, const T &y) const
{
return *x < *y;
}
struct RNLess
{
bool operator()(const T& x, const T& y) const
{
return *x < *y;
}
};
struct RNHasher {
size_t operator()(const ResourceNode *x) const
{
return x->lbid();
}
struct RNHasher
{
size_t operator()(const ResourceNode* x) const
{
return x->lbid();
}
};
struct RNEquals {
bool operator()(const ResourceNode *x, const ResourceNode *y) const
{
return *x == *y;
}
struct RNEquals
{
bool operator()(const ResourceNode* x, const ResourceNode* y) const
{
return *x == *y;
}
};
}

View File

@@ -26,72 +26,75 @@
using namespace std;
namespace BRM {
namespace BRM
{
RGNode::RGNode() : _color(0)
{
}
RGNode::RGNode(const RGNode &n) : out(n.out), in(n.in), _color(n._color)
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)
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)
void RGNode::addOutEdge(RGNode* n)
{
out.insert(n);
n->in.insert(this);
out.insert(n);
n->in.insert(this);
}
void RGNode::addInEdge(RGNode *n)
void RGNode::addInEdge(RGNode* n)
{
in.insert(n);
n->out.insert(this);
in.insert(n);
n->out.insert(this);
}
void RGNode::removeOutEdge(RGNode *n)
void RGNode::removeOutEdge(RGNode* n)
{
out.erase(n);
n->in.erase(this);
out.erase(n);
n->in.erase(this);
}
void RGNode::removeInEdge(RGNode *n)
void RGNode::removeInEdge(RGNode* n)
{
in.erase(n);
n->out.erase(this);
in.erase(n);
n->out.erase(this);
}
} // namespace

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class RGNode interface. This is a base class for the nodes in the resource graph.
*/
@@ -37,35 +37,37 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
class RGNode;
class RGNode {
public:
EXPORT RGNode();
EXPORT RGNode(const RGNode &);
EXPORT virtual ~RGNode();
class 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;
};
}

View File

@@ -22,7 +22,7 @@
/*
* A tool to print current transactions & roll them back if necessary.
*
*
* A tool to print current transactions & roll them back if necessary.
* The proper way to use it is:
* rollback -p (to get the transaction(s) that need to be rolled back)
@@ -42,69 +42,83 @@ 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()
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);
if (err != 0)
return;
for (it = txnList.begin(); it != txnList.end(); it++)
cout << *it << endl;
err = brm.getCurrentTxnIDs(txnList);
if (err != 0)
return;
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);
if (err != 0)
return;
err = brm.vbRollback(txnID, lbidList);
if (err != 0)
return;
cout << "OK." << endl;
err = brm.getUncommittedLBIDs(txnID, lbidList);
if (err != 0)
return;
err = brm.vbRollback(txnID, lbidList);
if (err != 0)
return;
cout << "OK." << endl;
}
int main(int argc, char **argv) {
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) {
switch (opt) {
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);
while ((opt = getopt (argc, argv, options)) != -1)
{
switch (opt)
{
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);
}

View File

@@ -33,15 +33,16 @@ using namespace std;
using namespace rwlock;
using namespace logging;
namespace BRM {
RWLockMonitor::RWLockMonitor(const bool *d, const bool *ls, const uint32_t k) :
die(d), lockStatus(ls), key(k)
namespace BRM
{
ts.tv_sec = 210; // 3:30 timer
ts.tv_nsec = 0;
secsBetweenAttempts = 30;
lock.reset(new RWLock(key));
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));
}
RWLockMonitor::~RWLockMonitor()
@@ -51,89 +52,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);
if (*die)
break;
if (!gotTheLock) {
if (state.mutexLocked) {
if (!reportedProblem) {
//Message msg(ERR_BRM_MUTEX);
Message msg(M0092);
logger.logMessage(LOG_TYPE_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
}
while (!(*die))
{
gotTheLock = lock->timed_write_lock(ts, &state);
else if (state.reading > 0) {
if (!reportedProblem) {
//Message msg(ERR_RECOVERABLE_LOCK_STATE);
Message msg(M0094);
Message::Args args;
if (*die)
break;
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();
}
if (!gotTheLock)
{
if (state.mutexLocked)
{
if (!reportedProblem)
{
//Message msg(ERR_BRM_MUTEX);
Message msg(M0092);
logger.logMessage(LOG_TYPE_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
}
// 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;
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_CRITICAL, msg, LoggingID());
reportedProblem = true;
}
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;
}
/* 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);
}
}
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

@@ -36,30 +36,32 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
class RWLockMonitor {
class RWLockMonitor
{
public:
// d = die, ls = lock status, k = key
EXPORT RWLockMonitor(const bool *d, const bool *ls, const uint32_t k);
// 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);
//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 */

View File

@@ -47,65 +47,77 @@ 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 {
prefix = config->getConfig("SystemConfig", "DBRMRoot");
if (prefix.length() == 0) {
cerr << "Error: Need a valid Calpont configuation file" << endl;
exit(1);
}
}
if (argc > 1)
prefix = argv[1];
else
{
prefix = config->getConfig("SystemConfig", "DBRMRoot");
idbdatafile::IDBPolicy::configIDBPolicy();
if (prefix.length() == 0)
{
cerr << "Error: Need a valid Calpont configuation file" << endl;
exit(1);
}
}
err = brm.saveState(prefix);
if (err == 0)
cout << "Saved to " << prefix << endl;
else {
cout << "Save failed" << endl;
exit(1);
}
idbdatafile::IDBPolicy::configIDBPolicy();
(void)::umask(0);
err = brm.saveState(prefix);
currentFilename = prefix + "_current";
currentFile = IDBDataFile::open(IDBPolicy::getType(currentFilename.c_str(),
IDBPolicy::WRITEENG),
currentFilename.c_str(),
"wb",
0);
if (err == 0)
cout << "Saved to " << prefix << endl;
else
{
cout << "Save failed" << endl;
exit(1);
}
if (!currentFile) {
cerr << "Error: could not open " << currentFilename << "for writing" << endl;
exit(1);
}
try {
(void)::umask(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);
}
try
{
#ifndef _MSC_VER
prefix += '\n';
prefix += '\n';
#endif
currentFile->write(prefix.c_str(), prefix.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);
}
currentFile->write(prefix.c_str(), prefix.length());
}
catch (exception& e)
{
cerr << "Error: failed to write to " << currentFilename << ": " << e.what() << endl;
exit(1);
}
return 0;
try
{
delete currentFile;
currentFile = NULL;
}
catch (exception& e)
{
cerr << "Error: failed to close " << currentFilename << ": " << e.what() << endl;
exit(1);
}
return 0;
}

View File

@@ -23,7 +23,7 @@
/*
* This class issues Transaction ID and keeps track of the current version ID
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <cerrno>
@@ -73,7 +73,8 @@ using namespace execplan;
using namespace idbdatafile;
namespace BRM {
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.
@@ -86,391 +87,451 @@ const uint32_t SessionManagerServer::SS_QUERY_READY = 1 << 6; // Set by Proc
SessionManagerServer::SessionManagerServer() : unique32(0), unique64(0), txnidfd(-1)
{
config::Config* conf;
string stmp;
const char *ctmp;
conf = config::Config::makeConfig();
try {
stmp = conf->getConfig("SessionManager", "MaxConcurrentTransactions");
}
catch(const std::exception &e) {
cout << e.what() << endl;
stmp.empty();
}
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);
}
else
maxTxns = 1;
txnidFilename = conf->getConfig("SessionManager", "TxnIDFile");
if (!IDBPolicy::useHdfs()) {
txnidfd = open(txnidFilename.c_str(), O_RDWR | O_CREAT | O_BINARY, 0664);
if (txnidfd < 0) {
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
//FIXME: do we need this on Win?
#ifndef _MSC_VER
else {
fchmod(txnidfd, 0664);
}
#endif
}
config::Config* conf;
string stmp;
const char* ctmp;
semValue = maxTxns;
_verID = 0;
_sysCatVerID = 0;
systemState = 0;
try {
loadState();
}
catch (...) {
// first-time run most likely, ignore the error
}
conf = config::Config::makeConfig();
try
{
stmp = conf->getConfig("SessionManager", "MaxConcurrentTransactions");
}
catch (const std::exception& e)
{
cout << e.what() << endl;
stmp.empty();
}
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);
}
else
maxTxns = 1;
txnidFilename = conf->getConfig("SessionManager", "TxnIDFile");
if (!IDBPolicy::useHdfs())
{
txnidfd = open(txnidFilename.c_str(), O_RDWR | O_CREAT | O_BINARY, 0664);
if (txnidfd < 0)
{
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
//FIXME: do we need this on Win?
#ifndef _MSC_VER
else
{
fchmod(txnidfd, 0664);
}
#endif
}
semValue = maxTxns;
_verID = 0;
_sysCatVerID = 0;
systemState = 0;
try
{
loadState();
}
catch (...)
{
// first-time run most likely, ignore the error
}
}
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::useHdfs()) {
// Last transaction id
lseek(txnidfd, 0, SEEK_SET);
err = read(txnidfd, &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;
if (!IDBPolicy::useHdfs())
{
// Last transaction id
lseek(txnidfd, 0, SEEK_SET);
err = read(txnidfd, &lastTxnID, 4);
// last system catalog version id
err = read(txnidfd, &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;
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;
// System state. Contains flags regarding the suspend state of the system.
err = read(txnidfd, &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;
}
}
else 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) {
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
// last system catalog version id
err = read(txnidfd, &lastSysCatVerId, 4);
// 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;
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;
// 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 = read(txnidfd, &systemState, 4);
// 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;
}
}
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;
}
}
else 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)
{
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()
{
if (!IDBPolicy::useHdfs()) {
int err = 0;
uint32_t lSystemState = systemState;
void SessionManagerServer::saveSystemState()
{
if (!IDBPolicy::useHdfs())
{
int err = 0;
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);
lseek(txnidfd, 8, SEEK_SET);
err = write(txnidfd, &lSystemState, sizeof(int));
if (err < 0) {
perror("SessionManagerServer::saveSystemState(): write(systemState)");
throw runtime_error("SessionManagerServer::saveSystemState(): write(systemState) failed");
}
}
else {
saveSMTxnIDAndState();
}
}
// 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);
lseek(txnidfd, 8, SEEK_SET);
err = write(txnidfd, &lSystemState, sizeof(int));
if (err < 0)
{
perror("SessionManagerServer::saveSystemState(): write(systemState)");
throw runtime_error("SessionManagerServer::saveSystemState(): write(systemState) failed");
}
}
else
{
saveSMTxnIDAndState();
}
}
const QueryContext SessionManagerServer::verID()
{
QueryContext ret;
QueryContext ret;
mutex::scoped_lock lk(mutex);
ret.currentScn = _verID;
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
return ret;
mutex::scoped_lock lk(mutex);
ret.currentScn = _verID;
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
return ret;
}
const QueryContext SessionManagerServer::sysCatVerID()
{
QueryContext ret;
QueryContext ret;
mutex::scoped_lock lk(mutex);
ret.currentScn = _sysCatVerID;
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
return ret;
mutex::scoped_lock lk(mutex);
ret.currentScn = _sysCatVerID;
for (iterator i = activeTxns.begin(); i != activeTxns.end(); ++i)
ret.currentTxns->push_back(i->second);
return ret;
}
const TxnID SessionManagerServer::newTxnID(const SID session, bool block, bool isDDL)
const TxnID SessionManagerServer::newTxnID(const SID session, bool block, bool isDDL)
{
TxnID ret; //ctor must set valid = false
iterator it;
mutex::scoped_lock lk(mutex);
TxnID ret; //ctor must set valid = false
iterator it;
// if it already has a txn...
it = activeTxns.find(session);
if (it != activeTxns.end()) {
ret.id = it->second;
ret.valid = true;
return ret;
}
mutex::scoped_lock lk(mutex);
if (!block && semValue == 0)
return ret;
else while (semValue == 0)
condvar.wait(lk);
// if it already has a txn...
it = activeTxns.find(session);
semValue--;
idbassert(semValue <= (uint32_t)maxTxns);
if (it != activeTxns.end())
{
ret.id = it->second;
ret.valid = true;
return ret;
}
ret.id = ++_verID;
ret.valid = true;
activeTxns[session] = ret.id;
if (isDDL)
++_sysCatVerID;
if (!block && semValue == 0)
return ret;
else while (semValue == 0)
condvar.wait(lk);
if (!IDBPolicy::useHdfs()) {
int filedata[2];
filedata[0] = _verID;
filedata[1] = _sysCatVerID;
semValue--;
idbassert(semValue <= (uint32_t)maxTxns);
lseek(txnidfd, 0, SEEK_SET);
int err = write(txnidfd, filedata, 8);
if (err < 0) {
perror("SessionManagerServer::newTxnID(): write(verid)");
throw runtime_error("SessionManagerServer::newTxnID(): write(verid) failed");
}
}
else {
saveSMTxnIDAndState();
}
ret.id = ++_verID;
ret.valid = true;
activeTxns[session] = ret.id;
return ret;
if (isDDL)
++_sysCatVerID;
if (!IDBPolicy::useHdfs())
{
int filedata[2];
filedata[0] = _verID;
filedata[1] = _sysCatVerID;
lseek(txnidfd, 0, SEEK_SET);
int err = write(txnidfd, filedata, 8);
if (err < 0)
{
perror("SessionManagerServer::newTxnID(): write(verid)");
throw runtime_error("SessionManagerServer::newTxnID(): write(verid) failed");
}
}
else
{
saveSMTxnIDAndState();
}
return ret;
}
void SessionManagerServer::finishTransaction(TxnID& txn)
{
iterator it;
mutex::scoped_lock lk(mutex);
bool found=false;
if (!txn.valid)
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction is invalid");
iterator it;
mutex::scoped_lock lk(mutex);
bool found = false;
for (it = activeTxns.begin(); it != activeTxns.end(); ) {
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 (!txn.valid)
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction is invalid");
if (found) {
semValue++;
idbassert(semValue <= (uint32_t)maxTxns);
condvar.notify_one();
}
else
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction doesn't exist");
for (it = activeTxns.begin(); it != activeTxns.end(); )
{
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();
}
else
throw invalid_argument("SessionManagerServer::finishTransaction(): transaction doesn't exist");
}
const TxnID SessionManagerServer::getTxnID(const SID session)
{
TxnID ret;
iterator it;
mutex::scoped_lock lk(mutex);
TxnID ret;
iterator it;
it = activeTxns.find(session);
if (it != activeTxns.end()) {
ret.id = it->second;
ret.valid = true;
}
return ret;
mutex::scoped_lock lk(mutex);
it = activeTxns.find(session);
if (it != activeTxns.end())
{
ret.id = it->second;
ret.valid = true;
}
return ret;
}
shared_array<SIDTIDEntry> SessionManagerServer::SIDTIDMap(int &len)
shared_array<SIDTIDEntry> SessionManagerServer::SIDTIDMap(int& len)
{
int j;
shared_array<SIDTIDEntry> ret;
mutex::scoped_lock lk(mutex);
iterator it;
int j;
shared_array<SIDTIDEntry> ret;
mutex::scoped_lock lk(mutex);
iterator it;
ret.reset(new SIDTIDEntry[activeTxns.size()]);
ret.reset(new SIDTIDEntry[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;
}
return ret;
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;
}
return ret;
}
void SessionManagerServer::setSystemState(uint32_t state)
{
mutex::scoped_lock lk(mutex);
mutex::scoped_lock lk(mutex);
systemState |= state;
saveSystemState();
systemState |= state;
saveSystemState();
}
void SessionManagerServer::clearSystemState(uint32_t state)
{
mutex::scoped_lock lk(mutex);
mutex::scoped_lock lk(mutex);
systemState &= ~state;
saveSystemState();
systemState &= ~state;
saveSystemState();
}
uint32_t SessionManagerServer::getTxnCount()
{
mutex::scoped_lock lk(mutex);
return activeTxns.size();
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));
if (!txnidfp) {
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
// caller holds the lock
scoped_ptr<IDBDataFile> txnidfp(IDBDataFile::open(
IDBPolicy::getType(txnidFilename.c_str(), IDBPolicy::WRITEENG),
txnidFilename.c_str(), "wb", 0));
int filedata[2];
filedata[0] = _verID;
filedata[1] = _sysCatVerID;
if (!txnidfp)
{
perror("SessionManagerServer(): open");
throw runtime_error("SessionManagerServer: Could not open the transaction ID file");
}
int err = txnidfp->write(filedata, 8);
if (err < 0) {
perror("SessionManagerServer::newTxnID(): write(verid)");
throw runtime_error("SessionManagerServer::newTxnID(): write(verid) failed");
}
int filedata[2];
filedata[0] = _verID;
filedata[1] = _sysCatVerID;
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");
}
int err = txnidfp->write(filedata, 8);
txnidfp->flush();
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));
if (err < 0)
{
perror("SessionManagerServer::saveSystemState(): write(systemState)");
throw runtime_error("SessionManagerServer::saveSystemState(): write(systemState) failed");
}
txnidfp->flush();
}
} //namespace

View File

@@ -20,10 +20,10 @@
*
*****************************************************************************/
/** @file
/** @file
* class SessionManagerServer interface
*/
#ifndef _SESSIONMANAGERSERVER_H
#define _SESSIONMANAGERSERVER_H
@@ -49,11 +49,12 @@
#pragma warning (disable : 4200)
#endif
namespace BRM {
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.
*
* 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.
@@ -75,8 +76,8 @@ namespace BRM {
* default is /tmp/CalpontShm.
* SessionManager/TxnIDFile: the file to store the last transaction ID issued
*/
/*
/*
* Define DESTROYSHMSEG if the SM should deallocate the shared memory segment
* after the last reference has died. This also enables the load/save
* operations. If it is undefined, the segment is never deallocated
@@ -89,181 +90,203 @@ namespace BRM {
*/
//#define DESTROYSHMSEG
class SessionManagerServer {
class SessionManagerServer
{
public:
/** @brief SID = Session ID */
typedef uint32_t SID;
/** @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() { if (txnidfd >=0 ) close(txnidfd); }
/** @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()
{
if (txnidfd >= 0 ) close(txnidfd);
}
/** @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 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 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 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 the current version ID
*
* Gets the current version ID.
*/
EXPORT const QueryContext verID();
/**
* get a unique 32-bit number
*/
uint32_t getUnique32() { return atomicops::atomicInc(&unique32); }
/** @brief Gets the current version ID
*
* Gets the current version ID.
*/
EXPORT const QueryContext sysCatVerID();
/**
* get a unique 64-bit number
*/
uint64_t getUnique64() { return atomicops::atomicInc(&unique64); }
/** @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 Resets the semaphores to their original state. For testing only.
*
* Resets the semaphores to their original state. For testing only.
*/
EXPORT void reset();
/** @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);
}
/**
* get the Txn ID filename
*/
std::string getTxnIDFilename() const { return txnidFilename; }
/** @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 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 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 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 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 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 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);
}
/** @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;
}
/** @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 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();
private:
SessionManagerServer(const SessionManagerServer&);
SessionManagerServer& operator=(const SessionManagerServer&);
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;
int txnidfd; // file descriptor for the "last txnid" file
execplan::CalpontSystemCatalog::SCN _verID;
execplan::CalpontSystemCatalog::SCN _sysCatVerID;
uint32_t systemState;
int maxTxns; // the maximum number of concurrent transactions
std::string txnidFilename;
int txnidfd; // file descriptor for the "last txnid" file
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

View File

@@ -35,36 +35,38 @@ 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");
if (brm_str.length() > 0)
BRM_UID = static_cast<uint32_t>(config::Config::uFromText(brm_str));
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));
#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;
STORAGESTATUS_SYSVKEY = 0xfa000000 | 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;
STORAGESTATUS_SYSVKEY = 0xfa000000 | 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();
}
}

View File

@@ -39,39 +39,39 @@ namespace BRM
struct ShmKeys
{
public:
EXPORT ShmKeys();
~ShmKeys() { }
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 STORAGESTATUS_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 STORAGESTATUS_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);
//defaults okay
//ShmKeys(const ShmKeys& rhs);
//ShmKeys operator=(const ShmKeys& rhs);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class XXX interface
*/
@@ -50,90 +50,92 @@ class IDBDataFile;
}
namespace BRM {
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();
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();
/** 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_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_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;
int currentSaveFD;
idbdatafile::IDBDataFile* currentSaveFile;
std::string journalName;
std::fstream journal;
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;
int currentSaveFD;
idbdatafile::IDBDataFile* currentSaveFile;
std::string journalName;
std::fstream journal;
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
};

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class SlaveDBRMNode
*/
@@ -46,7 +46,8 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
/** @brief The Slave node of the DBRM system
*
@@ -85,422 +86,423 @@ namespace BRM {
* <Port>
* </DBRM_WorkerN>
* \endcode
*/
*/
class SlaveDBRMNode {
public:
EXPORT SlaveDBRMNode() throw();
EXPORT ~SlaveDBRMNode() throw();
class SlaveDBRMNode
{
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 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 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 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 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 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 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 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 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 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 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 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 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 ();
EXPORT int bulkSetHWM(const std::vector<BulkSetHWMArg> &, VER_t transID,
bool firstNode) 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();
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 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();
EXPORT int bulkUpdateDBRoot(const std::vector<BulkUpdateDBRootArg> &) 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 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 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 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 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 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 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();
EXPORT int bulkSetHWM(const std::vector<BulkSetHWMArg>&, VER_t transID,
bool firstNode) throw();
/** @brief Delete all extent map rows for the specified dbroot
*
* @param dbroot (in) the dbroot
*/
EXPORT int deleteDBRoot(uint16_t dbroot) 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 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.
*/
EXPORT int bulkUpdateDBRoot(const std::vector<BulkUpdateDBRootArg>&) 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 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 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 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 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 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 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();
EXPORT int clear() 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 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();
/** @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();
EXPORT void confirmChanges() throw();
EXPORT void undoChanges() throw();
/** @brief Delete all extent map rows for the specified dbroot
*
* @param dbroot (in) the dbroot
*/
EXPORT int deleteDBRoot(uint16_t dbroot) throw();
EXPORT int loadExtentMap(const std::string &filename);
EXPORT int saveExtentMap(const std::string &filename);
/** @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();
// 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);
/** @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 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);
/* 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();
// 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 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 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);
/** @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();
/* Write-side copylocks interface */
EXPORT int dmlLockLBIDRanges(const std::vector<LBIDRange> &ranges, int txnID);
EXPORT int dmlReleaseLBIDRanges(const std::vector<LBIDRange> &ranges);
/** @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 loadState(std::string filename) throw();
EXPORT int saveState(std::string filename) 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();
EXPORT const bool *getEMFLLockStatus();
EXPORT const bool *getEMLockStatus();
EXPORT const bool *getVBBMLockStatus();
EXPORT const bool *getVSSLockStatus();
EXPORT int clear() throw();
private:
explicit SlaveDBRMNode(const SlaveDBRMNode& brm);
SlaveDBRMNode& operator=(const SlaveDBRMNode& brm);
int lookup(OID_t oid, LBIDRange_v& lbidList) 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 void confirmChanges() throw();
EXPORT void undoChanges() throw();
EXPORT int loadExtentMap(const std::string& filename);
EXPORT int saveExtentMap(const std::string& filename);
// 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);
/** @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 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 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);
/* Write-side copylocks interface */
EXPORT int dmlLockLBIDRanges(const std::vector<LBIDRange>& ranges, int txnID);
EXPORT int dmlReleaseLBIDRanges(const std::vector<LBIDRange>& ranges);
EXPORT int loadState(std::string filename) throw();
EXPORT int saveState(std::string filename) throw();
EXPORT const bool* getEMFLLockStatus();
EXPORT const bool* getEMLockStatus();
EXPORT const bool* getVBBMLockStatus();
EXPORT const bool* getVSSLockStatus();
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
MasterSegmentTable mst;
ExtentMap em;
VBBM vbbm;
VSS vss;
CopyLocks copylocks;
bool locked[3]; // 0 = VBBM, 1 = VSS, 2 = CopyLocks
};
}
#undef EXPORT
#endif
#endif

View File

@@ -40,127 +40,141 @@
using namespace BRM;
using namespace std;
SlaveComm *comm;
SlaveComm* comm;
bool die;
boost::thread_group monitorThreads;
void fail()
{
try {
oam::Oam oam;
try
{
oam::Oam oam;
oam.processInitFailure();
}
catch (exception&) {
cerr << "failed to notify OAM of server failure" << endl;
}
oam.processInitFailure();
}
catch (exception&)
{
cerr << "failed to notify OAM of server failure" << endl;
}
}
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();
}
int main(int argc, char **argv)
int main(int argc, char** argv)
{
// get and set locale language - BUG 5362
string systemLang = "C";
systemLang = funcexp::utf8::idb_setlocale();
// get and set locale language - BUG 5362
string systemLang = "C";
systemLang = funcexp::utf8::idb_setlocale();
BRM::logInit ( BRM::SubSystemLogId_workerNode );
BRM::logInit ( BRM::SubSystemLogId_workerNode );
string nodeName;
SlaveDBRMNode slave;
string arg;
int err = 0;
ShmKeys keys;
string nodeName;
SlaveDBRMNode slave;
string arg;
int err = 0;
ShmKeys keys;
if (argc < 2) {
ostringstream os;
os << "Usage: " << argv[0] << " DBRM_WorkerN";
cerr << os.str() << endl;
log(os.str());
fail();
exit(1);
}
if (argc < 2)
{
ostringstream os;
os << "Usage: " << argv[0] << " DBRM_WorkerN";
cerr << os.str() << endl;
log(os.str());
fail();
exit(1);
}
idbdatafile::IDBPolicy::configIDBPolicy();
idbdatafile::IDBPolicy::configIDBPolicy();
nodeName = argv[1];
try
{
comm = new SlaveComm(nodeName, &slave);
}
catch (exception& e)
{
ostringstream os;
os << "An error occured: " << e.what();
cerr << os.str() << endl;
log(os.str());
fail();
exit(1);
}
nodeName = argv[1];
try {
comm = new SlaveComm(nodeName, &slave);
}
catch (exception &e) {
ostringstream os;
os << "An error occured: " << e.what();
cerr << os.str() << endl;
log(os.str());
fail();
exit(1);
}
#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
if (!(argc >= 3 && (arg = argv[2]) == "fg"))
err = fork();
if (!(argc >= 3 && (arg = argv[2]) == "fg"))
err = fork();
if (err == 0) {
if (err == 0)
{
/* 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 {
oam::Oam oam;
oam.processInitComplete("DBRMWorkerNode");
}
catch (exception &e) {
ostringstream os;
os << "failed to notify OAM: " << e.what();
os << " continuing anyway";
cerr << os.str() << endl;
log(os.str(), logging::LOG_TYPE_WARNING);
}
try
{
oam::Oam oam;
try {
comm->run();
}
catch (exception &e) {
ostringstream os;
os << "An error occurred: " << e.what();
cerr << os.str() << endl;
log(os.str());
exit(1);
}
}
else if (err < 0) {
perror(argv[0]);
log_errno(string(argv[0]));
fail();
}
oam.processInitComplete("DBRMWorkerNode");
}
catch (exception& e)
{
ostringstream os;
os << "failed to notify OAM: " << e.what();
os << " continuing anyway";
cerr << os.str() << endl;
log(os.str(), logging::LOG_TYPE_WARNING);
}
exit(0);
try
{
comm->run();
}
catch (exception& e)
{
ostringstream os;
os << "An error occurred: " << e.what();
cerr << os.str() << endl;
log(os.str());
exit(1);
}
}
else if (err < 0)
{
perror(argv[0]);
log_errno(string(argv[0]));
fail();
}
exit(0);
}

View File

@@ -35,18 +35,20 @@ using namespace std;
using namespace boost;
using namespace idbdatafile;
namespace BRM {
TableLockServer::TableLockServer(SessionManagerServer *sm) : sms(sm)
namespace BRM
{
mutex::scoped_lock lk(mutex);
config::Config *config = config::Config::makeConfig();
filename = config->getConfig("SystemConfig", "TableLockSaveFile");
if (filename == "")
throw invalid_argument("TableLockServer: Need to define SystemConfig/TableLockSaveFile in config file"); // todo, replace this
TableLockServer::TableLockServer(SessionManagerServer* sm) : sms(sm)
{
mutex::scoped_lock lk(mutex);
config::Config* config = config::Config::makeConfig();
load();
filename = config->getConfig("SystemConfig", "TableLockSaveFile");
if (filename == "")
throw invalid_argument("TableLockServer: Need to define SystemConfig/TableLockSaveFile in config file"); // todo, replace this
load();
}
TableLockServer::~TableLockServer()
@@ -56,258 +58,326 @@ 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();
if (IDBPolicy::useHdfs()) {
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 write save file");
it->second.serialize(out.get());
}
}
else {
ofstream out(filename.c_str(), ios::trunc | ios::binary | ios::out );
const char* filename_p = filename.c_str();
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 write save file");
it->second.serialize(out);
}
}
if (IDBPolicy::useHdfs())
{
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 write save file");
it->second.serialize(out.get());
}
}
else
{
ofstream out(filename.c_str(), ios::trunc | ios::binary | ios::out );
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 write save file");
it->second.serialize(out);
}
}
}
// 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 */
if (IDBPolicy::useHdfs()) {
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) {
ostringstream os;
os << "TableLockServer::load(): could not open the save file"
<< filename;
log(os.str(), logging::LOG_TYPE_DEBUG);
return;
}
/* Need to standardize the file error handling */
if (IDBPolicy::useHdfs())
{
const char* filename_p = filename.c_str();
scoped_ptr<IDBDataFile> in(IDBDataFile::open(
IDBPolicy::getType(filename_p, IDBPolicy::WRITEENG),
filename_p, "rb", 0));
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;
}
}
else {
ifstream in(filename.c_str(), ios::binary | ios::in);
if (!in) {
ostringstream os;
os << "TableLockServer::load(): could not open the save file"
<< filename;
log(os.str(), logging::LOG_TYPE_DEBUG);
return;
}
in.exceptions(ios::failbit | ios::badbit);
try {
in.read((char *) &size, 4);
for (i = 0; i < size; i++) {
tli.deserialize(in);
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;
if (!in)
{
ostringstream os;
os << "TableLockServer::load(): could not open the save file"
<< filename;
log(os.str(), logging::LOG_TYPE_DEBUG);
return;
}
os << "TableLockServer::load(): could not load save file " << filename <<
" loaded " << i << "/" << size << " entries\n";
log(os.str(), logging::LOG_TYPE_DEBUG);
throw;
}
}
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;
}
}
else
{
ifstream in(filename.c_str(), ios::binary | ios::in);
if (!in)
{
ostringstream os;
os << "TableLockServer::load(): could not open the save file"
<< filename;
log(os.str(), logging::LOG_TYPE_DEBUG);
return;
}
in.exceptions(ios::failbit | ios::badbit);
try
{
in.read((char*) &size, 4);
for (i = 0; i < size; i++)
{
tli.deserialize(in);
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)
uint64_t TableLockServer::lock(TableLockInfo* tli)
{
set<uint32_t> dbroots;
lit_t it;
uint32_t i;
mutex::scoped_lock lk(mutex);
set<uint32_t> dbroots;
lit_t it;
uint32_t i;
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) {
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->id = sms->getUnique64();
if (tli->id == 0) // 0 is an error code
tli->id = sms->getUnique64();
locks[tli->id] = *tli;
try {
save();
}
catch (...) {
locks.erase(tli->id);
throw;
}
return tli->id;
for (it = locks.begin(); it != locks.end(); ++it)
{
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->id = sms->getUnique64();
if (tli->id == 0) // 0 is an error code
tli->id = sms->getUnique64();
locks[tli->id] = *tli;
try
{
save();
}
catch (...)
{
locks.erase(tli->id);
throw;
}
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;
mutex::scoped_lock lk(mutex);
it = locks.find(id);
if (it != locks.end()) {
tli = it->second;
locks.erase(it);
try {
save();
}
catch (...) {
locks[tli.id] = tli;
throw;
}
return true;
}
return false;
mutex::scoped_lock lk(mutex);
it = locks.find(id);
if (it != locks.end())
{
tli = it->second;
locks.erase(it);
try
{
save();
}
catch (...)
{
locks[tli.id] = tli;
throw;
}
return true;
}
return false;
}
bool TableLockServer::changeState(uint64_t id, LockState state)
{
lit_t it;
mutex::scoped_lock lk(mutex);
LockState old;
lit_t it;
mutex::scoped_lock lk(mutex);
LockState old;
it = locks.find(id);
if (it == locks.end())
return false;
old = it->second.state;
it->second.state = state;
try {
save();
}
catch (...) {
it->second.state = old;
throw;
}
return true;
it = locks.find(id);
if (it == locks.end())
return false;
old = it->second.state;
it->second.state = state;
try
{
save();
}
catch (...)
{
it->second.state = old;
throw;
}
return true;
}
bool TableLockServer::changeOwner(uint64_t id, const string &ownerName, uint32_t pid, int32_t session,
int32_t txnID)
bool TableLockServer::changeOwner(uint64_t id, const string& ownerName, uint32_t pid, int32_t session,
int32_t txnID)
{
lit_t it;
mutex::scoped_lock lk(mutex);
string oldName;
uint32_t oldPID;
int32_t oldSession;
int32_t oldTxnID;
lit_t it;
mutex::scoped_lock lk(mutex);
string oldName;
uint32_t oldPID;
int32_t oldSession;
int32_t oldTxnID;
it = locks.find(id);
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;
try {
save();
}
catch (...) {
it->second.ownerName = oldName;
it->second.ownerPID = oldPID;
it->second.ownerSessionID = oldSession;
it->second.ownerTxnID = oldTxnID;
throw;
}
return true;
it = locks.find(id);
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;
try
{
save();
}
catch (...)
{
it->second.ownerName = oldName;
it->second.ownerPID = oldPID;
it->second.ownerSessionID = oldSession;
it->second.ownerTxnID = oldTxnID;
throw;
}
return true;
}
vector<TableLockInfo> TableLockServer::getAllLocks() const
{
vector<TableLockInfo> ret;
mutex::scoped_lock lk(mutex);
constlit_t it;
vector<TableLockInfo> ret;
mutex::scoped_lock lk(mutex);
constlit_t it;
for (it = locks.begin(); it != locks.end(); ++it)
ret.push_back(it->second);
return ret;
for (it = locks.begin(); it != locks.end(); ++it)
ret.push_back(it->second);
return ret;
}
void TableLockServer::releaseAllLocks()
{
std::map<uint64_t, TableLockInfo> tmp;
std::map<uint64_t, TableLockInfo> tmp;
mutex::scoped_lock lk(mutex);
tmp.swap(locks);
try {
save();
}
catch (...) {
tmp.swap(locks);
throw;
}
mutex::scoped_lock lk(mutex);
tmp.swap(locks);
try
{
save();
}
catch (...)
{
tmp.swap(locks);
throw;
}
}
bool TableLockServer::getLockInfo(uint64_t id, TableLockInfo *out) const
bool TableLockServer::getLockInfo(uint64_t id, TableLockInfo* out) const
{
constlit_t it;
mutex::scoped_lock lk(mutex);
constlit_t it;
mutex::scoped_lock lk(mutex);
it = locks.find(id);
if (out == NULL)
return (it != locks.end());
if (it != locks.end()) {
*out = it->second;
return true;
}
return false;
it = locks.find(id);
if (out == NULL)
return (it != locks.end());
if (it != locks.end())
{
*out = it->second;
return true;
}
return false;
}
}

View File

@@ -34,32 +34,34 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
class TableLockServer {
class TableLockServer
{
public:
EXPORT TableLockServer(SessionManagerServer *);
virtual ~TableLockServer();
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();
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;
};
}

View File

@@ -8,196 +8,228 @@ 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";
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;
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;
}
void releaseAllLocks()
{
DBRM dbrm;
DBRM dbrm;
try {
dbrm.releaseAllTableLocks();
}
catch (exception &e) {
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
cout << "OK\n";
try
{
dbrm.releaseAllTableLocks();
}
catch (exception& e)
{
cout << "caught an exception: " << e.what() << endl;
exit(1);
}
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);
}
if (ret)
cout << "id=" << tli.id << " tableOID=" << tli.tableOID <<
" owner: " << tli.ownerName << ":" << tli.ownerPID << ":" <<
tli.ownerSessionID << endl;
else
cout << "failed\n";
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";
}
int main(int argc, char **argv)
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)
{
cout << "Usage: " << argv[0] << " g | r | s | o | p | R | z. Check the code to see what they do. :P\n";
exit(1);
}
char cmd = argv[1][0];
char cmd = argv[1][0];
if (cmd == 'g')
grabLock();
else if (cmd == 'r') {
if (argc < 3) {
cout << "need an ID\n";
exit(1);
}
releaseLock(atoi(argv[2]));
}
else if (cmd == 's') {
if (argc < 3) {
cout << "need an ID\n";
exit(1);
}
changeState(atoi(argv[2]));
}
else if (cmd == 'o') {
if (argc < 3) {
cout << "need an ID\n";
exit(1);
}
changeOwner(atoi(argv[2]));
}
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";
exit(0);
if (cmd == 'g')
grabLock();
else if (cmd == 'r')
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
releaseLock(atoi(argv[2]));
}
else if (cmd == 's')
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
changeState(atoi(argv[2]));
}
else if (cmd == 'o')
{
if (argc < 3)
{
cout << "need an ID\n";
exit(1);
}
changeOwner(atoi(argv[2]));
}
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";
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

@@ -36,149 +36,156 @@
using namespace std;
namespace BRM {
namespace BRM
{
#ifdef BRM_INFO
std::ofstream brmlog("/var/log/mariadb/columnstore/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())
{
if (writeNow)
writeBegin();
if (writeNow)
writeBegin();
}
Tracer::~Tracer()
{
writeEnd();
writeEnd();
}
void printIntVec(const pair<string,const int*>& p)
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)
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)
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)
void printInt64Vec(const pair<string, const int64_t*>& p)
{
brmlog << p.first << ": (" << *p.second << ") ";
brmlog << p.first << ": (" << *p.second << ") ";
}
void Tracer::writeBegin()
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()
void Tracer::writeEnd()
{
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;
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;
}
void Tracer::writeDirect(const std::string& msg)
{
brmlog << msg << endl;
brmlog << msg << endl;
}
string Tracer::timeStamp()
string Tracer::timeStamp()
{
time_t outputTime;
time(&outputTime);
string datestr(ctime(&outputTime));
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
{
std::cerr << __FILE__ << "@" << __LINE__ << " " << ex.what() << " ";
cerr << datestr << " length " << datestr.length() << " Source: ";
cerr << fFileName << "@" << fLine << " " << fMsg << endl;
return string("timestamp error:");
}
}
time_t outputTime;
time(&outputTime);
string datestr(ctime(&outputTime));
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
{
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)
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)
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)
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)
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)
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)
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)
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)
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)
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

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class DBRM
*/
@@ -38,7 +38,8 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
/** @brief Trace beginning and end of a call.
*
@@ -46,98 +47,99 @@ namespace BRM {
* 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.
* 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.
*
* 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);
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);
/** @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
@@ -147,46 +149,46 @@ class Tracer {
#define TRACER_WRITENOW(a)\
Tracer tracer(__FILE__, __LINE__, a, fDebug);
Tracer tracer(__FILE__, __LINE__, a, fDebug);
#define TRACER_WRITELATER(a)\
Tracer tracer(__FILE__, __LINE__, a, fDebug, false);
Tracer tracer(__FILE__, __LINE__, a, fDebug, false);
#define TRACER_ADDINPUT(a)\
tracer.addInput((std::string)#a, (int*)&a);
tracer.addInput((std::string)#a, (int*)&a);
#define TRACER_ADDSTRINPUT(a)\
tracer.addInput((std::string)#a, &a);
tracer.addInput((std::string)#a, &a);
#define TRACER_ADDBOOLINPUT(a)\
tracer.addInput((std::string)#a, &a);
tracer.addInput((std::string)#a, &a);
#define TRACER_ADDSHORTINPUT(a)\
tracer.addInput((std::string)#a, (short*)&a);
tracer.addInput((std::string)#a, (short*)&a);
#define TRACER_ADDINT64INPUT(a)\
tracer.addInput((std::string)#a, (int64_t*)&a);
tracer.addInput((std::string)#a, (int64_t*)&a);
#define TRACER_ADDOUTPUT(a)\
tracer.addOutput((std::string)#a, (int*)&a);
tracer.addOutput((std::string)#a, (int*)&a);
#define TRACER_ADDBOOLOUTPUT(a)\
tracer.addOutput((std::string)#a, &a);
tracer.addOutput((std::string)#a, &a);
#define TRACER_ADDSHORTOUTPUT(a)\
tracer.addOutput((std::string)#a, (short*)&a);
tracer.addOutput((std::string)#a, (short*)&a);
#define TRACER_ADDINT64OUTPUT(a)\
tracer.addOutput((std::string)#a, (int64_t*)&a);
tracer.addOutput((std::string)#a, (int64_t*)&a);
#define TRACER_WRITE\
tracer.writeBegin();
tracer.writeBegin();
#define TRACER_WRITEDIRECT(msg)\
tracer.writeDirect(msg);
tracer.writeDirect(msg);
}
#undef EXPORT
#endif
#endif

View File

@@ -27,7 +27,8 @@
#include "transactionnode.h"
#undef TRANSACTIONNODE_DLLEXPORT
namespace BRM {
namespace BRM
{
TransactionNode::TransactionNode(int txn) : txnID(txn), _die(false), _sleeping(false)
{
@@ -39,39 +40,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)
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

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* class XXX interface
*/
@@ -39,30 +39,31 @@
#define EXPORT
#endif
namespace BRM {
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 &);
boost::condition condVar;
VER_t txnID;
bool _die, _sleeping;
private:
TransactionNode(const TransactionNode&);
TransactionNode& operator=(const TransactionNode&);
boost::condition condVar;
VER_t txnID;
bool _die, _sleeping;
};
#undef EXPORT

View File

@@ -28,42 +28,43 @@
using namespace std;
namespace BRM {
namespace BRM
{
Undoable::Undoable()
{
}
Undoable::~Undoable()
Undoable::~Undoable()
{
}
inline void Undoable::makeUndoRecord(void *start, int size)
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();
}
}

View File

@@ -20,7 +20,7 @@
*
*****************************************************************************/
/** @file
/** @file
* This class defines the interface the BRM shared structures inherit
* to support revoking any changes made on error.
*/
@@ -38,20 +38,21 @@
#define EXPORT
#endif
namespace BRM {
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

File diff suppressed because it is too large Load Diff

View File

@@ -65,37 +65,42 @@
#endif
namespace idbdatafile {
namespace idbdatafile
{
class IDBDataFile;
}
namespace BRM {
namespace BRM
{
class VSS;
struct VBFileMetadata {
OID_t OID;
uint64_t fileSize;
uint64_t nextOffset;
struct VBFileMetadata
{
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();
struct 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;
struct VBShmsegHeader
{
int nFiles;
int vbCapacity;
int vbCurrentSize;
int vbLWM;
int numHashBuckets;
// the rest of the overlay looks like this
// the rest of the overlay looks like this
// VBFileMetadata files[nFiles];
// int hashBuckets[numHashBuckets];
// VBBMEntry storage[vbCapacity];
@@ -104,31 +109,52 @@ struct VBShmsegHeader {
class VBBMImpl
{
public:
static VBBMImpl* makeVBBMImpl(unsigned key, off_t size, bool readOnly=false);
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);
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)
@@ -159,74 +185,76 @@ private:
* is detached.
*/
class VBBM : public Undoable {
public:
enum OPS {
NONE,
READ,
WRITE
};
class VBBM : public Undoable
{
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 loadVersion1(idbdatafile::IDBDataFile* in);
EXPORT void loadVersion2(idbdatafile::IDBDataFile* in);
EXPORT void save(std::string filename);
EXPORT void clear();
EXPORT void load(std::string filename);
EXPORT void loadVersion1(idbdatafile::IDBDataFile* in);
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);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -76,71 +76,96 @@
#define EXPORT
#endif
namespace BRM {
namespace BRM
{
struct VSSEntry {
LBID_t lbid;
VER_t verID;
bool vbFlag;
bool locked;
int next;
struct VSSEntry
{
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;
struct VSSShmsegHeader
{
int capacity;
int currentSize;
int LWM;
int numHashBuckets;
int lockedEntryCount;
// the rest of the overlay looks like this
// int hashBuckets[numHashBuckets];
// VSSEntry storage[capacity];
};
class QueryContext_vss {
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;
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);
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);
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;
@@ -177,98 +202,100 @@ class ExtentMap;
* is detached.
*/
class VSS : public Undoable {
public:
class VSS : public Undoable
{
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 clear();
EXPORT void load(std::string filename);
#ifndef __LP64__
//This method is OBE now that the structs are padded correctly
EXPORT void load64(std::string filename);
//This method is OBE now that the structs are padded correctly
EXPORT void load64(std::string filename);
#endif
EXPORT void save(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;
};
}