8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:03:03 +01:00

1) An attempt to fix the endianess/alignment issues in the b-tree code.

2) Some adjustments in the pointers management.
This commit is contained in:
dimitr 2006-01-26 10:45:02 +00:00
parent aa9fc06acc
commit 8b20d04a8a
2 changed files with 142 additions and 272 deletions

View File

@ -27,7 +27,7 @@
#define MEMORY_ROUTINES_H
inline SSHORT get_short(const SCHAR* p)
inline USHORT get_short(const UCHAR* p)
{
/**************************************
*
@ -36,32 +36,30 @@ inline SSHORT get_short(const SCHAR* p)
**************************************
*
* Functional description
* gather one short int from two chars
*
* Based on BTR_get_quad
* Gather one unsigned short int
* from two chars
*
**************************************/
#if defined(i386) || defined(I386) || defined(_M_IX86) || defined(VMS) || defined(AMD64)
// For IA32 (little-endian) this optimization is a _very_ large speed-up!
// According to CTO32L definition in common.h this trick works for VAX/VMS
return *reinterpret_cast<const SSHORT*>(p);
#ifndef WORDS_BIGENDIAN
// little-endian
USHORT temp;
memcpy(&temp, p, sizeof(USHORT));
return temp;
#else
// Non-IA32
// big-endian
union {
USHORT n;
UCHAR c[2];
} temp;
union {
SSHORT n;
SCHAR c[2]; } value;
temp.c[0] = p[0];
temp.c[1] = p[1];
value.c[0] = p[0];
value.c[1] = p[1];
return value.n;
#endif // endianness
return temp.n;
#endif
}
inline SLONG get_long(const SCHAR* p)
inline SLONG get_long(const UCHAR* p)
{
/**************************************
*
@ -70,133 +68,91 @@ inline SLONG get_long(const SCHAR* p)
**************************************
*
* Functional description
* gather one long int from four chars
*
* Based on BTR_get_quad
* Gather one signed long int
* from four chars
*
**************************************/
#if defined(i386) || defined(I386) || defined(_M_IX86) || defined(VMS) || defined(AMD64)
// For IA32 (little-endian) this optimization is a _very_ large speed-up!
return *reinterpret_cast<const SLONG*>(p);
#else
// Non-IA32
union {
SLONG n;
SCHAR c[4]; } value;
value.c[0] = p[0];
value.c[1] = p[1];
value.c[2] = p[2];
value.c[3] = p[3];
return value.n;
#endif // endianness
}
inline SLONG get_long(const UCHAR* p)
{
/**************************************
*
* g e t _ l o n g (overloaded)
*
**************************************
*
* Functional description
* gather one unsigned long int from
* four unsigned chars
*
* Based on get_long and CTO32L macro
*
**************************************/
#if defined(i386) || defined(I386) || defined(_M_IX86) || defined(VMS) || defined(AMD64)
// For IA32 (little-endian) this optimization is a _very_ large speed-up!
return *reinterpret_cast<const SLONG*>(p);
#else
// Non-IA32 a bit slower implementation but faster than using union
#ifndef WORDS_BIGENDIAN
return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
// little-endian
SLONG temp;
memcpy(&temp, p, sizeof(SLONG));
return temp;
#else
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
#endif // WORDS_BIGENDIAN
// big-endian
union {
SLONG n;
UCHAR c[4];
} temp;
temp.c[0] = p[0];
temp.c[1] = p[1];
temp.c[2] = p[2];
temp.c[3] = p[3];
return temp.n;
#endif
}
inline SSHORT gather_short(const SCHAR*& p)
inline void put_short(UCHAR* p, USHORT value)
{
/**************************************
*
* g a t h e r _ s h o r t
* p u t _ s h o r t
*
**************************************
*
* Functional description
* gather one short int from two chars
* and advance the pointer
*
* Based on BTR_get_quad
* Store one unsigned short int as
* two chars
*
**************************************/
#if defined(i386) || defined(I386) || defined(_M_IX86) || defined(VMS) || defined(AMD64)
// For IA32 (little-endian) this optimization is a _very_ large speed-up!
const SSHORT value = *reinterpret_cast<const SSHORT*>(p);
p += 2;
return value;
#ifndef WORDS_BIGENDIAN
// little-endian
memcpy(p, &value, sizeof(USHORT));
#else
// Non-IA32
// big-endian
union {
USHORT n;
UCHAR c[2];
} temp;
union {
SSHORT n;
SCHAR c[2]; } value;
temp.n = value;
value.c[0] = *p++;
value.c[1] = *p++;
return value.n;
#endif // endianness
p[0] = temp.c[0];
p[1] = temp.c[1];
#endif
}
inline SLONG gather_long(const SCHAR*& p)
inline void put_long(UCHAR* p, SLONG value)
{
/**************************************
*
* g a t h e r _ l o n g
* p u t _ l o n g
*
**************************************
*
* Functional description
* gather one long int from four chars
* and advance the pointer
*
* Based on BTR_get_quad
* Store one signed long int as
* four chars
*
**************************************/
#if defined(i386) || defined(I386) || defined(_M_IX86) || defined(VMS) || defined(AMD64)
// For IA32 (little-endian) this optimization is a _very_ large speed-up!
const SLONG value = *reinterpret_cast<const SLONG*>(p);
p += 4;
return value;
#ifndef WORDS_BIGENDIAN
// little-endian
memcpy(p, &value, sizeof(SLONG));
#else
// Non-IA32
// big-endian
union {
SLONG n;
UCHAR c[4];
} temp;
union {
SLONG n;
SCHAR c[4]; } value;
temp.n = value;
value.c[0] = *p++;
value.c[1] = *p++;
value.c[2] = *p++;
value.c[3] = *p++;
return value.n;
#endif // endianness
p[0] = temp.c[0];
p[1] = temp.c[1];
p[2] = temp.c[2];
p[3] = temp.c[3];
#endif
}
#endif // MEMORY_ROUTINES_H

View File

@ -488,32 +488,6 @@ UCHAR* previousNode(IndexNode* node, UCHAR* pointer,
}
void quad_put(SLONG value, UCHAR* data)
{
/**************************************
*
* q u a d _ p u t
*
**************************************
*
* Functional description
* Move SLONG to a four byte vector.
*
**************************************/
#if defined(i386) || defined(I386) || defined(_M_IX86) || defined(VMS) || defined(AMD64)
*reinterpret_cast<SLONG*>(data) = value;
#else
const UCHAR* p = (UCHAR*) &value;
data[0] = p[0];
data[1] = p[1];
data[2] = p[2];
data[3] = p[3];
#endif
}
UCHAR* readJumpInfo(IndexJumpInfo* jumpInfo, UCHAR* pagePointer)
{
/**************************************
@ -529,12 +503,11 @@ UCHAR* readJumpInfo(IndexJumpInfo* jumpInfo, UCHAR* pagePointer)
* the read.
*
**************************************/
jumpInfo->firstNodeOffset = *reinterpret_cast<const USHORT*>(pagePointer);
jumpInfo->firstNodeOffset = get_short(pagePointer);
pagePointer += sizeof(USHORT);
jumpInfo->jumpAreaSize = *reinterpret_cast<const USHORT*>(pagePointer);
jumpInfo->jumpAreaSize = get_short(pagePointer);
pagePointer += sizeof(USHORT);
jumpInfo->jumpers = (USHORT)(*pagePointer);
++pagePointer;
jumpInfo->jumpers = (USHORT)(*pagePointer++);
return pagePointer;
}
@ -557,31 +530,25 @@ UCHAR* readJumpNode(IndexJumpNode* jumpNode, UCHAR* pagePointer,
jumpNode->nodePointer = pagePointer;
if (flags & btr_large_keys) {
// Get prefix
UCHAR tmp = *pagePointer;
pagePointer++;
UCHAR tmp = *pagePointer++;
jumpNode->prefix = (tmp & 0x7F);
if (tmp & 0x80) {
tmp = *pagePointer;
pagePointer++;
tmp = *pagePointer++;
jumpNode->prefix |= (tmp & 0x7F) << 7; // We get 14 bits at this point
}
// Get length
tmp = *pagePointer;
pagePointer++;
tmp = *pagePointer++;
jumpNode->length = (tmp & 0x7F);
if (tmp & 0x80) {
tmp = *pagePointer;
pagePointer++;
tmp = *pagePointer++;
jumpNode->length |= (tmp & 0x7F) << 7; // We get 14 bits at this point
}
}
else {
jumpNode->prefix = (USHORT)(*pagePointer);
pagePointer++;
jumpNode->length = (USHORT)(*pagePointer);
pagePointer++;
jumpNode->prefix = (USHORT)(*pagePointer++);
jumpNode->length = (USHORT)(*pagePointer++);
}
jumpNode->offset = *reinterpret_cast<const USHORT*>(pagePointer);
jumpNode->offset = get_short(pagePointer);
pagePointer += sizeof(USHORT);
jumpNode->data = pagePointer;
pagePointer += jumpNode->length;
@ -608,10 +575,9 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
// Get first byte that contains internal flags and 6 bits from number
UCHAR* localPointer = pagePointer;
UCHAR internalFlags = *localPointer;
UCHAR internalFlags = *localPointer++;
SINT64 number = (internalFlags & 0x1F);
internalFlags = ((internalFlags & 0xE0) >> 5);
localPointer++;
indexNode->isEndLevel = (internalFlags == BTN_END_LEVEL_FLAG);
indexNode->isEndBucket = (internalFlags == BTN_END_BUCKET_FLAG);
@ -626,37 +592,30 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
}
// Get remaining bits for number
ULONG tmp = *localPointer;
ULONG tmp = *localPointer++;
number |= (tmp & 0x7F) << 5;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (tmp & 0x7F) << 12;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (tmp & 0x7F) << 19;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (UINT64) (tmp & 0x7F) << 26;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (UINT64) (tmp & 0x7F) << 33;
/*
Uncomment this if you need more bits in record number
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (UINT64) (tmp & 0x7F) << 40;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (UINT64) (tmp & 0x7F) << 47;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (UINT64) (tmp & 0x7F) << 54; // We get 61 bits at this point!
}
}
@ -666,48 +625,39 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
}
}
}
localPointer++;
indexNode->recordNumber.setValue(number);
if (!leafNode) {
// Get page number for non-leaf pages
tmp = *localPointer;
tmp = *localPointer++;
number = (tmp & 0x7F);
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (tmp & 0x7F) << 7;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (tmp & 0x7F) << 14;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (tmp & 0x7F) << 21;
if (tmp >= 128) {
localPointer++;
tmp = *localPointer;
tmp = *localPointer++;
number |= (tmp & 0x0F) << 28;
/*
Change number to 64-bit type and enable this for 64-bit support
number |= (*localPointer & 0x7F) << 28;
number |= (*tmp & 0x7F) << 28;
if (tmp >= 128) {
tmp = *localPointer;
localPointer++;
tmp = *localPointer++;
number |= (*localPointer & 0x7F) << 35;
if (tmp >= 128) {
tmp = *localPointer;
localPointer++;
tmp = *localPointer++;
number |= (*localPointer & 0x7F) << 42;
if (tmp >= 128) {
tmp = *localPointer;
localPointer++;
tmp = *localPointer++;
number |= (*localPointer & 0x7F) << 49;
if (tmp >= 128) {
tmp = *localPointer;
localPointer++;
tmp = *localPointer++;
number |= (*localPointer & 0x7F) << 56; // We get 63 bits at this point!
}
}
@ -718,7 +668,6 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
}
}
}
localPointer++;
indexNode->pageNumber = number;
}
@ -728,14 +677,12 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
}
else {
// Get prefix
tmp = *localPointer;
tmp = *localPointer++;
indexNode->prefix = (tmp & 0x7F);
if (*localPointer & 0x80) {
localPointer++;
tmp = *localPointer;
if (tmp & 0x80) {
tmp = *localPointer++;
indexNode->prefix |= (tmp & 0x7F) << 7; // We get 14 bits at this point
}
localPointer++;
}
if ((internalFlags == BTN_ZERO_LENGTH_FLAG) ||
@ -750,14 +697,12 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
}
else {
// Get length
tmp = *localPointer;
tmp = *localPointer++;
indexNode->length = (tmp & 0x7F);
if (*localPointer & 0x80) {
localPointer++;
tmp = *localPointer;
if (tmp & 0x80) {
tmp = *localPointer++;
indexNode->length |= (tmp & 0x7F) << 7; // We get 14 bits at this point
}
localPointer++;
}
// Get pointer where data starts
@ -767,10 +712,8 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
return localPointer;
}
else {
indexNode->prefix = *pagePointer;
pagePointer++;
indexNode->length = *pagePointer;
pagePointer++;
indexNode->prefix = *pagePointer++;
indexNode->length = *pagePointer++;
if (leafNode) {
// Nice sign extension should happen here
indexNode->recordNumber.setValue(get_long(pagePointer));
@ -782,7 +725,7 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
indexNode->isEndLevel = (indexNode->pageNumber == END_LEVEL);
indexNode->isEndBucket = (indexNode->pageNumber == END_BUCKET);
}
pagePointer += 4;
pagePointer += sizeof(SLONG);
indexNode->data = pagePointer;
pagePointer += indexNode->length;
@ -794,7 +737,7 @@ UCHAR* readNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags, bool leaf
(leafNode && indexNode->isEndBucket && (indexNode->length == 0))))
{
indexNode->recordNumber.setValue(get_long(pagePointer));
pagePointer += 4;
pagePointer += sizeof(SLONG);
}
}
return pagePointer;
@ -815,12 +758,11 @@ UCHAR* writeJumpInfo(btree_page* page, const IndexJumpInfo* jumpInfo)
*
**************************************/
UCHAR* pointer = reinterpret_cast<UCHAR*>(page->btr_nodes);
*reinterpret_cast<USHORT*>(pointer) = jumpInfo->firstNodeOffset;
put_short(pointer, jumpInfo->firstNodeOffset);
pointer += sizeof(USHORT);
*reinterpret_cast<USHORT*>(pointer) = jumpInfo->jumpAreaSize;
put_short(pointer, jumpInfo->jumpAreaSize);
pointer += sizeof(USHORT);
*pointer = (UCHAR) jumpInfo->jumpers;
pointer++;
*pointer++ = (UCHAR) jumpInfo->jumpers;
return pointer;
}
@ -848,12 +790,10 @@ UCHAR* writeJumpNode(IndexJumpNode* jumpNode, UCHAR* pagePointer,
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (tmp & 0x80) {
tmp = (number & 0x7F);
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
}
// Write length, maximum 14 bits
@ -863,21 +803,17 @@ UCHAR* writeJumpNode(IndexJumpNode* jumpNode, UCHAR* pagePointer,
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (tmp & 0x80) {
tmp = (number & 0x7F);
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
}
}
else {
*pagePointer = (UCHAR) jumpNode->prefix;
pagePointer++;
*pagePointer = (UCHAR) jumpNode->length;
pagePointer++;
*pagePointer++ = (UCHAR) jumpNode->prefix;
*pagePointer++ = (UCHAR) jumpNode->length;
}
*reinterpret_cast<USHORT*>(pagePointer) = jumpNode->offset;
put_short(pagePointer, jumpNode->offset);
pagePointer += sizeof(USHORT);
memmove(pagePointer, jumpNode->data, jumpNode->length);
pagePointer += jumpNode->length;
@ -946,8 +882,7 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
}
// Store internal flags + 6 bits from number
UCHAR tmp = internalFlags;
*pagePointer = ((tmp << 5) | (number & 0x1F));
pagePointer++;
*pagePointer++ = ((tmp << 5) | (number & 0x1F));
if (indexNode->isEndLevel) {
return pagePointer;
@ -1034,37 +969,32 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
number >>= 7; //14
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
number >>= 7; //21
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
number >>= 7; //28
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x0F);
number >>= 7; //35
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
/*
Change number to 64-bit type and enable this for 64-bit support
tmp = (number & 0x7F);
@ -1072,36 +1002,31 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
number >>= 7; //42
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
number >>= 7; //49
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
number >>= 7; //56
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
}
}
}
@ -1120,12 +1045,10 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
}
}
@ -1140,12 +1063,10 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
if (number > 0) {
tmp |= 0x80;
}
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
if (number > 0) {
tmp = (number & 0x7F);
*pagePointer = tmp;
pagePointer++;
*pagePointer++ = tmp;
}
}
@ -1157,26 +1078,24 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
}
else {
// Write prefix
*pagePointer = (UCHAR)indexNode->prefix;
pagePointer++;
*pagePointer++ = (UCHAR)indexNode->prefix;
// Write length
*pagePointer = (UCHAR)indexNode->length;
pagePointer++;
*pagePointer++ = (UCHAR)indexNode->length;
if (indexNode->isEndLevel) {
quad_put(END_LEVEL, pagePointer);
put_long(pagePointer, END_LEVEL);
}
else if (indexNode->isEndBucket) {
quad_put(END_BUCKET, pagePointer);
put_long(pagePointer, END_BUCKET);
}
else {
if (leafNode) {
// Write record number
quad_put(indexNode->recordNumber.getValue(), pagePointer);
put_long(pagePointer, indexNode->recordNumber.getValue());
}
else {
// Write page number
quad_put(indexNode->pageNumber, pagePointer);
put_long(pagePointer, indexNode->pageNumber);
}
}
pagePointer += sizeof(SLONG);
@ -1198,12 +1117,7 @@ UCHAR* writeNode(IndexNode* indexNode, UCHAR* pagePointer, SCHAR flags,
(leafNode && indexNode->isEndBucket && (indexNode->length == 0))))
{
// Write record number
//if (flags & btr_large_keys) {
// *reinterpret_cast<SLONG*>(pagePointer) = indexNode->recordNumber.getValue();
//}
//else {
quad_put(indexNode->recordNumber.getValue(), pagePointer);
//}
put_long(pagePointer, indexNode->recordNumber.getValue());
pagePointer += sizeof(SLONG);
}
}