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

Wipe out multi-file database support (#8047)

* Wipe out multi-file database support

* Fix (fingers crossed) Windows build, some more cleanup and code simplification

* Fix gstat build on Windows and also Android/MacOS builds
This commit is contained in:
Dmitry Yemanov 2024-12-28 09:27:34 +03:00 committed by GitHub
parent 125140103d
commit f0740d2a32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 384 additions and 1504 deletions

View File

@ -4204,53 +4204,85 @@ bool get_files(BurpGlobals* tdgbl)
att_type attribute;
scan_attr_t scan_next_attr;
STORE (REQUEST_HANDLE tdgbl->handles_get_files_req_handle1)
X IN RDB$FILES
X.RDB$FILE_FLAGS = 0;
BASED_ON RDB$FILES.RDB$FILE_NAME filename = "";
SSHORT flags = 0, sequence = 0, number = 0;
SLONG start = 0, length = 0;
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
{
switch (attribute)
{
switch (attribute)
{
case att_file_filename:
GET_TEXT(X.RDB$FILE_NAME);
BURP_verbose (116, X.RDB$FILE_NAME);
// msg 116 restoring file %s
break;
case att_file_filename:
GET_TEXT(filename);
break;
case att_file_sequence:
X.RDB$FILE_SEQUENCE = (USHORT) get_int32(tdgbl);
break;
case att_file_sequence:
sequence = (SSHORT) get_int32(tdgbl);
break;
case att_file_start:
X.RDB$FILE_START = get_int32(tdgbl);
break;
case att_file_start:
start = get_int32(tdgbl);
break;
case att_file_length:
X.RDB$FILE_LENGTH = get_int32(tdgbl);
break;
case att_file_length:
length = get_int32(tdgbl);
break;
case att_file_flags:
X.RDB$FILE_FLAGS |= get_int32(tdgbl);
break;
case att_file_flags:
flags |= (SSHORT) get_int32(tdgbl);
break;
case att_shadow_number:
X.RDB$SHADOW_NUMBER = (USHORT) get_int32(tdgbl);
if (tdgbl->gbl_sw_kill && X.RDB$SHADOW_NUMBER)
X.RDB$FILE_FLAGS |= FILE_inactive;
break;
case att_shadow_number:
number = (SSHORT) get_int32(tdgbl);
if (tdgbl->gbl_sw_kill && number)
flags |= FILE_inactive;
break;
default:
bad_attribute(scan_next_attr, attribute, 85);
// msg 85 file
break;
}
default:
bad_attribute(scan_next_attr, attribute, 85);
// msg 85 file
break;
}
END_STORE;
ON_ERROR
general_on_error ();
END_ERROR;
}
const bool multiFileSupport = (tdgbl->runtimeODS <= DB_VERSION_DDL13_1);
if ((multiFileSupport || !sequence) && filename[0])
{
BURP_verbose (116, filename);
// msg 116 restoring file %s
STORE (REQUEST_HANDLE tdgbl->handles_get_files_req_handle1)
X IN RDB$FILES
strncpy(X.RDB$FILE_NAME, filename, sizeof(X.RDB$FILE_NAME));
X.RDB$FILE_FLAGS = flags;
X.RDB$SHADOW_NUMBER = number;
if (multiFileSupport)
{
X.RDB$FILE_SEQUENCE.NULL = FALSE;
X.RDB$FILE_SEQUENCE = sequence;
X.RDB$FILE_START.NULL = FALSE;
X.RDB$FILE_START = start;
X.RDB$FILE_LENGTH.NULL = FALSE;
X.RDB$FILE_LENGTH = length;
}
else
{
X.RDB$FILE_SEQUENCE.NULL = TRUE;
X.RDB$FILE_START.NULL = TRUE;
X.RDB$FILE_LENGTH.NULL = TRUE;
}
END_STORE;
ON_ERROR
general_on_error ();
END_ERROR;
}
return true;
}

View File

@ -80,9 +80,6 @@ static void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode*
dsql_fld* field, ValueSourceClause* clause, string& source, BlrDebugWriter::BlrData& value);
static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
const MetaName& relationName, const MetaName& constraintName, const MetaName& indexName);
static void defineFile(thread_db* tdbb, jrd_tra* transaction, SLONG shadowNumber, bool manualShadow,
bool conditionalShadow, SLONG& dbAlloc,
const PathName& name, SLONG start, SLONG length);
static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
const MetaName& fieldName);
static bool isItSqlRole(thread_db* tdbb, jrd_tra* transaction, const MetaName& inputName,
@ -490,46 +487,6 @@ static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
}
}
// Define a database or shadow file.
static void defineFile(thread_db* tdbb, jrd_tra* transaction, SLONG shadowNumber, bool manualShadow,
bool conditionalShadow, SLONG& dbAlloc, const PathName& name, SLONG start, SLONG length)
{
PathName expandedName = name;
if (!ISC_expand_filename(expandedName, false))
status_exception::raise(Arg::PrivateDyn(231)); // File name is invalid.
if (tdbb->getDatabase()->dbb_filename == expandedName)
status_exception::raise(Arg::PrivateDyn(166));
AutoCacheRequest request(tdbb, drq_l_files, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FIRST 1 X IN RDB$FILES
WITH X.RDB$FILE_NAME EQ expandedName.c_str()
{
status_exception::raise(Arg::PrivateDyn(166));
}
END_FOR
request.reset(tdbb, drq_s_files, DYN_REQUESTS);
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$FILES
{
expandedName.copyTo(X.RDB$FILE_NAME, sizeof(X.RDB$FILE_NAME));
X.RDB$SHADOW_NUMBER = shadowNumber;
X.RDB$FILE_FLAGS = (manualShadow ? FILE_manual : 0) |
(conditionalShadow ? FILE_conditional : 0);
dbAlloc = MAX(dbAlloc, start);
X.RDB$FILE_START = dbAlloc;
X.RDB$FILE_LENGTH = length;
dbAlloc += length;
}
END_STORE
}
// Checks to see if the given field already exists in a relation.
static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
const MetaName& fieldName)
@ -10462,7 +10419,7 @@ string CreateShadowNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, number);
NODE_PRINT(printer, manual);
NODE_PRINT(printer, conditional);
NODE_PRINT(printer, files);
NODE_PRINT(printer, fileName);
return "CreateShadowNode";
}
@ -10486,7 +10443,7 @@ void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
// If a shadow set identified by the shadow number already exists return error.
// If a shadow set identified by the shadow number already exists return error
AutoCacheRequest request(tdbb, drq_l_shadow, DYN_REQUESTS);
@ -10502,25 +10459,34 @@ void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
}
END_FOR
SLONG start = 0;
PathName expandedName = fileName.ToPathName();
for (NestConst<DbFileClause>* i = files.begin(); i != files.end(); ++i)
if (!ISC_expand_filename(expandedName, false))
status_exception::raise(Arg::PrivateDyn(231)); // File name is invalid
if (tdbb->getDatabase()->dbb_filename == expandedName)
status_exception::raise(Arg::PrivateDyn(166));
request.reset(tdbb, drq_l_files, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FIRST 1 X IN RDB$FILES
WITH X.RDB$FILE_NAME EQ expandedName.c_str()
{
bool first = i == files.begin();
DbFileClause* file = *i;
if (!first && i[-1]->length == 0 && file->start == 0)
{
// Preceding file did not specify length, so %s must include starting page number
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
Arg::Gds(isc_dsql_file_length_err) << file->name);
}
defineFile(tdbb, transaction, number, manual && first, conditional && first,
start, file->name.c_str(), file->start, file->length);
status_exception::raise(Arg::PrivateDyn(166));
}
END_FOR
request.reset(tdbb, drq_s_files, DYN_REQUESTS);
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$FILES
{
expandedName.copyTo(X.RDB$FILE_NAME, sizeof(X.RDB$FILE_NAME));
X.RDB$SHADOW_NUMBER = number;
X.RDB$FILE_FLAGS = (manual ? FILE_manual : 0) | (conditional ? FILE_conditional : 0);
}
END_STORE
savePoint.release(); // everything is ok
}
@ -12742,13 +12708,11 @@ string AlterDatabaseNode::internalPrint(NodePrinter& printer) const
DdlNode::internalPrint(printer);
NODE_PRINT(printer, create);
NODE_PRINT(printer, createLength);
NODE_PRINT(printer, linger);
NODE_PRINT(printer, clauses);
NODE_PRINT(printer, differenceFile);
NODE_PRINT(printer, setDefaultCharSet);
NODE_PRINT(printer, setDefaultCollation);
NODE_PRINT(printer, files);
NODE_PRINT(printer, cryptPlugin);
NODE_PRINT(printer, keyName);
@ -12924,18 +12888,6 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
}
}
SLONG dbAlloc = PageSpace::maxAlloc(tdbb->getDatabase());
SLONG start = create ? createLength + 1 : 0;
for (NestConst<DbFileClause>* i = files.begin(); i != files.end(); ++i)
{
DbFileClause* file = *i;
start = MAX(start, file->start);
defineFile(tdbb, transaction, 0, false, false, dbAlloc,
file->name.c_str(), start, file->length);
start += file->length;
}
if (differenceFile.hasData())
defineDifference(tdbb, transaction, differenceFile.c_str());
@ -13064,7 +13016,6 @@ void AlterDatabaseNode::changeBackupMode(thread_db* tdbb, jrd_tra* transaction,
X IN RDB$FILES
{
X.RDB$FILE_FLAGS = FILE_difference | FILE_backing_up;
X.RDB$FILE_START = 0;
}
END_STORE
@ -13116,7 +13067,6 @@ void AlterDatabaseNode::defineDifference(thread_db* tdbb, jrd_tra* transaction,
strcpy(FIL.RDB$FILE_NAME, file.c_str());
FIL.RDB$FILE_FLAGS = FILE_difference;
FIL.RDB$FILE_START = 0;
}
END_STORE
}

View File

@ -101,40 +101,6 @@ public:
};
class DbFileClause : public Printable
{
public:
DbFileClause(MemoryPool& p, const DbFileClause& o)
: name(p, o.name),
start(o.start),
length(o.length)
{
}
explicit DbFileClause(MemoryPool& p, const Firebird::string& aName)
: name(p, aName),
start(0),
length(0)
{
}
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
NODE_PRINT(printer, name);
NODE_PRINT(printer, start);
NODE_PRINT(printer, length);
return "DbFileClause";
}
public:
Firebird::string name; // File name
SLONG start; // Starting page
SLONG length; // File length in pages
};
class ExternalClause : public Printable
{
public:
@ -1967,12 +1933,13 @@ public:
class CreateShadowNode : public DdlNode
{
public:
CreateShadowNode(MemoryPool& p, const SSHORT aNumber)
CreateShadowNode(MemoryPool& p, SSHORT aNumber, bool aManual, bool aConditional,
const Firebird::string& aFileName)
: DdlNode(p),
number(aNumber),
manual(false),
conditional(false),
files(p)
manual(aManual),
conditional(aConditional),
fileName(p, aFileName)
{
}
@ -1996,7 +1963,7 @@ public:
SSHORT number;
bool manual;
bool conditional;
Firebird::Array<NestConst<DbFileClause> > files;
Firebird::string fileName;
bool createIfNotExistsOnly = false;
};
@ -2425,14 +2392,9 @@ public:
public:
AlterDatabaseNode(MemoryPool& p)
: DdlNode(p),
create(false),
createLength(0),
linger(-1),
clauses(0),
differenceFile(p),
setDefaultCharSet(p),
setDefaultCollation(p),
files(p),
cryptPlugin(p),
keyName(p),
pubTables(p)
@ -2468,13 +2430,12 @@ private:
void checkClauses(thread_db* tdbb);
public:
bool create; // Is the node created with a CREATE DATABASE command?
SLONG createLength, linger;
unsigned clauses;
bool create = false; // Is the node created with a CREATE DATABASE command?
SLONG linger = -1;
unsigned clauses = 0;
Firebird::string differenceFile;
MetaName setDefaultCharSet;
MetaName setDefaultCollation;
Firebird::Array<NestConst<DbFileClause> > files;
MetaName cryptPlugin;
MetaName keyName;
Firebird::TriState ssDefiner;

View File

@ -767,8 +767,6 @@ using namespace Firebird;
Firebird::string* stringPtr;
Jrd::IntlString* intlStringPtr;
Jrd::Lim64String* lim64ptr;
Jrd::DbFileClause* dbFileClause;
Firebird::Array<NestConst<Jrd::DbFileClause> >* dbFilesClause;
Jrd::ExternalClause* externalClause;
Firebird::NonPooledPair<Jrd::MetaName*, Jrd::ValueExprNode*>* namedArgument;
Firebird::NonPooledPair<Firebird::ObjectsArray<Jrd::MetaName>*, Jrd::ValueListNode*>* namedArguments;
@ -1807,16 +1805,8 @@ index_condition_opt
// CREATE SHADOW
%type <createShadowNode> shadow_clause
shadow_clause
: pos_short_integer manual_auto conditional utf_string first_file_length
{
$$ = newNode<CreateShadowNode>($1);
$$->manual = $2;
$$->conditional = $3;
$$->files.add(newNode<DbFileClause>(*$4));
$$->files.front()->length = $5;
}
sec_shadow_files(NOTRIAL(&$6->files))
{ $$ = $6; }
: pos_short_integer manual_auto conditional utf_string
{ $$ = newNode<CreateShadowNode>($1, $2, $3, *$4); }
;
%type <boolVal> manual_auto
@ -1832,24 +1822,6 @@ conditional
| CONDITIONAL { $$ = true; }
;
%type <int32Val> first_file_length
first_file_length
: /* nothing */ { $$ = 0; }
| LENGTH equals long_integer page_noise { $$ = $3; }
;
%type sec_shadow_files(<dbFilesClause>)
sec_shadow_files($dbFilesClause)
: // nothing
| db_file_list($dbFilesClause)
;
%type db_file_list(<dbFilesClause>)
db_file_list($dbFilesClause)
: db_file { $dbFilesClause->add($1); }
| db_file_list db_file { $dbFilesClause->add($2); }
;
// CREATE DOMAIN
@ -2279,8 +2251,6 @@ db_initial_option($alterDatabaseNode)
| ROLE utf_string
| PASSWORD utf_string
| SET NAMES utf_string
| LENGTH equals long_integer page_noise
{ $alterDatabaseNode->createLength = $3; }
;
%type db_rem_desc1(<alterDatabaseNode>)
@ -2297,9 +2267,7 @@ db_rem_desc($alterDatabaseNode)
%type db_rem_option(<alterDatabaseNode>)
db_rem_option($alterDatabaseNode)
: db_file
{ $alterDatabaseNode->files.add($1); }
| DEFAULT CHARACTER SET symbol_character_set_name
: DEFAULT CHARACTER SET symbol_character_set_name
{ $alterDatabaseNode->setDefaultCharSet = *$4; }
| DEFAULT CHARACTER SET symbol_character_set_name COLLATION symbol_collation_name
{
@ -2310,49 +2278,6 @@ db_rem_option($alterDatabaseNode)
{ $alterDatabaseNode->differenceFile = *$3; }
;
%type <dbFileClause> db_file
db_file
: FILE utf_string
{
DbFileClause* clause = newNode<DbFileClause>(*$2);
$$ = clause;
}
file_desc1($3)
{ $$ = $3; }
;
%type file_desc1(<dbFileClause>)
file_desc1($dbFileClause)
: // nothing
| file_desc($dbFileClause)
;
%type file_desc(<dbFileClause>)
file_desc($dbFileClause)
: file_clause($dbFileClause)
| file_desc file_clause($dbFileClause)
;
%type file_clause(<dbFileClause>)
file_clause($dbFileClause)
: STARTING file_clause_noise long_integer
{ $dbFileClause->start = $3; }
| LENGTH equals long_integer page_noise
{ $dbFileClause->length = $3; }
;
file_clause_noise
: // nothing
| AT
| AT PAGE
;
page_noise
: // nothing
| PAGE
| PAGES
;
// CREATE TABLE
@ -4770,8 +4695,7 @@ alter_db($alterDatabaseNode)
%type db_alter_clause(<alterDatabaseNode>)
db_alter_clause($alterDatabaseNode)
: ADD db_file_list(NOTRIAL(&$alterDatabaseNode->files))
| ADD DIFFERENCE FILE utf_string
: ADD DIFFERENCE FILE utf_string
{ $alterDatabaseNode->differenceFile = *$4; }
| DROP DIFFERENCE FILE
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DROP_DIFFERENCE; }

View File

@ -2489,15 +2489,6 @@ bool CCH_write_all_shadows(thread_db* tdbb, Shadow* shadow, BufferDesc* bdb, Ods
PAG_add_header_entry(tdbb, header, HDR_root_file_name,
(USHORT) strlen((const char*) q), q);
jrd_file* next_file = shadow_file->fil_next;
if (next_file)
{
q = (UCHAR *) next_file->fil_string;
const SLONG last = next_file->fil_min_page - 1;
PAG_add_header_entry(tdbb, header, HDR_file, (USHORT) strlen((const char*) q), q);
PAG_add_header_entry(tdbb, header, HDR_last_page, sizeof(last), (const UCHAR*) &last);
}
header->hdr_flags |= hdr_active_shadow;
header->hdr_header.pag_pageno = bdb->bdb_page.getPageNum();
}

View File

@ -56,7 +56,7 @@
* BUGCHECK(291) took place. To avoid that issue, it was decided not to modify data
* in system transaction. An exception is RDB$FORMATS relation, which is always modified
* by transaction zero. Also an aspect of 'dirty' access from system transaction was
* taken into an account in add_file(), make_version() and create_index().
* taken into an account in make_version() and create_index().
*
*/
@ -449,7 +449,6 @@ private:
*
*==================================================================
*/
static bool add_file(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool add_shadow(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool delete_shadow(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool compute_security(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
@ -1272,7 +1271,6 @@ namespace
static const deferred_task task_table[] =
{
{ dfw_add_file, add_file },
{ dfw_add_shadow, add_shadow },
{ dfw_delete_index, modify_index },
{ dfw_delete_rfr, delete_rfr },
@ -1876,133 +1874,6 @@ void DFW_update_index(const TEXT* name, USHORT id, const SelectivityList& select
}
static bool add_file(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
{
/**************************************
*
* a d d _ f i l e
*
**************************************
*
* Functional description
* Add a file to a database.
* This file could be a regular database
* file or a shadow file. Either way we
* require exclusive access to the database.
*
**************************************/
USHORT section, shadow_number;
SLONG start, min_start;
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
switch (phase)
{
case 0:
CCH_release_exclusive(tdbb);
return false;
case 1:
case 2:
return true;
case 3:
if (!CCH_exclusive(tdbb, LCK_EX, WAIT_PERIOD, NULL))
raiseDatabaseInUseError(true);
return true;
case 4:
CCH_flush(tdbb, FLUSH_FINI, 0);
start = PageSpace::maxAlloc(dbb) + 1;
AutoRequest handle;
AutoRequest handle2;
// Check the file name for node name. This has already
// been done for shadows in add_shadow()
if (work->dfw_type != dfw_add_shadow) {
check_filename(work->dfw_name, true);
}
// User transaction may be safely used instead of system, cause
// we requested and got exclusive database access. AP-2008.
// get any files to extend into
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction) X IN RDB$FILES
WITH X.RDB$FILE_NAME EQ work->dfw_name.c_str()
// First expand the file name This has already been done
// for shadows in add_shadow ())
if (work->dfw_type != dfw_add_shadow)
{
MODIFY X USING
ISC_expand_filename(X.RDB$FILE_NAME, 0,
X.RDB$FILE_NAME, sizeof(X.RDB$FILE_NAME), false);
END_MODIFY
}
// Check the previous file length
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE transaction)
FIRST 1 Y IN RDB$FILES
WITH Y.RDB$SHADOW_NUMBER EQ X.RDB$SHADOW_NUMBER
AND Y.RDB$FILE_SEQUENCE NOT MISSING
SORTED BY DESCENDING Y.RDB$FILE_SEQUENCE
{
if (!Y.RDB$FILE_START.NULL && !Y.RDB$FILE_LENGTH.NULL)
{
min_start = Y.RDB$FILE_START + (Y.RDB$FILE_LENGTH ? Y.RDB$FILE_LENGTH : 1);
start = MAX(min_start, start);
}
}
END_FOR
// If there is no starting position specified, or if it is
// too low a value, raise the error.
if (X.RDB$FILE_START < start)
{
ERR_post(Arg::Gds(isc_file_starting_page_err) <<
Arg::Str(X.RDB$FILE_NAME) << Arg::Num(start));
}
start = X.RDB$FILE_START;
shadow_number = X.RDB$SHADOW_NUMBER;
if ((shadow_number &&
(section = SDW_add_file(tdbb, X.RDB$FILE_NAME, start, shadow_number))) ||
(section = PAG_add_file(tdbb, X.RDB$FILE_NAME, start)))
{
MODIFY X USING
X.RDB$FILE_SEQUENCE = section;
X.RDB$FILE_START = start;
END_MODIFY
}
END_FOR
if (section)
{
handle.reset();
section--;
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction) X IN RDB$FILES
WITH X.RDB$FILE_SEQUENCE EQ section
AND X.RDB$SHADOW_NUMBER EQ shadow_number
{
MODIFY X USING
X.RDB$FILE_LENGTH = start - X.RDB$FILE_START;
END_MODIFY
}
END_FOR
}
CCH_release_exclusive(tdbb);
break;
}
return false;
}
static bool add_shadow(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
{
/**************************************
@ -2053,11 +1924,11 @@ static bool add_shadow(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tr
finished = false;
handle.reset();
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
F IN RDB$FILES
WITH F.RDB$FILE_NAME EQ work->dfw_name.c_str()
F IN RDB$FILES WITH F.RDB$FILE_NAME EQ work->dfw_name.c_str()
{
expanded_fname = F.RDB$FILE_NAME;
ISC_expand_filename(expanded_fname, false);
MODIFY F USING
expanded_fname.copyTo(F.RDB$FILE_NAME, sizeof(F.RDB$FILE_NAME));
END_MODIFY
@ -2066,94 +1937,34 @@ static bool add_shadow(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tr
{
if ((F.RDB$SHADOW_NUMBER == shadow->sdw_number) && !(shadow->sdw_flags & SDW_IGNORE))
{
if (F.RDB$FILE_FLAGS & FILE_shadow)
{
// This is the case of a bogus duplicate posted
// work when we added a multi-file shadow
finished = true;
}
else if (shadow->sdw_flags & (SDW_dumped))
{
/* Case of adding a file to a currently active
* shadow set.
* Note: as of 1995-January-31 there is
* no SQL syntax that supports this, but there
* may be GDML
*/
add_file(tdbb, 3, work, transaction);
add_file(tdbb, 4, work, transaction);
finished = true;
}
else
if (!(F.RDB$FILE_FLAGS & FILE_shadow))
{
// We cannot add a file to a shadow that is still
// in the process of being created.
raiseDatabaseInUseError(false);
}
// This is the case of a bogus duplicate posted
// work when we added a multi-file shadow
finished = true;
break;
}
}
}
END_FOR
if (finished)
return false;
// this file is part of a new shadow, so get all files for the shadow
// in order of the starting page for the file
// Note that for a multi-file shadow, we have several pieces of
// work posted (one dfw_add_shadow for each file). Rather than
// trying to cancel the other pieces of work we ignore them
// when they arrive in this routine.
sequence = 0;
min_page = 0;
shadow = NULL;
handle.reset();
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
X IN RDB$FILES CROSS
Y IN RDB$FILES
OVER RDB$SHADOW_NUMBER
WITH X.RDB$FILE_NAME EQ expanded_fname.c_str()
SORTED BY Y.RDB$FILE_START
F IN RDB$FILES WITH F.RDB$FILE_NAME EQ expanded_fname.c_str()
{
// for the first file, create a brand new shadow; for secondary
// files that have a starting page specified, add a file
if (!sequence)
SDW_add(tdbb, Y.RDB$FILE_NAME, Y.RDB$SHADOW_NUMBER, Y.RDB$FILE_FLAGS);
else if (Y.RDB$FILE_START)
{
if (!shadow)
{
for (shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
{
if ((Y.RDB$SHADOW_NUMBER == shadow->sdw_number) &&
!(shadow->sdw_flags & SDW_IGNORE))
{
break;
}
}
}
SDW_add(tdbb, F.RDB$FILE_NAME, F.RDB$SHADOW_NUMBER, F.RDB$FILE_FLAGS);
if (!shadow)
BUGCHECK(203); // msg 203 shadow block not found for extend file
min_page = MAX((min_page + 1), (ULONG) Y.RDB$FILE_START);
add_sequence = SDW_add_file(tdbb, Y.RDB$FILE_NAME, min_page, Y.RDB$SHADOW_NUMBER);
}
// update the sequence number and bless the file entry as being good
if (!sequence || (Y.RDB$FILE_START && add_sequence))
{
MODIFY Y
Y.RDB$FILE_FLAGS |= FILE_shadow;
Y.RDB$FILE_SEQUENCE = sequence;
Y.RDB$FILE_START = min_page;
END_MODIFY
sequence++;
}
MODIFY F
F.RDB$FILE_FLAGS |= FILE_shadow;
END_MODIFY
}
END_FOR

View File

@ -1301,7 +1301,7 @@ private:
static void check_database(thread_db* tdbb, bool async = false);
static void commit(thread_db*, jrd_tra*, const bool);
static bool drop_files(const jrd_file*);
static bool drop_file(Database*, const jrd_file*);
static void find_intl_charset(thread_db*, Jrd::Attachment*, const DatabaseOptions*);
static void init_database_lock(thread_db*);
static void run_commit_triggers(thread_db* tdbb, jrd_tra* transaction);
@ -1831,7 +1831,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
dbb->dbb_crypto_manager = FB_NEW_POOL(*dbb->dbb_permanent) CryptoManager(tdbb);
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
PAG_init2(tdbb, 0);
PAG_init2(tdbb);
PAG_header(tdbb, false, newForceWrite);
dbb->dbb_page_manager.initTempPageSpace(tdbb);
dbb->dbb_crypto_manager->attach(tdbb, attachment);
@ -3552,11 +3552,9 @@ void JAttachment::internalDropDatabase(CheckStatusWrapper* user_status)
// This point on database is useless
// drop the files here
bool err = drop_files(file);
bool err = drop_file(dbb, file);
for (; shadow; shadow = shadow->sdw_next)
{
err = drop_files(shadow->sdw_file) || err;
}
err = drop_file(dbb, shadow->sdw_file) || err;
tdbb->setDatabase(NULL);
Database::destroy(dbb);
@ -6797,31 +6795,28 @@ static void commit(thread_db* tdbb, jrd_tra* transaction, const bool retaining_f
}
static bool drop_files(const jrd_file* file)
static bool drop_file(Database* dbb, const jrd_file* file)
{
/**************************************
*
* d r o p _ f i l e s
* d r o p _ f i l e
*
**************************************
*
* Functional description
* drop a linked list of files
* Drop a file.
*
**************************************/
FbLocalStatus status;
for (; file; file = file->fil_next)
if (unlink(file->fil_string))
{
if (unlink(file->fil_string))
{
ERR_build_status(&status, Arg::Gds(isc_io_error) << Arg::Str("unlink") <<
Arg::Str(file->fil_string) <<
Arg::Gds(isc_io_delete_err) << SYS_ERR(errno));
Database* dbb = GET_DBB();
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
iscDbLogStatus(pageSpace->file->fil_string, &status);
}
ERR_build_status(&status, Arg::Gds(isc_io_error) << Arg::Str("unlink") <<
Arg::Str(file->fil_string) <<
Arg::Gds(isc_io_delete_err) << SYS_ERR(errno));
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
iscDbLogStatus(pageSpace->file->fil_string, &status);
}
return status->getState() & IStatus::STATE_ERRORS ? true : false;

View File

@ -1782,7 +1782,6 @@ void MET_get_shadow_files(thread_db* tdbb, bool delete_files)
FOR(REQUEST_HANDLE handle) X IN RDB$FILES
WITH X.RDB$SHADOW_NUMBER NOT MISSING
AND X.RDB$SHADOW_NUMBER NE 0
AND X.RDB$FILE_SEQUENCE EQ 0
{
if ((X.RDB$FILE_FLAGS & FILE_shadow) && !(X.RDB$FILE_FLAGS & FILE_inactive))
{

View File

@ -531,8 +531,8 @@ static_assert(offsetof(struct header_page, hdr_data) == 128, "hdr_data offset mi
inline constexpr UCHAR HDR_end = 0;
inline constexpr UCHAR HDR_root_file_name = 1; // Original name of root file
inline constexpr UCHAR HDR_file = 2; // Secondary file
inline constexpr UCHAR HDR_last_page = 3; // Last logical page number of file
//inline constexpr UCHAR HDR_file = 2; // Secondary file
//inline constexpr UCHAR HDR_last_page = 3; // Last logical page number of file
inline constexpr UCHAR HDR_sweep_interval = 4; // Transactions between sweeps
inline constexpr UCHAR HDR_crypt_checksum = 5; // Checksum of critical crypt parameters
inline constexpr UCHAR HDR_difference_file = 6; // Delta file that is used during backup lock

View File

@ -41,11 +41,6 @@ namespace Jrd {
class jrd_file : public pool_alloc_rpt<SCHAR, type_fil>
{
public:
jrd_file* fil_next; // Next file in database
ULONG fil_min_page; // Minimum page number in file
ULONG fil_max_page; // Maximum page number in file
USHORT fil_sequence; // Sequence number of file
USHORT fil_fudge; // Fudge factor for page relocation
int fil_desc;
Firebird::Mutex fil_mutex;
USHORT fil_flags;
@ -69,11 +64,6 @@ public:
delete fil_ext_lock;
}
jrd_file* fil_next; // Next file in database
ULONG fil_min_page; // Minimum page number in file
ULONG fil_max_page; // Maximum page number in file
USHORT fil_sequence; // Sequence number of file
USHORT fil_fudge; // Fudge factor for page relocation
HANDLE fil_desc; // File descriptor
Firebird::RWLock* fil_ext_lock; // file extend lock
USHORT fil_flags;

View File

@ -36,7 +36,6 @@ namespace Ods {
struct pag;
}
int PIO_add_file(Jrd::thread_db*, Jrd::jrd_file*, const Firebird::PathName&, SLONG);
void PIO_close(Jrd::jrd_file*);
Jrd::jrd_file* PIO_create(Jrd::thread_db*, const Firebird::PathName&,
const bool, const bool);

View File

@ -132,7 +132,7 @@ using namespace Firebird;
static const mode_t MASK = 0660;
static jrd_file* seek_file(jrd_file*, BufferDesc*, FB_UINT64*, FbStatusVector*);
static bool seek_file(jrd_file*, BufferDesc*, FB_UINT64*, FbStatusVector*);
static jrd_file* setup_file(Database*, const PathName&, int, USHORT);
static void lockDatabaseFile(int& desc, const bool shareMode, const bool temporary,
const char* fileName, ISC_STATUS operation);
@ -149,42 +149,8 @@ static int raw_devices_unlink_database (const PathName&);
static int openFile(const Firebird::PathName&, const bool, const bool, const bool);
static void maybeCloseFile(int&);
int PIO_add_file(thread_db* tdbb, jrd_file* main_file, const PathName& file_name, SLONG start)
{
/**************************************
*
* P I O _ a d d _ f i l e
*
**************************************
*
* Functional description
* Add a file to an existing database. Return the sequence
* number of the new file. If anything goes wrong, return a
* sequence of 0.
* NOTE: This routine does not lock any mutexes on
* its own behalf. It is assumed that mutexes will
* have been locked before entry.
*
**************************************/
jrd_file* new_file = PIO_create(tdbb, file_name, false, false);
if (!new_file)
return 0;
new_file->fil_min_page = start;
USHORT sequence = 1;
jrd_file* file;
for (file = main_file; file->fil_next; file = file->fil_next)
++sequence;
file->fil_max_page = start - 1;
file->fil_next = new_file;
return sequence;
}
void PIO_close(jrd_file* main_file)
void PIO_close(jrd_file* file)
{
/**************************************
*
@ -199,13 +165,10 @@ void PIO_close(jrd_file* main_file)
*
**************************************/
for (jrd_file* file = main_file; file; file = file->fil_next)
if (file->fil_desc && file->fil_desc != -1)
{
if (file->fil_desc && file->fil_desc != -1)
{
close(file->fil_desc);
file->fil_desc = -1;
}
close(file->fil_desc);
file->fil_desc = -1;
}
}
@ -336,7 +299,7 @@ bool PIO_expand(const TEXT* file_name, USHORT file_length, TEXT* expanded_name,
}
void PIO_extend(thread_db* tdbb, jrd_file* main_file, const ULONG extPages, const USHORT pageSize)
void PIO_extend(thread_db* tdbb, jrd_file* file, const ULONG extPages, const USHORT pageSize)
{
/**************************************
*
@ -348,56 +311,46 @@ void PIO_extend(thread_db* tdbb, jrd_file* main_file, const ULONG extPages, cons
* Extend file by extPages pages of pageSize size.
*
**************************************/
fb_assert(extPages);
#if defined(HAVE_LINUX_FALLOC_H) && defined(HAVE_FALLOCATE)
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
ULONG leftPages = extPages;
for (jrd_file* file = main_file; file && leftPages; file = file->fil_next)
if (file->fil_flags & FIL_no_fast_extend)
return;
const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
const ULONG extendBy = MIN(MAX_ULONG - filePages, extPages);
int r;
for (r = 0; r < IO_RETRY; r++)
{
const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
const ULONG fileMaxPages = (file->fil_max_page == MAX_ULONG) ?
MAX_ULONG : file->fil_max_page - file->fil_min_page + 1;
if (filePages < fileMaxPages)
{
if (file->fil_flags & FIL_no_fast_extend)
return;
int err = fallocate(file->fil_desc, 0, filePages * pageSize, extendBy * pageSize);
if (err == 0)
break;
const ULONG extendBy = MIN(fileMaxPages - filePages + file->fil_fudge, leftPages);
err = errno;
if (SYSCALL_INTERRUPTED(err))
continue;
int r;
for (r = 0; r < IO_RETRY; r++)
{
int err = fallocate(file->fil_desc, 0, filePages * pageSize, extendBy * pageSize);
if (err == 0)
break;
if (err != EOPNOTSUPP && err != ENOSYS)
unix_error("fallocate", file, isc_io_write_err);
err = errno;
if (SYSCALL_INTERRUPTED(err))
continue;
file->fil_flags |= FIL_no_fast_extend;
return;
}
if (err != EOPNOTSUPP && err != ENOSYS)
unix_error("fallocate", file, isc_io_write_err);
file->fil_flags |= FIL_no_fast_extend;
return;
}
if (r == IO_RETRY)
{
if (r == IO_RETRY)
{
#ifdef DEV_BUILD
fprintf(stderr, "PIO_extend: retry count exceeded\n");
fflush(stderr);
fprintf(stderr, "PIO_extend: retry count exceeded\n");
fflush(stderr);
#endif
unix_error("fallocate_retry", file, isc_io_write_err);
}
leftPages -= extendBy;
}
unix_error("fallocate_retry", file, isc_io_write_err);
}
#else
main_file->fil_flags |= FIL_no_fast_extend;
file->fil_flags |= FIL_no_fast_extend;
#endif // fallocate present
// not implemented
@ -405,7 +358,7 @@ void PIO_extend(thread_db* tdbb, jrd_file* main_file, const ULONG extPages, cons
}
void PIO_flush(thread_db* tdbb, jrd_file* main_file)
void PIO_flush(thread_db* tdbb, jrd_file* file)
{
/**************************************
*
@ -422,15 +375,12 @@ void PIO_flush(thread_db* tdbb, jrd_file* main_file)
#ifndef SUPERSERVER_V2
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
MutexLockGuard guard(main_file->fil_mutex, FB_FUNCTION);
MutexLockGuard guard(file->fil_mutex, FB_FUNCTION);
for (jrd_file* file = main_file; file; file = file->fil_next)
if (file->fil_desc != -1)
{
if (file->fil_desc != -1)
{
// This really should be an error
fsync(file->fil_desc);
}
// This really should be an error
fsync(file->fil_desc);
}
#endif
}
@ -615,7 +565,7 @@ void PIO_header(thread_db* tdbb, UCHAR* address, int length)
static Firebird::InitInstance<ZeroBuffer> zeros;
USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* status_vector,
USHORT PIO_init_data(thread_db* tdbb, jrd_file* file, FbStatusVector* status_vector,
ULONG startPage, USHORT initPages)
{
/**************************************
@ -642,16 +592,14 @@ USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* statu
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
jrd_file* file = seek_file(main_file, &bdb, &offset, status_vector);
if (!file)
if (!seek_file(file, &bdb, &offset, status_vector))
return 0;
if (file->fil_min_page + 8 > startPage)
if (startPage < 8)
return 0;
USHORT leftPages = initPages;
const ULONG initBy = MIN(file->fil_max_page - startPage, leftPages);
const ULONG initBy = MIN(MAX_ULONG - startPage, leftPages);
if (initBy < leftPages)
leftPages = initBy;
@ -667,15 +615,16 @@ USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* statu
for (int r = 0; r < IO_RETRY; r++)
{
if (!(file = seek_file(file, &bdb, &offset, status_vector)))
return false;
if (!seek_file(file, &bdb, &offset, status_vector))
return 0;
if ((written = os_utils::pwrite(file->fil_desc, zero_buff, to_write, LSEEK_OFFSET_CAST offset)) == to_write)
break;
if (written < 0 && !SYSCALL_INTERRUPTED(errno))
return unix_error("write", file, isc_io_write_err, status_vector);
}
leftPages -= write_pages;
i += write_pages;
}
@ -812,7 +761,7 @@ bool PIO_read(thread_db* tdbb, jrd_file* file, BufferDesc* bdb, Ods::pag* page,
for (i = 0; i < IO_RETRY; i++)
{
if (!(file = seek_file(file, bdb, &offset, status_vector)))
if (!seek_file(file, bdb, &offset, status_vector))
return false;
if ((bytes = os_utils::pread(file->fil_desc, page, size, LSEEK_OFFSET_CAST offset)) == size)
@ -864,7 +813,7 @@ bool PIO_write(thread_db* tdbb, jrd_file* file, BufferDesc* bdb, Ods::pag* page,
for (i = 0; i < IO_RETRY; i++)
{
if (!(file = seek_file(file, bdb, &offset, status_vector)))
if (!seek_file(file, bdb, &offset, status_vector))
return false;
if ((bytes = os_utils::pwrite(file->fil_desc, page, size, LSEEK_OFFSET_CAST offset)) == size)
@ -881,8 +830,8 @@ bool PIO_write(thread_db* tdbb, jrd_file* file, BufferDesc* bdb, Ods::pag* page,
}
static jrd_file* seek_file(jrd_file* file, BufferDesc* bdb, FB_UINT64* offset,
FbStatusVector* status_vector)
static bool seek_file(jrd_file* file, BufferDesc* bdb, FB_UINT64* offset,
FbStatusVector* status_vector)
{
/**************************************
*
@ -891,43 +840,29 @@ static jrd_file* seek_file(jrd_file* file, BufferDesc* bdb, FB_UINT64* offset,
**************************************
*
* Functional description
* Given a buffer descriptor block, find the appropriate
* file block and seek to the proper page in that file.
* Given a buffer descriptor block, seek to the proper page in that file.
*
**************************************/
BufferControl* bcb = bdb->bdb_bcb;
Database* dbb = bcb->bcb_database;
ULONG page = bdb->bdb_page.getPageNum();
for (;; file = file->fil_next)
{
if (!file) {
CORRUPT(158); // msg 158 database file not available
}
else if (page >= file->fil_min_page && page <= file->fil_max_page)
break;
}
BufferControl* const bcb = bdb->bdb_bcb;
const ULONG page = bdb->bdb_page.getPageNum();
if (file->fil_desc == -1)
{
unix_error("lseek", file, isc_io_access_err, status_vector);
return 0;
return false;
}
page -= file->fil_min_page - file->fil_fudge;
FB_UINT64 lseek_offset = page;
lseek_offset *= dbb->dbb_page_size;
lseek_offset *= bcb->bcb_page_size;
if (lseek_offset != (FB_UINT64) LSEEK_OFFSET_CAST lseek_offset)
{
unix_error("lseek", file, isc_io_32bit_exceeded_err, status_vector);
return 0;
return false;
}
*offset = lseek_offset;
return file;
return true;
}
@ -999,7 +934,6 @@ static jrd_file* setup_file(Database* dbb, const PathName& file_name, int desc,
{
file = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
file->fil_desc = desc;
file->fil_max_page = MAX_ULONG;
file->fil_flags = flags;
strcpy(file->fil_string, file_name.c_str());
}

View File

@ -106,7 +106,7 @@ using namespace Firebird;
#define TEXT SCHAR
static bool maybeCloseFile(HANDLE&);
static jrd_file* seek_file(jrd_file*, BufferDesc*, OVERLAPPED*);
static bool seek_file(jrd_file*, BufferDesc*, OVERLAPPED*);
static jrd_file* setup_file(Database*, const Firebird::PathName&, HANDLE, USHORT);
static bool nt_error(const TEXT*, const jrd_file*, ISC_STATUS, FbStatusVector* const);
@ -121,39 +121,7 @@ static const DWORD g_dwExtraTempFlags = FILE_ATTRIBUTE_TEMPORARY |
FILE_FLAG_DELETE_ON_CLOSE;
int PIO_add_file(thread_db* tdbb, jrd_file* main_file, const Firebird::PathName& file_name, SLONG start)
{
/**************************************
*
* P I O _ a d d _ f i l e
*
**************************************
*
* Functional description
* Add a file to an existing database. Return the sequence
* number of the new file. If anything goes wrong, return a
* sequence of 0.
*
**************************************/
jrd_file* const new_file = PIO_create(tdbb, file_name, false, false);
if (!new_file)
return 0;
new_file->fil_min_page = start;
USHORT sequence = 1;
jrd_file* file;
for (file = main_file; file->fil_next; file = file->fil_next)
++sequence;
file->fil_max_page = start - 1;
file->fil_next = new_file;
return sequence;
}
void PIO_close(jrd_file* main_file)
void PIO_close(jrd_file* file)
{
/**************************************
*
@ -164,10 +132,7 @@ void PIO_close(jrd_file* main_file)
* Functional description
*
**************************************/
for (jrd_file* file = main_file; file; file = file->fil_next)
{
maybeCloseFile(file->fil_desc);
}
maybeCloseFile(file->fil_desc);
}
@ -251,7 +216,7 @@ bool PIO_expand(const TEXT* file_name, USHORT file_length, TEXT* expanded_name,
}
void PIO_extend(thread_db* tdbb, jrd_file* main_file, const ULONG extPages, const USHORT pageSize)
void PIO_extend(thread_db* tdbb, jrd_file* file, const ULONG extPages, const USHORT pageSize)
{
/**************************************
*
@ -263,6 +228,8 @@ void PIO_extend(thread_db* tdbb, jrd_file* main_file, const ULONG extPages, cons
* Extend file by extPages pages of pageSize size.
*
**************************************/
fb_assert(extPages);
// hvlad: prevent other reading\writing threads from changing file pointer.
// As we open file without FILE_FLAG_OVERLAPPED, ReadFile\WriteFile calls
// will change file pointer we set here and file truncation instead of file
@ -271,42 +238,30 @@ void PIO_extend(thread_db* tdbb, jrd_file* main_file, const ULONG extPages, cons
// and read\write activity performed simultaneously)
// if file have no extend lock it is better to not extend file than corrupt it
if (!main_file->fil_ext_lock)
if (!file->fil_ext_lock)
return;
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
FileExtendLockGuard extLock(main_file->fil_ext_lock, true);
FileExtendLockGuard extLock(file->fil_ext_lock, true);
ULONG leftPages = extPages;
for (jrd_file* file = main_file; file && leftPages; file = file->fil_next)
{
const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
const ULONG fileMaxPages = (file->fil_max_page == MAX_ULONG) ?
MAX_ULONG : file->fil_max_page - file->fil_min_page + 1;
if (filePages < fileMaxPages)
{
const ULONG extendBy = MIN(fileMaxPages - filePages + file->fil_fudge, leftPages);
const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
const ULONG extendBy = MIN(MAX_ULONG - filePages, extPages);
HANDLE hFile = file->fil_desc;
const HANDLE hFile = file->fil_desc;
LARGE_INTEGER newSize;
newSize.QuadPart = ((ULONGLONG) filePages + extendBy) * pageSize;
LARGE_INTEGER newSize;
newSize.QuadPart = ((ULONGLONG) filePages + extendBy) * pageSize;
const DWORD ret = SetFilePointer(hFile, newSize.LowPart, &newSize.HighPart, FILE_BEGIN);
if (ret == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
nt_error("SetFilePointer", file, isc_io_write_err, NULL);
}
if (!SetEndOfFile(hFile)) {
nt_error("SetEndOfFile", file, isc_io_write_err, NULL);
}
const DWORD ret = SetFilePointer(hFile, newSize.LowPart, &newSize.HighPart, FILE_BEGIN);
if (ret == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
nt_error("SetFilePointer", file, isc_io_write_err, NULL);
leftPages -= extendBy;
}
}
if (!SetEndOfFile(hFile))
nt_error("SetEndOfFile", file, isc_io_write_err, NULL);
}
void PIO_flush(thread_db* tdbb, jrd_file* main_file)
void PIO_flush(thread_db* tdbb, jrd_file* file)
{
/**************************************
*
@ -320,7 +275,7 @@ void PIO_flush(thread_db* tdbb, jrd_file* main_file)
**************************************/
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
for (jrd_file* file = main_file; file; file = file->fil_next)
if (file->fil_desc != INVALID_HANDLE_VALUE)
FlushFileBuffers(file->fil_desc);
}
@ -417,7 +372,7 @@ void PIO_header(thread_db* tdbb, UCHAR* address, int length)
static Firebird::InitInstance<ZeroBuffer> zeros;
USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* status_vector,
USHORT PIO_init_data(thread_db* tdbb, jrd_file* file, FbStatusVector* status_vector,
ULONG startPage, USHORT initPages)
{
/**************************************
@ -436,7 +391,7 @@ USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* statu
Database* const dbb = tdbb->getDatabase();
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
FileExtendLockGuard extLock(main_file->fil_ext_lock, false);
FileExtendLockGuard extLock(file->fil_ext_lock, false);
// Fake buffer, used in seek_file. Page space ID doesn't matter there
// as we already know file to work with
@ -444,16 +399,14 @@ USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* statu
bdb.bdb_page = PageNumber(0, startPage);
OVERLAPPED overlapped;
jrd_file* file = seek_file(main_file, &bdb, &overlapped);
if (!file)
if (!seek_file(file, &bdb, &overlapped))
return 0;
if (file->fil_min_page + 8 > startPage)
if (startPage < 8)
return 0;
USHORT leftPages = initPages;
const ULONG initBy = MIN(file->fil_max_page - startPage, leftPages);
const ULONG initBy = MIN(MAX_ULONG - startPage, leftPages);
if (initBy < leftPages)
leftPages = initBy;
@ -464,8 +417,8 @@ USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* statu
if (write_pages > leftPages)
write_pages = leftPages;
jrd_file* file1 = seek_file(main_file, &bdb, &overlapped);
fb_assert(file1 == file);
if (!seek_file(file, &bdb, &overlapped))
return 0;
const DWORD to_write = (DWORD) write_pages * dbb->dbb_page_size;
DWORD written;
@ -590,7 +543,7 @@ bool PIO_read(thread_db* tdbb, jrd_file* file, BufferDesc* bdb, Ods::pag* page,
FileExtendLockGuard extLock(file->fil_ext_lock, false);
OVERLAPPED overlapped;
if (!(file = seek_file(file, bdb, &overlapped)))
if (!seek_file(file, bdb, &overlapped))
return false;
HANDLE desc = file->fil_desc;
@ -625,14 +578,12 @@ bool PIO_read_ahead(thread_db* tdbb,
**************************************
*
* Functional description
* Read a contiguous set of pages. The only
* tricky part is to segment the I/O when crossing
* file boundaries.
* Read a contiguous set of pages.
*
**************************************/
OVERLAPPED overlapped, *overlapped_ptr;
Database* const dbb = tdbb->getDatabase();
const auto dbb = tdbb->getDatabase();
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
@ -647,60 +598,45 @@ bool PIO_read_ahead(thread_db* tdbb,
piob->piob_flags = 0;
}
// Setup up a dummy buffer descriptor block for seeking file
BufferDesc bdb;
while (pages)
bdb.bdb_dbb = dbb;
bdb.bdb_page = start_page;
const jrd_file* const file = dbb->dbb_file;
if (!seek_file(file, &bdb, status_vector, overlapped_ptr, &overlapped_ptr))
return false;
const HANDLE desc = file->fil_desc;
const DWORD length = pages * dbb->dbb_page_size;
DWORD actual_length;
if (ReadFile(desc, buffer, length, &actual_length, overlapped_ptr) &&
actual_length == length)
{
// Setup up a dummy buffer descriptor block for seeking file.
bdb.bdb_dbb = dbb;
bdb.bdb_page = start_page;
jrd_file* file = seek_file(dbb->dbb_file, &bdb, status_vector, overlapped_ptr, &overlapped_ptr);
if (!file)
return false;
// Check that every page within the set resides in the same database
// file. If not read what you can and loop back for the rest.
DWORD segmented_length = 0;
while (pages && start_page >= file->fil_min_page && start_page <= file->fil_max_page)
{
segmented_length += dbb->dbb_page_size;
++start_page;
--pages;
}
HANDLE desc = file->fil_desc;
DWORD actual_length;
if (ReadFile(desc, buffer, segmented_length, &actual_length, overlapped_ptr) &&
actual_length == segmented_length)
{
if (piob && !pages)
piob->piob_flags = PIOB_success;
}
else if (piob && !pages)
{
piob->piob_flags = PIOB_pending;
piob->piob_desc = reinterpret_cast<SLONG>(desc);
piob->piob_file = file;
piob->piob_io_length = segmented_length;
}
else if (!GetOverlappedResult(desc, overlapped_ptr, &actual_length, TRUE) ||
actual_length != segmented_length)
{
if (piob)
piob->piob_flags = PIOB_error;
release_io_event(file, overlapped_ptr);
return nt_error("GetOverlappedResult", file, isc_io_read_err, status_vector);
}
if (!piob || (piob->piob_flags & (PIOB_success | PIOB_error)))
release_io_event(file, overlapped_ptr);
buffer += segmented_length;
if (piob)
piob->piob_flags = PIOB_success;
}
else if (piob)
{
piob->piob_flags = PIOB_pending;
piob->piob_desc = reinterpret_cast<SLONG>(desc);
piob->piob_file = file;
piob->piob_io_length = segmented_length;
}
else if (!GetOverlappedResult(desc, overlapped_ptr, &actual_length, TRUE) ||
actual_length != length)
{
if (piob)
piob->piob_flags = PIOB_error;
release_io_event(file, overlapped_ptr);
return nt_error("GetOverlappedResult", file, isc_io_read_err, status_vector);
}
if (!piob || (piob->piob_flags & (PIOB_success | PIOB_error)))
release_io_event(file, overlapped_ptr);
return true;
}
@ -767,8 +703,7 @@ bool PIO_write(thread_db* tdbb, jrd_file* file, BufferDesc* bdb, Ods::pag* page,
FileExtendLockGuard extLock(file->fil_ext_lock, false);
OVERLAPPED overlapped;
file = seek_file(file, bdb, &overlapped);
if (!file)
if (!seek_file(file, bdb, &overlapped))
return false;
HANDLE desc = file->fil_desc;
@ -813,9 +748,7 @@ ULONG PIO_get_number_of_pages(const jrd_file* file, const USHORT pagesize)
}
static jrd_file* seek_file(jrd_file* file,
BufferDesc* bdb,
OVERLAPPED* overlapped)
static bool seek_file(jrd_file* file, BufferDesc* bdb, OVERLAPPED* overlapped)
{
/**************************************
*
@ -824,24 +757,11 @@ static jrd_file* seek_file(jrd_file* file,
**************************************
*
* Functional description
* Given a buffer descriptor block, find the appropriate
* file block and seek to the proper page in that file.
* Given a buffer descriptor block, seek to the proper page in that file.
*
**************************************/
BufferControl *bcb = bdb->bdb_bcb;
ULONG page = bdb->bdb_page.getPageNum();
for (;; file = file->fil_next)
{
if (!file) {
CORRUPT(158); // msg 158 database file not available
}
else if (page >= file->fil_min_page && page <= file->fil_max_page) {
break;
}
}
page -= file->fil_min_page - file->fil_fudge;
BufferControl* const bcb = bdb->bdb_bcb;
const ULONG page = bdb->bdb_page.getPageNum();
LARGE_INTEGER liOffset;
liOffset.QuadPart = UInt32x32To64((DWORD) page, (DWORD) bcb->bcb_page_size);
@ -854,7 +774,7 @@ static jrd_file* seek_file(jrd_file* file,
ThreadSync* thd = ThreadSync::getThread(FB_FUNCTION);
overlapped->hEvent = thd->getIOEvent();
return file;
return true;
}
@ -876,7 +796,6 @@ static jrd_file* setup_file(Database* dbb, const Firebird::PathName& file_name,
{
file = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
file->fil_desc = desc;
file->fil_max_page = MAX_ULONG;
file->fil_flags = flags;
strcpy(file->fil_string, file_name.c_str());

View File

@ -364,115 +364,6 @@ namespace
} // namespace
USHORT PAG_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start)
{
/**************************************
*
* P A G _ a d d _ f i l e
*
**************************************
*
* Functional description
* Add a file to the current database. Return the sequence number for the new file.
*
**************************************/
SET_TDBB(tdbb);
ensureDbWritable(tdbb);
const auto dbb = tdbb->getDatabase();
// Find current last file
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
jrd_file* file = pageSpace->file;
while (file->fil_next) {
file = file->fil_next;
}
// Verify database file path against DatabaseAccess entry of firebird.conf
if (!JRD_verify_database_access(file_name))
{
string fileName(file_name);
ISC_systemToUtf8(fileName);
ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("additional database file") <<
Arg::Str(fileName));
}
// Create the file. If the sequence number comes back zero, it didn't work, so punt
const USHORT sequence = PIO_add_file(tdbb, pageSpace->file, file_name, start);
if (!sequence)
return 0;
// Create header page for new file
jrd_file* next = file->fil_next;
WIN window(DB_PAGE_SPACE, next->fil_min_page);
header_page* header = (header_page*) CCH_fake(tdbb, &window, 1);
header->hdr_header.pag_type = pag_header;
header->hdr_sequence = sequence;
header->hdr_page_size = dbb->dbb_page_size;
header->hdr_data[0] = HDR_end;
header->hdr_end = HDR_SIZE;
next->fil_sequence = sequence;
#ifdef SUPPORT_RAW_DEVICES
// The following lines (taken from PAG_format_header) are needed to identify
// this file in raw_devices_validate_database as a valid database attachment.
*(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentGmtTimeStamp().utc_timestamp;
// should we include milliseconds or not?
//TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0);
header->hdr_ods_version = ODS_VERSION | ODS_FIREBIRD_FLAG;
DbImplementation::current.store(header);
header->hdr_ods_minor = ODS_CURRENT;
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3)
header->hdr_flags |= hdr_SQL_dialect_3;
#endif
header->hdr_header.pag_pageno = window.win_page.getPageNum();
// It's header, never encrypted
PIO_write(tdbb, pageSpace->file, window.win_bdb, window.win_buffer, tdbb->tdbb_status_vector);
CCH_RELEASE(tdbb, &window);
next->fil_fudge = 1;
// Update the previous header page to point to new file
file->fil_fudge = 0;
window.win_page = file->fil_min_page;
header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
if (!file->fil_min_page)
CCH_MARK_MUST_WRITE(tdbb, &window);
else
CCH_MARK(tdbb, &window);
--start;
if (file->fil_min_page)
{
PAG_add_header_entry(tdbb, header, HDR_file, static_cast<USHORT>(strlen(file_name)),
reinterpret_cast<const UCHAR*>(file_name));
PAG_add_header_entry(tdbb, header, HDR_last_page, sizeof(SLONG), (UCHAR*) &start);
}
else
{
storeClump(tdbb, HDR_file, static_cast<USHORT>(strlen(file_name)),
reinterpret_cast<const UCHAR*>(file_name));
storeClump(tdbb, HDR_last_page, sizeof(SLONG), (UCHAR*) &start);
}
header->hdr_header.pag_pageno = window.win_page.getPageNum();
// It's header, never encrypted
PIO_write(tdbb, pageSpace->file, window.win_bdb, window.win_buffer, tdbb->tdbb_status_vector);
CCH_RELEASE(tdbb, &window);
if (file->fil_min_page)
file->fil_fudge = 1;
return sequence;
}
void PAG_add_header_entry(thread_db* tdbb, header_page* header,
USHORT type, USHORT len, const UCHAR* entry)
{
@ -1136,8 +1027,7 @@ void PAG_header(thread_db* tdbb, bool info, const TriState newForceWrite)
// Ensure the file-level FW mode matches the actual FW mode in the database
const auto pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
for (jrd_file* file = pageSpace->file; file; file = file->fil_next)
PIO_force_write(file, forceWrite && !readOnly);
PIO_force_write(pageSpace->file, forceWrite && !readOnly);
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
dbb->dbb_backup_manager->setForcedWrites(forceWrite);
@ -1327,7 +1217,7 @@ void PAG_init(thread_db* tdbb)
}
void PAG_init2(thread_db* tdbb, USHORT shadow_number)
void PAG_init2(thread_db* tdbb)
{
/**************************************
*
@ -1336,128 +1226,40 @@ void PAG_init2(thread_db* tdbb, USHORT shadow_number)
**************************************
*
* Functional description
* Perform second phase of page initialization -- the eternal
* search for additional files.
* Read and apply the database header options.
*
**************************************/
SET_TDBB(tdbb);
const auto dbb = tdbb->getDatabase();
FbStatusVector* status = tdbb->tdbb_status_vector;
WIN window(HEADER_PAGE_NUMBER);
const auto header = (header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
// allocate a spare buffer which is large enough,
// and set up to release it in case of error. Align
// the temporary page buffer for raw disk access.
Array<UCHAR> temp;
UCHAR* const temp_page = temp.getAlignedBuffer(dbb->dbb_page_size, dbb->getIOBlockSize());
PageSpace* const pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
jrd_file* file = pageSpace->file;
if (shadow_number)
for (const UCHAR* p = header->hdr_data; *p != HDR_end; p += 2 + p[1])
{
Shadow* shadow = dbb->dbb_shadow;
for (; shadow; shadow = shadow->sdw_next)
switch (*p)
{
if (shadow->sdw_number == shadow_number)
{
file = shadow->sdw_file;
break;
}
}
if (!shadow)
BUGCHECK(161); // msg 161 shadow block not found
}
USHORT sequence = 1;
WIN window(DB_PAGE_SPACE, -1);
// Loop thru files and header pages until everything is open
while (true)
{
window.win_page = file->fil_min_page;
ULONG last_page = 0;
BufferDesc temp_bdb(dbb->dbb_bcb);
// note that we do not have to get a read lock on
// the header page (except for header page 0) because
// the only time it will be modified is when adding a file,
// which must be done with an exclusive lock on the database --
// if this changes, this policy will have to be reevaluated;
// at any rate there is a problem with getting a read lock
// because the corresponding page in the main database file may not exist
if (!file->fil_min_page)
CCH_FETCH(tdbb, &window, LCK_read, pag_header);
header_page* header = (header_page*) temp_page;
temp_bdb.bdb_buffer = (pag*) header;
temp_bdb.bdb_page = window.win_page;
// Read the required page into the local buffer
// It's header, never encrypted
PIO_read(tdbb, file, &temp_bdb, (PAG) header, status);
if (shadow_number && !file->fil_min_page)
CCH_RELEASE(tdbb, &window);
PathName nextFileName;
for (const UCHAR* p = header->hdr_data; *p != HDR_end; p += 2 + p[1])
{
switch (*p)
{
case HDR_file:
nextFileName.assign(p + 2, p[1]);
break;
case HDR_last_page:
fb_assert(p[1] == sizeof(last_page));
memcpy(&last_page, p + 2, sizeof(last_page));
break;
case HDR_sweep_interval:
fb_assert(p[1] == sizeof(SLONG));
memcpy(&dbb->dbb_sweep_interval, p + 2, sizeof(SLONG));
break;
case HDR_db_guid:
fb_assert(p[1] == Guid::SIZE);
dbb->dbb_guid = Guid(p + 2);
break;
case HDR_repl_seq:
fb_assert(p[1] == sizeof(FB_UINT64));
memcpy(&dbb->dbb_repl_sequence, p + 2, sizeof(FB_UINT64));
break;
}
}
if (!shadow_number && !file->fil_min_page)
CCH_RELEASE(tdbb, &window);
if (file->fil_min_page)
file->fil_fudge = 1;
if (nextFileName.isEmpty())
case HDR_sweep_interval:
fb_assert(p[1] == sizeof(SLONG));
memcpy(&dbb->dbb_sweep_interval, p + 2, sizeof(SLONG));
break;
// Verify database file path against DatabaseAccess entry of firebird.conf
if (!JRD_verify_database_access(nextFileName))
{
ISC_systemToUtf8(nextFileName);
ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("additional database file") <<
Arg::Str(nextFileName));
case HDR_db_guid:
fb_assert(p[1] == Guid::SIZE);
dbb->dbb_guid = Guid(p + 2);
break;
case HDR_repl_seq:
fb_assert(p[1] == sizeof(FB_UINT64));
memcpy(&dbb->dbb_repl_sequence, p + 2, sizeof(FB_UINT64));
break;
default:
break;
}
file->fil_next = PIO_open(tdbb, nextFileName, nextFileName);
file->fil_max_page = last_page;
file = file->fil_next;
file->fil_min_page = last_page + 1;
file->fil_sequence = sequence++;
}
CCH_RELEASE(tdbb, &window);
}
@ -1644,14 +1446,10 @@ void PAG_set_force_write(thread_db* tdbb, bool flag)
CCH_RELEASE(tdbb, &window);
PageSpace* const pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
for (jrd_file* file = pageSpace->file; file; file = file->fil_next)
PIO_force_write(file, flag);
PIO_force_write(pageSpace->file, flag);
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
{
for (jrd_file* file = shadow->sdw_file; file; file = file->fil_next)
PIO_force_write(file, flag);
}
PIO_force_write(shadow->sdw_file, flag);
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
dbb->dbb_backup_manager->setForcedWrites(flag);
@ -1917,13 +1715,7 @@ PageSpace::~PageSpace()
if (file)
{
PIO_close(file);
while (file)
{
jrd_file* next = file->fil_next;
delete file;
file = next;
}
delete file;
}
}
@ -1936,15 +1728,7 @@ ULONG PageSpace::actAlloc()
*
**************************************/
// Traverse the linked list of files and add up the
// number of pages in each file
const USHORT pageSize = dbb->dbb_page_size;
ULONG tot_pages = 0;
for (const jrd_file* f = file; f != NULL; f = f->fil_next) {
tot_pages += PIO_get_number_of_pages(f, pageSize);
}
return tot_pages;
return PIO_get_number_of_pages(file, dbb->dbb_page_size);
}
ULONG PageSpace::actAlloc(const Database* dbb)
@ -1961,17 +1745,7 @@ ULONG PageSpace::maxAlloc()
* Compute last physically allocated page of database.
*
**************************************/
const USHORT pageSize = dbb->dbb_page_size;
const jrd_file* f = file;
ULONG nPages = PIO_get_number_of_pages(f, pageSize);
while (f->fil_next && nPages == f->fil_max_page - f->fil_min_page + 1 + f->fil_fudge)
{
f = f->fil_next;
nPages = PIO_get_number_of_pages(f, pageSize);
}
nPages += f->fil_min_page - f->fil_fudge;
const ULONG nPages = PIO_get_number_of_pages(file, dbb->dbb_page_size);
if (maxPageNumber < nPages)
maxPageNumber = nPages;
@ -1987,15 +1761,7 @@ ULONG PageSpace::maxAlloc(const Database* dbb)
bool PageSpace::onRawDevice() const
{
#ifdef SUPPORT_RAW_DEVICES
for (const jrd_file* f = file; f != NULL; f = f->fil_next)
{
if (f->fil_flags & FIL_raw_device)
return true;
}
#endif
return false;
return (file->fil_flags & FIL_raw_device) != 0;
}
ULONG PageSpace::lastUsedPage()

View File

@ -37,7 +37,6 @@ namespace Ods {
struct header_page;
}
USHORT PAG_add_file(Jrd::thread_db* tdbb, const TEXT*, SLONG);
void PAG_add_header_entry(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*);
bool PAG_replace_entry_first(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*);
Ods::pag* PAG_allocate_pages(Jrd::thread_db* tdbb, Jrd::win* window, unsigned cntAlloc, bool aligned);
@ -49,7 +48,7 @@ bool PAG_get_clump(Jrd::thread_db*, USHORT, USHORT*, UCHAR*);
void PAG_header(Jrd::thread_db*, bool, const Firebird::TriState newForceWrite = Firebird::TriState());
void PAG_header_init(Jrd::thread_db*);
void PAG_init(Jrd::thread_db*);
void PAG_init2(Jrd::thread_db*, USHORT);
void PAG_init2(Jrd::thread_db*);
SLONG PAG_last_page(Jrd::thread_db* tdbb);
void PAG_release_page(Jrd::thread_db* tdbb, const Jrd::PageNumber&, const Jrd::PageNumber&);
void PAG_release_pages(Jrd::thread_db* tdbb, USHORT pageSpaceID, int cntRelease,

View File

@ -64,7 +64,6 @@ static bool check_for_file(thread_db* tdbb, const SCHAR*, USHORT);
#ifdef NOT_USED_OR_REPLACED
static void check_if_got_ast(thread_db* tdbb, jrd_file*);
#endif
static void copy_header(thread_db* tdbb);
static void update_dbb_to_sdw(Database*);
@ -112,147 +111,6 @@ void SDW_add(thread_db* tdbb, const TEXT* file_name, USHORT shadow_number, USHOR
}
int SDW_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start, USHORT shadow_number)
{
/**************************************
*
* S D W _ a d d _ f i l e
*
**************************************
*
* Functional description
* Add a file to a shadow set.
* Return the sequence number for the new file.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_add_file");
// Find the file to be extended
jrd_file* shadow_file = 0;
Shadow* shadow;
for (shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
{
if ((shadow->sdw_number == shadow_number) &&
!(shadow->sdw_flags & (SDW_IGNORE | SDW_rollover)))
{
shadow_file = shadow->sdw_file;
break;
}
}
if (!shadow) {
return 0;
}
// find the last file in the list, open the new file
jrd_file* file = shadow_file;
while (file->fil_next) {
file = file->fil_next;
}
// Verify shadow file path against DatabaseAccess entry of firebird.conf
if (!JRD_verify_database_access(file_name))
{
ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("database shadow") <<
Arg::Str(file_name));
}
const SLONG sequence = PIO_add_file(tdbb, shadow_file, file_name, start);
if (!sequence)
return 0;
jrd_file* next = file->fil_next;
// Always write the header page, even for a conditional
// shadow that hasn't been activated.
// allocate a spare buffer which is large enough,
// and set up to release it in case of error. Align
// the spare page buffer for raw disk access.
Array<UCHAR> temp;
UCHAR* const spare_page = temp.getAlignedBuffer(dbb->dbb_page_size, dbb->getIOBlockSize());
// create the header using the spare_buffer
header_page* header = (header_page*) spare_page;
header->hdr_header.pag_type = pag_header;
header->hdr_sequence = sequence;
header->hdr_page_size = dbb->dbb_page_size;
header->hdr_data[0] = HDR_end;
header->hdr_end = HDR_SIZE;
// fool PIO_write into writing the scratch page into the correct place
BufferDesc temp_bdb(dbb->dbb_bcb);
temp_bdb.bdb_page = next->fil_min_page;
temp_bdb.bdb_buffer = (PAG) header;
header->hdr_header.pag_pageno = temp_bdb.bdb_page.getPageNum();
// It's header, never encrypted
if (!PIO_write(tdbb, shadow_file, &temp_bdb, reinterpret_cast<Ods::pag*>(header), 0))
return 0;
next->fil_fudge = 1;
// Update the previous header page to point to new file --
// we can use the same header page, suitably modified,
// because they all look pretty much the same at this point
/*******************
Fix for bug 7925. drop_gdb wan not dropping secondary file in
multi-shadow files. The structure was not being filled with the
info. Commented some code so that the structure will always be filled.
-Sudesh 07/06/95
The original code :
===
if (shadow_file == file)
copy_header(tdbb);
else
===
************************/
// Temporarly reverting the change ------- Sudesh 07/07/95 *******
if (shadow_file == file)
{
copy_header(tdbb);
}
else
{
--start;
header->hdr_data[0] = HDR_end;
header->hdr_end = HDR_SIZE;
PAG_add_header_entry(tdbb, header, HDR_file, static_cast<USHORT>(strlen(file_name)),
reinterpret_cast<const UCHAR*>(file_name));
PAG_add_header_entry(tdbb, header, HDR_last_page, sizeof(start),
reinterpret_cast<const UCHAR*>(&start));
file->fil_fudge = 0;
temp_bdb.bdb_page = file->fil_min_page;
header->hdr_header.pag_pageno = temp_bdb.bdb_page.getPageNum();
// It's header, never encrypted
if (!PIO_write(tdbb, shadow_file, &temp_bdb, reinterpret_cast<Ods::pag*>(header), 0))
return 0;
if (file->fil_min_page) {
file->fil_fudge = 1;
}
}
if (file->fil_min_page) {
file->fil_fudge = 1;
}
return sequence;
}
void SDW_check(thread_db* tdbb)
{
/**************************************
@ -814,12 +672,7 @@ bool SDW_rollover_to_shadow(thread_db* tdbb, jrd_file* file, const bool inAst)
// close the main database file if possible and release all file blocks
PIO_close(pageSpace->file);
while ( (file = pageSpace->file) )
{
pageSpace->file = file->fil_next;
delete file;
}
delete pageSpace->file;
/* point the main database file at the file of the first shadow
in the list and mark that shadow as rolled over to
@ -894,13 +747,7 @@ static void shutdown_shadow(Shadow* shadow)
// close the shadow files and free up the associated memory
PIO_close(shadow->sdw_file);
jrd_file* file;
jrd_file* free = shadow->sdw_file;
for (; (file = free->fil_next); free = file)
delete free;
delete free;
delete shadow->sdw_file;
delete shadow;
}
@ -1003,12 +850,6 @@ void SDW_start(thread_db* tdbb, const TEXT* file_name,
const header_page* shadow_header = (header_page*) spare_page;
// NOTE ! NOTE! NOTE!
// Starting V4.0, header pages can have overflow pages. For the shadow,
// we are making an assumption that the shadow header page will not
// overflow, as the only things written on a shadow header is the
// HDR_root_file_name, HDR_file, and HDR_last_page
const UCHAR* p = shadow_header->hdr_data;
while (*p != HDR_end && *p != HDR_root_file_name) {
p += 2 + p[1];
@ -1046,10 +887,6 @@ void SDW_start(thread_db* tdbb, const TEXT* file_name,
shadow->sdw_flags |= SDW_dumped;
}
// get the ancillary files and reset the error environment
PAG_init2(tdbb, shadow_number);
} // try
catch (const Firebird::Exception& ex)
{
@ -1257,35 +1094,6 @@ static void check_if_got_ast(thread_db* tdbb, jrd_file* file)
}
#endif
static void copy_header(thread_db* tdbb)
{
/**************************************
*
* c o p y _ h e a d e r
*
**************************************
*
* Functional description
* Fetch the header page from the database
* and write it to the shadow file. This is
* done so that if this shadow is extended,
* the header page will be there for writing
* the name of the extend file.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
// get the database header page and write it out --
// CCH will take care of modifying it
WIN window(HEADER_PAGE_NUMBER);
CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK_MUST_WRITE(tdbb, &window);
CCH_RELEASE(tdbb, &window);
}
static void update_dbb_to_sdw(Database* dbb)
{
@ -1319,13 +1127,7 @@ static void update_dbb_to_sdw(Database* dbb)
// hvlad: need sync for this code
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
PIO_close(pageSpace->file);
jrd_file* file;
while ( (file = pageSpace->file) )
{
pageSpace->file = file->fil_next;
delete file;
}
delete pageSpace->file;
pageSpace->file = shadow->sdw_file;
shadow->sdw_flags |= SDW_rollover;

View File

@ -29,7 +29,6 @@ namespace Jrd {
}
void SDW_add(Jrd::thread_db* tdbb, const TEXT*, USHORT, USHORT);
int SDW_add_file(Jrd::thread_db* tdbb, const TEXT*, SLONG, USHORT);
void SDW_check(Jrd::thread_db* tdbb);
bool SDW_check_conditional(Jrd::thread_db* tdbb);
void SDW_close();

View File

@ -478,7 +478,6 @@ enum dfw_t {
dfw_create_index,
dfw_delete_index,
dfw_compute_security,
dfw_add_file,
dfw_add_shadow,
dfw_delete_shadow,
dfw_delete_shadow_nodelete,

View File

@ -2240,27 +2240,32 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
case rel_files:
protect_system_table_delupd(tdbb, relation, "DELETE");
{
const bool name_defined = EVL_field(0, rpb->rpb_record, f_file_name, &desc);
const USHORT file_flags = EVL_field(0, rpb->rpb_record, f_file_flags, &desc2) ?
const bool nameDefined = EVL_field(0, rpb->rpb_record, f_file_name, &desc);
const auto shadowNumber = EVL_field(0, rpb->rpb_record, f_file_shad_num, &desc2) ?
MOV_get_long(tdbb, &desc2, 0) : 0;
if (file_flags & FILE_difference)
const auto fileFlags = EVL_field(0, rpb->rpb_record, f_file_flags, &desc2) ?
MOV_get_long(tdbb, &desc2, 0) : 0;
if (shadowNumber)
{
if (file_flags & FILE_backing_up)
DFW_post_work(transaction, dfw_end_backup, &desc, 0);
if (name_defined)
DFW_post_work(transaction, dfw_delete_difference, &desc, 0);
}
else if (EVL_field(0, rpb->rpb_record, f_file_shad_num, &desc2) &&
(id = MOV_get_long(tdbb, &desc2, 0)))
{
if (!(file_flags & FILE_inactive))
if (!(fileFlags & FILE_inactive))
{
if (file_flags & FILE_nodelete)
DFW_post_work(transaction, dfw_delete_shadow_nodelete, &desc, id);
else
DFW_post_work(transaction, dfw_delete_shadow, &desc, id);
const auto work = (fileFlags & FILE_nodelete) ?
dfw_delete_shadow_nodelete : dfw_delete_shadow;
DFW_post_work(transaction, work, &desc, shadowNumber);
}
}
else if (fileFlags & FILE_difference)
{
if (fileFlags & FILE_backing_up)
DFW_post_work(transaction, dfw_end_backup, &desc, 0);
if (nameDefined)
DFW_post_work(transaction, dfw_delete_difference, &desc, 0);
}
}
break;
@ -3617,18 +3622,24 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
case rel_files:
protect_system_table_delupd(tdbb, relation, "UPDATE");
{
SSHORT new_rel_flags, old_rel_flags;
EVL_field(0, new_rpb->rpb_record, f_file_name, &desc1);
if (EVL_field(0, new_rpb->rpb_record, f_file_flags, &desc2) &&
((new_rel_flags = MOV_get_long(tdbb, &desc2, 0)) & FILE_difference) &&
EVL_field(0, org_rpb->rpb_record, f_file_flags, &desc2) &&
((old_rel_flags = MOV_get_long(tdbb, &desc2, 0)) != new_rel_flags))
const auto orgFileFlags = EVL_field(0, org_rpb->rpb_record, f_file_flags, &desc2) ?
MOV_get_long(tdbb, &desc2, 0) : 0;
const auto newFileFlags = EVL_field(0, new_rpb->rpb_record, f_file_flags, &desc2) ?
MOV_get_long(tdbb, &desc2, 0) : 0;
if ((newFileFlags & FILE_difference) && orgFileFlags != newFileFlags)
{
DFW_post_work(transaction,
(new_rel_flags & FILE_backing_up ? dfw_begin_backup : dfw_end_backup),
(newFileFlags & FILE_backing_up) ? dfw_begin_backup : dfw_end_backup,
&desc1, 0);
}
}
// Nullify the unsupported fields
new_rpb->rpb_record->setNull(f_file_seq);
new_rpb->rpb_record->setNull(f_file_start);
new_rpb->rpb_record->setNull(f_file_length);
break;
case rel_charsets:
@ -4175,34 +4186,32 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
case rel_files:
protect_system_table_insert(tdbb, request, relation);
{
const bool name_defined = EVL_field(0, rpb->rpb_record, f_file_name, &desc);
if (EVL_field(0, rpb->rpb_record, f_file_shad_num, &desc2) &&
MOV_get_long(tdbb, &desc2, 0))
const bool nameDefined = EVL_field(0, rpb->rpb_record, f_file_name, &desc);
const auto shadowNumber = EVL_field(0, rpb->rpb_record, f_file_shad_num, &desc2) ?
MOV_get_long(tdbb, &desc2, 0) : 0;
const auto fileFlags = EVL_field(0, rpb->rpb_record, f_file_flags, &desc2) ?
MOV_get_long(tdbb, &desc2, 0) : 0;
if (shadowNumber)
{
EVL_field(0, rpb->rpb_record, f_file_flags, &desc2);
if (!(MOV_get_long(tdbb, &desc2, 0) & FILE_inactive)) {
if (!(fileFlags & FILE_inactive))
DFW_post_work(transaction, dfw_add_shadow, &desc, 0);
}
}
else
else if (fileFlags & FILE_difference)
{
USHORT rel_flags;
if (EVL_field(0, rpb->rpb_record, f_file_flags, &desc2) &&
((rel_flags = MOV_get_long(tdbb, &desc2, 0)) & FILE_difference))
{
if (name_defined) {
DFW_post_work(transaction, dfw_add_difference, &desc, 0);
}
if (rel_flags & FILE_backing_up)
{
DFW_post_work(transaction, dfw_begin_backup, &desc, 0);
}
}
else {
DFW_post_work(transaction, dfw_add_file, &desc, 0);
}
if (nameDefined)
DFW_post_work(transaction, dfw_add_difference, &desc, 0);
if (fileFlags & FILE_backing_up)
DFW_post_work(transaction, dfw_begin_backup, &desc, 0);
}
}
// Nullify the unsupported fields
rpb->rpb_record->setNull(f_file_seq);
rpb->rpb_record->setNull(f_file_start);
rpb->rpb_record->setNull(f_file_length);
break;
case rel_triggers:

View File

@ -164,10 +164,6 @@ struct dba_rel
struct dba_fil
{
dba_fil* fil_next; // Next file in database
ULONG fil_min_page; // Minimum page number in file
ULONG fil_max_page; // Maximum page number in file
USHORT fil_fudge; // Fudge factor for page relocation
#ifdef WIN_NT
void *fil_desc;
#else
@ -216,16 +212,6 @@ static void print_help();
#include "../utilities/gstat/dba_proto.h"
struct open_files
{
#ifdef WIN_NT
void* desc;
#else
int desc;
#endif
open_files* open_files_next;
};
struct dba_mem
{
char* memory;
@ -241,7 +227,7 @@ public:
: ThreadData(tddDBA), uSvc(us)
{
//dba_throw = false;
files = 0;
file = 0;
relations = 0;
page_size = 0;
dp_per_pp = 0;
@ -252,14 +238,13 @@ public:
global_buffer = 0;
exit_code = 0;
head_of_mem_list = 0;
head_of_files_list = 0;
memset(dba_status_vector, 0, sizeof (dba_status_vector));
dba_status = dba_status_vector;
}
//bool dba_throw;
Firebird::UtilSvc* uSvc;
dba_fil* files;
dba_fil* file;
dba_rel* relations;
USHORT page_size;
USHORT dp_per_pp;
@ -270,7 +255,6 @@ public:
pag* global_buffer;
int exit_code;
dba_mem *head_of_mem_list;
open_files *head_of_files_list;
ISC_STATUS *dba_status;
ISC_STATUS_ARRAY dba_status_vector;
@ -613,7 +597,7 @@ int gstat(Firebird::UtilSvc* uSvc)
expandDatabaseName(fileName, tempStr, NULL);
fileName = tempStr;
dba_fil* current = db_open(fileName.c_str(), fileName.length());
dba_fil* file = db_open(fileName.c_str(), fileName.length());
alignas(DIRECT_IO_BLOCK_SIZE) SCHAR temp[MAX(RAW_HEADER_SIZE, DIRECT_IO_BLOCK_SIZE)];
tddba->page_size = MAX(RAW_HEADER_SIZE, DIRECT_IO_BLOCK_SIZE);
@ -661,38 +645,6 @@ int gstat(Firebird::UtilSvc* uSvc)
if (sw_header)
dba_exit(FINI_OK, tddba);
// gather continuation files
while (true)
{
if (page != HEADER_PAGE)
{
current = db_open(file_name, static_cast<USHORT>(strlen(file_name)));
header = (const header_page*) db_read(page);
}
if (current != tddba->files)
current->fil_fudge = 1; // ignore header page once read it
PathName nextFileName;
const UCHAR* vp = header->hdr_data;
for (const auto vend = reinterpret_cast<const UCHAR*>(header) + header->hdr_page_size;
vp < vend && *vp != HDR_end; vp += 2 + vp[1])
{
if (*vp == HDR_file)
nextFileName.assign(vp + 2, vp[1]);
if (*vp == HDR_last_page)
memcpy(&current->fil_max_page, vp + 2, sizeof(current->fil_max_page));
}
if (nextFileName.isEmpty())
break;
page = current->fil_max_page + 1; // first page of next file
}
if (sw_enc)
{
class Statist
@ -724,6 +676,7 @@ int gstat(Firebird::UtilSvc* uSvc)
private:
ULONG enc, non;
};
Statist data, index, blob, generator, other;
ULONG last = lastUsedPage(header->hdr_page_size);
@ -766,18 +719,6 @@ int gstat(Firebird::UtilSvc* uSvc)
dba_exit(FINI_OK, tddba);
}
// print continuation file sequence
dba_print(false, 7);
// msg 7: \n\nDatabase file sequence:
for (current = tddba->files; current->fil_next; current = current->fil_next)
{
dba_print(false, 8, SafeArg() << current->fil_string << current->fil_next->fil_string);
// msg 8: File %s continues as file %s
}
dba_print(false, 9, SafeArg() << current->fil_string << ((current == tddba->files) ? "only" : "last"));
// msg 9: File %s is the %s file\n
// Check to make sure that the user accessing the database is either
// SYSDBA or owner of the database
@ -1192,22 +1133,11 @@ int gstat(Firebird::UtilSvc* uSvc)
alloced = alloced->mem_next;
}
// close files
open_files* open_file = tddba->head_of_files_list;
while (open_file)
{
db_close(open_file->desc);
open_file = open_file->open_files_next;
}
// close file
if (tddba->file)
db_close(tddba->file->fil_desc);
// free linked lists
while (tddba->head_of_files_list != 0)
{
open_files* tmp1 = tddba->head_of_files_list;
tddba->head_of_files_list = tddba->head_of_files_list->open_files_next;
delete tmp1;
}
while (tddba->head_of_mem_list != 0)
{
dba_mem* tmp2 = tddba->head_of_mem_list;
@ -1865,29 +1795,12 @@ static dba_fil* db_open(const char* file_name, USHORT file_length)
**************************************/
tdba* tddba = tdba::getSpecific();
dba_fil* fil;
const auto file = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
if (tddba->files)
{
for (fil = tddba->files; fil->fil_next; fil = fil->fil_next);
fil->fil_next = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
fil->fil_next->fil_min_page = fil->fil_max_page + 1;
fil = fil->fil_next;
}
else
{
// empty list
fil = tddba->files = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
fil->fil_min_page = 0L;
}
strcpy(file->fil_string, file_name);
file->fil_length = file_length;
fil->fil_next = NULL;
strcpy(fil->fil_string, file_name);
fil->fil_length = file_length;
fil->fil_fudge = 0;
fil->fil_max_page = 0L;
fil->fil_desc = CreateFile( file_name,
file->fil_desc = CreateFile(file_name,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
@ -1895,31 +1808,15 @@ static dba_fil* db_open(const char* file_name, USHORT file_length)
FILE_ATTRIBUTE_NORMAL,
0);
if (fil->fil_desc == INVALID_HANDLE_VALUE)
if (file->fil_desc == INVALID_HANDLE_VALUE)
{
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 29, SafeArg() << file_name);
// msg 29: Can't open database file %s
db_error(GetLastError());
}
open_files* file_list = FB_NEW_POOL(*getDefaultMemoryPool()) open_files;
if (!file_list)
{
// NOMEM: return error
dba_error(31);
}
file_list->desc = fil->fil_desc;
file_list->open_files_next = 0;
if (tddba->head_of_files_list == 0)
tddba->head_of_files_list = file_list;
else
{
file_list->open_files_next = tddba->head_of_files_list;
tddba->head_of_files_list = file_list;
}
return fil;
tddba->file = file;
return file;
}
@ -1945,17 +1842,9 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
tddba->page_number = page_number;
dba_fil* fil;
for (fil = tddba->files; page_number > (SLONG) fil->fil_max_page && fil->fil_next;)
{
fil = fil->fil_next;
}
page_number -= fil->fil_min_page - fil->fil_fudge;
LARGE_INTEGER liOffset;
liOffset.QuadPart = UInt32x32To64((DWORD) page_number, (DWORD) tddba->page_size);
if (SetFilePointer(fil->fil_desc, (LONG) liOffset.LowPart, &liOffset.HighPart, FILE_BEGIN) ==
if (SetFilePointer(tddba->file->fil_desc, (LONG) liOffset.LowPart, &liOffset.HighPart, FILE_BEGIN) ==
(DWORD) -1)
{
int lastError = GetLastError();
@ -1968,7 +1857,7 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
}
SLONG actual_length;
if (!ReadFile( fil->fil_desc,
if (!ReadFile( tddba->file->fil_desc,
tddba->global_buffer,
tddba->page_size,
reinterpret_cast<LPDWORD>(&actual_length),
@ -2057,54 +1946,20 @@ static dba_fil* db_open(const char* file_name, USHORT file_length)
**************************************/
tdba* tddba = tdba::getSpecific();
dba_fil* fil;
if (tddba->files)
{
for (fil = tddba->files; fil->fil_next; fil = fil->fil_next)
;
fil->fil_next = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
fil->fil_next->fil_min_page = fil->fil_max_page + 1;
fil = fil->fil_next;
}
else
{
// empty list
const auto file = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
fil = tddba->files = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
fil->fil_min_page = 0L;
}
strcpy(file->fil_string, file_name);
file->fil_length = file_length;
fil->fil_next = NULL;
strcpy(fil->fil_string, file_name);
fil->fil_length = file_length;
fil->fil_fudge = 0;
fil->fil_max_page = 0L;
if ((fil->fil_desc = os_utils::open(file_name, O_RDONLY)) == -1)
if ((file->fil_desc = os_utils::open(file_name, O_RDONLY)) == -1)
{
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 29, SafeArg() << file_name);
// msg 29: Can't open database file %s
db_error(errno);
}
open_files* file_list = FB_NEW_POOL(*getDefaultMemoryPool()) open_files;
if (!file_list)
{
// NOMEM: return error
dba_error(31);
}
file_list->desc = fil->fil_desc;
file_list->open_files_next = 0;
if (tddba->head_of_files_list == 0)
tddba->head_of_files_list = file_list;
else
{
file_list->open_files_next = tddba->head_of_files_list;
tddba->head_of_files_list = file_list;
}
return fil;
tddba->file = file;
return file;
}
@ -2127,15 +1982,8 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
tddba->page_number = page_number;
dba_fil* fil;
for (fil = tddba->files; page_number > (SLONG) fil->fil_max_page && fil->fil_next;)
{
fil = fil->fil_next;
}
page_number -= fil->fil_min_page - fil->fil_fudge;
const FB_UINT64 offset = ((FB_UINT64) page_number) * ((FB_UINT64) tddba->page_size);
if (os_utils::lseek (fil->fil_desc, offset, 0) == -1)
if (os_utils::lseek (tddba->file->fil_desc, offset, 0) == -1)
{
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 30, SafeArg());
// msg 30: Can't read a database page
@ -2145,7 +1993,7 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
USHORT length = tddba->page_size;
for (SCHAR* p = (SCHAR *) tddba->global_buffer; length > 0;)
{
const int l = read(fil->fil_desc, p, length);
const int l = read(tddba->file->fil_desc, p, length);
if (l < 0)
{
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 30, SafeArg());

View File

@ -231,17 +231,6 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util
uSvc->printf(false, "\tRoot file name:\t\t%s\n", temp);
break;
case HDR_file:
memcpy(temp, p + 2, p[1]);
temp[p[1]] = '\0';
uSvc->printf(false, "\tContinuation file:\t\t%s\n", temp);
break;
case HDR_last_page:
memcpy(&number, p + 2, sizeof(number));
uSvc->printf(false, "\tLast logical page:\t\t%ld\n", number);
break;
case HDR_sweep_interval:
memcpy(&number, p + 2, sizeof(number));
uSvc->printf(false, "\tSweep interval:\t\t%ld\n", number);

View File

@ -63,7 +63,6 @@ static void format_index_root(index_root_page*, int, SSHORT, SSHORT);
static void format_pointer(pointer_page*, int, SSHORT, SSHORT, bool, SSHORT, const SLONG*);
static void format_pip(page_inv_page*, int, int);
static void format_tip(tx_inv_page*, int, SLONG);
static void get_next_file(rbdb*, header_page*);
static void get_range(TEXT***, const TEXT* const* const, ULONG*, ULONG*);
static void get_switch(TEXT**, swc*);
static header_page* open_database(rbdb*, ULONG);
@ -197,8 +196,7 @@ int main( int argc, char *argv[])
rbdb = (rbdb*) RBDB_alloc((SLONG) (sizeof(struct rbdb) + strlen(db_in)));
strcpy(rbdb->rbdb_file.fil_name, db_in);
rbdb->rbdb_file.fil_length = strlen(db_in);
if (header = open_database(rbdb, pg_size))
get_next_file(rbdb, header);
header = open_database(rbdb, pg_size);
// some systems don't care for this write sharing stuff...
if (rbdb && (sw_dump_tips || sw_dump_pages))
@ -210,7 +208,6 @@ int main( int argc, char *argv[])
}
}
gdbb = &tdbb_struct;
gdbb->tdbb_database = &dbb_struct;
gdbb->tdbb_transaction = &dull;
@ -252,17 +249,15 @@ int main( int argc, char *argv[])
fclose(dbg_file);
if (rbdb)
{
RBDB_close(rbdb);
while (rbdb)
{
rbdb* const next_db = rbdb->rbdb_next;
if (rbdb->rbdb_buffer1)
gds__free(rbdb->rbdb_buffer1);
if (rbdb->rbdb_buffer2)
gds__free(rbdb->rbdb_buffer2);
gds__free(rbdb);
rbdb = next_db;
}
return 0;
@ -332,8 +327,7 @@ void RBDB_close( rbdb* rbdb)
* Functional description
*
**************************************/
for (; rbdb; rbdb = rbdb->rbdb_next)
close(rbdb->rbdb_file.fil_file);
close(rbdb->rbdb_file.fil_file);
}
@ -732,36 +726,6 @@ static void format_tip( tx_inv_page* page, int page_size, SLONG next_page)
}
static void get_next_file( rbdb* rbdb, header_page* header)
{
/**************************************
*
* g e t _ n e x t _ f i l e
*
**************************************
*
* Functional description
* If there's another file as part of
* this database, get it now.
*
**************************************/
rbdb** next = &rbdb->rbdb_next;
const UCHAR* p = header->hdr_data;
for (const UCHAR* const end = p + header->hdr_page_size; p < end && *p != HDR_end; p += 2 + p[1])
{
if (*p == HDR_file)
{
rbdb* next_rbdb = (rbdb*) RBDB_alloc(sizeof(struct rbdb) + (SSHORT) p[1]);
next_rbdb->rbdb_file.fil_length = (SSHORT) p[1];
strncpy(next_rbdb->rbdb_file.fil_name, p + 2, (SSHORT) p[1]);
*next = next_rbdb;
next = &next_rbdb->rbdb_next;
break;
}
}
}
static void get_range(TEXT*** argv, const TEXT* const* const end, ULONG* lower, ULONG* upper)
{
/**************************************