/* 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: objectidmanager.cpp 9210 2013-01-21 14:10:42Z rdempsey $ * ****************************************************************************/ /** @file * This file implements ObjectIDManager * * The ObjectIDManager is responsible for allocating and deallocating * Object IDs from a 24-bit space consistently across all processes & threads. * The expected allocation size is 1 or 2 OIDs, and the usage pattern is * unknown. The OID space is described by a 16Mbit bitmap file on disk * and a brief free list. Accesses are synchronized by using flock(). * * This class must implement a high degree of correctness. However, it * also requires file IO. Most functions throw an exception if a hard IO error * occurs more than MaxRetries times in a row. Right now the code makes * no attempt to back out changes that occurred before the error although it * may be possible to do so for certain errors. Probably the best course of * action would be to halt the system if an exception is thrown here * to prevent database corruption resulting allocation of OIDs from a * possibly corrupt OID bitmap. The OID bitmap can be rebuilt at system * startup if necessary (need to write a tool to do that still). * * There are a few checks to verify the safety of allocations and * deallocations & the correctness of this implementation in general. * Those errors will throw logic_error. IO errors will throw * ios_base::failure. * * There are probably oodles of optimizations possible given this implmementation. * For example: * - make fullScan() construct a freelist * - sorting & coalescing free list entries will raise the hit rate * (at what cost?) * - implement a bias for high numbered OIDs in the free list to reduce * the number of fullScans searching far in the bitmap * - avoid the extra read in flipOIDBlock when called by fullscan * - singleton object operating entirely in memory (no file IO) * - singleton object using only a free list (no bitmap) * - a different implementation altogether. * * Time permitting we might look into those things. */ #include "objectidmanager.h" #include "configcpp.h" #include #include #include #include #include //#define NDEBUG #include using namespace std; #include "dbrm.h" #ifndef O_BINARY #define O_BINARY 0 #endif #ifndef O_DIRECT #define O_DIRECT 0 #endif #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif #ifndef O_NOATIME #define O_NOATIME 0 #endif namespace { boost::mutex CtorMutex; } namespace execplan { ObjectIDManager::ObjectIDManager() { boost::mutex::scoped_lock lk(CtorMutex); config::Config* conf; string tmp; conf = config::Config::makeConfig(); try { fFilename = conf->getConfig("OIDManager", "OIDBitmapFile"); } catch (exception&) { fFilename = "/mnt/OAM/dbrm/oidbitmap"; } if (fFilename.empty()) fFilename = "/mnt/OAM/dbrm/oidbitmap"; } ObjectIDManager::~ObjectIDManager() { } int ObjectIDManager::allocOID() { return allocOIDs(1); } int ObjectIDManager::allocVBOID(uint32_t dbroot) { return dbrm.allocVBOID(dbroot); } int ObjectIDManager::getDBRootOfVBOID(uint32_t vboid) { return dbrm.getDBRootOfVBOID(vboid); } int ObjectIDManager::allocOIDs(int num) { return dbrm.allocOIDs(num); } void ObjectIDManager::returnOID(int oid) { returnOIDs(oid, oid); } void ObjectIDManager::returnOIDs(int start, int end) { //@Bug 1412. Do not reuse oids for now. return; } const string ObjectIDManager::getFilename() const { return fFilename; } int ObjectIDManager::size() { return dbrm.oidm_size(); } vector ObjectIDManager::getVBOIDToDBRootMap() { return dbrm.getVBOIDToDBRootMap(); } } // namespace execplan