1
0
Fork 0
arangodb/arangod/BitIndexes/masterblocktable.h

472 lines
18 KiB
C
Executable File

////////////////////////////////////////////////////////////////////////////////
/// @brief master block table implementation
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. O
/// @author Copyright 2006-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_BASICS_C_BITINDEXES_MASTER_BLOCK_TABLE_H
#define TRIAGENS_BASICS_C_BITINDEXES_MASTER_BLOCK_TABLE_H 1
#include "BasicsC/associative.h"
#include "BasicsC/common.h"
#include "BasicsC/hashes.h"
#include "BasicsC/locks.h"
#include "BasicsC/vector.h"
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- bitarray private types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup bitarray
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief private structure for the master table
////////////////////////////////////////////////////////////////////////////////
typedef struct MasterTableBlockData_s {
void* _tablePointer;
// later todo: if the same bit mask appears then rather than storing one element
// we store a sequence of elements -- _numPointers below tells us how many elements
// are stored here. However we need some overhead to array extension etc. do later or use vector
size_t _numPointers;
} MasterTableBlockData_t;
typedef struct MasterTableBlock_s {
uint8_t _usedPointers;
uint8_t _deletedPointers;
bit_column_int_t _deleted;
MasterTableBlockData_t _tablePointers [BITARRAY_MASTER_TABLE_BLOCKSIZE];
// ............................................................................
// to test for deleted value
// Let 0 <= n <= (BITARRAY_MASTER_TABLE_BLOCKSIZE - 1).
// if ((1 << n) && deleted) == 0, then item has been removed, otherwise not.
// ............................................................................
} MasterTableBlock_t;
///////////////////////////////////////////////////////////////////////////////
// The actual structure for a Master Table
// A Master Table (MT) is a sequence of one or more 'blocks' (see above structure).
// Currently the MT is a sequence of contiguous 'blocks' rather than a linked
// list of 'blocks'.
///////////////////////////////////////////////////////////////////////////////
typedef struct MasterTable_s {
size_t _numBlocks; // the number of blocks allocated in the memory zone for the Master Table
size_t _usedBlocks; // the number of used block (not necessarily completed) within the Master Table.
MasterTableBlock_t* _blocks; // a list of blocks storing the document pointers
TRI_memory_zone_t* _memoryZone; // the memory zone where the blocks will reside NOT where the table structure will reside
TRI_associative_array_t _tablePosition; // The associated array - which stores the table position of a document
} MasterTable_t;
///////////////////////////////////////////////////////////////////////////////
// The input-output structure to the Master Table
///////////////////////////////////////////////////////////////////////////////
// ............................................................................
// The shared Master Table if we allow sharing
// ............................................................................
//static MasterTable_t* _masterTable_ = NULL;
// ............................................................................
// forward declared functions
// ............................................................................
static int extendMasterTable (MasterTable_t*);
static int createMasterTable (MasterTable_t**, TRI_memory_zone_t*);
static void destroyMasterTable (MasterTable_t* mt);
static void freeMasterTable (MasterTable_t* mt);
static int insertMasterTable (MasterTable_t*, TRI_master_table_position_t*);
static int removeElementMasterTable (MasterTable_t*, TRI_master_table_position_t*, bool*);
static int storeElementMasterTable (MasterTable_t*, TRI_vector_pointer_t*, TRI_master_table_position_t*);
// ............................................................................
// forward declared functions associative array
// ............................................................................
static uint64_t tablePositionHashKey (TRI_associative_array_t*, void*);
static uint64_t tablePositionHashElement (TRI_associative_array_t*, void*);
static void tablePositionClearElement (TRI_associative_array_t*, void*);
static bool tablePositionIsEmptyElement (TRI_associative_array_t*, void*);
static bool tablePositionIsEqualKeyElement (TRI_associative_array_t*, void*, void*);
static bool tablePositionIsEqualElementElement (TRI_associative_array_t*, void*, void*);
// ............................................................................
// Implementation of master table functions
// ............................................................................
///////////////////////////////////////////////////////////////////////////////
// Creates a Master Table (MT). Failure will return an appropriate error number
///////////////////////////////////////////////////////////////////////////////
static int createMasterTable(MasterTable_t** mt, TRI_memory_zone_t* memoryZone) {
int j;
MasterTableBlock_t* block;
// ..........................................................................
// If the MT has already been created, return, do nothing and report no error
// ..........................................................................
if ( *mt != NULL) {
return TRI_ERROR_NO_ERROR;
}
// ..........................................................................
// If the memoryZone is invalid, return internal error
// ..........................................................................
if ( memoryZone == NULL) {
return TRI_ERROR_INTERNAL;
}
// ..........................................................................
// Create the MT structure
// ..........................................................................
*mt = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(MasterTable_t), false);
if (*mt == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;
}
// ..........................................................................
// Create the blocks
// ..........................................................................
(*mt)->_numBlocks = BITARRAY_MASTER_TABLE_INITIAL_SIZE;
(*mt)->_usedBlocks = 0;
(*mt)->_blocks = TRI_Allocate(memoryZone, (sizeof(MasterTableBlock_t) * (*mt)->_numBlocks), false);
(*mt)->_memoryZone = memoryZone;
if ((*mt)->_blocks == NULL) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, *mt);
return TRI_ERROR_OUT_OF_MEMORY;
}
// ..........................................................................
// Clear all blocks in the table
// ..........................................................................
for (j = 0; j < (*mt)->_numBlocks; ++j) {
block = &((*mt)->_blocks[j]);
block->_usedPointers = 0;
block->_deletedPointers = 0;
memset(&(block->_tablePointers), 0, BITARRAY_MASTER_TABLE_BLOCKSIZE * sizeof(MasterTableBlockData_t) );
}
// ............................................................................
// The associative array for table position of a document
// ............................................................................
TRI_InitAssociativeArray(&((*mt)->_tablePosition),
memoryZone,
sizeof(TRI_master_table_position_t),
tablePositionHashKey,
tablePositionHashElement,
tablePositionClearElement,
tablePositionIsEmptyElement,
tablePositionIsEqualKeyElement,
tablePositionIsEqualElementElement);
return TRI_ERROR_NO_ERROR;
}
static void destroyMasterTable(MasterTable_t* mt) {
if (mt == NULL) {
return;
}
freeMasterTable(mt);
TRI_Free(mt->_memoryZone, mt);
}
///////////////////////////////////////////////////////////////////////////////
// extends a given MT. Error reported if failure results
// The given position must be < mt->_numBlocks, otherwise the table is
// is extended to accomdate that position
///////////////////////////////////////////////////////////////////////////////
static int extendMasterTable(MasterTable_t* mt) {
MasterTableBlock_t* newBlocks;
MasterTableBlock_t* block;
size_t newNumBlocks;
int j;
if (mt->_usedBlocks < mt->_numBlocks) {
return TRI_ERROR_NO_ERROR;
}
newNumBlocks = (mt->_numBlocks * BITARRAY_MASTER_TABLE_GROW_FACTOR) + 1;
newBlocks = TRI_Allocate(mt->_memoryZone, (sizeof(MasterTableBlock_t) * newNumBlocks), false);
if (newBlocks == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;
}
for (j = mt->_usedBlocks; j < newNumBlocks; ++j) {
block = &(newBlocks[j]);
block->_usedPointers = 0;
block->_deletedPointers = 0;
memset(&(block->_tablePointers), 0, BITARRAY_MASTER_TABLE_BLOCKSIZE * sizeof(MasterTableBlockData_t) );
}
memcpy(newBlocks, mt->_blocks, mt->_usedBlocks * sizeof(MasterTableBlock_t));
TRI_Free(mt->_memoryZone, mt->_blocks);
mt->_blocks = newBlocks;
mt->_numBlocks = newNumBlocks;
return TRI_ERROR_NO_ERROR;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
static void freeMasterTable(MasterTable_t* mt) {
if (mt == NULL) {
return;
}
TRI_Free(mt->_memoryZone, mt->_blocks);
}
///////////////////////////////////////////////////////////////////////////////
// Always insert first, then apply the generated position
// Not optimised as yet for document handles with the same bit masks
///////////////////////////////////////////////////////////////////////////////
static int insertMasterTable(MasterTable_t* mt, TRI_master_table_position_t* tableEntry) {
int result;
MasterTableBlock_t* block;
// ..........................................................................
// Check whether or not we have enough room remaining in the master table
// array to store the new table entry.
// ..........................................................................
result = extendMasterTable(mt);
if (result != TRI_ERROR_NO_ERROR) {
return result;
}
// ..........................................................................
// Extract the block in which we are going to operate on
// ..........................................................................
block = &(mt->_blocks[mt->_usedBlocks]);
// ..........................................................................
// Check that we do not need a new block if the currrent block is full
// ..........................................................................
if (block->_usedPointers == BITARRAY_MASTER_TABLE_BLOCKSIZE) {
++(mt->_usedBlocks);
// ........................................................................
// Need to check again if we have enough remove
// ........................................................................
result = extendMasterTable(mt);
if (result != TRI_ERROR_NO_ERROR) {
return result;
}
// ........................................................................
// Extract the block again this time we know it is empty
// ........................................................................
block = &(mt->_blocks[mt->_usedBlocks]);
}
// ..........................................................................
// Set the document handle in the table
// ..........................................................................
((block->_tablePointers)[block->_usedPointers])._tablePointer = tableEntry->_docPointer;
((block->_tablePointers)[block->_usedPointers])._numPointers = 1;
++(block->_usedPointers);
// ..........................................................................
// Set the position information so this can be passed back to the bitarray
// ..........................................................................
tableEntry->_blockNum = mt->_usedBlocks;
tableEntry->_bitNum = block->_usedPointers;
tableEntry->_vectorNum = 0; // not currently used in this revision
// ..........................................................................
// Insert the tableEntry into the associative array with the key being
// the document handle.
// ..........................................................................
if (!TRI_InsertKeyAssociativeArray(&(mt->_tablePosition), tableEntry->_docPointer, tableEntry, false)) {
return TRI_ERROR_INTERNAL;
}
return TRI_ERROR_NO_ERROR;
}
int removeElementMasterTable(MasterTable_t* mt, TRI_master_table_position_t* position, bool* compactColumns) {
/*
size_t _blockNum; // the block within the Master Table
uint8_t _offset; // with the given block, an integer from 0..255 which indicates where within the block the document pointer resides
void* _docPointer; // the document pointer stored in that position
*/
return TRI_ERROR_NO_ERROR;
}
int storeElementMasterTable(MasterTable_t* mt, TRI_vector_pointer_t* results, TRI_master_table_position_t* position) {
MasterTableBlock_t* tableBlock;
tableBlock = mt->_blocks + position->_blockNum;
// ...........................................................................
// Determine if the entry has been deleted
// ...........................................................................
if ((tableBlock->_deleted >> position->_bitNum) == 1) {
return TRI_ERROR_NO_ERROR;
}
// ...........................................................................
// entry not deleted so append it to the results vector
// ...........................................................................
TRI_PushBackVectorPointer(results,(tableBlock->_tablePointers[position->_bitNum])._tablePointer);
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION OF FORWARD DECLARED FUNCTIONS FOR ASSOCIATIVE ARRAY
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Given a doc pointer returns a hash
///////////////////////////////////////////////////////////////////////////////
uint64_t tablePositionHashKey(TRI_associative_array_t* aa, void* key) {
uint64_t hash = TRI_FnvHashBlockInitial();
hash = TRI_FnvHashBlock(hash, key, sizeof(void*));
return hash;
}
uint64_t tablePositionHashElement(TRI_associative_array_t* aa, void* element) {
TRI_master_table_position_t* mtp = (TRI_master_table_position_t*)(element);
uint64_t hash = TRI_FnvHashBlockInitial();
hash = TRI_FnvHashBlock(hash, mtp->_docPointer, sizeof(void*));
return hash;
}
void tablePositionClearElement(TRI_associative_array_t* aa, void* element) {
TRI_master_table_position_t* mtp = (TRI_master_table_position_t*)(element);
mtp->_blockNum = 0;
mtp->_bitNum = 0;
mtp->_docPointer = NULL;
}
bool tablePositionIsEmptyElement(TRI_associative_array_t* aa, void* element) {
TRI_master_table_position_t* mtp = (TRI_master_table_position_t*)(element);
if (mtp->_blockNum == 0 && mtp->_bitNum == 0 && mtp->_docPointer == NULL) {
return true;
}
return false;
}
bool tablePositionIsEqualKeyElement(TRI_associative_array_t* aa, void* key, void* element) {
TRI_master_table_position_t* mtp = (TRI_master_table_position_t*)(element);
if (key == mtp->_docPointer) {
return true;
}
return false;
}
bool tablePositionIsEqualElementElement(TRI_associative_array_t* aa, void* left, void* right) {
TRI_master_table_position_t* left_mtp = (TRI_master_table_position_t*)(left);
TRI_master_table_position_t* right_mtp = (TRI_master_table_position_t*)(right);
if (left_mtp->_blockNum == right_mtp->_blockNum &&
left_mtp->_bitNum == right_mtp->_bitNum &&
left_mtp->_docPointer == right_mtp->_docPointer) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End: