2004-09-28 08:33:53 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
2006-09-07 03:55:49 +02:00
|
|
|
inline RecordNumber() : value(EMPTY_NUMBER), valid(false) {}
|
2004-09-28 08:33:53 +02:00
|
|
|
|
|
|
|
// Copy constructor
|
2006-09-07 03:55:49 +02:00
|
|
|
inline RecordNumber(const RecordNumber& from) : value(from.value), valid(from.valid) {}
|
2004-09-28 08:33:53 +02:00
|
|
|
|
|
|
|
// Explicit constructor from 64-bit record number value
|
2006-09-07 03:55:49 +02:00
|
|
|
inline explicit RecordNumber(SINT64 number) : value(number), valid(true) {}
|
2004-09-28 08:33:53 +02:00
|
|
|
|
|
|
|
// 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; }
|
|
|
|
|
2004-10-27 11:28:26 +02:00
|
|
|
inline void setValue(SINT64 avalue) { value = avalue; }
|
2004-09-28 08:33:53 +02:00
|
|
|
|
2004-10-02 11:33:06 +02:00
|
|
|
bool isBof() const { return value == BOF_NUMBER; }
|
2004-09-28 08:33:53 +02:00
|
|
|
|
2004-10-02 11:33:06 +02:00
|
|
|
bool isEmpty() const { return value == EMPTY_NUMBER; }
|
2004-09-28 08:33:53 +02:00
|
|
|
|
2006-09-07 03:55:49 +02:00
|
|
|
bool isValid() const { return valid; }
|
|
|
|
|
2004-09-28 08:33:53 +02:00
|
|
|
inline bool checkNumber(
|
|
|
|
USHORT records_per_page, // ~400 (8k page)
|
|
|
|
USHORT data_pages_per_pointer_page // ~2000 (8k page)
|
2004-10-02 11:33:06 +02:00
|
|
|
) const
|
2004-09-28 08:33:53 +02:00
|
|
|
{
|
|
|
|
// 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;
|
2004-10-03 06:49:04 +02:00
|
|
|
const ULONG sequence = value / records_per_page;
|
2004-09-28 08:33:53 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-02-06 13:18:18 +01:00
|
|
|
inline void setValid(bool to_value)
|
2006-09-07 03:55:49 +02:00
|
|
|
{
|
2007-02-06 13:18:18 +01:00
|
|
|
valid = to_value;
|
2006-09-07 03:55:49 +02:00
|
|
|
}
|
|
|
|
|
2004-09-28 08:33:53 +02:00
|
|
|
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;
|
2006-09-07 03:55:49 +02:00
|
|
|
bool valid;
|
2004-09-28 08:33:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // JRD_RECORDNUMBER_H
|