mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 06:43:03 +01:00
Style.
This commit is contained in:
parent
22dbbc1a08
commit
05271261e1
@ -35,7 +35,7 @@ namespace Firebird {
|
|||||||
class StatusHolder
|
class StatusHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StatusHolder(const ISC_STATUS* status = NULL)
|
explicit StatusHolder(const ISC_STATUS* status = NULL)
|
||||||
{
|
{
|
||||||
memset(m_status_vector, 0, sizeof(m_status_vector));
|
memset(m_status_vector, 0, sizeof(m_status_vector));
|
||||||
m_raised = false;
|
m_raised = false;
|
||||||
|
@ -35,7 +35,8 @@ namespace Firebird {
|
|||||||
|
|
||||||
// Aligns output parameter (i.e. transfers data in destructor).
|
// Aligns output parameter (i.e. transfers data in destructor).
|
||||||
template <typename C>
|
template <typename C>
|
||||||
class OutAligner {
|
class OutAligner
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
UCHAR* userBuffer;
|
UCHAR* userBuffer;
|
||||||
#ifdef RISC_ALIGNMENT
|
#ifdef RISC_ALIGNMENT
|
||||||
@ -81,7 +82,8 @@ public:
|
|||||||
|
|
||||||
// Aligns input parameter.
|
// Aligns input parameter.
|
||||||
template <typename C>
|
template <typename C>
|
||||||
class Aligner {
|
class Aligner
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
#ifdef RISC_ALIGNMENT
|
#ifdef RISC_ALIGNMENT
|
||||||
Firebird::HalfStaticArray<C, BUFFER_SMALL> localBuffer;
|
Firebird::HalfStaticArray<C, BUFFER_SMALL> localBuffer;
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
|
|
||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
|
|
||||||
class MetaName {
|
class MetaName
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
char data[MAX_SQL_IDENTIFIER_SIZE];
|
char data[MAX_SQL_IDENTIFIER_SIZE];
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
@ -182,7 +182,8 @@ inline size_t get_map_page_size()
|
|||||||
#ifdef USE_VALGRIND
|
#ifdef USE_VALGRIND
|
||||||
// Circular FIFO buffer of read/write protected extents pending free operation
|
// Circular FIFO buffer of read/write protected extents pending free operation
|
||||||
// Race protected via cache_mutex.
|
// Race protected via cache_mutex.
|
||||||
struct DelayedExtent {
|
struct DelayedExtent
|
||||||
|
{
|
||||||
void *memory; // Extent pointer
|
void *memory; // Extent pointer
|
||||||
size_t size; // Size of extent
|
size_t size; // Size of extent
|
||||||
int handle; // Valgrind handle of protected extent block
|
int handle; // Valgrind handle of protected extent block
|
||||||
@ -508,7 +509,8 @@ void* MemoryPool::external_alloc(size_t &size)
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryPool::external_free(void *blk, size_t &size, bool pool_destroying) {
|
void MemoryPool::external_free(void *blk, size_t &size, bool pool_destroying)
|
||||||
|
{
|
||||||
# if !defined(DEBUG_GDS_ALLOC) && (defined(WIN_NT) || defined(HAVE_MMAP))
|
# if !defined(DEBUG_GDS_ALLOC) && (defined(WIN_NT) || defined(HAVE_MMAP))
|
||||||
if (size == EXTENT_SIZE) {
|
if (size == EXTENT_SIZE) {
|
||||||
MutexLockGuard guard(*cache_mutex);
|
MutexLockGuard guard(*cache_mutex);
|
||||||
@ -539,7 +541,8 @@ void MemoryPool::external_free(void *blk, size_t &size, bool pool_destroying) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void* MemoryPool::tree_alloc(size_t size) {
|
void* MemoryPool::tree_alloc(size_t size)
|
||||||
|
{
|
||||||
if (size == sizeof(FreeBlocksTree::ItemList))
|
if (size == sizeof(FreeBlocksTree::ItemList))
|
||||||
// This condition is to handle case when nodelist and itemlist have equal size
|
// This condition is to handle case when nodelist and itemlist have equal size
|
||||||
if (sizeof(FreeBlocksTree::ItemList) != sizeof(FreeBlocksTree::NodeList) ||
|
if (sizeof(FreeBlocksTree::ItemList) != sizeof(FreeBlocksTree::NodeList) ||
|
||||||
@ -564,7 +567,8 @@ void* MemoryPool::tree_alloc(size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryPool::tree_free(void* block) {
|
void MemoryPool::tree_free(void* block)
|
||||||
|
{
|
||||||
// This method doesn't merge nearby pages
|
// This method doesn't merge nearby pages
|
||||||
((PendingFreeBlock*)block)->next = pendingFree;
|
((PendingFreeBlock*)block)->next = pendingFree;
|
||||||
ptrToBlock(block)->mbk_flags &= ~MBK_USED;
|
ptrToBlock(block)->mbk_flags &= ~MBK_USED;
|
||||||
@ -586,12 +590,15 @@ void* MemoryPool::allocate_nothrow(size_t size
|
|||||||
size = MEM_ALIGN(size);
|
size = MEM_ALIGN(size);
|
||||||
#endif
|
#endif
|
||||||
// Blocks with internal length of zero make allocator unhappy
|
// Blocks with internal length of zero make allocator unhappy
|
||||||
if (!size) size = MEM_ALIGN(1);
|
if (!size)
|
||||||
|
size = MEM_ALIGN(1);
|
||||||
|
|
||||||
if (parent_redirect) {
|
if (parent_redirect)
|
||||||
|
{
|
||||||
// We do not synchronize redirect_amount here. In the worst case we redirect slightly
|
// We do not synchronize redirect_amount here. In the worst case we redirect slightly
|
||||||
// more allocations to parent than we wanted. This shouldn't cause problems
|
// more allocations to parent than we wanted. This shouldn't cause problems
|
||||||
if (redirect_amount + size < REDIRECT_THRESHOLD) {
|
if (redirect_amount + size < REDIRECT_THRESHOLD)
|
||||||
|
{
|
||||||
parent->lock.enter();
|
parent->lock.enter();
|
||||||
// Allocate block from parent
|
// Allocate block from parent
|
||||||
void* result = parent->internal_alloc(size + MEM_ALIGN(sizeof(MemoryRedirectList)), 0
|
void* result = parent->internal_alloc(size + MEM_ALIGN(sizeof(MemoryRedirectList)), 0
|
||||||
@ -626,64 +633,64 @@ void* MemoryPool::allocate_nothrow(size_t size
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
lock.enter();
|
|
||||||
if (parent_redirect) { // It may have changed while we were taking the lock
|
|
||||||
parent_redirect = false;
|
|
||||||
// Do some hard manual work to initialize first extent
|
|
||||||
|
|
||||||
// This is the exact initial layout of memory pool in the first extent //
|
|
||||||
// MemoryExtent
|
|
||||||
// MemoryBlock
|
|
||||||
// FreeBlocksTree::ItemList
|
|
||||||
// MemoryBlock
|
|
||||||
// free space
|
|
||||||
//
|
|
||||||
// ******************************************************************* //
|
|
||||||
size_t ext_size = EXTENT_SIZE;
|
|
||||||
MemoryExtent *extent = (MemoryExtent*)external_alloc(ext_size);
|
|
||||||
fb_assert(ext_size == EXTENT_SIZE); // Make sure exent size is a multiply of page size
|
|
||||||
|
|
||||||
if (!extent) {
|
lock.enter();
|
||||||
lock.leave();
|
if (parent_redirect)
|
||||||
return NULL;
|
{ // It may have changed while we were taking the lock
|
||||||
}
|
parent_redirect = false;
|
||||||
extent->mxt_next = NULL;
|
// Do some hard manual work to initialize first extent
|
||||||
extent->mxt_prev = NULL;
|
|
||||||
extents = extent;
|
// This is the exact initial layout of memory pool in the first extent //
|
||||||
increment_mapping(EXTENT_SIZE);
|
// MemoryExtent
|
||||||
|
// MemoryBlock
|
||||||
|
// FreeBlocksTree::ItemList
|
||||||
|
// MemoryBlock
|
||||||
|
// free space
|
||||||
|
//
|
||||||
|
// ******************************************************************* //
|
||||||
|
size_t ext_size = EXTENT_SIZE;
|
||||||
|
MemoryExtent *extent = (MemoryExtent*)external_alloc(ext_size);
|
||||||
|
fb_assert(ext_size == EXTENT_SIZE); // Make sure exent size is a multiply of page size
|
||||||
|
|
||||||
MemoryBlock* hdr = (MemoryBlock*) ((char*)extent +
|
if (!extent) {
|
||||||
MEM_ALIGN(sizeof(MemoryExtent)));
|
lock.leave();
|
||||||
hdr->mbk_pool = this;
|
return NULL;
|
||||||
hdr->mbk_flags = MBK_USED;
|
|
||||||
hdr->mbk_type = TYPE_LEAFPAGE;
|
|
||||||
hdr->mbk_small.mbk_length = MEM_ALIGN(sizeof(FreeBlocksTree::ItemList));
|
|
||||||
hdr->mbk_small.mbk_prev_length = 0;
|
|
||||||
spareLeafs.add((char*)hdr + MEM_ALIGN(sizeof(MemoryBlock)));
|
|
||||||
|
|
||||||
MemoryBlock* blk = (MemoryBlock *)((char*)extent +
|
|
||||||
MEM_ALIGN(sizeof(MemoryExtent)) +
|
|
||||||
MEM_ALIGN(sizeof(MemoryBlock)) +
|
|
||||||
MEM_ALIGN(sizeof(FreeBlocksTree::ItemList)));
|
|
||||||
int blockLength = EXTENT_SIZE -
|
|
||||||
MEM_ALIGN(sizeof(MemoryExtent)) -
|
|
||||||
MEM_ALIGN(sizeof(MemoryBlock)) -
|
|
||||||
MEM_ALIGN(sizeof(FreeBlocksTree::ItemList)) -
|
|
||||||
MEM_ALIGN(sizeof(MemoryBlock));
|
|
||||||
blk->mbk_flags = MBK_LAST;
|
|
||||||
blk->mbk_type = 0;
|
|
||||||
blk->mbk_small.mbk_length = blockLength;
|
|
||||||
blk->mbk_small.mbk_prev_length = hdr->mbk_small.mbk_length;
|
|
||||||
blk->mbk_prev_fragment = NULL;
|
|
||||||
FreeMemoryBlock *freeBlock = blockToPtr<FreeMemoryBlock*>(blk);
|
|
||||||
freeBlock->fbk_next_fragment = NULL;
|
|
||||||
BlockInfo temp = {blockLength, freeBlock};
|
|
||||||
freeBlocks.add(temp);
|
|
||||||
updateSpare();
|
|
||||||
}
|
}
|
||||||
lock.leave();
|
extent->mxt_next = NULL;
|
||||||
|
extent->mxt_prev = NULL;
|
||||||
|
extents = extent;
|
||||||
|
increment_mapping(EXTENT_SIZE);
|
||||||
|
|
||||||
|
MemoryBlock* hdr = (MemoryBlock*) ((char*)extent +
|
||||||
|
MEM_ALIGN(sizeof(MemoryExtent)));
|
||||||
|
hdr->mbk_pool = this;
|
||||||
|
hdr->mbk_flags = MBK_USED;
|
||||||
|
hdr->mbk_type = TYPE_LEAFPAGE;
|
||||||
|
hdr->mbk_small.mbk_length = MEM_ALIGN(sizeof(FreeBlocksTree::ItemList));
|
||||||
|
hdr->mbk_small.mbk_prev_length = 0;
|
||||||
|
spareLeafs.add((char*)hdr + MEM_ALIGN(sizeof(MemoryBlock)));
|
||||||
|
|
||||||
|
MemoryBlock* blk = (MemoryBlock *)((char*)extent +
|
||||||
|
MEM_ALIGN(sizeof(MemoryExtent)) +
|
||||||
|
MEM_ALIGN(sizeof(MemoryBlock)) +
|
||||||
|
MEM_ALIGN(sizeof(FreeBlocksTree::ItemList)));
|
||||||
|
int blockLength = EXTENT_SIZE -
|
||||||
|
MEM_ALIGN(sizeof(MemoryExtent)) -
|
||||||
|
MEM_ALIGN(sizeof(MemoryBlock)) -
|
||||||
|
MEM_ALIGN(sizeof(FreeBlocksTree::ItemList)) -
|
||||||
|
MEM_ALIGN(sizeof(MemoryBlock));
|
||||||
|
blk->mbk_flags = MBK_LAST;
|
||||||
|
blk->mbk_type = 0;
|
||||||
|
blk->mbk_small.mbk_length = blockLength;
|
||||||
|
blk->mbk_small.mbk_prev_length = hdr->mbk_small.mbk_length;
|
||||||
|
blk->mbk_prev_fragment = NULL;
|
||||||
|
FreeMemoryBlock *freeBlock = blockToPtr<FreeMemoryBlock*>(blk);
|
||||||
|
freeBlock->fbk_next_fragment = NULL;
|
||||||
|
BlockInfo temp = {blockLength, freeBlock};
|
||||||
|
freeBlocks.add(temp);
|
||||||
|
updateSpare();
|
||||||
}
|
}
|
||||||
|
lock.leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.enter();
|
lock.enter();
|
||||||
@ -762,7 +769,8 @@ void* MemoryPool::allocate(size_t size
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryPool::verify_pool(bool fast_checks_only) {
|
bool MemoryPool::verify_pool(bool fast_checks_only)
|
||||||
|
{
|
||||||
lock.enter();
|
lock.enter();
|
||||||
mem_assert(!pendingFree || needSpare); // needSpare flag should be set if we are in
|
mem_assert(!pendingFree || needSpare); // needSpare flag should be set if we are in
|
||||||
// a critically low memory condition
|
// a critically low memory condition
|
||||||
@ -837,10 +845,12 @@ bool MemoryPool::verify_pool(bool fast_checks_only) {
|
|||||||
mem_assert(blk->mbk_small.mbk_prev_length == prev_length); // Prev is correct ?
|
mem_assert(blk->mbk_small.mbk_prev_length == prev_length); // Prev is correct ?
|
||||||
bool foundPending = false;
|
bool foundPending = false;
|
||||||
for (PendingFreeBlock *tmp = pendingFree; tmp; tmp = tmp->next)
|
for (PendingFreeBlock *tmp = pendingFree; tmp; tmp = tmp->next)
|
||||||
|
{
|
||||||
if (tmp == (PendingFreeBlock *)((char*)blk + MEM_ALIGN(sizeof(MemoryBlock)))) {
|
if (tmp == (PendingFreeBlock *)((char*)blk + MEM_ALIGN(sizeof(MemoryBlock)))) {
|
||||||
mem_assert(!foundPending); // Block may be in pending list only one time
|
mem_assert(!foundPending); // Block may be in pending list only one time
|
||||||
foundPending = true;
|
foundPending = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bool foundTree = false;
|
bool foundTree = false;
|
||||||
if (freeBlocks.locate(blk->mbk_small.mbk_length)) {
|
if (freeBlocks.locate(blk->mbk_small.mbk_length)) {
|
||||||
// Check previous fragment pointer if block is marked as unused
|
// Check previous fragment pointer if block is marked as unused
|
||||||
@ -874,10 +884,12 @@ bool MemoryPool::verify_pool(bool fast_checks_only) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (FreeMemoryBlock* freeBlk = freeBlocks.current().bli_fragments; freeBlk; freeBlk = freeBlk->fbk_next_fragment)
|
for (FreeMemoryBlock* freeBlk = freeBlocks.current().bli_fragments; freeBlk; freeBlk = freeBlk->fbk_next_fragment)
|
||||||
|
{
|
||||||
if (ptrToBlock(freeBlk) == blk) {
|
if (ptrToBlock(freeBlk) == blk) {
|
||||||
mem_assert(!foundTree); // Block may be present in free blocks tree only once
|
mem_assert(!foundTree); // Block may be present in free blocks tree only once
|
||||||
foundTree = true;
|
foundTree = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mem_assert(!(foundTree && foundPending)); // Block shouldn't be present both in
|
mem_assert(!(foundTree && foundPending)); // Block shouldn't be present both in
|
||||||
@ -1348,7 +1360,8 @@ void* MemoryPool::internal_alloc(size_t size, SSHORT type
|
|||||||
PendingFreeBlock *itr = pendingFree, *prev = NULL;
|
PendingFreeBlock *itr = pendingFree, *prev = NULL;
|
||||||
while (itr) {
|
while (itr) {
|
||||||
MemoryBlock *temp = ptrToBlock(itr);
|
MemoryBlock *temp = ptrToBlock(itr);
|
||||||
if (temp->mbk_small.mbk_length >= size) {
|
if (temp->mbk_small.mbk_length >= size)
|
||||||
|
{
|
||||||
if (temp->mbk_small.mbk_length - size < MEM_ALIGN(sizeof(MemoryBlock)) + ALLOC_ALIGNMENT)
|
if (temp->mbk_small.mbk_length - size < MEM_ALIGN(sizeof(MemoryBlock)) + ALLOC_ALIGNMENT)
|
||||||
{
|
{
|
||||||
// Block is small enough to be returned AS IS
|
// Block is small enough to be returned AS IS
|
||||||
@ -1365,30 +1378,30 @@ void* MemoryPool::internal_alloc(size_t size, SSHORT type
|
|||||||
else
|
else
|
||||||
pendingFree = itr->next;
|
pendingFree = itr->next;
|
||||||
PATTERN_FILL(itr, size, ALLOC_PATTERN);
|
PATTERN_FILL(itr, size, ALLOC_PATTERN);
|
||||||
|
|
||||||
return itr;
|
return itr;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Cut a piece at the end of block
|
// Cut a piece at the end of block
|
||||||
// We don't need to modify tree of free blocks or a list of
|
// We don't need to modify tree of free blocks or a list of
|
||||||
// pending free blocks in this case
|
// pending free blocks in this case
|
||||||
temp->mbk_small.mbk_length -= MEM_ALIGN(sizeof(MemoryBlock)) + size;
|
temp->mbk_small.mbk_length -= MEM_ALIGN(sizeof(MemoryBlock)) + size;
|
||||||
blk = next_block(temp);
|
blk = next_block(temp);
|
||||||
blk->mbk_pool = this;
|
blk->mbk_pool = this;
|
||||||
blk->mbk_flags = MBK_USED | (temp->mbk_flags & MBK_LAST);
|
blk->mbk_flags = MBK_USED | (temp->mbk_flags & MBK_LAST);
|
||||||
#ifdef DEBUG_GDS_ALLOC
|
#ifdef DEBUG_GDS_ALLOC
|
||||||
blk->mbk_file = file;
|
blk->mbk_file = file;
|
||||||
blk->mbk_line = line;
|
blk->mbk_line = line;
|
||||||
#endif
|
#endif
|
||||||
temp->mbk_flags &= ~MBK_LAST;
|
temp->mbk_flags &= ~MBK_LAST;
|
||||||
blk->mbk_type = type;
|
blk->mbk_type = type;
|
||||||
blk->mbk_small.mbk_length = size;
|
blk->mbk_small.mbk_length = size;
|
||||||
blk->mbk_small.mbk_prev_length = temp->mbk_small.mbk_length;
|
blk->mbk_small.mbk_prev_length = temp->mbk_small.mbk_length;
|
||||||
if (!(blk->mbk_flags & MBK_LAST))
|
if (!(blk->mbk_flags & MBK_LAST))
|
||||||
next_block(blk)->mbk_small.mbk_prev_length = blk->mbk_small.mbk_length;
|
next_block(blk)->mbk_small.mbk_prev_length = blk->mbk_small.mbk_length;
|
||||||
void *result = blockToPtr<void*>(blk);
|
void *result = blockToPtr<void*>(blk);
|
||||||
PATTERN_FILL(result, size, ALLOC_PATTERN);
|
PATTERN_FILL(result, size, ALLOC_PATTERN);
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
prev = itr;
|
prev = itr;
|
||||||
itr = itr->next;
|
itr = itr->next;
|
||||||
@ -1760,7 +1773,8 @@ void MemoryPool::deallocate(void *block)
|
|||||||
lock.leave();
|
lock.leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPool& AutoStorage::getAutoMemoryPool() {
|
MemoryPool& AutoStorage::getAutoMemoryPool()
|
||||||
|
{
|
||||||
#ifndef SUPERCLIENT
|
#ifndef SUPERCLIENT
|
||||||
MemoryPool* p = MemoryPool::getContextPool();
|
MemoryPool* p = MemoryPool::getContextPool();
|
||||||
if (! p)
|
if (! p)
|
||||||
@ -1775,7 +1789,8 @@ MemoryPool& AutoStorage::getAutoMemoryPool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEV_BUILD)
|
#if defined(DEV_BUILD)
|
||||||
void AutoStorage::ProbeStack() const {
|
void AutoStorage::ProbeStack() const
|
||||||
|
{
|
||||||
//
|
//
|
||||||
// AutoStorage() default constructor can be used only
|
// AutoStorage() default constructor can be used only
|
||||||
// for objects on the stack. ProbeStack() uses the
|
// for objects on the stack. ProbeStack() uses the
|
||||||
|
@ -81,7 +81,8 @@ const int MAX_TREE_DEPTH = 4;
|
|||||||
// Alignment for all memory blocks. Sizes of memory blocks in headers are measured in this units
|
// Alignment for all memory blocks. Sizes of memory blocks in headers are measured in this units
|
||||||
const size_t ALLOC_ALIGNMENT = ALIGNMENT;
|
const size_t ALLOC_ALIGNMENT = ALIGNMENT;
|
||||||
|
|
||||||
static inline size_t MEM_ALIGN(size_t value) {
|
static inline size_t MEM_ALIGN(size_t value)
|
||||||
|
{
|
||||||
return FB_ALIGN(value, ALLOC_ALIGNMENT);
|
return FB_ALIGN(value, ALLOC_ALIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,17 +93,21 @@ const USHORT MBK_USED = 4; // Block is used
|
|||||||
const USHORT MBK_LAST = 8; // Block is last in the extent
|
const USHORT MBK_LAST = 8; // Block is last in the extent
|
||||||
const USHORT MBK_DELAYED = 16; // Block is pending in the delayed free queue
|
const USHORT MBK_DELAYED = 16; // Block is pending in the delayed free queue
|
||||||
|
|
||||||
struct FreeMemoryBlock {
|
struct FreeMemoryBlock
|
||||||
|
{
|
||||||
FreeMemoryBlock* fbk_next_fragment;
|
FreeMemoryBlock* fbk_next_fragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Block header.
|
// Block header.
|
||||||
// Has size of 12 bytes for 32-bit targets and 16 bytes on 64-bit ones
|
// Has size of 12 bytes for 32-bit targets and 16 bytes on 64-bit ones
|
||||||
struct MemoryBlock {
|
struct MemoryBlock
|
||||||
|
{
|
||||||
USHORT mbk_flags;
|
USHORT mbk_flags;
|
||||||
SSHORT mbk_type;
|
SSHORT mbk_type;
|
||||||
union {
|
union
|
||||||
struct {
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
// Length and offset are measured in bytes thus memory extent size is limited to 64k
|
// Length and offset are measured in bytes thus memory extent size is limited to 64k
|
||||||
// Larger extents are not needed now, but this may be icreased later via using allocation units
|
// Larger extents are not needed now, but this may be icreased later via using allocation units
|
||||||
USHORT mbk_length; // Actual block size: header not included, redirection list is included if applicable
|
USHORT mbk_length; // Actual block size: header not included, redirection list is included if applicable
|
||||||
@ -115,7 +120,8 @@ struct MemoryBlock {
|
|||||||
const char* mbk_file;
|
const char* mbk_file;
|
||||||
int mbk_line;
|
int mbk_line;
|
||||||
#endif
|
#endif
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
class MemoryPool* mbk_pool;
|
class MemoryPool* mbk_pool;
|
||||||
FreeMemoryBlock* mbk_prev_fragment;
|
FreeMemoryBlock* mbk_prev_fragment;
|
||||||
};
|
};
|
||||||
@ -127,7 +133,8 @@ struct MemoryBlock {
|
|||||||
|
|
||||||
// This structure is appended to the end of block redirected to parent pool or operating system
|
// This structure is appended to the end of block redirected to parent pool or operating system
|
||||||
// It is a doubly-linked list which we are going to use when our pool is going to be deleted
|
// It is a doubly-linked list which we are going to use when our pool is going to be deleted
|
||||||
struct MemoryRedirectList {
|
struct MemoryRedirectList
|
||||||
|
{
|
||||||
MemoryBlock* mrl_prev;
|
MemoryBlock* mrl_prev;
|
||||||
MemoryBlock* mrl_next;
|
MemoryBlock* mrl_next;
|
||||||
};
|
};
|
||||||
@ -139,24 +146,29 @@ const SSHORT TYPE_TREEPAGE = -4;
|
|||||||
|
|
||||||
// We store BlkInfo structures instead of BlkHeader pointers to get benefits from
|
// We store BlkInfo structures instead of BlkHeader pointers to get benefits from
|
||||||
// processor cache-hit optimizations
|
// processor cache-hit optimizations
|
||||||
struct BlockInfo {
|
struct BlockInfo
|
||||||
|
{
|
||||||
size_t bli_length;
|
size_t bli_length;
|
||||||
FreeMemoryBlock* bli_fragments;
|
FreeMemoryBlock* bli_fragments;
|
||||||
inline static const size_t& generate(const void* sender, const BlockInfo& i) {
|
inline static const size_t& generate(const void* sender, const BlockInfo& i)
|
||||||
|
{
|
||||||
return i.bli_length;
|
return i.bli_length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemoryExtent {
|
struct MemoryExtent
|
||||||
|
{
|
||||||
MemoryExtent *mxt_next;
|
MemoryExtent *mxt_next;
|
||||||
MemoryExtent *mxt_prev;
|
MemoryExtent *mxt_prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PendingFreeBlock {
|
struct PendingFreeBlock
|
||||||
|
{
|
||||||
PendingFreeBlock *next;
|
PendingFreeBlock *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemoryStats {
|
class MemoryStats
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
MemoryStats() : mst_usage(0), mst_mapped(0), mst_max_usage(0), mst_max_mapped(0) {}
|
MemoryStats() : mst_usage(0), mst_mapped(0), mst_max_usage(0), mst_max_mapped(0) {}
|
||||||
~MemoryStats() {}
|
~MemoryStats() {}
|
||||||
@ -193,14 +205,18 @@ private:
|
|||||||
// MemoryPool inheritance looks weird because we cannot use
|
// MemoryPool inheritance looks weird because we cannot use
|
||||||
// any pointers to functions in shared memory. VMT usage in
|
// any pointers to functions in shared memory. VMT usage in
|
||||||
// MemoryPool and its descendants is prohibited
|
// MemoryPool and its descendants is prohibited
|
||||||
class MemoryPool {
|
class MemoryPool
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
class InternalAllocator {
|
class InternalAllocator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
void* allocate(size_t size) {
|
void* allocate(size_t size)
|
||||||
|
{
|
||||||
return ((MemoryPool*)this)->tree_alloc(size);
|
return ((MemoryPool*)this)->tree_alloc(size);
|
||||||
}
|
}
|
||||||
void deallocate(void* block) {
|
void deallocate(void* block)
|
||||||
|
{
|
||||||
((MemoryPool*)this)->tree_free(block);
|
((MemoryPool*)this)->tree_free(block);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -291,8 +307,7 @@ protected:
|
|||||||
MemoryPool(MemoryPool* _parent, MemoryStats &_stats, void* first_extent, void* root_page);
|
MemoryPool(MemoryPool* _parent, MemoryStats &_stats, void* first_extent, void* root_page);
|
||||||
|
|
||||||
// This should never be called
|
// This should never be called
|
||||||
~MemoryPool() {
|
~MemoryPool() {}
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Default statistics group for process
|
// Default statistics group for process
|
||||||
@ -352,7 +367,8 @@ public:
|
|||||||
const char* filter_path = 0);
|
const char* filter_path = 0);
|
||||||
|
|
||||||
// Deallocate memory block. Pool is derived from block header
|
// Deallocate memory block. Pool is derived from block header
|
||||||
static void globalFree(void* block) {
|
static void globalFree(void* block)
|
||||||
|
{
|
||||||
if (block)
|
if (block)
|
||||||
((MemoryBlock*)((char*)block - MEM_ALIGN(sizeof(MemoryBlock))))->mbk_pool->deallocate(block);
|
((MemoryBlock*)((char*)block - MEM_ALIGN(sizeof(MemoryBlock))))->mbk_pool->deallocate(block);
|
||||||
}
|
}
|
||||||
@ -387,12 +403,15 @@ public:
|
|||||||
// Class intended to manage execution context pool stack
|
// Class intended to manage execution context pool stack
|
||||||
// Declare instance of this class when you need to set new context pool and it
|
// Declare instance of this class when you need to set new context pool and it
|
||||||
// will be restored automatically as soon holder variable gets out of scope
|
// will be restored automatically as soon holder variable gets out of scope
|
||||||
class ContextPoolHolder {
|
class ContextPoolHolder
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
ContextPoolHolder(MemoryPool* newPool) {
|
ContextPoolHolder(MemoryPool* newPool)
|
||||||
|
{
|
||||||
savedPool = MemoryPool::setContextPool(newPool);
|
savedPool = MemoryPool::setContextPool(newPool);
|
||||||
}
|
}
|
||||||
~ContextPoolHolder() {
|
~ContextPoolHolder()
|
||||||
|
{
|
||||||
MemoryPool::setContextPool(savedPool);
|
MemoryPool::setContextPool(savedPool);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -417,7 +436,8 @@ public:
|
|||||||
{
|
{
|
||||||
savedThreadData->setDefaultPool(newPool);
|
savedThreadData->setDefaultPool(newPool);
|
||||||
}
|
}
|
||||||
~SubsystemContextPoolHolder() {
|
~SubsystemContextPoolHolder()
|
||||||
|
{
|
||||||
savedThreadData->setDefaultPool(savedPool);
|
savedThreadData->setDefaultPool(savedPool);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -468,19 +488,23 @@ inline void operator delete[](void* mem) throw()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_GDS_ALLOC
|
#ifdef DEBUG_GDS_ALLOC
|
||||||
inline void* operator new(size_t s, Firebird::MemoryPool& pool, const char* file, int line) {
|
inline void* operator new(size_t s, Firebird::MemoryPool& pool, const char* file, int line)
|
||||||
|
{
|
||||||
return pool.allocate(s, file, line);
|
return pool.allocate(s, file, line);
|
||||||
}
|
}
|
||||||
inline void* operator new[](size_t s, Firebird::MemoryPool& pool, const char* file, int line) {
|
inline void* operator new[](size_t s, Firebird::MemoryPool& pool, const char* file, int line)
|
||||||
|
{
|
||||||
return pool.allocate(s, file, line);
|
return pool.allocate(s, file, line);
|
||||||
}
|
}
|
||||||
#define FB_NEW(pool) new(pool, __FILE__, __LINE__)
|
#define FB_NEW(pool) new(pool, __FILE__, __LINE__)
|
||||||
#define FB_NEW_RPT(pool, count) new(pool, count, __FILE__, __LINE__)
|
#define FB_NEW_RPT(pool, count) new(pool, count, __FILE__, __LINE__)
|
||||||
#else
|
#else
|
||||||
inline void* operator new(size_t s, Firebird::MemoryPool& pool) {
|
inline void* operator new(size_t s, Firebird::MemoryPool& pool)
|
||||||
|
{
|
||||||
return pool.allocate(s);
|
return pool.allocate(s);
|
||||||
}
|
}
|
||||||
inline void* operator new[](size_t s, Firebird::MemoryPool& pool) {
|
inline void* operator new[](size_t s, Firebird::MemoryPool& pool)
|
||||||
|
{
|
||||||
return pool.allocate(s);
|
return pool.allocate(s);
|
||||||
}
|
}
|
||||||
#define FB_NEW(pool) new(pool)
|
#define FB_NEW(pool) new(pool)
|
||||||
@ -492,7 +516,8 @@ namespace Firebird
|
|||||||
{
|
{
|
||||||
// Global storage makes it possible to use new and delete for classes,
|
// Global storage makes it possible to use new and delete for classes,
|
||||||
// based on it, to behave traditionally, i.e. get memory from permanent pool.
|
// based on it, to behave traditionally, i.e. get memory from permanent pool.
|
||||||
class GlobalStorage {
|
class GlobalStorage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
void* operator new(size_t size)
|
void* operator new(size_t size)
|
||||||
{
|
{
|
||||||
@ -516,7 +541,8 @@ namespace Firebird
|
|||||||
// constructors of this objects. Permanent means that pool,
|
// constructors of this objects. Permanent means that pool,
|
||||||
// which will be later used for such allocations, must
|
// which will be later used for such allocations, must
|
||||||
// be explicitly passed in all constructors of such object.
|
// be explicitly passed in all constructors of such object.
|
||||||
class PermanentStorage {
|
class PermanentStorage
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
MemoryPool& pool;
|
MemoryPool& pool;
|
||||||
protected:
|
protected:
|
||||||
@ -529,7 +555,8 @@ namespace Firebird
|
|||||||
// parameter. In this case AutoStorage sends AutoMemoryPool
|
// parameter. In this case AutoStorage sends AutoMemoryPool
|
||||||
// to PermanentStorage. To ensure this operation to be safe
|
// to PermanentStorage. To ensure this operation to be safe
|
||||||
// such trick possible only for local (on stack) variables.
|
// such trick possible only for local (on stack) variables.
|
||||||
class AutoStorage : public PermanentStorage {
|
class AutoStorage : public PermanentStorage
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
#if defined(DEV_BUILD)
|
#if defined(DEV_BUILD)
|
||||||
void ProbeStack() const;
|
void ProbeStack() const;
|
||||||
@ -537,7 +564,8 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
static MemoryPool& getAutoMemoryPool();
|
static MemoryPool& getAutoMemoryPool();
|
||||||
protected:
|
protected:
|
||||||
AutoStorage() : PermanentStorage(getAutoMemoryPool()) {
|
AutoStorage() : PermanentStorage(getAutoMemoryPool())
|
||||||
|
{
|
||||||
#if defined(DEV_BUILD)
|
#if defined(DEV_BUILD)
|
||||||
ProbeStack();
|
ProbeStack();
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,15 +35,18 @@ namespace Firebird {
|
|||||||
|
|
||||||
// Static part of the array
|
// Static part of the array
|
||||||
template <typename T, size_t Capacity>
|
template <typename T, size_t Capacity>
|
||||||
class InlineStorage : public AutoStorage {
|
class InlineStorage : public AutoStorage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit InlineStorage(MemoryPool& p) : AutoStorage(p) { }
|
explicit InlineStorage(MemoryPool& p) : AutoStorage(p) { }
|
||||||
InlineStorage() : AutoStorage() { }
|
InlineStorage() : AutoStorage() { }
|
||||||
protected:
|
protected:
|
||||||
T* getStorage() {
|
T* getStorage()
|
||||||
|
{
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
size_t getStorageSize() const {
|
size_t getStorageSize() const
|
||||||
|
{
|
||||||
return Capacity;
|
return Capacity;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -52,7 +55,8 @@ private:
|
|||||||
|
|
||||||
// Used when array doesn't have static part
|
// Used when array doesn't have static part
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class EmptyStorage : public AutoStorage {
|
class EmptyStorage : public AutoStorage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit EmptyStorage(MemoryPool& p) : AutoStorage(p) { }
|
explicit EmptyStorage(MemoryPool& p) : AutoStorage(p) { }
|
||||||
EmptyStorage() : AutoStorage() { }
|
EmptyStorage() : AutoStorage() { }
|
||||||
@ -63,7 +67,8 @@ protected:
|
|||||||
|
|
||||||
// Dynamic array of simple types
|
// Dynamic array of simple types
|
||||||
template <typename T, typename Storage = EmptyStorage<T> >
|
template <typename T, typename Storage = EmptyStorage<T> >
|
||||||
class Array : protected Storage {
|
class Array : protected Storage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit Array(MemoryPool& p) :
|
explicit Array(MemoryPool& p) :
|
||||||
Storage(p), count(0), capacity(this->getStorageSize()), data(this->getStorage()) { }
|
Storage(p), count(0), capacity(this->getStorageSize()), data(this->getStorage()) { }
|
||||||
@ -85,11 +90,13 @@ public:
|
|||||||
}
|
}
|
||||||
void clear() { count = 0; }
|
void clear() { count = 0; }
|
||||||
protected:
|
protected:
|
||||||
const T& getElement(size_t index) const {
|
const T& getElement(size_t index) const
|
||||||
|
{
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
T& getElement(size_t index) {
|
T& getElement(size_t index)
|
||||||
|
{
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
@ -108,96 +115,113 @@ public:
|
|||||||
count = L.count;
|
count = L.count;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
const T& operator[](size_t index) const {
|
const T& operator[](size_t index) const
|
||||||
|
{
|
||||||
return getElement(index);
|
return getElement(index);
|
||||||
}
|
}
|
||||||
T& operator[](size_t index) {
|
T& operator[](size_t index)
|
||||||
|
{
|
||||||
return getElement(index);
|
return getElement(index);
|
||||||
}
|
}
|
||||||
const T& front() const {
|
const T& front() const
|
||||||
|
{
|
||||||
fb_assert(count > 0);
|
fb_assert(count > 0);
|
||||||
return *data;
|
return *data;
|
||||||
}
|
}
|
||||||
const T& back() const {
|
const T& back() const
|
||||||
|
{
|
||||||
fb_assert(count > 0);
|
fb_assert(count > 0);
|
||||||
return *(data + count - 1);
|
return *(data + count - 1);
|
||||||
}
|
}
|
||||||
const T* begin() const { return data; }
|
const T* begin() const { return data; }
|
||||||
const T* end() const { return data + count; }
|
const T* end() const { return data + count; }
|
||||||
T& front() {
|
T& front()
|
||||||
|
{
|
||||||
fb_assert(count > 0);
|
fb_assert(count > 0);
|
||||||
return *data;
|
return *data;
|
||||||
}
|
}
|
||||||
T& back() {
|
T& back()
|
||||||
|
{
|
||||||
fb_assert(count > 0);
|
fb_assert(count > 0);
|
||||||
return *(data + count - 1);
|
return *(data + count - 1);
|
||||||
}
|
}
|
||||||
T* begin() { return data; }
|
T* begin() { return data; }
|
||||||
T* end() { return data + count; }
|
T* end() { return data + count; }
|
||||||
void insert(size_t index, const T& item) {
|
void insert(size_t index, const T& item)
|
||||||
|
{
|
||||||
fb_assert(index <= count);
|
fb_assert(index <= count);
|
||||||
ensureCapacity(count + 1);
|
ensureCapacity(count + 1);
|
||||||
memmove(data + index + 1, data + index, sizeof(T) * (count++ - index));
|
memmove(data + index + 1, data + index, sizeof(T) * (count++ - index));
|
||||||
data[index] = item;
|
data[index] = item;
|
||||||
}
|
}
|
||||||
void insert(size_t index, const Array<T, Storage>& L) {
|
void insert(size_t index, const Array<T, Storage>& L)
|
||||||
|
{
|
||||||
fb_assert(index <= count);
|
fb_assert(index <= count);
|
||||||
ensureCapacity(count + L.count);
|
ensureCapacity(count + L.count);
|
||||||
memmove(data + index + L.count, data + index, sizeof(T) * (count - index));
|
memmove(data + index + L.count, data + index, sizeof(T) * (count - index));
|
||||||
memcpy(data + index, L.data, L.count);
|
memcpy(data + index, L.data, L.count);
|
||||||
count += L.count;
|
count += L.count;
|
||||||
}
|
}
|
||||||
void insert(size_t index, const T* items, size_t itemsSize) {
|
void insert(size_t index, const T* items, size_t itemsSize)
|
||||||
|
{
|
||||||
fb_assert(index <= count);
|
fb_assert(index <= count);
|
||||||
ensureCapacity(count + itemsSize);
|
ensureCapacity(count + itemsSize);
|
||||||
memmove(data + index + itemsSize, data + index, sizeof(T) * (count - index));
|
memmove(data + index + itemsSize, data + index, sizeof(T) * (count - index));
|
||||||
memcpy(data + index, items, sizeof(T) * itemsSize);
|
memcpy(data + index, items, sizeof(T) * itemsSize);
|
||||||
count += itemsSize;
|
count += itemsSize;
|
||||||
}
|
}
|
||||||
size_t add(const T& item) {
|
size_t add(const T& item)
|
||||||
|
{
|
||||||
ensureCapacity(count + 1);
|
ensureCapacity(count + 1);
|
||||||
data[count] = item;
|
data[count] = item;
|
||||||
return ++count;
|
return ++count;
|
||||||
}
|
}
|
||||||
// NOTE: remove method must be signal safe
|
// NOTE: remove method must be signal safe
|
||||||
// This function may be called in AST. The function doesn't wait.
|
// This function may be called in AST. The function doesn't wait.
|
||||||
T* remove(size_t index) {
|
T* remove(size_t index)
|
||||||
|
{
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
memmove(data + index, data + index + 1, sizeof(T) * (--count - index));
|
memmove(data + index, data + index + 1, sizeof(T) * (--count - index));
|
||||||
return &data[index];
|
return &data[index];
|
||||||
}
|
}
|
||||||
T* removeRange(size_t from, size_t to) {
|
T* removeRange(size_t from, size_t to)
|
||||||
|
{
|
||||||
fb_assert(from <= to);
|
fb_assert(from <= to);
|
||||||
fb_assert(to <= count);
|
fb_assert(to <= count);
|
||||||
memmove(data + from, data + to, sizeof(T) * (count - to));
|
memmove(data + from, data + to, sizeof(T) * (count - to));
|
||||||
count -= (to - from);
|
count -= (to - from);
|
||||||
return &data[from];
|
return &data[from];
|
||||||
}
|
}
|
||||||
T* removeCount(size_t index, size_t n) {
|
T* removeCount(size_t index, size_t n)
|
||||||
|
{
|
||||||
fb_assert(index + n <= count);
|
fb_assert(index + n <= count);
|
||||||
memmove(data + index, data + index + n, sizeof(T) * (count - index - n));
|
memmove(data + index, data + index + n, sizeof(T) * (count - index - n));
|
||||||
count -= n;
|
count -= n;
|
||||||
return &data[index];
|
return &data[index];
|
||||||
}
|
}
|
||||||
T* remove(T* itr) {
|
T* remove(T* itr)
|
||||||
|
{
|
||||||
const size_t index = itr - begin();
|
const size_t index = itr - begin();
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
memmove(data + index, data + index + 1, sizeof(T) * (--count - index));
|
memmove(data + index, data + index + 1, sizeof(T) * (--count - index));
|
||||||
return &data[index];
|
return &data[index];
|
||||||
}
|
}
|
||||||
void shrink(size_t newCount) {
|
void shrink(size_t newCount)
|
||||||
|
{
|
||||||
fb_assert(newCount <= count);
|
fb_assert(newCount <= count);
|
||||||
count = newCount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
// Grow size of our array and zero-initialize new items
|
// Grow size of our array and zero-initialize new items
|
||||||
void grow(size_t newCount) {
|
void grow(size_t newCount)
|
||||||
|
{
|
||||||
fb_assert(newCount >= count);
|
fb_assert(newCount >= count);
|
||||||
ensureCapacity(newCount);
|
ensureCapacity(newCount);
|
||||||
memset(data + count, 0, sizeof(T) * (newCount - count));
|
memset(data + count, 0, sizeof(T) * (newCount - count));
|
||||||
count = newCount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
// Resize array according to STL's vector::resize() rules
|
// Resize array according to STL's vector::resize() rules
|
||||||
void resize(size_t newCount, const T& val) {
|
void resize(size_t newCount, const T& val)
|
||||||
|
{
|
||||||
if (newCount > count) {
|
if (newCount > count) {
|
||||||
ensureCapacity(newCount);
|
ensureCapacity(newCount);
|
||||||
while (count < newCount) {
|
while (count < newCount) {
|
||||||
@ -209,7 +233,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Resize array according to STL's vector::resize() rules
|
// Resize array according to STL's vector::resize() rules
|
||||||
void resize(size_t newCount) {
|
void resize(size_t newCount)
|
||||||
|
{
|
||||||
if (newCount > count) {
|
if (newCount > count) {
|
||||||
grow(newCount);
|
grow(newCount);
|
||||||
}
|
}
|
||||||
@ -217,7 +242,8 @@ public:
|
|||||||
count = newCount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void join(const Array<T, Storage>& L) {
|
void join(const Array<T, Storage>& L)
|
||||||
|
{
|
||||||
ensureCapacity(count + L.count);
|
ensureCapacity(count + L.count);
|
||||||
memcpy(data + count, L.data, sizeof(T) * L.count);
|
memcpy(data + count, L.data, sizeof(T) * L.count);
|
||||||
count += L.count;
|
count += L.count;
|
||||||
@ -226,21 +252,25 @@ public:
|
|||||||
// Used as such in GlobalRWLock::blockingAstHandler
|
// Used as such in GlobalRWLock::blockingAstHandler
|
||||||
size_t getCount() const { return count; }
|
size_t getCount() const { return count; }
|
||||||
size_t getCapacity() const { return capacity; }
|
size_t getCapacity() const { return capacity; }
|
||||||
void push(const T& item) {
|
void push(const T& item)
|
||||||
|
{
|
||||||
add(item);
|
add(item);
|
||||||
}
|
}
|
||||||
void push(const T* items, size_t itemsSize) {
|
void push(const T* items, size_t itemsSize)
|
||||||
|
{
|
||||||
ensureCapacity(count + itemsSize);
|
ensureCapacity(count + itemsSize);
|
||||||
memcpy(data + count, items, sizeof(T) * itemsSize);
|
memcpy(data + count, items, sizeof(T) * itemsSize);
|
||||||
count += itemsSize;
|
count += itemsSize;
|
||||||
}
|
}
|
||||||
T pop() {
|
T pop()
|
||||||
|
{
|
||||||
fb_assert(count > 0);
|
fb_assert(count > 0);
|
||||||
count--;
|
count--;
|
||||||
return data[count];
|
return data[count];
|
||||||
}
|
}
|
||||||
// prepare array to be used as a buffer of capacity items
|
// prepare array to be used as a buffer of capacity items
|
||||||
T* getBuffer(size_t capacityL) {
|
T* getBuffer(size_t capacityL)
|
||||||
|
{
|
||||||
ensureCapacity(capacityL);
|
ensureCapacity(capacityL);
|
||||||
count = capacityL;
|
count = capacityL;
|
||||||
return data;
|
return data;
|
||||||
@ -254,7 +284,8 @@ public:
|
|||||||
data = this->getStorage();
|
data = this->getStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool find(const T& item, size_t& pos) const {
|
bool find(const T& item, size_t& pos) const
|
||||||
|
{
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
if (data[i] == item) {
|
if (data[i] == item) {
|
||||||
pos = i;
|
pos = i;
|
||||||
@ -264,7 +295,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exist(const T& item) const {
|
bool exist(const T& item) const
|
||||||
|
{
|
||||||
size_t pos; // ignored
|
size_t pos; // ignored
|
||||||
return find(item, pos);
|
return find(item, pos);
|
||||||
}
|
}
|
||||||
@ -272,7 +304,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
size_t count, capacity;
|
size_t count, capacity;
|
||||||
T* data;
|
T* data;
|
||||||
void ensureCapacity(size_t newcapacity) {
|
void ensureCapacity(size_t newcapacity)
|
||||||
|
{
|
||||||
if (newcapacity > capacity) {
|
if (newcapacity > capacity) {
|
||||||
if (newcapacity < capacity * 2) {
|
if (newcapacity < capacity * 2) {
|
||||||
newcapacity = capacity * 2;
|
newcapacity = capacity * 2;
|
||||||
@ -297,14 +330,16 @@ template <typename Value,
|
|||||||
typename Key = Value,
|
typename Key = Value,
|
||||||
typename KeyOfValue = DefaultKeyValue<Value>,
|
typename KeyOfValue = DefaultKeyValue<Value>,
|
||||||
typename Cmp = DefaultComparator<Key> >
|
typename Cmp = DefaultComparator<Key> >
|
||||||
class SortedArray : public Array<Value, Storage> {
|
class SortedArray : public Array<Value, Storage>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SortedArray(MemoryPool& p, size_t s) : Array<Value, Storage>(p, s) {}
|
SortedArray(MemoryPool& p, size_t s) : Array<Value, Storage>(p, s) {}
|
||||||
explicit SortedArray(MemoryPool& p) : Array<Value, Storage>(p) {}
|
explicit SortedArray(MemoryPool& p) : Array<Value, Storage>(p) {}
|
||||||
explicit SortedArray(size_t s) : Array<Value, Storage>(s) {}
|
explicit SortedArray(size_t s) : Array<Value, Storage>(s) {}
|
||||||
SortedArray() : Array<Value, Storage>() {}
|
SortedArray() : Array<Value, Storage>() {}
|
||||||
|
|
||||||
bool find(const Key& item, size_t& pos) const {
|
bool find(const Key& item, size_t& pos) const
|
||||||
|
{
|
||||||
size_t highBound = this->count, lowBound = 0;
|
size_t highBound = this->count, lowBound = 0;
|
||||||
while (highBound > lowBound) {
|
while (highBound > lowBound) {
|
||||||
const size_t temp = (highBound + lowBound) >> 1;
|
const size_t temp = (highBound + lowBound) >> 1;
|
||||||
@ -324,7 +359,8 @@ public:
|
|||||||
return find(item, pos);
|
return find(item, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t add(const Value& item) {
|
size_t add(const Value& item)
|
||||||
|
{
|
||||||
size_t pos;
|
size_t pos;
|
||||||
find(KeyOfValue::generate(this, item), pos);
|
find(KeyOfValue::generate(this, item), pos);
|
||||||
insert(pos, item);
|
insert(pos, item);
|
||||||
@ -334,7 +370,8 @@ public:
|
|||||||
|
|
||||||
// Nice shorthand for arrays with static part
|
// Nice shorthand for arrays with static part
|
||||||
template <typename T, size_t InlineCapacity>
|
template <typename T, size_t InlineCapacity>
|
||||||
class HalfStaticArray : public Array<T, InlineStorage<T, InlineCapacity> > {
|
class HalfStaticArray : public Array<T, InlineStorage<T, InlineCapacity> >
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit HalfStaticArray(MemoryPool& p) : Array<T, InlineStorage<T, InlineCapacity> > (p) {}
|
explicit HalfStaticArray(MemoryPool& p) : Array<T, InlineStorage<T, InlineCapacity> > (p) {}
|
||||||
HalfStaticArray(MemoryPool& p, size_t InitialCapacity) :
|
HalfStaticArray(MemoryPool& p, size_t InitialCapacity) :
|
||||||
|
@ -54,7 +54,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Where, typename Clear = SimpleDelete<Where> >
|
template <typename Where, typename Clear = SimpleDelete<Where> >
|
||||||
class AutoPtr {
|
class AutoPtr
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
Where* ptr;
|
Where* ptr;
|
||||||
public:
|
public:
|
||||||
@ -62,35 +63,42 @@ public:
|
|||||||
: ptr(v)
|
: ptr(v)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~AutoPtr() {
|
~AutoPtr()
|
||||||
|
{
|
||||||
Clear::clear(ptr);
|
Clear::clear(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoPtr<Where, Clear>& operator= (Where* v) {
|
AutoPtr<Where, Clear>& operator= (Where* v)
|
||||||
|
{
|
||||||
Clear::clear(ptr);
|
Clear::clear(ptr);
|
||||||
ptr = v;
|
ptr = v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator Where*() {
|
operator Where*()
|
||||||
|
{
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator !() const {
|
bool operator !() const
|
||||||
|
{
|
||||||
return !ptr;
|
return !ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Where* operator->() {
|
Where* operator->()
|
||||||
|
{
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Where* release() {
|
Where* release()
|
||||||
|
{
|
||||||
Where* tmp = ptr;
|
Where* tmp = ptr;
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(Where* v = NULL) {
|
void reset(Where* v = NULL)
|
||||||
|
{
|
||||||
if (v != ptr) {
|
if (v != ptr) {
|
||||||
Clear::clear(ptr);
|
Clear::clear(ptr);
|
||||||
ptr = v;
|
ptr = v;
|
||||||
|
@ -46,24 +46,29 @@
|
|||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Win32Tls {
|
class Win32Tls
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Win32Tls() {
|
Win32Tls()
|
||||||
|
{
|
||||||
if ((key = TlsAlloc()) == 0xFFFFFFFF)
|
if ((key = TlsAlloc()) == 0xFFFFFFFF)
|
||||||
system_call_failed::raise("TlsAlloc");
|
system_call_failed::raise("TlsAlloc");
|
||||||
}
|
}
|
||||||
const T get() {
|
const T get()
|
||||||
|
{
|
||||||
LPVOID value = TlsGetValue(key);
|
LPVOID value = TlsGetValue(key);
|
||||||
if ((value == NULL) && (GetLastError() != NO_ERROR))
|
if ((value == NULL) && (GetLastError() != NO_ERROR))
|
||||||
system_call_failed::raise("TlsGetValue");
|
system_call_failed::raise("TlsGetValue");
|
||||||
// return reinterpret_cast<T>(value);
|
// return reinterpret_cast<T>(value);
|
||||||
return (T)value;
|
return (T)value;
|
||||||
}
|
}
|
||||||
void set(const T value) {
|
void set(const T value)
|
||||||
|
{
|
||||||
if (TlsSetValue(key, (LPVOID)value) == 0)
|
if (TlsSetValue(key, (LPVOID)value) == 0)
|
||||||
system_call_failed::raise("TlsSetValue");
|
system_call_failed::raise("TlsSetValue");
|
||||||
}
|
}
|
||||||
~Win32Tls() {
|
~Win32Tls()
|
||||||
|
{
|
||||||
if (TlsFree(key) == 0)
|
if (TlsFree(key) == 0)
|
||||||
system_call_failed::raise("TlsFree");
|
system_call_failed::raise("TlsFree");
|
||||||
}
|
}
|
||||||
@ -96,22 +101,27 @@ namespace Firebird {
|
|||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TlsValue {
|
class TlsValue
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
TlsValue() {
|
TlsValue()
|
||||||
|
{
|
||||||
if (pthread_key_create(&key, NULL))
|
if (pthread_key_create(&key, NULL))
|
||||||
system_call_failed::raise("pthread_key_create");
|
system_call_failed::raise("pthread_key_create");
|
||||||
}
|
}
|
||||||
const T get() {
|
const T get()
|
||||||
|
{
|
||||||
// We use double C-style cast to allow using scalar datatypes
|
// We use double C-style cast to allow using scalar datatypes
|
||||||
// with sizes up to size of pointer without warnings
|
// with sizes up to size of pointer without warnings
|
||||||
return (T)(IPTR)pthread_getspecific(key);
|
return (T)(IPTR)pthread_getspecific(key);
|
||||||
}
|
}
|
||||||
void set(const T value) {
|
void set(const T value)
|
||||||
|
{
|
||||||
if (pthread_setspecific(key, (void*)(IPTR)value))
|
if (pthread_setspecific(key, (void*)(IPTR)value))
|
||||||
system_call_failed::raise("pthread_setspecific");
|
system_call_failed::raise("pthread_setspecific");
|
||||||
}
|
}
|
||||||
~TlsValue() {
|
~TlsValue()
|
||||||
|
{
|
||||||
if (pthread_key_delete(key))
|
if (pthread_key_delete(key))
|
||||||
system_call_failed::raise("pthread_key_delete");
|
system_call_failed::raise("pthread_key_delete");
|
||||||
}
|
}
|
||||||
@ -126,9 +136,11 @@ namespace Firebird {
|
|||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TlsValue {
|
class TlsValue
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static void TlsV_on_thread_exit (void * pval) {
|
static void TlsV_on_thread_exit (void * pval)
|
||||||
|
{
|
||||||
/* Usually should delete pval like this
|
/* Usually should delete pval like this
|
||||||
T * ptempT= (T*) pval ;
|
T * ptempT= (T*) pval ;
|
||||||
delete ptempT;
|
delete ptempT;
|
||||||
@ -136,25 +148,29 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TlsValue() {
|
TlsValue()
|
||||||
|
{
|
||||||
if (thr_keycreate(&key, TlsV_on_thread_exit) )
|
if (thr_keycreate(&key, TlsV_on_thread_exit) )
|
||||||
system_call_failed::raise("thr_key_create");
|
system_call_failed::raise("thr_key_create");
|
||||||
}
|
}
|
||||||
const T get() {
|
const T get()
|
||||||
|
{
|
||||||
// We use double C-style cast to allow using scalar datatypes
|
// We use double C-style cast to allow using scalar datatypes
|
||||||
// with sizes up to size of pointer without warnings
|
// with sizes up to size of pointer without warnings
|
||||||
T * valuep;
|
T* valuep;
|
||||||
if (thr_getspecific(key, (void **) &valuep) == 0)
|
if (thr_getspecific(key, (void **) &valuep) == 0)
|
||||||
return (T)(IPTR) (valuep) ;
|
return (T)(IPTR) valuep ;
|
||||||
else
|
|
||||||
system_call_failed::raise("thr_getspecific");
|
system_call_failed::raise("thr_getspecific");
|
||||||
return (T)NULL;
|
return (T)NULL;
|
||||||
}
|
}
|
||||||
void set(const T value) {
|
void set(const T value)
|
||||||
|
{
|
||||||
if (thr_setspecific(key, (void*)(IPTR)value))
|
if (thr_setspecific(key, (void*)(IPTR)value))
|
||||||
system_call_failed::raise("thr_setspecific");
|
system_call_failed::raise("thr_setspecific");
|
||||||
}
|
}
|
||||||
~TlsValue() {
|
~TlsValue()
|
||||||
|
{
|
||||||
/* Do nothing if no pthread_key_delete */
|
/* Do nothing if no pthread_key_delete */
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
@ -58,32 +58,38 @@ namespace Firebird
|
|||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
iterator& operator++() {
|
iterator& operator++()
|
||||||
|
{
|
||||||
++pos;
|
++pos;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
iterator operator++(int) {
|
iterator operator++(int)
|
||||||
|
{
|
||||||
iterator tmp = *this;
|
iterator tmp = *this;
|
||||||
++pos;
|
++pos;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
iterator& operator--() {
|
iterator& operator--()
|
||||||
|
{
|
||||||
fb_assert(pos > 0);
|
fb_assert(pos > 0);
|
||||||
--pos;
|
--pos;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
iterator operator--(int) {
|
iterator operator--(int)
|
||||||
|
{
|
||||||
fb_assert(pos > 0);
|
fb_assert(pos > 0);
|
||||||
iterator tmp = *this;
|
iterator tmp = *this;
|
||||||
--pos;
|
--pos;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
T* operator->() {
|
T* operator->()
|
||||||
|
{
|
||||||
fb_assert(lst);
|
fb_assert(lst);
|
||||||
T* pointer = lst->getPointer(pos);
|
T* pointer = lst->getPointer(pos);
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
T& operator*() {
|
T& operator*()
|
||||||
|
{
|
||||||
fb_assert(lst);
|
fb_assert(lst);
|
||||||
T* pointer = lst->getPointer(pos);
|
T* pointer = lst->getPointer(pos);
|
||||||
return *pointer;
|
return *pointer;
|
||||||
@ -118,32 +124,38 @@ namespace Firebird
|
|||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const_iterator& operator++() {
|
const_iterator& operator++()
|
||||||
|
{
|
||||||
++pos;
|
++pos;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
const_iterator operator++(int) {
|
const_iterator operator++(int)
|
||||||
|
{
|
||||||
const_iterator tmp = *this;
|
const_iterator tmp = *this;
|
||||||
++pos;
|
++pos;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
const_iterator& operator--() {
|
const_iterator& operator--()
|
||||||
|
{
|
||||||
fb_assert(pos > 0);
|
fb_assert(pos > 0);
|
||||||
--pos;
|
--pos;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
const_iterator operator--(int) {
|
const_iterator operator--(int)
|
||||||
|
{
|
||||||
fb_assert(pos > 0);
|
fb_assert(pos > 0);
|
||||||
const_iterator tmp = *this;
|
const_iterator tmp = *this;
|
||||||
--pos;
|
--pos;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
const T* operator->() {
|
const T* operator->()
|
||||||
|
{
|
||||||
fb_assert(lst);
|
fb_assert(lst);
|
||||||
const T* pointer = lst->getPointer(pos);
|
const T* pointer = lst->getPointer(pos);
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
const T& operator*() {
|
const T& operator*()
|
||||||
|
{
|
||||||
fb_assert(lst);
|
fb_assert(lst);
|
||||||
const T* pointer = lst->getPointer(pos);
|
const T* pointer = lst->getPointer(pos);
|
||||||
return *pointer;
|
return *pointer;
|
||||||
@ -173,81 +185,100 @@ namespace Firebird
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void insert(size_t index, const T& item) {
|
void insert(size_t index, const T& item)
|
||||||
|
{
|
||||||
T* dataL = FB_NEW(this->getPool()) T(this->getPool(), item);
|
T* dataL = FB_NEW(this->getPool()) T(this->getPool(), item);
|
||||||
inherited::insert(index, dataL);
|
inherited::insert(index, dataL);
|
||||||
}
|
}
|
||||||
size_t add(const T& item) {
|
size_t add(const T& item)
|
||||||
|
{
|
||||||
T* dataL = FB_NEW(this->getPool()) T(this->getPool(), item);
|
T* dataL = FB_NEW(this->getPool()) T(this->getPool(), item);
|
||||||
return inherited::add(dataL);
|
return inherited::add(dataL);
|
||||||
}
|
}
|
||||||
T& add() {
|
T& add()
|
||||||
|
{
|
||||||
T* dataL = FB_NEW(this->getPool()) T(this->getPool());
|
T* dataL = FB_NEW(this->getPool()) T(this->getPool());
|
||||||
inherited::add(dataL);
|
inherited::add(dataL);
|
||||||
return *dataL;
|
return *dataL;
|
||||||
}
|
}
|
||||||
void push(const T& item) {
|
void push(const T& item)
|
||||||
|
{
|
||||||
add(item);
|
add(item);
|
||||||
}
|
}
|
||||||
T pop() {
|
T pop()
|
||||||
|
{
|
||||||
T* pntr = inherited::pop();
|
T* pntr = inherited::pop();
|
||||||
T rc = *pntr;
|
T rc = *pntr;
|
||||||
delete pntr;
|
delete pntr;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
void remove(size_t index) {
|
void remove(size_t index)
|
||||||
|
{
|
||||||
fb_assert(index < getCount());
|
fb_assert(index < getCount());
|
||||||
delete getPointer(index);
|
delete getPointer(index);
|
||||||
inherited::remove(index);
|
inherited::remove(index);
|
||||||
}
|
}
|
||||||
void remove(iterator itr) {
|
void remove(iterator itr)
|
||||||
|
{
|
||||||
fb_assert(itr.lst == this);
|
fb_assert(itr.lst == this);
|
||||||
remove(itr.pos);
|
remove(itr.pos);
|
||||||
}
|
}
|
||||||
void shrink(size_t newCount) {
|
void shrink(size_t newCount)
|
||||||
|
{
|
||||||
for (size_t i = newCount; i < getCount(); i++) {
|
for (size_t i = newCount; i < getCount(); i++) {
|
||||||
delete getPointer(i);
|
delete getPointer(i);
|
||||||
}
|
}
|
||||||
inherited::shrink(newCount);
|
inherited::shrink(newCount);
|
||||||
}
|
}
|
||||||
iterator begin() {
|
iterator begin()
|
||||||
|
{
|
||||||
return iterator(this, 0);
|
return iterator(this, 0);
|
||||||
}
|
}
|
||||||
iterator end() {
|
iterator end()
|
||||||
|
{
|
||||||
return iterator(this, getCount());
|
return iterator(this, getCount());
|
||||||
}
|
}
|
||||||
iterator back() {
|
iterator back()
|
||||||
|
{
|
||||||
fb_assert(getCount() > 0);
|
fb_assert(getCount() > 0);
|
||||||
return iterator(this, getCount() - 1);
|
return iterator(this, getCount() - 1);
|
||||||
}
|
}
|
||||||
const_iterator begin() const {
|
const_iterator begin() const
|
||||||
|
{
|
||||||
return const_iterator(this, 0);
|
return const_iterator(this, 0);
|
||||||
}
|
}
|
||||||
const_iterator end() const {
|
const_iterator end() const
|
||||||
|
{
|
||||||
return const_iterator(this, getCount());
|
return const_iterator(this, getCount());
|
||||||
}
|
}
|
||||||
const T& operator[](size_t index) const {
|
const T& operator[](size_t index) const
|
||||||
|
{
|
||||||
return *getPointer(index);
|
return *getPointer(index);
|
||||||
}
|
}
|
||||||
const T* getPointer(size_t index) const {
|
const T* getPointer(size_t index) const
|
||||||
|
{
|
||||||
return inherited::getElement(index);
|
return inherited::getElement(index);
|
||||||
}
|
}
|
||||||
T& operator[](size_t index) {
|
T& operator[](size_t index)
|
||||||
|
{
|
||||||
return *getPointer(index);
|
return *getPointer(index);
|
||||||
}
|
}
|
||||||
T* getPointer(size_t index) {
|
T* getPointer(size_t index)
|
||||||
|
{
|
||||||
return inherited::getElement(index);
|
return inherited::getElement(index);
|
||||||
}
|
}
|
||||||
explicit ObjectsArray(MemoryPool& p) : A(p) { }
|
explicit ObjectsArray(MemoryPool& p) : A(p) { }
|
||||||
ObjectsArray() : A() { }
|
ObjectsArray() : A() { }
|
||||||
~ObjectsArray() {
|
~ObjectsArray()
|
||||||
|
{
|
||||||
for (size_t i = 0; i < getCount(); i++) {
|
for (size_t i = 0; i < getCount(); i++) {
|
||||||
delete getPointer(i);
|
delete getPointer(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size_t getCount() const {return inherited::getCount();}
|
size_t getCount() const {return inherited::getCount();}
|
||||||
size_t getCapacity() const {return inherited::getCapacity();}
|
size_t getCapacity() const {return inherited::getCapacity();}
|
||||||
void clear() {
|
void clear()
|
||||||
|
{
|
||||||
for (size_t i = 0; i < getCount(); i++) {
|
for (size_t i = 0; i < getCount(); i++) {
|
||||||
delete getPointer(i);
|
delete getPointer(i);
|
||||||
}
|
}
|
||||||
@ -276,16 +307,19 @@ namespace Firebird
|
|||||||
|
|
||||||
// Template to convert object value to index directly
|
// Template to convert object value to index directly
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ObjectKeyValue {
|
class ObjectKeyValue
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const T& generate(const void* sender, const T* Item) { return Item; }
|
static const T& generate(const void* sender, const T* Item) { return Item; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Template for default value comparator
|
// Template for default value comparator
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ObjectComparator {
|
class ObjectComparator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static bool greaterThan(const T i1, const T i2) {
|
static bool greaterThan(const T i1, const T i2)
|
||||||
|
{
|
||||||
return *i1 > *i2;
|
return *i1 > *i2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -322,7 +356,8 @@ namespace Firebird
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
return find(item, pos);
|
return find(item, pos);
|
||||||
}
|
}
|
||||||
size_t add(const ObjectValue& item) {
|
size_t add(const ObjectValue& item)
|
||||||
|
{
|
||||||
return inherited::add(item);
|
return inherited::add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
|
|
||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
|
|
||||||
struct BitmapTypes_32 {
|
struct BitmapTypes_32
|
||||||
|
{
|
||||||
typedef ULONG BUNCH_T;
|
typedef ULONG BUNCH_T;
|
||||||
enum {
|
enum {
|
||||||
LOG2_BUNCH_BITS = 7,
|
LOG2_BUNCH_BITS = 7,
|
||||||
@ -42,7 +43,8 @@ struct BitmapTypes_32 {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BitmapTypes_64 {
|
struct BitmapTypes_64
|
||||||
|
{
|
||||||
typedef FB_UINT64 BUNCH_T;
|
typedef FB_UINT64 BUNCH_T;
|
||||||
enum {
|
enum {
|
||||||
LOG2_BUNCH_BITS = 8,
|
LOG2_BUNCH_BITS = 8,
|
||||||
@ -53,7 +55,8 @@ struct BitmapTypes_64 {
|
|||||||
#define BUNCH_ONE ((BUNCH_T)1)
|
#define BUNCH_ONE ((BUNCH_T)1)
|
||||||
|
|
||||||
template <typename T, typename InternalTypes = BitmapTypes_64>
|
template <typename T, typename InternalTypes = BitmapTypes_64>
|
||||||
class SparseBitmap : public AutoStorage {
|
class SparseBitmap : public AutoStorage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
// Default constructor, stack placement
|
// Default constructor, stack placement
|
||||||
SparseBitmap() :
|
SparseBitmap() :
|
||||||
@ -66,34 +69,23 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Default accessor methods
|
// Default accessor methods
|
||||||
bool locate(T key) {
|
bool locate(T key) { return defaultAccessor.locate(locEqual, key); }
|
||||||
return defaultAccessor.locate(locEqual, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool locate(LocType lt, T key) {
|
bool locate(LocType lt, T key) { return defaultAccessor.locate(lt, key); }
|
||||||
return defaultAccessor.locate(lt, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getFirst() {
|
bool getFirst() { return defaultAccessor.getFirst(); }
|
||||||
return defaultAccessor.getFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getLast() {
|
bool getLast() { return defaultAccessor.getLast(); }
|
||||||
return defaultAccessor.getLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getNext() {
|
bool getNext() { return defaultAccessor.getNext(); }
|
||||||
return defaultAccessor.getNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getPrev() {
|
bool getPrev() { return defaultAccessor.getPrev(); }
|
||||||
return defaultAccessor.getPrev();
|
|
||||||
}
|
|
||||||
|
|
||||||
T current() const { return defaultAccessor.current(); }
|
T current() const { return defaultAccessor.current(); }
|
||||||
|
|
||||||
// Set bit
|
// Set bit
|
||||||
void set(T value) {
|
void set(T value)
|
||||||
|
{
|
||||||
if (singular) {
|
if (singular) {
|
||||||
// If we are trying to set the same bit as already set - do nothing
|
// If we are trying to set the same bit as already set - do nothing
|
||||||
if (singular_value == value)
|
if (singular_value == value)
|
||||||
@ -130,7 +122,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool clear(T value) {
|
bool clear(T value)
|
||||||
|
{
|
||||||
if (singular) {
|
if (singular) {
|
||||||
fb_assert(tree.isEmpty());
|
fb_assert(tree.isEmpty());
|
||||||
|
|
||||||
@ -155,7 +148,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test(T value) {
|
bool test(T value)
|
||||||
|
{
|
||||||
if (singular) {
|
if (singular) {
|
||||||
fb_assert(tree.isEmpty());
|
fb_assert(tree.isEmpty());
|
||||||
return (value == singular_value);
|
return (value == singular_value);
|
||||||
@ -169,24 +163,28 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test(SparseBitmap* bitmap, T value) {
|
static bool test(SparseBitmap* bitmap, T value)
|
||||||
|
{
|
||||||
if (!bitmap)
|
if (!bitmap)
|
||||||
return false;
|
return false;
|
||||||
return bitmap->test(value);
|
return bitmap->test(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear bitmap if it is not NULL
|
// Clear bitmap if it is not NULL
|
||||||
static void reset(SparseBitmap* bitmap) {
|
static void reset(SparseBitmap* bitmap)
|
||||||
|
{
|
||||||
if (bitmap)
|
if (bitmap)
|
||||||
bitmap->clear();
|
bitmap->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t approxSize() const {
|
size_t approxSize() const
|
||||||
|
{
|
||||||
return sizeof(*this) + tree.approxSize();
|
return sizeof(*this) + tree.approxSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make bitmap empty
|
// Make bitmap empty
|
||||||
void clear() {
|
void clear()
|
||||||
|
{
|
||||||
singular = false;
|
singular = false;
|
||||||
tree.clear();
|
tree.clear();
|
||||||
}
|
}
|
||||||
@ -208,10 +206,12 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Bucket with bits
|
// Bucket with bits
|
||||||
struct Bucket {
|
struct Bucket
|
||||||
|
{
|
||||||
T start_value; // starting value, BUNCH_BITS-aligned
|
T start_value; // starting value, BUNCH_BITS-aligned
|
||||||
BUNCH_T bits; // bits data
|
BUNCH_T bits; // bits data
|
||||||
inline static const T& generate(const void* sender, const Bucket& i) {
|
inline static const T& generate(const void* sender, const Bucket& i)
|
||||||
|
{
|
||||||
return i.start_value;
|
return i.start_value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -230,18 +230,21 @@ private:
|
|||||||
SparseBitmap& operator =(const SparseBitmap& from); // Assignment operator. Not implemented for now.
|
SparseBitmap& operator =(const SparseBitmap& from); // Assignment operator. Not implemented for now.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Accessor {
|
class Accessor
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Accessor(SparseBitmap* _bitmap) :
|
Accessor(SparseBitmap* _bitmap) :
|
||||||
bitmap(_bitmap), treeAccessor(_bitmap ? &_bitmap->tree : NULL), bit_mask(BUNCH_ONE), current_value(0) {}
|
bitmap(_bitmap), treeAccessor(_bitmap ? &_bitmap->tree : NULL), bit_mask(BUNCH_ONE), current_value(0) {}
|
||||||
|
|
||||||
bool locate(T key) {
|
bool locate(T key)
|
||||||
|
{
|
||||||
return locate(locEqual, key);
|
return locate(locEqual, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position accessor on item having LocType relationship with given key
|
// Position accessor on item having LocType relationship with given key
|
||||||
// If method returns false position of accessor is not defined.
|
// If method returns false position of accessor is not defined.
|
||||||
bool locate(LocType lt, T key) {
|
bool locate(LocType lt, T key)
|
||||||
|
{
|
||||||
// Small convenience related to fact engine likes to use NULL SparseBitmap pointers
|
// Small convenience related to fact engine likes to use NULL SparseBitmap pointers
|
||||||
if (!bitmap)
|
if (!bitmap)
|
||||||
return false;
|
return false;
|
||||||
@ -297,7 +300,8 @@ public:
|
|||||||
current_value = key;
|
current_value = key;
|
||||||
bit_mask = BUNCH_ONE << (key - key_aligned);
|
bit_mask = BUNCH_ONE << (key - key_aligned);
|
||||||
return treeAccessor.current().bits & bit_mask;
|
return treeAccessor.current().bits & bit_mask;
|
||||||
case locGreatEqual: {
|
case locGreatEqual:
|
||||||
|
{
|
||||||
// Initialize bit_mask
|
// Initialize bit_mask
|
||||||
if (treeAccessor.current().start_value == key_aligned) {
|
if (treeAccessor.current().start_value == key_aligned) {
|
||||||
current_value = key;
|
current_value = key;
|
||||||
@ -335,7 +339,8 @@ public:
|
|||||||
// Bucket must contain one bit at least
|
// Bucket must contain one bit at least
|
||||||
fb_assert(false);
|
fb_assert(false);
|
||||||
}
|
}
|
||||||
case locLessEqual: {
|
case locLessEqual:
|
||||||
|
{
|
||||||
// Initialize bit_mask
|
// Initialize bit_mask
|
||||||
if (treeAccessor.current().start_value == key_aligned) {
|
if (treeAccessor.current().start_value == key_aligned) {
|
||||||
current_value = key;
|
current_value = key;
|
||||||
@ -380,7 +385,8 @@ public:
|
|||||||
|
|
||||||
// If method returns false it means list is empty and
|
// If method returns false it means list is empty and
|
||||||
// position of accessor is not defined.
|
// position of accessor is not defined.
|
||||||
bool getFirst() {
|
bool getFirst()
|
||||||
|
{
|
||||||
// Small convenience related to fact engine likes to use NULL SparseBitmap pointers
|
// Small convenience related to fact engine likes to use NULL SparseBitmap pointers
|
||||||
if (!bitmap)
|
if (!bitmap)
|
||||||
return false;
|
return false;
|
||||||
@ -409,7 +415,8 @@ public:
|
|||||||
|
|
||||||
// If method returns false it means list is empty and
|
// If method returns false it means list is empty and
|
||||||
// position of accessor is not defined.
|
// position of accessor is not defined.
|
||||||
bool getLast() {
|
bool getLast()
|
||||||
|
{
|
||||||
// Small convenience related to fact engine likes to use NULL SparseBitmap pointers
|
// Small convenience related to fact engine likes to use NULL SparseBitmap pointers
|
||||||
if (!bitmap)
|
if (!bitmap)
|
||||||
return false;
|
return false;
|
||||||
@ -438,7 +445,8 @@ public:
|
|||||||
|
|
||||||
// Accessor position must be establised via successful call to getFirst(),
|
// Accessor position must be establised via successful call to getFirst(),
|
||||||
// getLast() or locate() before you can call this method
|
// getLast() or locate() before you can call this method
|
||||||
bool getNext() {
|
bool getNext()
|
||||||
|
{
|
||||||
if (bitmap->singular)
|
if (bitmap->singular)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -487,7 +495,8 @@ public:
|
|||||||
|
|
||||||
// Accessor position must be establised via successful call to getFirst(),
|
// Accessor position must be establised via successful call to getFirst(),
|
||||||
// getLast() or locate() before you can call this method
|
// getLast() or locate() before you can call this method
|
||||||
bool getPrev() {
|
bool getPrev()
|
||||||
|
{
|
||||||
if (bitmap->singular)
|
if (bitmap->singular)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -681,16 +690,16 @@ SparseBitmap<T, InternalTypes>::bit_and(
|
|||||||
if (map1->singular) {
|
if (map1->singular) {
|
||||||
if (map2->test(map1->singular_value))
|
if (map2->test(map1->singular_value))
|
||||||
return bitmap1;
|
return bitmap1;
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second bitmap is singular. Test appropriate bit in first and return second
|
// Second bitmap is singular. Test appropriate bit in first and return second
|
||||||
if (map2->singular) {
|
if (map2->singular) {
|
||||||
if (map1->test(map2->singular_value))
|
if (map1->test(map2->singular_value))
|
||||||
return bitmap2;
|
return bitmap2;
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SparseBitmap *source, *dest, **result;
|
SparseBitmap *source, *dest, **result;
|
||||||
|
@ -224,8 +224,8 @@ namespace Firebird {
|
|||||||
|
|
||||||
if (stk && stk->next)
|
if (stk && stk->next)
|
||||||
return stk->next->hasMore(value);
|
return stk->next->hasMore(value);
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasData() const
|
bool hasData() const
|
||||||
@ -256,8 +256,8 @@ namespace Firebird {
|
|||||||
|
|
||||||
bool operator== (const Stack<Object, Capacity>& s) const
|
bool operator== (const Stack<Object, Capacity>& s) const
|
||||||
{
|
{
|
||||||
return (this->stk == s.stk) &&
|
return (this->stk == s.stk) &&
|
||||||
(s.stk ? this->elem == s.stk->getCount() : true);
|
(s.stk ? this->elem == s.stk->getCount() : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!= (const Stack<Object, Capacity>& s) const
|
bool operator!= (const Stack<Object, Capacity>& s) const
|
||||||
@ -327,8 +327,8 @@ namespace Firebird {
|
|||||||
|
|
||||||
if (stk && stk->next)
|
if (stk && stk->next)
|
||||||
return stk->next->hasMore(value);
|
return stk->next->hasMore(value);
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasData() const
|
bool hasData() const
|
||||||
|
@ -270,12 +270,14 @@ void TimeStamp::round_time(ISC_TIME &ntime, int precision)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encode timestamp from UNIX datetime structure
|
// Encode timestamp from UNIX datetime structure
|
||||||
void TimeStamp::encode(const struct tm* times, int fractions) {
|
void TimeStamp::encode(const struct tm* times, int fractions)
|
||||||
|
{
|
||||||
mValue = encode_timestamp(times, fractions);
|
mValue = encode_timestamp(times, fractions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode timestamp into UNIX datetime structure
|
// Decode timestamp into UNIX datetime structure
|
||||||
void TimeStamp::decode(struct tm* times, int* fractions) const {
|
void TimeStamp::decode(struct tm* times, int* fractions) const
|
||||||
|
{
|
||||||
decode_timestamp(mValue, times, fractions);
|
decode_timestamp(mValue, times, fractions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +37,18 @@ namespace Firebird {
|
|||||||
|
|
||||||
// Very fast static array of simple types
|
// Very fast static array of simple types
|
||||||
template <typename T, size_t Capacity>
|
template <typename T, size_t Capacity>
|
||||||
class Vector {
|
class Vector
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Vector() : count(0) {}
|
Vector() : count(0) {}
|
||||||
|
|
||||||
T& operator[](size_t index) {
|
T& operator[](size_t index)
|
||||||
|
{
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
const T& operator[](size_t index) const {
|
const T& operator[](size_t index) const
|
||||||
|
{
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
@ -57,34 +60,40 @@ public:
|
|||||||
size_t getCapacity() const { return Capacity; }
|
size_t getCapacity() const { return Capacity; }
|
||||||
|
|
||||||
void clear() { count = 0; }
|
void clear() { count = 0; }
|
||||||
void insert(size_t index, const T& item) {
|
void insert(size_t index, const T& item)
|
||||||
|
{
|
||||||
fb_assert(index <= count);
|
fb_assert(index <= count);
|
||||||
fb_assert(count < Capacity);
|
fb_assert(count < Capacity);
|
||||||
memmove(data + index + 1, data + index, sizeof(T) * (count++ - index));
|
memmove(data + index + 1, data + index, sizeof(T) * (count++ - index));
|
||||||
data[index] = item;
|
data[index] = item;
|
||||||
}
|
}
|
||||||
size_t add(const T& item) {
|
size_t add(const T& item)
|
||||||
|
{
|
||||||
fb_assert(count < Capacity);
|
fb_assert(count < Capacity);
|
||||||
data[count] = item;
|
data[count] = item;
|
||||||
return ++count;
|
return ++count;
|
||||||
}
|
}
|
||||||
T* remove(size_t index) {
|
T* remove(size_t index)
|
||||||
|
{
|
||||||
fb_assert(index < count);
|
fb_assert(index < count);
|
||||||
memmove(data + index, data + index + 1, sizeof(T) * (--count - index));
|
memmove(data + index, data + index + 1, sizeof(T) * (--count - index));
|
||||||
return &data[index];
|
return &data[index];
|
||||||
}
|
}
|
||||||
void shrink(size_t newCount) {
|
void shrink(size_t newCount)
|
||||||
|
{
|
||||||
fb_assert(newCount <= count);
|
fb_assert(newCount <= count);
|
||||||
count = newCount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
void join(const Vector<T, Capacity>& L) {
|
void join(const Vector<T, Capacity>& L)
|
||||||
|
{
|
||||||
fb_assert(count + L.count <= Capacity);
|
fb_assert(count + L.count <= Capacity);
|
||||||
memcpy(data + count, L.data, sizeof(T) * L.count);
|
memcpy(data + count, L.data, sizeof(T) * L.count);
|
||||||
count += L.count;
|
count += L.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare vector to be used as a buffer of capacity items
|
// prepare vector to be used as a buffer of capacity items
|
||||||
T* getBuffer(size_t capacityL) {
|
T* getBuffer(size_t capacityL)
|
||||||
|
{
|
||||||
fb_assert(capacityL <= Capacity);
|
fb_assert(capacityL <= Capacity);
|
||||||
count = capacityL;
|
count = capacityL;
|
||||||
return data;
|
return data;
|
||||||
@ -97,16 +106,19 @@ protected:
|
|||||||
|
|
||||||
// Template for default value comparsion
|
// Template for default value comparsion
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class DefaultComparator {
|
class DefaultComparator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static bool greaterThan(const T& i1, const T& i2) {
|
static bool greaterThan(const T& i1, const T& i2)
|
||||||
|
{
|
||||||
return i1 > i2;
|
return i1 > i2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Template to convert value to index directly
|
// Template to convert value to index directly
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class DefaultKeyValue {
|
class DefaultKeyValue
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const T& generate(const void* sender, const T& Item) { return Item; }
|
static const T& generate(const void* sender, const T& Item) { return Item; }
|
||||||
};
|
};
|
||||||
@ -116,10 +128,12 @@ public:
|
|||||||
template <typename Value, size_t Capacity, typename Key = Value,
|
template <typename Value, size_t Capacity, typename Key = Value,
|
||||||
typename KeyOfValue = DefaultKeyValue<Value>,
|
typename KeyOfValue = DefaultKeyValue<Value>,
|
||||||
typename Cmp = DefaultComparator<Key> >
|
typename Cmp = DefaultComparator<Key> >
|
||||||
class SortedVector : public Vector<Value, Capacity> {
|
class SortedVector : public Vector<Value, Capacity>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SortedVector() : Vector<Value, Capacity>() {}
|
SortedVector() : Vector<Value, Capacity>() {}
|
||||||
bool find(const Key& item, size_t& pos) const {
|
bool find(const Key& item, size_t& pos) const
|
||||||
|
{
|
||||||
size_t highBound = this->count, lowBound = 0;
|
size_t highBound = this->count, lowBound = 0;
|
||||||
while (highBound > lowBound) {
|
while (highBound > lowBound) {
|
||||||
const size_t temp = (highBound + lowBound) >> 1;
|
const size_t temp = (highBound + lowBound) >> 1;
|
||||||
@ -132,7 +146,8 @@ public:
|
|||||||
return highBound != this->count &&
|
return highBound != this->count &&
|
||||||
!Cmp::greaterThan(KeyOfValue::generate(this, this->data[lowBound]), item);
|
!Cmp::greaterThan(KeyOfValue::generate(this, this->data[lowBound]), item);
|
||||||
}
|
}
|
||||||
size_t add(const Value& item) {
|
size_t add(const Value& item)
|
||||||
|
{
|
||||||
size_t pos;
|
size_t pos;
|
||||||
find(KeyOfValue::generate(this, item), pos);
|
find(KeyOfValue::generate(this, item), pos);
|
||||||
insert(pos, item);
|
insert(pos, item);
|
||||||
|
@ -70,7 +70,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DirectoryList : public ObjectsArray<ParsedPath> {
|
class DirectoryList : public ObjectsArray<ParsedPath>
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
typedef ObjectsArray<ParsedPath> inherited;
|
typedef ObjectsArray<ParsedPath> inherited;
|
||||||
// ListMode must be changed together with ListKeys in dir_list.cpp
|
// ListMode must be changed together with ListKeys in dir_list.cpp
|
||||||
@ -85,7 +86,8 @@ private:
|
|||||||
PathName key, PathName next);
|
PathName key, PathName next);
|
||||||
protected:
|
protected:
|
||||||
// Clear allocated memory and reinitialize
|
// Clear allocated memory and reinitialize
|
||||||
void clear(void) {
|
void clear(void)
|
||||||
|
{
|
||||||
((inherited*)this)->clear();
|
((inherited*)this)->clear();
|
||||||
mode = NotInitialized;
|
mode = NotInitialized;
|
||||||
}
|
}
|
||||||
@ -110,13 +112,11 @@ public:
|
|||||||
// Search for file Name in all directories of DirectoryList.
|
// Search for file Name in all directories of DirectoryList.
|
||||||
// If found, return full path to it in Path.
|
// If found, return full path to it in Path.
|
||||||
// Otherwise Path = Name.
|
// Otherwise Path = Name.
|
||||||
bool expandFileName(PathName& path,
|
bool expandFileName(PathName& path, const PathName& name) const;
|
||||||
const PathName& name) const;
|
|
||||||
|
|
||||||
// Use first directory in this directory list
|
// Use first directory in this directory list
|
||||||
// to build default full name for a file
|
// to build default full name for a file
|
||||||
bool defaultName(PathName& path,
|
bool defaultName(PathName& path, const PathName& name) const;
|
||||||
const PathName& name) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TempDirectoryList : public DirectoryList {
|
class TempDirectoryList : public DirectoryList {
|
||||||
|
@ -17,7 +17,8 @@ const size_t ENGINE_FAILURE_SPACE = 4096;
|
|||||||
|
|
||||||
typedef Firebird::CircularStringsBuffer<ENGINE_FAILURE_SPACE> CircularBuffer;
|
typedef Firebird::CircularStringsBuffer<ENGINE_FAILURE_SPACE> CircularBuffer;
|
||||||
|
|
||||||
class InterlockedStringsBuffer : public CircularBuffer {
|
class InterlockedStringsBuffer : public CircularBuffer
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit InterlockedStringsBuffer(Firebird::MemoryPool&)
|
explicit InterlockedStringsBuffer(Firebird::MemoryPool&)
|
||||||
: CircularBuffer() { }
|
: CircularBuffer() { }
|
||||||
|
@ -215,14 +215,17 @@ public:
|
|||||||
ISC_STATUS *dba_status;
|
ISC_STATUS *dba_status;
|
||||||
ISC_STATUS_ARRAY dba_status_vector;
|
ISC_STATUS_ARRAY dba_status_vector;
|
||||||
|
|
||||||
static inline tdba* getSpecific() {
|
static inline tdba* getSpecific()
|
||||||
|
{
|
||||||
return (tdba*) ThreadData::getSpecific();
|
return (tdba*) ThreadData::getSpecific();
|
||||||
}
|
}
|
||||||
static inline void putSpecific(tdba* &tddba, tdba* thd_context) {
|
static inline void putSpecific(tdba* &tddba, tdba* thd_context)
|
||||||
|
{
|
||||||
tddba = thd_context;
|
tddba = thd_context;
|
||||||
tddba->ThreadData::putSpecific();
|
tddba->ThreadData::putSpecific();
|
||||||
}
|
}
|
||||||
static inline void restoreSpecific() {
|
static inline void restoreSpecific()
|
||||||
|
{
|
||||||
ThreadData::restoreSpecific();
|
ThreadData::restoreSpecific();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -105,16 +105,17 @@ void missing_parameter_for_switch(const char* sw) {
|
|||||||
class b_error : public Firebird::LongJump
|
class b_error : public Firebird::LongJump
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit b_error(const char* message) {
|
explicit b_error(const char* message)
|
||||||
|
{
|
||||||
size_t len = sizeof(txt) - 1;
|
size_t len = sizeof(txt) - 1;
|
||||||
strncpy(txt, message, len);
|
strncpy(txt, message, len);
|
||||||
txt[len] = 0;
|
txt[len] = 0;
|
||||||
}
|
}
|
||||||
enum {MSG_LEN = 1024};
|
enum {MSG_LEN = 1024};
|
||||||
virtual ~b_error() throw() {}
|
virtual ~b_error() throw() {}
|
||||||
virtual const char* what() const throw()
|
virtual const char* what() const throw() { return txt; }
|
||||||
{ return txt; }
|
static void raise(const char* message, ...)
|
||||||
static void raise(const char* message, ...) {
|
{
|
||||||
char temp[MSG_LEN];
|
char temp[MSG_LEN];
|
||||||
va_list params;
|
va_list params;
|
||||||
va_start(params, message);
|
va_start(params, message);
|
||||||
@ -144,7 +145,8 @@ const char local_prefix[] = "localhost:";
|
|||||||
|
|
||||||
const char backup_signature[4] = {'N','B','A','K'};
|
const char backup_signature[4] = {'N','B','A','K'};
|
||||||
|
|
||||||
struct inc_header {
|
struct inc_header
|
||||||
|
{
|
||||||
char signature[4]; // 'NBAK'
|
char signature[4]; // 'NBAK'
|
||||||
SSHORT version; // Incremental backup format version.
|
SSHORT version; // Incremental backup format version.
|
||||||
SSHORT level; // Backup level.
|
SSHORT level; // Backup level.
|
||||||
@ -157,7 +159,8 @@ struct inc_header {
|
|||||||
ULONG prev_scn; // SCN of previous level backup
|
ULONG prev_scn; // SCN of previous level backup
|
||||||
};
|
};
|
||||||
|
|
||||||
class nbackup {
|
class nbackup
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
nbackup(const char* _database, const char* _username, const char* _password, bool _run_db_triggers)
|
nbackup(const char* _database, const char* _username, const char* _password, bool _run_db_triggers)
|
||||||
{
|
{
|
||||||
@ -557,7 +560,8 @@ void nbackup::backup_database(int level, const char* fname)
|
|||||||
attach_database();
|
attach_database();
|
||||||
try {
|
try {
|
||||||
// Look for SCN and GUID of previous-level backup in history table
|
// Look for SCN and GUID of previous-level backup in history table
|
||||||
if (level) {
|
if (level)
|
||||||
|
{
|
||||||
if (isc_start_transaction(status, &trans, 1, &newdb, 0, NULL))
|
if (isc_start_transaction(status, &trans, 1, &newdb, 0, NULL))
|
||||||
pr_error(status, "start transaction");
|
pr_error(status, "start transaction");
|
||||||
char out_sqlda_data[XSQLDA_LENGTH(2)];
|
char out_sqlda_data[XSQLDA_LENGTH(2)];
|
||||||
|
Loading…
Reference in New Issue
Block a user