You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-27 21:01:50 +03:00
292 lines
8.1 KiB
C++
292 lines
8.1 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: vss.h 1926 2013-06-30 21:18:14Z wweeks $
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/** @file
|
|
* class XXX interface
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <set>
|
|
//#define NDEBUG
|
|
#include <cassert>
|
|
#include <boost/thread.hpp>
|
|
|
|
#include "brmshmimpl.h"
|
|
|
|
#include "brmtypes.h"
|
|
#include "undoable.h"
|
|
#include "mastersegmenttable.h"
|
|
#include "shmkeys.h"
|
|
#include "hasher.h"
|
|
|
|
#ifdef NONE
|
|
#undef NONE
|
|
#endif
|
|
#ifdef READ
|
|
#undef READ
|
|
#endif
|
|
#ifdef WRITE
|
|
#undef WRITE
|
|
#endif
|
|
|
|
// These config parameters need to be loaded
|
|
|
|
// will get a small hash function performance boost by using powers of 2
|
|
#define VSSSTORAGE_INITIAL_COUNT 200000
|
|
#define VSSSTORAGE_INITIAL_SIZE (VSSSTORAGE_INITIAL_COUNT * sizeof(VSSEntry))
|
|
#define VSSSTORAGE_INCREMENT_COUNT 20000
|
|
#define VSSSTORAGE_INCREMENT (VSSSTORAGE_INCREMENT_COUNT * sizeof(VSSEntry))
|
|
|
|
// (average list length = 4)
|
|
#define VSSTABLE_INITIAL_SIZE (50000 * sizeof(int))
|
|
#define VSSTABLE_INCREMENT (5000 * sizeof(int))
|
|
|
|
#define VSS_INITIAL_SIZE (sizeof(VSSShmsegHeader) + VSSSTORAGE_INITIAL_SIZE + VSSTABLE_INITIAL_SIZE)
|
|
|
|
#define VSS_INCREMENT (VSSTABLE_INCREMENT + VSSSTORAGE_INCREMENT)
|
|
|
|
#define VSS_SIZE(entries) \
|
|
((entries * sizeof(VSSEntry)) + (entries / 4 * sizeof(int)) + sizeof(VSSShmsegHeader))
|
|
|
|
#define EXPORT
|
|
|
|
namespace BRM
|
|
{
|
|
struct VSSEntry
|
|
{
|
|
LBID_t lbid;
|
|
VER_t verID;
|
|
bool vbFlag;
|
|
bool locked;
|
|
int next;
|
|
#ifndef __LP64__
|
|
uint32_t pad1;
|
|
#endif
|
|
EXPORT VSSEntry();
|
|
};
|
|
|
|
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
|
|
{
|
|
public:
|
|
QueryContext_vss() : currentScn(0)
|
|
{
|
|
txns.reset(new std::set<VER_t>());
|
|
}
|
|
QueryContext_vss(const QueryContext& qc);
|
|
VER_t currentScn;
|
|
boost::shared_ptr<std::set<VER_t> > txns;
|
|
};
|
|
|
|
class VSSImpl
|
|
{
|
|
public:
|
|
static VSSImpl* makeVSSImpl(unsigned key, off_t size, bool readOnly = false);
|
|
|
|
inline void grow(unsigned key, off_t size)
|
|
#ifndef NDBUG
|
|
{
|
|
fVSS.grow(key, size);
|
|
}
|
|
#else
|
|
{
|
|
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 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);
|
|
|
|
BRMShmImpl fVSS;
|
|
|
|
static boost::mutex fInstanceMutex;
|
|
static VSSImpl* fInstance;
|
|
};
|
|
|
|
class VBBM;
|
|
class ExtentMap;
|
|
|
|
/** @brief The Version Substitution Structure (VSS)
|
|
*
|
|
* At a high level, the VSS maintains a table that associates an LBID with
|
|
* a version number and 2 flags that indicate whether or not the block
|
|
* identified by the <LBID, VerID> pair exists in the main database files
|
|
* or the Version Buffer. The VSS's main purpose is to resolve the version of
|
|
* a specified block the caller can safely use given that there may be concurrent
|
|
* writes to that block.
|
|
*
|
|
* As implemented, it is a hash table and a set of lists that exist in
|
|
* shared memory. The hash table is keyed by LBID, and
|
|
* each valid entry points to the head of a unique list. Each list element
|
|
* contains the LBID, VerID, & the two flags that encapsulate "an entry in the
|
|
* VSS table". Every list contains all elements that collide on that hash table
|
|
* entry that points to it, "load factor" has no bearing on performance,
|
|
* and lists can grow arbitrarily large.
|
|
* Technically lookups are O(n), but in normal circumstances it'll
|
|
* be constant time. As things are right now, we expect there to be about
|
|
* 200k VSS entries. The hash table is sized such that on average there will be 4
|
|
* entries per list when it's at capacity.
|
|
*
|
|
* The memory management & structure manipulation code is nearly identical
|
|
* to that in the VBBM, so any bugs found here are likely there as well.
|
|
*
|
|
* Shared memory is managed using code similar to the ExtentMap & VBBM. When
|
|
* the shared memory segment needs to grow, it is write-locked, a new one
|
|
* is created, the contents are reinserted to the new one, the key is
|
|
* registered, and the old segment is destroyed when the last reference to it
|
|
* is detached.
|
|
*/
|
|
|
|
class VSS : public Undoable
|
|
{
|
|
public:
|
|
enum OPS
|
|
{
|
|
NONE,
|
|
READ,
|
|
WRITE
|
|
};
|
|
|
|
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);
|
|
|
|
// 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 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;
|
|
|
|
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 void clear();
|
|
EXPORT void load(std::string filename);
|
|
EXPORT void save(std::string filename);
|
|
|
|
#ifdef BRM_DEBUG
|
|
EXPORT int getShmid() const;
|
|
#endif
|
|
|
|
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;
|
|
|
|
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
|
|
|
|
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);
|
|
|
|
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;
|
|
};
|
|
|
|
} // namespace BRM
|
|
|
|
#undef EXPORT
|