2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
|
|
|
* MODULE: pag.h
|
|
|
|
* DESCRIPTION: Page interface definitions
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase 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.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, 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 Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Modified by: Patrick J. P. Griffin
|
|
|
|
* Date: 11/29/2000
|
|
|
|
* Problem: Bug 116733 Too many generators corrupt database.
|
|
|
|
* DPM_gen_id was not calculating page and offset correctly.
|
|
|
|
* Change: Add pgc_gpg, number of generators per page,
|
|
|
|
* for use in DPM_gen_id.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
#ifndef JRD_PAG_H
|
|
|
|
#define JRD_PAG_H
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
#include "../include/fb_blk.h"
|
2006-05-22 00:07:35 +02:00
|
|
|
#include "../common/classes/array.h"
|
2009-01-28 13:27:18 +01:00
|
|
|
#include "../jrd/ods.h"
|
2011-01-21 18:55:04 +01:00
|
|
|
#include "../jrd/lls.h"
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
namespace Jrd {
|
2008-12-05 01:56:15 +01:00
|
|
|
|
2009-11-27 09:34:34 +01:00
|
|
|
// Page control block -- used by PAG to keep track of critical constants
|
2006-05-22 00:07:35 +02:00
|
|
|
/**
|
2004-03-19 07:14:53 +01:00
|
|
|
class PageControl : public pool_alloc<type_pgc>
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
|
|
|
public:
|
2008-12-05 01:56:15 +01:00
|
|
|
SLONG pgc_high_water; // Lowest PIP with space
|
|
|
|
SLONG pgc_ppp; // Pages per pip
|
|
|
|
SLONG pgc_pip; // First pointer page
|
|
|
|
ULONG pgc_bytes; // Number of bytes of bit in PIP
|
|
|
|
ULONG pgc_tpt; // Transactions per TIP
|
|
|
|
ULONG pgc_gpg; // Generators per generator page
|
2006-05-22 00:07:35 +02:00
|
|
|
};
|
|
|
|
**/
|
|
|
|
|
2011-04-02 06:45:26 +02:00
|
|
|
// page spaces below TRANS_PAGE_SPACE contain regular database pages
|
|
|
|
// TEMP_PAGE_SPACE and page spaces above TEMP_PAGE_SPACE contain temporary pages
|
2011-01-21 18:55:04 +01:00
|
|
|
// TRANS_PAGE_SPACE is pseudo space to store transaction numbers in precedence stack
|
2011-04-02 06:45:26 +02:00
|
|
|
// INVALID_PAGE_SPACE is to ???
|
2011-01-21 18:55:04 +01:00
|
|
|
const USHORT INVALID_PAGE_SPACE = 0;
|
2006-05-22 00:07:35 +02:00
|
|
|
const USHORT DB_PAGE_SPACE = 1;
|
2011-01-21 18:55:04 +01:00
|
|
|
const USHORT TRANS_PAGE_SPACE = 255;
|
2008-12-05 01:56:15 +01:00
|
|
|
const USHORT TEMP_PAGE_SPACE = 256;
|
2006-05-22 00:07:35 +02:00
|
|
|
|
|
|
|
class jrd_file;
|
2008-02-14 13:24:27 +01:00
|
|
|
class Database;
|
|
|
|
class thread_db;
|
2009-12-21 00:13:01 +01:00
|
|
|
class PageManager;
|
2006-05-22 00:07:35 +02:00
|
|
|
|
|
|
|
class PageSpace : public pool_alloc<type_PageSpace>
|
|
|
|
{
|
|
|
|
public:
|
2009-12-23 02:19:18 +01:00
|
|
|
explicit PageSpace(Database* aDbb, USHORT aPageSpaceID)
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
2006-05-24 05:03:52 +02:00
|
|
|
pageSpaceID = aPageSpaceID;
|
|
|
|
pipHighWater = 0;
|
2009-12-17 11:25:23 +01:00
|
|
|
pipFirst = 0;
|
2009-12-21 00:13:01 +01:00
|
|
|
scnFirst = 0;
|
2006-05-24 05:03:52 +02:00
|
|
|
file = 0;
|
2009-12-21 00:13:01 +01:00
|
|
|
dbb = aDbb;
|
2007-04-25 23:08:57 +02:00
|
|
|
maxPageNumber = 0;
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
~PageSpace();
|
|
|
|
|
|
|
|
USHORT pageSpaceID;
|
2011-01-21 18:55:04 +01:00
|
|
|
ULONG pipHighWater; // Lowest PIP with space
|
|
|
|
ULONG pipFirst; // First pointer page
|
|
|
|
ULONG scnFirst; // First SCN's page
|
2006-05-22 00:07:35 +02:00
|
|
|
|
|
|
|
jrd_file* file;
|
|
|
|
|
2013-12-11 11:19:13 +01:00
|
|
|
static inline bool isTemporary(USHORT aPageSpaceID)
|
|
|
|
{
|
|
|
|
return (aPageSpaceID >= TEMP_PAGE_SPACE);
|
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool isTemporary() const
|
|
|
|
{
|
2013-12-11 11:19:13 +01:00
|
|
|
return isTemporary(pageSpaceID);
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:46:10 +02:00
|
|
|
static inline SLONG generate(const PageSpace* Item)
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2006-05-24 05:03:52 +02:00
|
|
|
return Item->pageSpaceID;
|
|
|
|
}
|
2007-04-25 23:08:57 +02:00
|
|
|
|
|
|
|
// how many pages allocated
|
2009-12-21 00:13:01 +01:00
|
|
|
ULONG actAlloc();
|
2007-07-02 12:28:50 +02:00
|
|
|
static ULONG actAlloc(const Database* dbb);
|
2007-04-25 23:08:57 +02:00
|
|
|
|
|
|
|
// number of last allocated page
|
2009-12-21 00:13:01 +01:00
|
|
|
ULONG maxAlloc();
|
2007-07-02 12:28:50 +02:00
|
|
|
static ULONG maxAlloc(const Database* dbb);
|
2007-04-25 23:08:57 +02:00
|
|
|
|
2009-12-21 00:13:01 +01:00
|
|
|
// number of last used page
|
|
|
|
ULONG lastUsedPage();
|
|
|
|
static ULONG lastUsedPage(const Database* dbb);
|
|
|
|
|
2007-04-25 23:08:57 +02:00
|
|
|
// extend page space
|
2014-06-10 11:00:58 +02:00
|
|
|
bool extend(thread_db*, const ULONG, const bool);
|
2007-04-25 23:08:57 +02:00
|
|
|
|
2009-12-21 00:13:01 +01:00
|
|
|
// get SCN's page number
|
|
|
|
ULONG getSCNPageNum(ULONG sequence);
|
|
|
|
static ULONG getSCNPageNum(const Database* dbb, ULONG sequence);
|
|
|
|
|
2007-04-25 23:08:57 +02:00
|
|
|
private:
|
|
|
|
ULONG maxPageNumber;
|
2009-12-23 02:19:18 +01:00
|
|
|
Database* dbb;
|
2006-05-22 00:07:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class PageManager : public pool_alloc<type_PageManager>
|
|
|
|
{
|
|
|
|
public:
|
2009-12-23 02:19:18 +01:00
|
|
|
explicit PageManager(Database* aDbb, Firebird::MemoryPool& aPool) :
|
2009-12-21 00:13:01 +01:00
|
|
|
dbb(aDbb),
|
2006-05-24 05:03:52 +02:00
|
|
|
pageSpaces(aPool),
|
|
|
|
pool(aPool)
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
2006-05-24 05:03:52 +02:00
|
|
|
pagesPerPIP = 0;
|
|
|
|
bytesBitPIP = 0;
|
|
|
|
transPerTIP = 0;
|
|
|
|
gensPerPage = 0;
|
2009-12-21 00:13:01 +01:00
|
|
|
pagesPerSCN = 0;
|
2008-12-05 01:56:15 +01:00
|
|
|
|
2006-05-24 05:03:52 +02:00
|
|
|
dbPageSpace = addPageSpace(DB_PAGE_SPACE);
|
|
|
|
// addPageSpace(TEMP_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
~PageManager()
|
|
|
|
{
|
2012-06-21 17:37:38 +02:00
|
|
|
while (pageSpaces.hasData())
|
|
|
|
delete pageSpaces.pop();
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
PageSpace* addPageSpace(const USHORT pageSpaceID);
|
2007-07-02 12:28:50 +02:00
|
|
|
PageSpace* findPageSpace(const USHORT pageSpaceID) const;
|
2006-05-22 00:07:35 +02:00
|
|
|
void delPageSpace(const USHORT pageSpaceID);
|
|
|
|
|
|
|
|
USHORT getTempPageSpaceID(thread_db* tdbb);
|
|
|
|
|
|
|
|
void closeAll();
|
|
|
|
|
2011-01-21 18:55:04 +01:00
|
|
|
ULONG pagesPerPIP; // Pages per pip
|
2008-12-05 01:56:15 +01:00
|
|
|
ULONG bytesBitPIP; // Number of bytes of bit in PIP
|
2012-05-19 14:04:37 +02:00
|
|
|
ULONG transPerTIP; // Transactions per TIP
|
2008-12-05 01:56:15 +01:00
|
|
|
ULONG gensPerPage; // Generators per generator page
|
2009-12-21 00:13:01 +01:00
|
|
|
ULONG pagesPerSCN; // Slots per SCN's page
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpace* dbPageSpace; // database page space
|
|
|
|
|
|
|
|
private:
|
2008-12-22 10:00:05 +01:00
|
|
|
typedef Firebird::SortedArray<PageSpace*, Firebird::EmptyStorage<PageSpace*>,
|
2006-05-22 00:07:35 +02:00
|
|
|
USHORT, PageSpace> PageSpaceArray;
|
|
|
|
|
2009-12-23 02:19:18 +01:00
|
|
|
Database* dbb;
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpaceArray pageSpaces;
|
|
|
|
Firebird::MemoryPool& pool;
|
2001-12-24 03:51:06 +01:00
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
class PageNumber
|
|
|
|
{
|
|
|
|
public:
|
2012-05-19 14:04:37 +02:00
|
|
|
// CVC: To be completely in sync, the second param would have to be TraNumber
|
2011-01-21 18:55:04 +01:00
|
|
|
inline PageNumber(const USHORT aPageSpace, const ULONG aPageNum)
|
|
|
|
: pageNum(aPageNum), pageSpaceID(aPageSpace)
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
// Some asserts are commented cause 0 was also used as 'does not matter' pagespace
|
|
|
|
// fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
2011-01-21 18:55:04 +01:00
|
|
|
|
|
|
|
// Required to be able to keep it in Firebird::Stack
|
|
|
|
inline PageNumber()
|
|
|
|
: pageNum(0), pageSpaceID(INVALID_PAGE_SPACE)
|
|
|
|
{ }
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline PageNumber(const PageNumber& from)
|
2011-01-21 18:55:04 +01:00
|
|
|
: pageNum(from.pageNum), pageSpaceID(from.pageSpaceID)
|
|
|
|
{ }
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2011-01-21 18:55:04 +01:00
|
|
|
inline ULONG getPageNum() const
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
// fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
return pageNum;
|
2008-12-22 10:00:05 +01:00
|
|
|
}
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2011-01-21 18:55:04 +01:00
|
|
|
inline USHORT getPageSpaceID() const
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
return pageSpaceID;
|
2008-12-05 01:56:15 +01:00
|
|
|
}
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2011-01-21 18:55:04 +01:00
|
|
|
inline USHORT setPageSpaceID(const USHORT aPageSpaceID)
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
fb_assert(aPageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
pageSpaceID = aPageSpaceID;
|
|
|
|
return pageSpaceID;
|
2008-12-05 01:56:15 +01:00
|
|
|
}
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool isTemporary() const
|
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
2013-12-11 11:19:13 +01:00
|
|
|
return PageSpace::isTemporary(pageSpaceID);
|
2007-02-22 15:12:04 +01:00
|
|
|
}
|
|
|
|
|
2012-06-21 17:37:38 +02:00
|
|
|
inline static USHORT getLockLen()
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
return 2 * sizeof(ULONG);
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline void getLockStr(UCHAR* str) const
|
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
|
|
|
|
|
|
|
memcpy(str, &pageNum, sizeof(ULONG));
|
|
|
|
str += sizeof(ULONG);
|
2007-09-07 09:41:07 +02:00
|
|
|
|
|
|
|
const ULONG val = pageSpaceID;
|
|
|
|
memcpy(str, &val, sizeof(ULONG));
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline PageNumber& operator=(const PageNumber& from)
|
|
|
|
{
|
2006-05-22 00:07:35 +02:00
|
|
|
pageSpaceID = from.pageSpaceID;
|
2011-01-21 18:55:04 +01:00
|
|
|
// fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
pageNum = from.pageNum;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2011-01-21 18:55:04 +01:00
|
|
|
inline ULONG operator=(const ULONG from)
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
// fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
pageNum = from;
|
|
|
|
return pageNum;
|
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool operator==(const PageNumber& other) const
|
|
|
|
{
|
2010-02-26 03:16:31 +01:00
|
|
|
return (pageNum == other.pageNum) && (pageSpaceID == other.pageSpaceID);
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool operator!=(const PageNumber& other) const
|
|
|
|
{
|
2006-05-22 00:07:35 +02:00
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool operator>(const PageNumber& other) const
|
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
|
|
|
fb_assert(other.pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
return (pageSpaceID > other.pageSpaceID) ||
|
|
|
|
(pageSpaceID == other.pageSpaceID) && (pageNum > other.pageNum);
|
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool operator>=(const PageNumber& other) const
|
|
|
|
{
|
2011-01-21 18:55:04 +01:00
|
|
|
fb_assert(pageSpaceID != INVALID_PAGE_SPACE);
|
|
|
|
fb_assert(other.pageSpaceID != INVALID_PAGE_SPACE);
|
2006-05-22 00:07:35 +02:00
|
|
|
return (pageSpaceID > other.pageSpaceID) ||
|
|
|
|
(pageSpaceID == other.pageSpaceID) && (pageNum >= other.pageNum);
|
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool operator<(const PageNumber& other) const
|
|
|
|
{
|
2006-05-22 00:07:35 +02:00
|
|
|
return !(*this >= other);
|
|
|
|
}
|
|
|
|
|
2008-05-10 05:44:57 +02:00
|
|
|
inline bool operator<=(const PageNumber& other) const
|
|
|
|
{
|
2006-05-22 00:07:35 +02:00
|
|
|
return !(*this > other);
|
|
|
|
}
|
|
|
|
|
2006-05-24 05:03:52 +02:00
|
|
|
/*
|
2011-01-21 18:55:04 +01:00
|
|
|
inline operator ULONG() const
|
2008-05-10 05:44:57 +02:00
|
|
|
{
|
2006-05-22 00:07:35 +02:00
|
|
|
return pageNum;
|
|
|
|
}
|
2006-05-24 05:03:52 +02:00
|
|
|
*/
|
2011-01-22 18:15:52 +01:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
private:
|
2011-01-21 18:55:04 +01:00
|
|
|
ULONG pageNum;
|
2006-05-22 00:07:35 +02:00
|
|
|
USHORT pageSpaceID;
|
|
|
|
};
|
|
|
|
|
|
|
|
const PageNumber ZERO_PAGE_NUMBER(0, 0);
|
|
|
|
const PageNumber HEADER_PAGE_NUMBER(DB_PAGE_SPACE, HEADER_PAGE);
|
|
|
|
|
2011-01-21 18:55:04 +01:00
|
|
|
typedef Firebird::Stack<PageNumber> PageStack;
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
} //namespace Jrd
|
|
|
|
|
2009-11-27 09:34:34 +01:00
|
|
|
#endif // JRD_PAG_H
|