8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 20:03:03 +01:00
firebird-mirror/src/jrd/RecordNumber.h

226 lines
6.2 KiB
C
Raw Normal View History

/*
* 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);
2008-12-05 01:56:15 +01:00
// 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.
2008-04-19 11:42:01 +02:00
class RecordNumber
{
public:
// Packed record number represents common layout of RDB$DB_KEY and BLOB ID.
2008-12-05 01:56:15 +01:00
// To ensure binary compatibility with old (pre-ODS11) databases it differs
// for big- and little-endian machines.
class Packed
{
#ifdef WORDS_BIGENDIAN
private:
UCHAR bid_number_up; // Upper byte of 40-bit record number
UCHAR bid_reserved_for_relation; // Reserved for future
public:
USHORT bid_relation_id; // Relation id (or null)
private:
ULONG bid_number; // Lower bytes of 40-bit record number
// or 32-bit temporary ID of blob or array
#else
public:
USHORT bid_relation_id; /* Relation id (or null) */
private:
UCHAR bid_reserved_for_relation; /* Reserved for future expansion of relation space. */
UCHAR bid_number_up; // Upper byte of 40-bit record number
ULONG bid_number; // Lower bytes of 40-bit record number
// or 32-bit temporary ID of blob or array
#endif
public:
2008-12-05 01:56:15 +01:00
ULONG& bid_temp_id()
{
return bid_number;
}
2008-12-05 01:56:15 +01:00
ULONG bid_temp_id() const
{
return bid_number;
}
2008-12-05 01:56:15 +01:00
// Handle encoding of record number for RDB$DB_KEY and BLOB ID structure.
2008-12-05 01:56:15 +01:00
// 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.
2008-04-19 11:42:01 +02:00
inline void bid_encode(SINT64 value)
{
// Store lower 32 bits of number
bid_number = value;
// Store high 8 bits of number
bid_number_up = value >> 32;
}
2008-04-19 11:42:01 +02:00
inline SINT64 bid_decode() const
{
2007-11-12 15:26:44 +01:00
return bid_number + (((FB_UINT64) bid_number_up) << 32);
}
};
2008-12-05 01:56:15 +01:00
// 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
2008-04-19 11:42:01 +02:00
inline RecordNumber& operator =(const RecordNumber& from)
2008-12-05 01:56:15 +01:00
{
value = from.value;
valid = from.valid;
return *this;
}
2008-04-19 11:42:01 +02:00
inline bool operator ==(const RecordNumber& other) const
2008-12-05 01:56:15 +01:00
{
return value == other.value;
}
2008-04-19 11:42:01 +02:00
inline bool operator !=(const RecordNumber& other) const
2008-12-05 01:56:15 +01:00
{
return value != other.value;
}
2008-04-19 11:42:01 +02:00
inline bool operator > (const RecordNumber& other) const
2008-12-05 01:56:15 +01:00
{
return value > other.value;
}
2008-04-19 11:42:01 +02:00
inline bool operator < (const RecordNumber& other) const
2008-12-05 01:56:15 +01:00
{
return value < other.value;
}
2008-04-19 11:42:01 +02:00
inline bool operator >= (const RecordNumber& other) const
2008-12-05 01:56:15 +01:00
{
return value >= other.value;
}
2008-04-19 11:42:01 +02:00
inline bool operator <= (const RecordNumber& other) const
2008-12-05 01:56:15 +01:00
{
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; }
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
2008-12-05 01:56:15 +01:00
// 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
2008-12-05 01:56:15 +01:00
// Large page size values are recommended for large databases because
// page allocators are generally linear.
2008-12-05 01:56:15 +01:00
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
2008-12-05 01:56:15 +01:00
)
{
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.
2008-04-19 11:42:01 +02:00
inline void bid_encode(Packed* recno) const
{
recno->bid_encode(value);
}
2008-04-19 11:42:01 +02:00
inline void bid_decode(const Packed* recno)
{
value = recno->bid_decode();
}
2007-02-06 13:18:18 +01:00
inline void setValid(bool to_value)
{
2007-02-06 13:18:18 +01:00
valid = to_value;
}
private:
2008-12-05 01:56:15 +01:00
// 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