/* 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 #include 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::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::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::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::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::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::iterator it; it = sequences.find(oid); if (it != sequences.end()) sequences.erase(it); } } /* namespace BRM */