8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 05:23:02 +01:00
firebird-mirror/src/jrd/RecordNumber.h
2007-02-06 12:18:18 +00:00

175 lines
5.3 KiB
C++

/*
* PROGRAM: JRD Access Method
* MODULE: RecordNumber.h
* DESCRIPTION: Handler class for table record number
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*
*
*/
#ifndef JRD_RECORDNUMBER_H
#define JRD_RECORDNUMBER_H
const SINT64 EMPTY_NUMBER = QUADCONST(0);
const SINT64 BOF_NUMBER = QUADCONST(-1);
// This class is to be used everywhere you may need to handle record numbers. We
// deliberately not define implicit conversions to and from integer to allow
// compiler check errors on our migration path from 32-bit to 64-bit record
// numbers.
class RecordNumber {
public:
// Default constructor.
inline RecordNumber() : value(EMPTY_NUMBER), valid(false) {}
// Copy constructor
inline RecordNumber(const RecordNumber& from) : value(from.value), valid(from.valid) {}
// Explicit constructor from 64-bit record number value
inline explicit RecordNumber(SINT64 number) : value(number), valid(true) {}
// Assignment operator
inline RecordNumber& operator =(const RecordNumber& from) {
value = from.value;
return *this;
}
inline bool operator ==(const RecordNumber& other) const {
return value == other.value;
}
inline bool operator !=(const RecordNumber& other) const {
return value != other.value;
}
inline bool operator > (const RecordNumber& other) const {
return value > other.value;
}
inline bool operator < (const RecordNumber& other) const {
return value < other.value;
}
inline bool operator >= (const RecordNumber& other) const {
return value >= other.value;
}
inline bool operator <= (const RecordNumber& other) const {
return value <= other.value;
}
inline void decrement() { value--; }
inline void increment() { value++; }
inline SINT64 getValue() const { return value; }
inline void setValue(SINT64 avalue) { value = avalue; }
bool isBof() const { return value == BOF_NUMBER; }
bool isEmpty() const { return value == EMPTY_NUMBER; }
bool isValid() const { return valid; }
inline bool checkNumber(
USHORT records_per_page, // ~400 (8k page)
USHORT data_pages_per_pointer_page // ~2000 (8k page)
) const
{
// We limit record number value to 40 bits and make sure decomposed value
// fits into 3 USHORTs. This all makes practical table size limit (not
// counting allocation threshold and overhead) roughtly equal to:
// 16k page - 20000 GB
// 8k page - 10000 GB
// 4k page - 2500 GB
// 2k page - 600 GB
// 1k page - 150 GB
// Large page size values are recommended for large databases because
// page allocators are generally linear.
return value < QUADCONST(0x10000000000) &&
value < (SINT64) MAX_USHORT * records_per_page * data_pages_per_pointer_page;
}
inline void decompose(
USHORT records_per_page, // ~400 (8k page)
USHORT data_pages_per_pointer_page, // ~2000 (8k page)
SSHORT& line,
SSHORT& slot,
USHORT& pp_sequence
) const
{
line = value % records_per_page;
const ULONG sequence = value / records_per_page;
slot = sequence % data_pages_per_pointer_page;
pp_sequence = sequence / data_pages_per_pointer_page;
}
inline void compose(
USHORT records_per_page, // ~400 (8k page)
USHORT data_pages_per_pointer_page, // ~2000 (8k page)
SSHORT line,
SSHORT slot,
USHORT pp_sequence
)
{
value = (((SINT64) pp_sequence) * data_pages_per_pointer_page + slot) * records_per_page + line;
}
// Handle encoding of record number for RDB$DB_KEY and BLOB ID structure.
// bid_number array has special alignment requirement - its second byte must
// be 4-byte aligned. This is generally not a problem because this routine is
// called for BID or DB_KEY structure member which is already aligned
// appropriately.
inline void bid_encode(UCHAR* bid_number) const {
// BLOB ID is stored in database thus we do encode large record numbers
// in a manner which preserves backward compatibility with older ODS.
// The same applies to bid_decode routine below.
// Store lower 32 bits of number
*reinterpret_cast<ULONG*>(bid_number + 1) = value;
// Store high 8 bits of number
bid_number[0] = value >> 32;
}
inline void bid_decode(const UCHAR* bid_number) {
value =
*reinterpret_cast<const ULONG*>(bid_number + 1) +
(((UINT64) bid_number[0]) << 32);
}
inline void setValid(bool to_value)
{
valid = to_value;
}
private:
// Use signed value because negative values are widely used as flags in the
// engine. Since page number is the signed 32-bit integer and it is also may
// be stored in this structure we want sign extension to take place.
SINT64 value;
bool valid;
};
#endif // JRD_RECORDNUMBER_H