mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 15:23:03 +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:
parent
125140103d
commit
f0740d2a32
@ -4204,53 +4204,85 @@ bool get_files(BurpGlobals* tdgbl)
|
|||||||
att_type attribute;
|
att_type attribute;
|
||||||
scan_attr_t scan_next_attr;
|
scan_attr_t scan_next_attr;
|
||||||
|
|
||||||
STORE (REQUEST_HANDLE tdgbl->handles_get_files_req_handle1)
|
BASED_ON RDB$FILES.RDB$FILE_NAME filename = "";
|
||||||
X IN RDB$FILES
|
SSHORT flags = 0, sequence = 0, number = 0;
|
||||||
X.RDB$FILE_FLAGS = 0;
|
SLONG start = 0, length = 0;
|
||||||
|
|
||||||
skip_init(&scan_next_attr);
|
skip_init(&scan_next_attr);
|
||||||
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
|
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
|
||||||
|
{
|
||||||
|
switch (attribute)
|
||||||
{
|
{
|
||||||
switch (attribute)
|
case att_file_filename:
|
||||||
{
|
GET_TEXT(filename);
|
||||||
case att_file_filename:
|
break;
|
||||||
GET_TEXT(X.RDB$FILE_NAME);
|
|
||||||
BURP_verbose (116, X.RDB$FILE_NAME);
|
|
||||||
// msg 116 restoring file %s
|
|
||||||
break;
|
|
||||||
|
|
||||||
case att_file_sequence:
|
case att_file_sequence:
|
||||||
X.RDB$FILE_SEQUENCE = (USHORT) get_int32(tdgbl);
|
sequence = (SSHORT) get_int32(tdgbl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case att_file_start:
|
case att_file_start:
|
||||||
X.RDB$FILE_START = get_int32(tdgbl);
|
start = get_int32(tdgbl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case att_file_length:
|
case att_file_length:
|
||||||
X.RDB$FILE_LENGTH = get_int32(tdgbl);
|
length = get_int32(tdgbl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case att_file_flags:
|
case att_file_flags:
|
||||||
X.RDB$FILE_FLAGS |= get_int32(tdgbl);
|
flags |= (SSHORT) get_int32(tdgbl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case att_shadow_number:
|
case att_shadow_number:
|
||||||
X.RDB$SHADOW_NUMBER = (USHORT) get_int32(tdgbl);
|
number = (SSHORT) get_int32(tdgbl);
|
||||||
if (tdgbl->gbl_sw_kill && X.RDB$SHADOW_NUMBER)
|
if (tdgbl->gbl_sw_kill && number)
|
||||||
X.RDB$FILE_FLAGS |= FILE_inactive;
|
flags |= FILE_inactive;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bad_attribute(scan_next_attr, attribute, 85);
|
bad_attribute(scan_next_attr, attribute, 85);
|
||||||
// msg 85 file
|
// msg 85 file
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
END_STORE;
|
}
|
||||||
ON_ERROR
|
|
||||||
general_on_error ();
|
const bool multiFileSupport = (tdgbl->runtimeODS <= DB_VERSION_DDL13_1);
|
||||||
END_ERROR;
|
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -80,9 +80,6 @@ static void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode*
|
|||||||
dsql_fld* field, ValueSourceClause* clause, string& source, BlrDebugWriter::BlrData& value);
|
dsql_fld* field, ValueSourceClause* clause, string& source, BlrDebugWriter::BlrData& value);
|
||||||
static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
|
static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
|
||||||
const MetaName& relationName, const MetaName& constraintName, const MetaName& indexName);
|
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,
|
static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
|
||||||
const MetaName& fieldName);
|
const MetaName& fieldName);
|
||||||
static bool isItSqlRole(thread_db* tdbb, jrd_tra* transaction, const MetaName& inputName,
|
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.
|
// Checks to see if the given field already exists in a relation.
|
||||||
static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
|
static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
|
||||||
const MetaName& fieldName)
|
const MetaName& fieldName)
|
||||||
@ -10462,7 +10419,7 @@ string CreateShadowNode::internalPrint(NodePrinter& printer) const
|
|||||||
NODE_PRINT(printer, number);
|
NODE_PRINT(printer, number);
|
||||||
NODE_PRINT(printer, manual);
|
NODE_PRINT(printer, manual);
|
||||||
NODE_PRINT(printer, conditional);
|
NODE_PRINT(printer, conditional);
|
||||||
NODE_PRINT(printer, files);
|
NODE_PRINT(printer, fileName);
|
||||||
|
|
||||||
return "CreateShadowNode";
|
return "CreateShadowNode";
|
||||||
}
|
}
|
||||||
@ -10486,7 +10443,7 @@ void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
|
|||||||
// run all statements under savepoint control
|
// run all statements under savepoint control
|
||||||
AutoSavePoint savePoint(tdbb, transaction);
|
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);
|
AutoCacheRequest request(tdbb, drq_l_shadow, DYN_REQUESTS);
|
||||||
|
|
||||||
@ -10502,25 +10459,34 @@ void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
|
|||||||
}
|
}
|
||||||
END_FOR
|
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();
|
status_exception::raise(Arg::PrivateDyn(166));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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
|
savePoint.release(); // everything is ok
|
||||||
}
|
}
|
||||||
@ -12742,13 +12708,11 @@ string AlterDatabaseNode::internalPrint(NodePrinter& printer) const
|
|||||||
DdlNode::internalPrint(printer);
|
DdlNode::internalPrint(printer);
|
||||||
|
|
||||||
NODE_PRINT(printer, create);
|
NODE_PRINT(printer, create);
|
||||||
NODE_PRINT(printer, createLength);
|
|
||||||
NODE_PRINT(printer, linger);
|
NODE_PRINT(printer, linger);
|
||||||
NODE_PRINT(printer, clauses);
|
NODE_PRINT(printer, clauses);
|
||||||
NODE_PRINT(printer, differenceFile);
|
NODE_PRINT(printer, differenceFile);
|
||||||
NODE_PRINT(printer, setDefaultCharSet);
|
NODE_PRINT(printer, setDefaultCharSet);
|
||||||
NODE_PRINT(printer, setDefaultCollation);
|
NODE_PRINT(printer, setDefaultCollation);
|
||||||
NODE_PRINT(printer, files);
|
|
||||||
NODE_PRINT(printer, cryptPlugin);
|
NODE_PRINT(printer, cryptPlugin);
|
||||||
NODE_PRINT(printer, keyName);
|
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())
|
if (differenceFile.hasData())
|
||||||
defineDifference(tdbb, transaction, differenceFile.c_str());
|
defineDifference(tdbb, transaction, differenceFile.c_str());
|
||||||
|
|
||||||
@ -13064,7 +13016,6 @@ void AlterDatabaseNode::changeBackupMode(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
X IN RDB$FILES
|
X IN RDB$FILES
|
||||||
{
|
{
|
||||||
X.RDB$FILE_FLAGS = FILE_difference | FILE_backing_up;
|
X.RDB$FILE_FLAGS = FILE_difference | FILE_backing_up;
|
||||||
X.RDB$FILE_START = 0;
|
|
||||||
}
|
}
|
||||||
END_STORE
|
END_STORE
|
||||||
|
|
||||||
@ -13116,7 +13067,6 @@ void AlterDatabaseNode::defineDifference(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
|
|
||||||
strcpy(FIL.RDB$FILE_NAME, file.c_str());
|
strcpy(FIL.RDB$FILE_NAME, file.c_str());
|
||||||
FIL.RDB$FILE_FLAGS = FILE_difference;
|
FIL.RDB$FILE_FLAGS = FILE_difference;
|
||||||
FIL.RDB$FILE_START = 0;
|
|
||||||
}
|
}
|
||||||
END_STORE
|
END_STORE
|
||||||
}
|
}
|
||||||
|
@ -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
|
class ExternalClause : public Printable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1967,12 +1933,13 @@ public:
|
|||||||
class CreateShadowNode : public DdlNode
|
class CreateShadowNode : public DdlNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CreateShadowNode(MemoryPool& p, const SSHORT aNumber)
|
CreateShadowNode(MemoryPool& p, SSHORT aNumber, bool aManual, bool aConditional,
|
||||||
|
const Firebird::string& aFileName)
|
||||||
: DdlNode(p),
|
: DdlNode(p),
|
||||||
number(aNumber),
|
number(aNumber),
|
||||||
manual(false),
|
manual(aManual),
|
||||||
conditional(false),
|
conditional(aConditional),
|
||||||
files(p)
|
fileName(p, aFileName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1996,7 +1963,7 @@ public:
|
|||||||
SSHORT number;
|
SSHORT number;
|
||||||
bool manual;
|
bool manual;
|
||||||
bool conditional;
|
bool conditional;
|
||||||
Firebird::Array<NestConst<DbFileClause> > files;
|
Firebird::string fileName;
|
||||||
bool createIfNotExistsOnly = false;
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2425,14 +2392,9 @@ public:
|
|||||||
public:
|
public:
|
||||||
AlterDatabaseNode(MemoryPool& p)
|
AlterDatabaseNode(MemoryPool& p)
|
||||||
: DdlNode(p),
|
: DdlNode(p),
|
||||||
create(false),
|
|
||||||
createLength(0),
|
|
||||||
linger(-1),
|
|
||||||
clauses(0),
|
|
||||||
differenceFile(p),
|
differenceFile(p),
|
||||||
setDefaultCharSet(p),
|
setDefaultCharSet(p),
|
||||||
setDefaultCollation(p),
|
setDefaultCollation(p),
|
||||||
files(p),
|
|
||||||
cryptPlugin(p),
|
cryptPlugin(p),
|
||||||
keyName(p),
|
keyName(p),
|
||||||
pubTables(p)
|
pubTables(p)
|
||||||
@ -2468,13 +2430,12 @@ private:
|
|||||||
void checkClauses(thread_db* tdbb);
|
void checkClauses(thread_db* tdbb);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool create; // Is the node created with a CREATE DATABASE command?
|
bool create = false; // Is the node created with a CREATE DATABASE command?
|
||||||
SLONG createLength, linger;
|
SLONG linger = -1;
|
||||||
unsigned clauses;
|
unsigned clauses = 0;
|
||||||
Firebird::string differenceFile;
|
Firebird::string differenceFile;
|
||||||
MetaName setDefaultCharSet;
|
MetaName setDefaultCharSet;
|
||||||
MetaName setDefaultCollation;
|
MetaName setDefaultCollation;
|
||||||
Firebird::Array<NestConst<DbFileClause> > files;
|
|
||||||
MetaName cryptPlugin;
|
MetaName cryptPlugin;
|
||||||
MetaName keyName;
|
MetaName keyName;
|
||||||
Firebird::TriState ssDefiner;
|
Firebird::TriState ssDefiner;
|
||||||
|
@ -767,8 +767,6 @@ using namespace Firebird;
|
|||||||
Firebird::string* stringPtr;
|
Firebird::string* stringPtr;
|
||||||
Jrd::IntlString* intlStringPtr;
|
Jrd::IntlString* intlStringPtr;
|
||||||
Jrd::Lim64String* lim64ptr;
|
Jrd::Lim64String* lim64ptr;
|
||||||
Jrd::DbFileClause* dbFileClause;
|
|
||||||
Firebird::Array<NestConst<Jrd::DbFileClause> >* dbFilesClause;
|
|
||||||
Jrd::ExternalClause* externalClause;
|
Jrd::ExternalClause* externalClause;
|
||||||
Firebird::NonPooledPair<Jrd::MetaName*, Jrd::ValueExprNode*>* namedArgument;
|
Firebird::NonPooledPair<Jrd::MetaName*, Jrd::ValueExprNode*>* namedArgument;
|
||||||
Firebird::NonPooledPair<Firebird::ObjectsArray<Jrd::MetaName>*, Jrd::ValueListNode*>* namedArguments;
|
Firebird::NonPooledPair<Firebird::ObjectsArray<Jrd::MetaName>*, Jrd::ValueListNode*>* namedArguments;
|
||||||
@ -1807,16 +1805,8 @@ index_condition_opt
|
|||||||
// CREATE SHADOW
|
// CREATE SHADOW
|
||||||
%type <createShadowNode> shadow_clause
|
%type <createShadowNode> shadow_clause
|
||||||
shadow_clause
|
shadow_clause
|
||||||
: pos_short_integer manual_auto conditional utf_string first_file_length
|
: pos_short_integer manual_auto conditional utf_string
|
||||||
{
|
{ $$ = newNode<CreateShadowNode>($1, $2, $3, *$4); }
|
||||||
$$ = newNode<CreateShadowNode>($1);
|
|
||||||
$$->manual = $2;
|
|
||||||
$$->conditional = $3;
|
|
||||||
$$->files.add(newNode<DbFileClause>(*$4));
|
|
||||||
$$->files.front()->length = $5;
|
|
||||||
}
|
|
||||||
sec_shadow_files(NOTRIAL(&$6->files))
|
|
||||||
{ $$ = $6; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
%type <boolVal> manual_auto
|
%type <boolVal> manual_auto
|
||||||
@ -1832,24 +1822,6 @@ conditional
|
|||||||
| CONDITIONAL { $$ = true; }
|
| 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
|
// CREATE DOMAIN
|
||||||
|
|
||||||
@ -2279,8 +2251,6 @@ db_initial_option($alterDatabaseNode)
|
|||||||
| ROLE utf_string
|
| ROLE utf_string
|
||||||
| PASSWORD utf_string
|
| PASSWORD utf_string
|
||||||
| SET NAMES utf_string
|
| SET NAMES utf_string
|
||||||
| LENGTH equals long_integer page_noise
|
|
||||||
{ $alterDatabaseNode->createLength = $3; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
%type db_rem_desc1(<alterDatabaseNode>)
|
%type db_rem_desc1(<alterDatabaseNode>)
|
||||||
@ -2297,9 +2267,7 @@ db_rem_desc($alterDatabaseNode)
|
|||||||
|
|
||||||
%type db_rem_option(<alterDatabaseNode>)
|
%type db_rem_option(<alterDatabaseNode>)
|
||||||
db_rem_option($alterDatabaseNode)
|
db_rem_option($alterDatabaseNode)
|
||||||
: db_file
|
: DEFAULT CHARACTER SET symbol_character_set_name
|
||||||
{ $alterDatabaseNode->files.add($1); }
|
|
||||||
| DEFAULT CHARACTER SET symbol_character_set_name
|
|
||||||
{ $alterDatabaseNode->setDefaultCharSet = *$4; }
|
{ $alterDatabaseNode->setDefaultCharSet = *$4; }
|
||||||
| DEFAULT CHARACTER SET symbol_character_set_name COLLATION symbol_collation_name
|
| DEFAULT CHARACTER SET symbol_character_set_name COLLATION symbol_collation_name
|
||||||
{
|
{
|
||||||
@ -2310,49 +2278,6 @@ db_rem_option($alterDatabaseNode)
|
|||||||
{ $alterDatabaseNode->differenceFile = *$3; }
|
{ $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
|
// CREATE TABLE
|
||||||
|
|
||||||
@ -4770,8 +4695,7 @@ alter_db($alterDatabaseNode)
|
|||||||
|
|
||||||
%type db_alter_clause(<alterDatabaseNode>)
|
%type db_alter_clause(<alterDatabaseNode>)
|
||||||
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; }
|
{ $alterDatabaseNode->differenceFile = *$4; }
|
||||||
| DROP DIFFERENCE FILE
|
| DROP DIFFERENCE FILE
|
||||||
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DROP_DIFFERENCE; }
|
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DROP_DIFFERENCE; }
|
||||||
|
@ -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,
|
PAG_add_header_entry(tdbb, header, HDR_root_file_name,
|
||||||
(USHORT) strlen((const char*) q), q);
|
(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_flags |= hdr_active_shadow;
|
||||||
header->hdr_header.pag_pageno = bdb->bdb_page.getPageNum();
|
header->hdr_header.pag_pageno = bdb->bdb_page.getPageNum();
|
||||||
}
|
}
|
||||||
|
219
src/jrd/dfw.epp
219
src/jrd/dfw.epp
@ -56,7 +56,7 @@
|
|||||||
* BUGCHECK(291) took place. To avoid that issue, it was decided not to modify data
|
* 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
|
* 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
|
* 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 add_shadow(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
|
||||||
static bool delete_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*);
|
static bool compute_security(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
|
||||||
@ -1272,7 +1271,6 @@ namespace
|
|||||||
|
|
||||||
static const deferred_task task_table[] =
|
static const deferred_task task_table[] =
|
||||||
{
|
{
|
||||||
{ dfw_add_file, add_file },
|
|
||||||
{ dfw_add_shadow, add_shadow },
|
{ dfw_add_shadow, add_shadow },
|
||||||
{ dfw_delete_index, modify_index },
|
{ dfw_delete_index, modify_index },
|
||||||
{ dfw_delete_rfr, delete_rfr },
|
{ 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)
|
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;
|
finished = false;
|
||||||
handle.reset();
|
handle.reset();
|
||||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||||
F IN RDB$FILES
|
F IN RDB$FILES WITH F.RDB$FILE_NAME EQ work->dfw_name.c_str()
|
||||||
WITH F.RDB$FILE_NAME EQ work->dfw_name.c_str()
|
{
|
||||||
|
|
||||||
expanded_fname = F.RDB$FILE_NAME;
|
expanded_fname = F.RDB$FILE_NAME;
|
||||||
ISC_expand_filename(expanded_fname, false);
|
ISC_expand_filename(expanded_fname, false);
|
||||||
|
|
||||||
MODIFY F USING
|
MODIFY F USING
|
||||||
expanded_fname.copyTo(F.RDB$FILE_NAME, sizeof(F.RDB$FILE_NAME));
|
expanded_fname.copyTo(F.RDB$FILE_NAME, sizeof(F.RDB$FILE_NAME));
|
||||||
END_MODIFY
|
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$SHADOW_NUMBER == shadow->sdw_number) && !(shadow->sdw_flags & SDW_IGNORE))
|
||||||
{
|
{
|
||||||
if (F.RDB$FILE_FLAGS & FILE_shadow)
|
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
|
|
||||||
{
|
{
|
||||||
// We cannot add a file to a shadow that is still
|
// We cannot add a file to a shadow that is still
|
||||||
// in the process of being created.
|
// in the process of being created.
|
||||||
raiseDatabaseInUseError(false);
|
raiseDatabaseInUseError(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the case of a bogus duplicate posted
|
||||||
|
// work when we added a multi-file shadow
|
||||||
|
finished = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
if (finished)
|
if (finished)
|
||||||
return false;
|
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();
|
handle.reset();
|
||||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||||
X IN RDB$FILES CROSS
|
F IN RDB$FILES WITH F.RDB$FILE_NAME EQ expanded_fname.c_str()
|
||||||
Y IN RDB$FILES
|
|
||||||
OVER RDB$SHADOW_NUMBER
|
|
||||||
WITH X.RDB$FILE_NAME EQ expanded_fname.c_str()
|
|
||||||
SORTED BY Y.RDB$FILE_START
|
|
||||||
{
|
{
|
||||||
// for the first file, create a brand new shadow; for secondary
|
SDW_add(tdbb, F.RDB$FILE_NAME, F.RDB$SHADOW_NUMBER, F.RDB$FILE_FLAGS);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shadow)
|
MODIFY F
|
||||||
BUGCHECK(203); // msg 203 shadow block not found for extend file
|
F.RDB$FILE_FLAGS |= FILE_shadow;
|
||||||
|
END_MODIFY
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
|
@ -1301,7 +1301,7 @@ private:
|
|||||||
|
|
||||||
static void check_database(thread_db* tdbb, bool async = false);
|
static void check_database(thread_db* tdbb, bool async = false);
|
||||||
static void commit(thread_db*, jrd_tra*, const bool);
|
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 find_intl_charset(thread_db*, Jrd::Attachment*, const DatabaseOptions*);
|
||||||
static void init_database_lock(thread_db*);
|
static void init_database_lock(thread_db*);
|
||||||
static void run_commit_triggers(thread_db* tdbb, jrd_tra* transaction);
|
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_crypto_manager = FB_NEW_POOL(*dbb->dbb_permanent) CryptoManager(tdbb);
|
||||||
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
|
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
|
||||||
|
|
||||||
PAG_init2(tdbb, 0);
|
PAG_init2(tdbb);
|
||||||
PAG_header(tdbb, false, newForceWrite);
|
PAG_header(tdbb, false, newForceWrite);
|
||||||
dbb->dbb_page_manager.initTempPageSpace(tdbb);
|
dbb->dbb_page_manager.initTempPageSpace(tdbb);
|
||||||
dbb->dbb_crypto_manager->attach(tdbb, attachment);
|
dbb->dbb_crypto_manager->attach(tdbb, attachment);
|
||||||
@ -3552,11 +3552,9 @@ void JAttachment::internalDropDatabase(CheckStatusWrapper* user_status)
|
|||||||
// This point on database is useless
|
// This point on database is useless
|
||||||
|
|
||||||
// drop the files here
|
// drop the files here
|
||||||
bool err = drop_files(file);
|
bool err = drop_file(dbb, file);
|
||||||
for (; shadow; shadow = shadow->sdw_next)
|
for (; shadow; shadow = shadow->sdw_next)
|
||||||
{
|
err = drop_file(dbb, shadow->sdw_file) || err;
|
||||||
err = drop_files(shadow->sdw_file) || err;
|
|
||||||
}
|
|
||||||
|
|
||||||
tdbb->setDatabase(NULL);
|
tdbb->setDatabase(NULL);
|
||||||
Database::destroy(dbb);
|
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
|
* Functional description
|
||||||
* drop a linked list of files
|
* Drop a file.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
FbLocalStatus status;
|
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) <<
|
||||||
ERR_build_status(&status, Arg::Gds(isc_io_error) << Arg::Str("unlink") <<
|
Arg::Gds(isc_io_delete_err) << SYS_ERR(errno));
|
||||||
Arg::Str(file->fil_string) <<
|
|
||||||
Arg::Gds(isc_io_delete_err) << SYS_ERR(errno));
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||||
Database* dbb = GET_DBB();
|
iscDbLogStatus(pageSpace->file->fil_string, &status);
|
||||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
|
||||||
iscDbLogStatus(pageSpace->file->fil_string, &status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status->getState() & IStatus::STATE_ERRORS ? true : false;
|
return status->getState() & IStatus::STATE_ERRORS ? true : false;
|
||||||
|
@ -1782,7 +1782,6 @@ void MET_get_shadow_files(thread_db* tdbb, bool delete_files)
|
|||||||
FOR(REQUEST_HANDLE handle) X IN RDB$FILES
|
FOR(REQUEST_HANDLE handle) X IN RDB$FILES
|
||||||
WITH X.RDB$SHADOW_NUMBER NOT MISSING
|
WITH X.RDB$SHADOW_NUMBER NOT MISSING
|
||||||
AND X.RDB$SHADOW_NUMBER NE 0
|
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))
|
if ((X.RDB$FILE_FLAGS & FILE_shadow) && !(X.RDB$FILE_FLAGS & FILE_inactive))
|
||||||
{
|
{
|
||||||
|
@ -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_end = 0;
|
||||||
inline constexpr UCHAR HDR_root_file_name = 1; // Original name of root file
|
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_file = 2; // Secondary file
|
||||||
inline constexpr UCHAR HDR_last_page = 3; // Last logical page number of 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_sweep_interval = 4; // Transactions between sweeps
|
||||||
inline constexpr UCHAR HDR_crypt_checksum = 5; // Checksum of critical crypt parameters
|
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
|
inline constexpr UCHAR HDR_difference_file = 6; // Delta file that is used during backup lock
|
||||||
|
@ -41,11 +41,6 @@ namespace Jrd {
|
|||||||
class jrd_file : public pool_alloc_rpt<SCHAR, type_fil>
|
class jrd_file : public pool_alloc_rpt<SCHAR, type_fil>
|
||||||
{
|
{
|
||||||
public:
|
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;
|
int fil_desc;
|
||||||
Firebird::Mutex fil_mutex;
|
Firebird::Mutex fil_mutex;
|
||||||
USHORT fil_flags;
|
USHORT fil_flags;
|
||||||
@ -69,11 +64,6 @@ public:
|
|||||||
delete fil_ext_lock;
|
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
|
HANDLE fil_desc; // File descriptor
|
||||||
Firebird::RWLock* fil_ext_lock; // file extend lock
|
Firebird::RWLock* fil_ext_lock; // file extend lock
|
||||||
USHORT fil_flags;
|
USHORT fil_flags;
|
||||||
|
@ -36,7 +36,6 @@ namespace Ods {
|
|||||||
struct pag;
|
struct pag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PIO_add_file(Jrd::thread_db*, Jrd::jrd_file*, const Firebird::PathName&, SLONG);
|
|
||||||
void PIO_close(Jrd::jrd_file*);
|
void PIO_close(Jrd::jrd_file*);
|
||||||
Jrd::jrd_file* PIO_create(Jrd::thread_db*, const Firebird::PathName&,
|
Jrd::jrd_file* PIO_create(Jrd::thread_db*, const Firebird::PathName&,
|
||||||
const bool, const bool);
|
const bool, const bool);
|
||||||
|
@ -132,7 +132,7 @@ using namespace Firebird;
|
|||||||
|
|
||||||
static const mode_t MASK = 0660;
|
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 jrd_file* setup_file(Database*, const PathName&, int, USHORT);
|
||||||
static void lockDatabaseFile(int& desc, const bool shareMode, const bool temporary,
|
static void lockDatabaseFile(int& desc, const bool shareMode, const bool temporary,
|
||||||
const char* fileName, ISC_STATUS operation);
|
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 int openFile(const Firebird::PathName&, const bool, const bool, const bool);
|
||||||
static void maybeCloseFile(int&);
|
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;
|
void PIO_close(jrd_file* file)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -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.
|
* Extend file by extPages pages of pageSize size.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
fb_assert(extPages);
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_FALLOC_H) && defined(HAVE_FALLOCATE)
|
#if defined(HAVE_LINUX_FALLOC_H) && defined(HAVE_FALLOCATE)
|
||||||
|
|
||||||
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
||||||
|
|
||||||
ULONG leftPages = extPages;
|
if (file->fil_flags & FIL_no_fast_extend)
|
||||||
for (jrd_file* file = main_file; file && leftPages; file = file->fil_next)
|
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);
|
int err = fallocate(file->fil_desc, 0, filePages * pageSize, extendBy * pageSize);
|
||||||
const ULONG fileMaxPages = (file->fil_max_page == MAX_ULONG) ?
|
if (err == 0)
|
||||||
MAX_ULONG : file->fil_max_page - file->fil_min_page + 1;
|
break;
|
||||||
if (filePages < fileMaxPages)
|
|
||||||
{
|
|
||||||
if (file->fil_flags & FIL_no_fast_extend)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const ULONG extendBy = MIN(fileMaxPages - filePages + file->fil_fudge, leftPages);
|
err = errno;
|
||||||
|
if (SYSCALL_INTERRUPTED(err))
|
||||||
|
continue;
|
||||||
|
|
||||||
int r;
|
if (err != EOPNOTSUPP && err != ENOSYS)
|
||||||
for (r = 0; r < IO_RETRY; r++)
|
unix_error("fallocate", file, isc_io_write_err);
|
||||||
{
|
|
||||||
int err = fallocate(file->fil_desc, 0, filePages * pageSize, extendBy * pageSize);
|
|
||||||
if (err == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
err = errno;
|
file->fil_flags |= FIL_no_fast_extend;
|
||||||
if (SYSCALL_INTERRUPTED(err))
|
return;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
if (err != EOPNOTSUPP && err != ENOSYS)
|
if (r == IO_RETRY)
|
||||||
unix_error("fallocate", file, isc_io_write_err);
|
{
|
||||||
|
|
||||||
file->fil_flags |= FIL_no_fast_extend;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r == IO_RETRY)
|
|
||||||
{
|
|
||||||
#ifdef DEV_BUILD
|
#ifdef DEV_BUILD
|
||||||
fprintf(stderr, "PIO_extend: retry count exceeded\n");
|
fprintf(stderr, "PIO_extend: retry count exceeded\n");
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
#endif
|
#endif
|
||||||
unix_error("fallocate_retry", file, isc_io_write_err);
|
unix_error("fallocate_retry", file, isc_io_write_err);
|
||||||
}
|
|
||||||
|
|
||||||
leftPages -= extendBy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
main_file->fil_flags |= FIL_no_fast_extend;
|
file->fil_flags |= FIL_no_fast_extend;
|
||||||
#endif // fallocate present
|
#endif // fallocate present
|
||||||
|
|
||||||
// not implemented
|
// 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
|
#ifndef SUPERSERVER_V2
|
||||||
|
|
||||||
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
@ -615,7 +565,7 @@ void PIO_header(thread_db* tdbb, UCHAR* address, int length)
|
|||||||
static Firebird::InitInstance<ZeroBuffer> zeros;
|
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)
|
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);
|
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
||||||
|
|
||||||
jrd_file* file = seek_file(main_file, &bdb, &offset, status_vector);
|
if (!seek_file(file, &bdb, &offset, status_vector))
|
||||||
|
|
||||||
if (!file)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (file->fil_min_page + 8 > startPage)
|
if (startPage < 8)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
USHORT leftPages = initPages;
|
USHORT leftPages = initPages;
|
||||||
const ULONG initBy = MIN(file->fil_max_page - startPage, leftPages);
|
const ULONG initBy = MIN(MAX_ULONG - startPage, leftPages);
|
||||||
if (initBy < leftPages)
|
if (initBy < leftPages)
|
||||||
leftPages = initBy;
|
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++)
|
for (int r = 0; r < IO_RETRY; r++)
|
||||||
{
|
{
|
||||||
if (!(file = seek_file(file, &bdb, &offset, status_vector)))
|
if (!seek_file(file, &bdb, &offset, status_vector))
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
if ((written = os_utils::pwrite(file->fil_desc, zero_buff, to_write, LSEEK_OFFSET_CAST offset)) == to_write)
|
if ((written = os_utils::pwrite(file->fil_desc, zero_buff, to_write, LSEEK_OFFSET_CAST offset)) == to_write)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (written < 0 && !SYSCALL_INTERRUPTED(errno))
|
if (written < 0 && !SYSCALL_INTERRUPTED(errno))
|
||||||
return unix_error("write", file, isc_io_write_err, status_vector);
|
return unix_error("write", file, isc_io_write_err, status_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
leftPages -= write_pages;
|
leftPages -= write_pages;
|
||||||
i += 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++)
|
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;
|
return false;
|
||||||
|
|
||||||
if ((bytes = os_utils::pread(file->fil_desc, page, size, LSEEK_OFFSET_CAST offset)) == size)
|
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++)
|
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;
|
return false;
|
||||||
|
|
||||||
if ((bytes = os_utils::pwrite(file->fil_desc, page, size, LSEEK_OFFSET_CAST offset)) == size)
|
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,
|
static bool seek_file(jrd_file* file, BufferDesc* bdb, FB_UINT64* offset,
|
||||||
FbStatusVector* status_vector)
|
FbStatusVector* status_vector)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -891,43 +840,29 @@ static jrd_file* seek_file(jrd_file* file, BufferDesc* bdb, FB_UINT64* offset,
|
|||||||
**************************************
|
**************************************
|
||||||
*
|
*
|
||||||
* Functional description
|
* Functional description
|
||||||
* Given a buffer descriptor block, find the appropriate
|
* Given a buffer descriptor block, seek to the proper page in that file.
|
||||||
* file block and seek to the proper page in that file.
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
BufferControl* bcb = bdb->bdb_bcb;
|
BufferControl* const bcb = bdb->bdb_bcb;
|
||||||
Database* dbb = bcb->bcb_database;
|
const ULONG page = bdb->bdb_page.getPageNum();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file->fil_desc == -1)
|
if (file->fil_desc == -1)
|
||||||
{
|
{
|
||||||
unix_error("lseek", file, isc_io_access_err, status_vector);
|
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;
|
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)
|
if (lseek_offset != (FB_UINT64) LSEEK_OFFSET_CAST lseek_offset)
|
||||||
{
|
{
|
||||||
unix_error("lseek", file, isc_io_32bit_exceeded_err, status_vector);
|
unix_error("lseek", file, isc_io_32bit_exceeded_err, status_vector);
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*offset = lseek_offset;
|
*offset = lseek_offset;
|
||||||
|
return true;
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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 = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
|
||||||
file->fil_desc = desc;
|
file->fil_desc = desc;
|
||||||
file->fil_max_page = MAX_ULONG;
|
|
||||||
file->fil_flags = flags;
|
file->fil_flags = flags;
|
||||||
strcpy(file->fil_string, file_name.c_str());
|
strcpy(file->fil_string, file_name.c_str());
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ using namespace Firebird;
|
|||||||
#define TEXT SCHAR
|
#define TEXT SCHAR
|
||||||
|
|
||||||
static bool maybeCloseFile(HANDLE&);
|
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 jrd_file* setup_file(Database*, const Firebird::PathName&, HANDLE, USHORT);
|
||||||
static bool nt_error(const TEXT*, const jrd_file*, ISC_STATUS, FbStatusVector* const);
|
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;
|
FILE_FLAG_DELETE_ON_CLOSE;
|
||||||
|
|
||||||
|
|
||||||
int PIO_add_file(thread_db* tdbb, jrd_file* main_file, const Firebird::PathName& file_name, SLONG start)
|
void PIO_close(jrd_file* file)
|
||||||
{
|
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -164,10 +132,7 @@ void PIO_close(jrd_file* main_file)
|
|||||||
* Functional description
|
* 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.
|
* Extend file by extPages pages of pageSize size.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
fb_assert(extPages);
|
||||||
|
|
||||||
// hvlad: prevent other reading\writing threads from changing file pointer.
|
// hvlad: prevent other reading\writing threads from changing file pointer.
|
||||||
// As we open file without FILE_FLAG_OVERLAPPED, ReadFile\WriteFile calls
|
// As we open file without FILE_FLAG_OVERLAPPED, ReadFile\WriteFile calls
|
||||||
// will change file pointer we set here and file truncation instead of file
|
// 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)
|
// and read\write activity performed simultaneously)
|
||||||
|
|
||||||
// if file have no extend lock it is better to not extend file than corrupt it
|
// 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;
|
return;
|
||||||
|
|
||||||
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
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;
|
const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
|
||||||
for (jrd_file* file = main_file; file && leftPages; file = file->fil_next)
|
const ULONG extendBy = MIN(MAX_ULONG - filePages, extPages);
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
HANDLE hFile = file->fil_desc;
|
const HANDLE hFile = file->fil_desc;
|
||||||
|
|
||||||
LARGE_INTEGER newSize;
|
LARGE_INTEGER newSize;
|
||||||
newSize.QuadPart = ((ULONGLONG) filePages + extendBy) * pageSize;
|
newSize.QuadPart = ((ULONGLONG) filePages + extendBy) * pageSize;
|
||||||
|
|
||||||
const DWORD ret = SetFilePointer(hFile, newSize.LowPart, &newSize.HighPart, FILE_BEGIN);
|
const DWORD ret = SetFilePointer(hFile, newSize.LowPart, &newSize.HighPart, FILE_BEGIN);
|
||||||
if (ret == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
|
if (ret == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
||||||
nt_error("SetFilePointer", file, isc_io_write_err, NULL);
|
nt_error("SetFilePointer", file, isc_io_write_err, NULL);
|
||||||
}
|
|
||||||
if (!SetEndOfFile(hFile)) {
|
|
||||||
nt_error("SetEndOfFile", 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);
|
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);
|
FlushFileBuffers(file->fil_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +372,7 @@ void PIO_header(thread_db* tdbb, UCHAR* address, int length)
|
|||||||
static Firebird::InitInstance<ZeroBuffer> zeros;
|
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)
|
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();
|
Database* const dbb = tdbb->getDatabase();
|
||||||
|
|
||||||
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
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
|
// Fake buffer, used in seek_file. Page space ID doesn't matter there
|
||||||
// as we already know file to work with
|
// 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);
|
bdb.bdb_page = PageNumber(0, startPage);
|
||||||
|
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED overlapped;
|
||||||
jrd_file* file = seek_file(main_file, &bdb, &overlapped);
|
if (!seek_file(file, &bdb, &overlapped))
|
||||||
|
|
||||||
if (!file)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (file->fil_min_page + 8 > startPage)
|
if (startPage < 8)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
USHORT leftPages = initPages;
|
USHORT leftPages = initPages;
|
||||||
const ULONG initBy = MIN(file->fil_max_page - startPage, leftPages);
|
const ULONG initBy = MIN(MAX_ULONG - startPage, leftPages);
|
||||||
if (initBy < leftPages)
|
if (initBy < leftPages)
|
||||||
leftPages = initBy;
|
leftPages = initBy;
|
||||||
|
|
||||||
@ -464,8 +417,8 @@ USHORT PIO_init_data(thread_db* tdbb, jrd_file* main_file, FbStatusVector* statu
|
|||||||
if (write_pages > leftPages)
|
if (write_pages > leftPages)
|
||||||
write_pages = leftPages;
|
write_pages = leftPages;
|
||||||
|
|
||||||
jrd_file* file1 = seek_file(main_file, &bdb, &overlapped);
|
if (!seek_file(file, &bdb, &overlapped))
|
||||||
fb_assert(file1 == file);
|
return 0;
|
||||||
|
|
||||||
const DWORD to_write = (DWORD) write_pages * dbb->dbb_page_size;
|
const DWORD to_write = (DWORD) write_pages * dbb->dbb_page_size;
|
||||||
DWORD written;
|
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);
|
FileExtendLockGuard extLock(file->fil_ext_lock, false);
|
||||||
|
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED overlapped;
|
||||||
if (!(file = seek_file(file, bdb, &overlapped)))
|
if (!seek_file(file, bdb, &overlapped))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
HANDLE desc = file->fil_desc;
|
HANDLE desc = file->fil_desc;
|
||||||
@ -625,14 +578,12 @@ bool PIO_read_ahead(thread_db* tdbb,
|
|||||||
**************************************
|
**************************************
|
||||||
*
|
*
|
||||||
* Functional description
|
* Functional description
|
||||||
* Read a contiguous set of pages. The only
|
* Read a contiguous set of pages.
|
||||||
* tricky part is to segment the I/O when crossing
|
|
||||||
* file boundaries.
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
OVERLAPPED overlapped, *overlapped_ptr;
|
OVERLAPPED overlapped, *overlapped_ptr;
|
||||||
|
|
||||||
Database* const dbb = tdbb->getDatabase();
|
const auto dbb = tdbb->getDatabase();
|
||||||
|
|
||||||
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY);
|
||||||
|
|
||||||
@ -647,60 +598,45 @@ bool PIO_read_ahead(thread_db* tdbb,
|
|||||||
piob->piob_flags = 0;
|
piob->piob_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup up a dummy buffer descriptor block for seeking file
|
||||||
BufferDesc bdb;
|
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.
|
if (piob)
|
||||||
|
piob->piob_flags = PIOB_success;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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;
|
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);
|
FileExtendLockGuard extLock(file->fil_ext_lock, false);
|
||||||
|
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED overlapped;
|
||||||
file = seek_file(file, bdb, &overlapped);
|
if (!seek_file(file, bdb, &overlapped))
|
||||||
if (!file)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
HANDLE desc = file->fil_desc;
|
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,
|
static bool seek_file(jrd_file* file, BufferDesc* bdb, OVERLAPPED* overlapped)
|
||||||
BufferDesc* bdb,
|
|
||||||
OVERLAPPED* overlapped)
|
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -824,24 +757,11 @@ static jrd_file* seek_file(jrd_file* file,
|
|||||||
**************************************
|
**************************************
|
||||||
*
|
*
|
||||||
* Functional description
|
* Functional description
|
||||||
* Given a buffer descriptor block, find the appropriate
|
* Given a buffer descriptor block, seek to the proper page in that file.
|
||||||
* file block and seek to the proper page in that file.
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
BufferControl *bcb = bdb->bdb_bcb;
|
BufferControl* const bcb = bdb->bdb_bcb;
|
||||||
ULONG page = bdb->bdb_page.getPageNum();
|
const 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;
|
|
||||||
|
|
||||||
LARGE_INTEGER liOffset;
|
LARGE_INTEGER liOffset;
|
||||||
liOffset.QuadPart = UInt32x32To64((DWORD) page, (DWORD) bcb->bcb_page_size);
|
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);
|
ThreadSync* thd = ThreadSync::getThread(FB_FUNCTION);
|
||||||
overlapped->hEvent = thd->getIOEvent();
|
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 = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
|
||||||
file->fil_desc = desc;
|
file->fil_desc = desc;
|
||||||
file->fil_max_page = MAX_ULONG;
|
|
||||||
file->fil_flags = flags;
|
file->fil_flags = flags;
|
||||||
strcpy(file->fil_string, file_name.c_str());
|
strcpy(file->fil_string, file_name.c_str());
|
||||||
|
|
||||||
|
294
src/jrd/pag.cpp
294
src/jrd/pag.cpp
@ -364,115 +364,6 @@ namespace
|
|||||||
} // 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,
|
void PAG_add_header_entry(thread_db* tdbb, header_page* header,
|
||||||
USHORT type, USHORT len, const UCHAR* entry)
|
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
|
// 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);
|
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(pageSpace->file, forceWrite && !readOnly);
|
||||||
PIO_force_write(file, forceWrite && !readOnly);
|
|
||||||
|
|
||||||
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
|
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
|
||||||
dbb->dbb_backup_manager->setForcedWrites(forceWrite);
|
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
|
* Functional description
|
||||||
* Perform second phase of page initialization -- the eternal
|
* Read and apply the database header options.
|
||||||
* search for additional files.
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
const auto dbb = tdbb->getDatabase();
|
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,
|
for (const UCHAR* p = header->hdr_data; *p != HDR_end; p += 2 + p[1])
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
Shadow* shadow = dbb->dbb_shadow;
|
switch (*p)
|
||||||
for (; shadow; shadow = shadow->sdw_next)
|
|
||||||
{
|
{
|
||||||
if (shadow->sdw_number == shadow_number)
|
case HDR_sweep_interval:
|
||||||
{
|
fb_assert(p[1] == sizeof(SLONG));
|
||||||
file = shadow->sdw_file;
|
memcpy(&dbb->dbb_sweep_interval, p + 2, sizeof(SLONG));
|
||||||
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())
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Verify database file path against DatabaseAccess entry of firebird.conf
|
case HDR_db_guid:
|
||||||
if (!JRD_verify_database_access(nextFileName))
|
fb_assert(p[1] == Guid::SIZE);
|
||||||
{
|
dbb->dbb_guid = Guid(p + 2);
|
||||||
ISC_systemToUtf8(nextFileName);
|
break;
|
||||||
ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("additional database file") <<
|
|
||||||
Arg::Str(nextFileName));
|
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);
|
CCH_RELEASE(tdbb, &window);
|
||||||
|
|
||||||
PageSpace* const pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
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(pageSpace->file, flag);
|
||||||
PIO_force_write(file, flag);
|
|
||||||
|
|
||||||
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
|
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
|
||||||
{
|
PIO_force_write(shadow->sdw_file, flag);
|
||||||
for (jrd_file* file = shadow->sdw_file; file; file = file->fil_next)
|
|
||||||
PIO_force_write(file, flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
|
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
|
||||||
dbb->dbb_backup_manager->setForcedWrites(flag);
|
dbb->dbb_backup_manager->setForcedWrites(flag);
|
||||||
@ -1917,13 +1715,7 @@ PageSpace::~PageSpace()
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
PIO_close(file);
|
PIO_close(file);
|
||||||
|
delete file;
|
||||||
while (file)
|
|
||||||
{
|
|
||||||
jrd_file* next = file->fil_next;
|
|
||||||
delete file;
|
|
||||||
file = next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1936,15 +1728,7 @@ ULONG PageSpace::actAlloc()
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
// Traverse the linked list of files and add up the
|
return PIO_get_number_of_pages(file, dbb->dbb_page_size);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG PageSpace::actAlloc(const Database* dbb)
|
ULONG PageSpace::actAlloc(const Database* dbb)
|
||||||
@ -1961,17 +1745,7 @@ ULONG PageSpace::maxAlloc()
|
|||||||
* Compute last physically allocated page of database.
|
* Compute last physically allocated page of database.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
const USHORT pageSize = dbb->dbb_page_size;
|
const ULONG nPages = PIO_get_number_of_pages(file, 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;
|
|
||||||
|
|
||||||
if (maxPageNumber < nPages)
|
if (maxPageNumber < nPages)
|
||||||
maxPageNumber = nPages;
|
maxPageNumber = nPages;
|
||||||
@ -1987,15 +1761,7 @@ ULONG PageSpace::maxAlloc(const Database* dbb)
|
|||||||
|
|
||||||
bool PageSpace::onRawDevice() const
|
bool PageSpace::onRawDevice() const
|
||||||
{
|
{
|
||||||
#ifdef SUPPORT_RAW_DEVICES
|
return (file->fil_flags & FIL_raw_device) != 0;
|
||||||
for (const jrd_file* f = file; f != NULL; f = f->fil_next)
|
|
||||||
{
|
|
||||||
if (f->fil_flags & FIL_raw_device)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG PageSpace::lastUsedPage()
|
ULONG PageSpace::lastUsedPage()
|
||||||
|
@ -37,7 +37,6 @@ namespace Ods {
|
|||||||
struct header_page;
|
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*);
|
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*);
|
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);
|
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(Jrd::thread_db*, bool, const Firebird::TriState newForceWrite = Firebird::TriState());
|
||||||
void PAG_header_init(Jrd::thread_db*);
|
void PAG_header_init(Jrd::thread_db*);
|
||||||
void PAG_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);
|
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_page(Jrd::thread_db* tdbb, const Jrd::PageNumber&, const Jrd::PageNumber&);
|
||||||
void PAG_release_pages(Jrd::thread_db* tdbb, USHORT pageSpaceID, int cntRelease,
|
void PAG_release_pages(Jrd::thread_db* tdbb, USHORT pageSpaceID, int cntRelease,
|
||||||
|
204
src/jrd/sdw.cpp
204
src/jrd/sdw.cpp
@ -64,7 +64,6 @@ static bool check_for_file(thread_db* tdbb, const SCHAR*, USHORT);
|
|||||||
#ifdef NOT_USED_OR_REPLACED
|
#ifdef NOT_USED_OR_REPLACED
|
||||||
static void check_if_got_ast(thread_db* tdbb, jrd_file*);
|
static void check_if_got_ast(thread_db* tdbb, jrd_file*);
|
||||||
#endif
|
#endif
|
||||||
static void copy_header(thread_db* tdbb);
|
|
||||||
static void update_dbb_to_sdw(Database*);
|
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)
|
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
|
// close the main database file if possible and release all file blocks
|
||||||
|
|
||||||
PIO_close(pageSpace->file);
|
PIO_close(pageSpace->file);
|
||||||
|
delete pageSpace->file;
|
||||||
while ( (file = pageSpace->file) )
|
|
||||||
{
|
|
||||||
pageSpace->file = file->fil_next;
|
|
||||||
delete file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* point the main database file at the file of the first shadow
|
/* point the main database file at the file of the first shadow
|
||||||
in the list and mark that shadow as rolled over to
|
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
|
// close the shadow files and free up the associated memory
|
||||||
|
|
||||||
PIO_close(shadow->sdw_file);
|
PIO_close(shadow->sdw_file);
|
||||||
jrd_file* file;
|
delete shadow->sdw_file;
|
||||||
jrd_file* free = shadow->sdw_file;
|
|
||||||
|
|
||||||
for (; (file = free->fil_next); free = file)
|
|
||||||
delete free;
|
|
||||||
|
|
||||||
delete free;
|
|
||||||
delete shadow;
|
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;
|
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;
|
const UCHAR* p = shadow_header->hdr_data;
|
||||||
while (*p != HDR_end && *p != HDR_root_file_name) {
|
while (*p != HDR_end && *p != HDR_root_file_name) {
|
||||||
p += 2 + p[1];
|
p += 2 + p[1];
|
||||||
@ -1046,10 +887,6 @@ void SDW_start(thread_db* tdbb, const TEXT* file_name,
|
|||||||
shadow->sdw_flags |= SDW_dumped;
|
shadow->sdw_flags |= SDW_dumped;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the ancillary files and reset the error environment
|
|
||||||
|
|
||||||
PAG_init2(tdbb, shadow_number);
|
|
||||||
|
|
||||||
} // try
|
} // try
|
||||||
catch (const Firebird::Exception& ex)
|
catch (const Firebird::Exception& ex)
|
||||||
{
|
{
|
||||||
@ -1257,35 +1094,6 @@ static void check_if_got_ast(thread_db* tdbb, jrd_file* file)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
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
|
// hvlad: need sync for this code
|
||||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||||
PIO_close(pageSpace->file);
|
PIO_close(pageSpace->file);
|
||||||
|
delete pageSpace->file;
|
||||||
jrd_file* file;
|
|
||||||
while ( (file = pageSpace->file) )
|
|
||||||
{
|
|
||||||
pageSpace->file = file->fil_next;
|
|
||||||
delete file;
|
|
||||||
}
|
|
||||||
|
|
||||||
pageSpace->file = shadow->sdw_file;
|
pageSpace->file = shadow->sdw_file;
|
||||||
shadow->sdw_flags |= SDW_rollover;
|
shadow->sdw_flags |= SDW_rollover;
|
||||||
|
@ -29,7 +29,6 @@ namespace Jrd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SDW_add(Jrd::thread_db* tdbb, const TEXT*, USHORT, USHORT);
|
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);
|
void SDW_check(Jrd::thread_db* tdbb);
|
||||||
bool SDW_check_conditional(Jrd::thread_db* tdbb);
|
bool SDW_check_conditional(Jrd::thread_db* tdbb);
|
||||||
void SDW_close();
|
void SDW_close();
|
||||||
|
@ -478,7 +478,6 @@ enum dfw_t {
|
|||||||
dfw_create_index,
|
dfw_create_index,
|
||||||
dfw_delete_index,
|
dfw_delete_index,
|
||||||
dfw_compute_security,
|
dfw_compute_security,
|
||||||
dfw_add_file,
|
|
||||||
dfw_add_shadow,
|
dfw_add_shadow,
|
||||||
dfw_delete_shadow,
|
dfw_delete_shadow,
|
||||||
dfw_delete_shadow_nodelete,
|
dfw_delete_shadow_nodelete,
|
||||||
|
@ -2240,27 +2240,32 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
|||||||
case rel_files:
|
case rel_files:
|
||||||
protect_system_table_delupd(tdbb, relation, "DELETE");
|
protect_system_table_delupd(tdbb, relation, "DELETE");
|
||||||
{
|
{
|
||||||
const bool name_defined = EVL_field(0, rpb->rpb_record, f_file_name, &desc);
|
const bool nameDefined = 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 auto shadowNumber = EVL_field(0, rpb->rpb_record, f_file_shad_num, &desc2) ?
|
||||||
MOV_get_long(tdbb, &desc2, 0) : 0;
|
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)
|
if (!(fileFlags & FILE_inactive))
|
||||||
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 (file_flags & FILE_nodelete)
|
const auto work = (fileFlags & FILE_nodelete) ?
|
||||||
DFW_post_work(transaction, dfw_delete_shadow_nodelete, &desc, id);
|
dfw_delete_shadow_nodelete : dfw_delete_shadow;
|
||||||
else
|
|
||||||
DFW_post_work(transaction, dfw_delete_shadow, &desc, id);
|
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;
|
break;
|
||||||
|
|
||||||
@ -3617,18 +3622,24 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
|
|||||||
case rel_files:
|
case rel_files:
|
||||||
protect_system_table_delupd(tdbb, relation, "UPDATE");
|
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);
|
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) &&
|
const auto orgFileFlags = EVL_field(0, org_rpb->rpb_record, f_file_flags, &desc2) ?
|
||||||
EVL_field(0, org_rpb->rpb_record, f_file_flags, &desc2) &&
|
MOV_get_long(tdbb, &desc2, 0) : 0;
|
||||||
((old_rel_flags = MOV_get_long(tdbb, &desc2, 0)) != new_rel_flags))
|
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,
|
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);
|
&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;
|
break;
|
||||||
|
|
||||||
case rel_charsets:
|
case rel_charsets:
|
||||||
@ -4175,34 +4186,32 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
|||||||
case rel_files:
|
case rel_files:
|
||||||
protect_system_table_insert(tdbb, request, relation);
|
protect_system_table_insert(tdbb, request, relation);
|
||||||
{
|
{
|
||||||
const bool name_defined = EVL_field(0, rpb->rpb_record, f_file_name, &desc);
|
const bool nameDefined = 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 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 (!(fileFlags & FILE_inactive))
|
||||||
if (!(MOV_get_long(tdbb, &desc2, 0) & FILE_inactive)) {
|
|
||||||
DFW_post_work(transaction, dfw_add_shadow, &desc, 0);
|
DFW_post_work(transaction, dfw_add_shadow, &desc, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else if (fileFlags & FILE_difference)
|
||||||
{
|
{
|
||||||
USHORT rel_flags;
|
if (nameDefined)
|
||||||
if (EVL_field(0, rpb->rpb_record, f_file_flags, &desc2) &&
|
DFW_post_work(transaction, dfw_add_difference, &desc, 0);
|
||||||
((rel_flags = MOV_get_long(tdbb, &desc2, 0)) & FILE_difference))
|
|
||||||
{
|
if (fileFlags & FILE_backing_up)
|
||||||
if (name_defined) {
|
DFW_post_work(transaction, dfw_begin_backup, &desc, 0);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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;
|
break;
|
||||||
|
|
||||||
case rel_triggers:
|
case rel_triggers:
|
||||||
|
@ -164,10 +164,6 @@ struct dba_rel
|
|||||||
|
|
||||||
struct dba_fil
|
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
|
#ifdef WIN_NT
|
||||||
void *fil_desc;
|
void *fil_desc;
|
||||||
#else
|
#else
|
||||||
@ -216,16 +212,6 @@ static void print_help();
|
|||||||
|
|
||||||
#include "../utilities/gstat/dba_proto.h"
|
#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
|
struct dba_mem
|
||||||
{
|
{
|
||||||
char* memory;
|
char* memory;
|
||||||
@ -241,7 +227,7 @@ public:
|
|||||||
: ThreadData(tddDBA), uSvc(us)
|
: ThreadData(tddDBA), uSvc(us)
|
||||||
{
|
{
|
||||||
//dba_throw = false;
|
//dba_throw = false;
|
||||||
files = 0;
|
file = 0;
|
||||||
relations = 0;
|
relations = 0;
|
||||||
page_size = 0;
|
page_size = 0;
|
||||||
dp_per_pp = 0;
|
dp_per_pp = 0;
|
||||||
@ -252,14 +238,13 @@ public:
|
|||||||
global_buffer = 0;
|
global_buffer = 0;
|
||||||
exit_code = 0;
|
exit_code = 0;
|
||||||
head_of_mem_list = 0;
|
head_of_mem_list = 0;
|
||||||
head_of_files_list = 0;
|
|
||||||
memset(dba_status_vector, 0, sizeof (dba_status_vector));
|
memset(dba_status_vector, 0, sizeof (dba_status_vector));
|
||||||
dba_status = dba_status_vector;
|
dba_status = dba_status_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool dba_throw;
|
//bool dba_throw;
|
||||||
Firebird::UtilSvc* uSvc;
|
Firebird::UtilSvc* uSvc;
|
||||||
dba_fil* files;
|
dba_fil* file;
|
||||||
dba_rel* relations;
|
dba_rel* relations;
|
||||||
USHORT page_size;
|
USHORT page_size;
|
||||||
USHORT dp_per_pp;
|
USHORT dp_per_pp;
|
||||||
@ -270,7 +255,6 @@ public:
|
|||||||
pag* global_buffer;
|
pag* global_buffer;
|
||||||
int exit_code;
|
int exit_code;
|
||||||
dba_mem *head_of_mem_list;
|
dba_mem *head_of_mem_list;
|
||||||
open_files *head_of_files_list;
|
|
||||||
ISC_STATUS *dba_status;
|
ISC_STATUS *dba_status;
|
||||||
ISC_STATUS_ARRAY dba_status_vector;
|
ISC_STATUS_ARRAY dba_status_vector;
|
||||||
|
|
||||||
@ -613,7 +597,7 @@ int gstat(Firebird::UtilSvc* uSvc)
|
|||||||
expandDatabaseName(fileName, tempStr, NULL);
|
expandDatabaseName(fileName, tempStr, NULL);
|
||||||
fileName = tempStr;
|
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)];
|
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);
|
tddba->page_size = MAX(RAW_HEADER_SIZE, DIRECT_IO_BLOCK_SIZE);
|
||||||
@ -661,38 +645,6 @@ int gstat(Firebird::UtilSvc* uSvc)
|
|||||||
if (sw_header)
|
if (sw_header)
|
||||||
dba_exit(FINI_OK, tddba);
|
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(¤t->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)
|
if (sw_enc)
|
||||||
{
|
{
|
||||||
class Statist
|
class Statist
|
||||||
@ -724,6 +676,7 @@ int gstat(Firebird::UtilSvc* uSvc)
|
|||||||
private:
|
private:
|
||||||
ULONG enc, non;
|
ULONG enc, non;
|
||||||
};
|
};
|
||||||
|
|
||||||
Statist data, index, blob, generator, other;
|
Statist data, index, blob, generator, other;
|
||||||
|
|
||||||
ULONG last = lastUsedPage(header->hdr_page_size);
|
ULONG last = lastUsedPage(header->hdr_page_size);
|
||||||
@ -766,18 +719,6 @@ int gstat(Firebird::UtilSvc* uSvc)
|
|||||||
dba_exit(FINI_OK, tddba);
|
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
|
// Check to make sure that the user accessing the database is either
|
||||||
// SYSDBA or owner of the database
|
// SYSDBA or owner of the database
|
||||||
|
|
||||||
@ -1192,22 +1133,11 @@ int gstat(Firebird::UtilSvc* uSvc)
|
|||||||
alloced = alloced->mem_next;
|
alloced = alloced->mem_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// close files
|
// close file
|
||||||
open_files* open_file = tddba->head_of_files_list;
|
if (tddba->file)
|
||||||
while (open_file)
|
db_close(tddba->file->fil_desc);
|
||||||
{
|
|
||||||
db_close(open_file->desc);
|
|
||||||
open_file = open_file->open_files_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// free linked lists
|
// 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)
|
while (tddba->head_of_mem_list != 0)
|
||||||
{
|
{
|
||||||
dba_mem* tmp2 = tddba->head_of_mem_list;
|
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();
|
tdba* tddba = tdba::getSpecific();
|
||||||
|
|
||||||
dba_fil* fil;
|
const auto file = (dba_fil*) alloc(sizeof(dba_fil) + file_length + 1);
|
||||||
|
|
||||||
if (tddba->files)
|
strcpy(file->fil_string, file_name);
|
||||||
{
|
file->fil_length = file_length;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
fil->fil_next = NULL;
|
file->fil_desc = CreateFile(file_name,
|
||||||
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,
|
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
NULL,
|
NULL,
|
||||||
@ -1895,31 +1808,15 @@ static dba_fil* db_open(const char* file_name, USHORT file_length)
|
|||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
0);
|
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);
|
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 29, SafeArg() << file_name);
|
||||||
// msg 29: Can't open database file %s
|
// msg 29: Can't open database file %s
|
||||||
db_error(GetLastError());
|
db_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
open_files* file_list = FB_NEW_POOL(*getDefaultMemoryPool()) open_files;
|
tddba->file = file;
|
||||||
if (!file_list)
|
return file;
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1945,17 +1842,9 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
|
|||||||
|
|
||||||
tddba->page_number = page_number;
|
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;
|
LARGE_INTEGER liOffset;
|
||||||
liOffset.QuadPart = UInt32x32To64((DWORD) page_number, (DWORD) tddba->page_size);
|
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)
|
(DWORD) -1)
|
||||||
{
|
{
|
||||||
int lastError = GetLastError();
|
int lastError = GetLastError();
|
||||||
@ -1968,7 +1857,7 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SLONG actual_length;
|
SLONG actual_length;
|
||||||
if (!ReadFile( fil->fil_desc,
|
if (!ReadFile( tddba->file->fil_desc,
|
||||||
tddba->global_buffer,
|
tddba->global_buffer,
|
||||||
tddba->page_size,
|
tddba->page_size,
|
||||||
reinterpret_cast<LPDWORD>(&actual_length),
|
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();
|
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);
|
strcpy(file->fil_string, file_name);
|
||||||
fil->fil_min_page = 0L;
|
file->fil_length = file_length;
|
||||||
}
|
|
||||||
|
|
||||||
fil->fil_next = NULL;
|
if ((file->fil_desc = os_utils::open(file_name, O_RDONLY)) == -1)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 29, SafeArg() << file_name);
|
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 29, SafeArg() << file_name);
|
||||||
// msg 29: Can't open database file %s
|
// msg 29: Can't open database file %s
|
||||||
db_error(errno);
|
db_error(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
open_files* file_list = FB_NEW_POOL(*getDefaultMemoryPool()) open_files;
|
tddba->file = file;
|
||||||
if (!file_list)
|
return file;
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2127,15 +1982,8 @@ static const pag* db_read( SLONG page_number, bool ok_enc)
|
|||||||
|
|
||||||
tddba->page_number = page_number;
|
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);
|
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());
|
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 30, SafeArg());
|
||||||
// msg 30: Can't read a database page
|
// 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;
|
USHORT length = tddba->page_size;
|
||||||
for (SCHAR* p = (SCHAR *) tddba->global_buffer; length > 0;)
|
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)
|
if (l < 0)
|
||||||
{
|
{
|
||||||
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 30, SafeArg());
|
tddba->uSvc->getStatusAccessor().setServiceStatus(GSTAT_MSG_FAC, 30, SafeArg());
|
||||||
|
@ -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);
|
uSvc->printf(false, "\tRoot file name:\t\t%s\n", temp);
|
||||||
break;
|
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:
|
case HDR_sweep_interval:
|
||||||
memcpy(&number, p + 2, sizeof(number));
|
memcpy(&number, p + 2, sizeof(number));
|
||||||
uSvc->printf(false, "\tSweep interval:\t\t%ld\n", number);
|
uSvc->printf(false, "\tSweep interval:\t\t%ld\n", number);
|
||||||
|
@ -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_pointer(pointer_page*, int, SSHORT, SSHORT, bool, SSHORT, const SLONG*);
|
||||||
static void format_pip(page_inv_page*, int, int);
|
static void format_pip(page_inv_page*, int, int);
|
||||||
static void format_tip(tx_inv_page*, int, SLONG);
|
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_range(TEXT***, const TEXT* const* const, ULONG*, ULONG*);
|
||||||
static void get_switch(TEXT**, swc*);
|
static void get_switch(TEXT**, swc*);
|
||||||
static header_page* open_database(rbdb*, ULONG);
|
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)));
|
rbdb = (rbdb*) RBDB_alloc((SLONG) (sizeof(struct rbdb) + strlen(db_in)));
|
||||||
strcpy(rbdb->rbdb_file.fil_name, db_in);
|
strcpy(rbdb->rbdb_file.fil_name, db_in);
|
||||||
rbdb->rbdb_file.fil_length = strlen(db_in);
|
rbdb->rbdb_file.fil_length = strlen(db_in);
|
||||||
if (header = open_database(rbdb, pg_size))
|
header = open_database(rbdb, pg_size);
|
||||||
get_next_file(rbdb, header);
|
|
||||||
|
|
||||||
// some systems don't care for this write sharing stuff...
|
// some systems don't care for this write sharing stuff...
|
||||||
if (rbdb && (sw_dump_tips || sw_dump_pages))
|
if (rbdb && (sw_dump_tips || sw_dump_pages))
|
||||||
@ -210,7 +208,6 @@ int main( int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gdbb = &tdbb_struct;
|
gdbb = &tdbb_struct;
|
||||||
gdbb->tdbb_database = &dbb_struct;
|
gdbb->tdbb_database = &dbb_struct;
|
||||||
gdbb->tdbb_transaction = &dull;
|
gdbb->tdbb_transaction = &dull;
|
||||||
@ -252,17 +249,15 @@ int main( int argc, char *argv[])
|
|||||||
fclose(dbg_file);
|
fclose(dbg_file);
|
||||||
|
|
||||||
if (rbdb)
|
if (rbdb)
|
||||||
|
{
|
||||||
RBDB_close(rbdb);
|
RBDB_close(rbdb);
|
||||||
|
|
||||||
while (rbdb)
|
|
||||||
{
|
|
||||||
rbdb* const next_db = rbdb->rbdb_next;
|
|
||||||
if (rbdb->rbdb_buffer1)
|
if (rbdb->rbdb_buffer1)
|
||||||
gds__free(rbdb->rbdb_buffer1);
|
gds__free(rbdb->rbdb_buffer1);
|
||||||
if (rbdb->rbdb_buffer2)
|
if (rbdb->rbdb_buffer2)
|
||||||
gds__free(rbdb->rbdb_buffer2);
|
gds__free(rbdb->rbdb_buffer2);
|
||||||
|
|
||||||
gds__free(rbdb);
|
gds__free(rbdb);
|
||||||
rbdb = next_db;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -332,8 +327,7 @@ void RBDB_close( rbdb* rbdb)
|
|||||||
* Functional description
|
* 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)
|
static void get_range(TEXT*** argv, const TEXT* const* const end, ULONG* lower, ULONG* upper)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user