1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
mariadb-columnstore-engine/versioning/BRM/autoincrementmanager.cpp
2022-01-21 16:43:49 +00:00

158 lines
3.7 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*****************************************************************************
* $Id$
*
****************************************************************************/
#define BRMAUTOINCMGR_DLLEXPORT
#include "autoincrementmanager.h"
#undef BRMAUTOINCMGR_DLLEXPORT
#include <math.h>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace std;
using namespace boost;
using namespace boost::posix_time;
namespace BRM
{
AutoincrementManager::AutoincrementManager()
{
}
AutoincrementManager::~AutoincrementManager()
{
}
void AutoincrementManager::startSequence(uint32_t oid, uint64_t firstNum, uint32_t colWidth,
execplan::CalpontSystemCatalog::ColDataType colDataType)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
sequence s;
it = sequences.find(oid);
if (it != sequences.end())
return;
s.value = firstNum;
if (isUnsigned(colDataType))
{
s.overflow = (0xFFFFFFFFFFFFFFFFULL >> (64 - colWidth * 8)) - 1;
}
else
{
s.overflow = (1ULL << (colWidth * 8 - 1));
}
sequences[oid] = s;
}
bool AutoincrementManager::getAIRange(uint32_t oid, uint64_t count, uint64_t* firstNum)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
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)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
it = sequences.find(oid);
if (it == sequences.end())
return;
it->second.value = value;
}
const uint32_t AutoincrementManager::lockTime = 30;
void AutoincrementManager::getLock(uint32_t oid)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
ptime stealTime = microsec_clock::local_time() + seconds(lockTime);
bool gotIt = false;
it = sequences.find(oid);
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)
{
boost::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->second.lock.unlock();
}
void AutoincrementManager::deleteSequence(uint32_t oid)
{
boost::mutex::scoped_lock lk(lock);
map<uint64_t, sequence>::iterator it;
it = sequences.find(oid);
if (it != sequences.end())
sequences.erase(it);
}
} /* namespace BRM */