8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 20:03:03 +01:00
firebird-mirror/src/alice/exe.cpp

416 lines
11 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
//____________________________________________________________
//
2001-05-23 15:26:42 +02:00
// PROGRAM: Alice (All Else) Utility
// MODULE: exe.cpp
// DESCRIPTION: Does the database calls
//
2001-05-23 15:26:42 +02:00
// The contents of this file are subject to the Interbase Public
// License Version 1.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy
// of the License at http://www.Inprise.com/IPL.html
//
2001-05-23 15:26:42 +02:00
// Software distributed under the License is distributed on an
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
// or implied. See the License for the specific language governing
// rights and limitations under the License.
//
2001-05-23 15:26:42 +02:00
// The Original Code was created by Inprise Corporation
// and its predecessors. Portions created by Inprise Corporation are
// Copyright (C) Inprise Corporation.
//
2001-05-23 15:26:42 +02:00
// All Rights Reserved.
// Contributor(s): ______________________________________.
//
2001-05-23 15:26:42 +02:00
//
//____________________________________________________________
//
//
// 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
// conditionals, as the engine now fully supports
// readonly databases.
2001-05-23 15:26:42 +02:00
//
// 2002.10.30 Sean Leyne - Removed obsolete "PC_PLATFORM" define
//
2001-05-23 15:26:42 +02:00
#include "firebird.h"
2004-04-29 00:00:03 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <stdlib.h>
#include <string.h>
2003-11-08 00:09:04 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/common.h"
#include "../alice/alice.h"
#include "../alice/alice_proto.h"
2001-05-23 15:26:42 +02:00
#include "../alice/aliceswi.h"
#include "../alice/alice_meta.h"
#include "../alice/tdr_proto.h"
#include "../jrd/gds_proto.h"
2008-01-16 06:58:53 +01:00
#include "../jrd/constants.h"
#include "../common/classes/ClumpletWriter.h"
2001-05-23 15:26:42 +02:00
static void buildDpb(Firebird::ClumpletWriter&, const ULONG);
static void extract_db_info(const UCHAR*, size_t);
2001-05-23 15:26:42 +02:00
// Keep always in sync with function extract_db_info()
static const TEXT val_errors[] =
2001-05-23 15:26:42 +02:00
{
isc_info_page_errors, isc_info_record_errors, isc_info_bpage_errors,
isc_info_dpage_errors, isc_info_ipage_errors, isc_info_ppage_errors,
2003-11-08 00:09:04 +01:00
isc_info_tpage_errors, isc_info_end
2001-05-23 15:26:42 +02:00
};
//____________________________________________________________
//
//
2001-05-23 15:26:42 +02:00
int EXE_action(const TEXT* database, const ULONG switches)
2001-05-23 15:26:42 +02:00
{
bool error = false;
2008-01-29 13:28:28 +01:00
Firebird::AutoMemoryPool newPool(MemoryPool::createPool());
{
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
AliceContextPoolHolder context(tdgbl, newPool);
2001-05-23 15:26:42 +02:00
for (USHORT i = 0; i < MAX_VAL_ERRORS; i++)
{
tdgbl->ALICE_data.ua_val_errors[i] = 0;
}
2001-05-23 15:26:42 +02:00
// generate the database parameter block for the attach,
// based on the various switches
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE);
2004-12-10 23:54:16 +01:00
buildDpb(dpb, switches);
2001-05-23 15:26:42 +02:00
FB_API_HANDLE handle = 0;
isc_attach_database(tdgbl->status, 0, database, &handle,
dpb.getBufferLength(),
reinterpret_cast<const SCHAR*>(dpb.getBuffer()));
2001-05-23 15:26:42 +02:00
2008-01-16 06:58:53 +01:00
tdgbl->uSvc->started();
2001-05-23 15:26:42 +02:00
if (tdgbl->status[1] &&
// Ignore isc_shutdown error produced when we switch to full shutdown mode. It is expected.
(tdgbl->status[1] != isc_shutdown || !(switches & sw_shut) || tdgbl->ALICE_data.ua_shutdown_mode != SHUT_FULL)
)
{
error = true;
}
if (tdgbl->status[2] == isc_arg_warning)
{
ALICE_print_status(tdgbl->status);
}
2001-05-23 15:26:42 +02:00
if (handle != 0)
{
UCHAR error_string[128];
if ((switches & sw_validate) && (tdgbl->status[1] != isc_bug_check))
{
isc_database_info(tdgbl->status, &handle, sizeof(val_errors),
2003-08-30 04:02:36 +02:00
val_errors, sizeof(error_string),
reinterpret_cast<char*>(error_string));
2001-05-23 15:26:42 +02:00
extract_db_info(error_string, sizeof(error_string));
}
2001-05-23 15:26:42 +02:00
if (switches & sw_disable)
{
MET_disable_wal(tdgbl->status, handle);
}
2001-05-23 15:26:42 +02:00
isc_detach_database(tdgbl->status, &handle);
}
2001-05-23 15:26:42 +02:00
}
return ((error) ? FINI_ERROR : FINI_OK);
}
//____________________________________________________________
//
//
2001-05-23 15:26:42 +02:00
int EXE_two_phase(const TEXT* database, const ULONG switches)
2001-05-23 15:26:42 +02:00
{
bool error = false;
2008-01-29 13:28:28 +01:00
Firebird::AutoMemoryPool newPool(MemoryPool::createPool());
{
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
AliceContextPoolHolder context(tdgbl, newPool);
2001-05-23 15:26:42 +02:00
for (USHORT i = 0; i < MAX_VAL_ERRORS; i++)
{
tdgbl->ALICE_data.ua_val_errors[i] = 0;
}
2001-05-23 15:26:42 +02:00
// generate the database parameter block for the attach,
// based on the various switches
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE);
2004-12-10 23:54:16 +01:00
buildDpb(dpb, switches);
2001-05-23 15:26:42 +02:00
FB_API_HANDLE handle = 0;
isc_attach_database(tdgbl->status, 0, database, &handle,
dpb.getBufferLength(),
reinterpret_cast<const SCHAR*>(dpb.getBuffer()));
2001-05-23 15:26:42 +02:00
2008-01-16 06:58:53 +01:00
tdgbl->uSvc->started();
2001-05-23 15:26:42 +02:00
if (tdgbl->status[1])
{
error = true;
}
else if (switches & sw_list)
{
TDR_list_limbo((handle), database, switches);
}
else if (switches & (sw_commit | sw_rollback | sw_two_phase))
{
error = TDR_reconnect_multiple((handle),
2003-09-10 19:52:12 +02:00
tdgbl->ALICE_data.ua_transaction, database,
switches);
}
2001-05-23 15:26:42 +02:00
if (handle)
{
isc_detach_database(tdgbl->status, &handle);
}
}
2001-05-23 15:26:42 +02:00
return (error ? FINI_ERROR : FINI_OK);
2001-05-23 15:26:42 +02:00
}
//____________________________________________________________
//
//
// generate the database parameter block for the attach,
// based on the various switches
//
2001-05-23 15:26:42 +02:00
2004-12-10 23:54:16 +01:00
static void buildDpb(Firebird::ClumpletWriter& dpb, const ULONG switches)
2001-05-23 15:26:42 +02:00
{
2004-07-02 12:02:46 +02:00
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
dpb.reset(isc_dpb_version1);
dpb.insertTag(isc_dpb_gfix_attach);
2001-05-23 15:26:42 +02:00
if (switches & sw_sweep) {
dpb.insertByte(isc_dpb_sweep, isc_dpb_records);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_activate) {
dpb.insertTag(isc_dpb_activate_shadow);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_validate) {
UCHAR b = isc_dpb_pages;
2001-05-23 15:26:42 +02:00
if (switches & sw_full)
b |= isc_dpb_records;
2001-05-23 15:26:42 +02:00
if (switches & sw_no_update)
b |= isc_dpb_no_update;
2001-05-23 15:26:42 +02:00
if (switches & sw_mend)
b |= isc_dpb_repair;
2001-05-23 15:26:42 +02:00
if (switches & sw_ignore)
b |= isc_dpb_ignore;
dpb.insertByte(isc_dpb_verify, b);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_housekeeping) {
dpb.insertInt(isc_dpb_sweep_interval,
tdgbl->ALICE_data.ua_sweep_interval);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_begin_log) {
dpb.insertString(isc_dpb_begin_log,
tdgbl->ALICE_data.ua_log_file,
strlen(tdgbl->ALICE_data.ua_log_file));
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_buffers) {
dpb.insertInt(isc_dpb_set_page_buffers,
tdgbl->ALICE_data.ua_page_buffers);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_quit_log) {
dpb.insertTag(isc_dpb_quit_log);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_kill) {
dpb.insertTag(isc_dpb_delete_shadow);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_write) {
dpb.insertByte(isc_dpb_force_write,
tdgbl->ALICE_data.ua_force ? 1 : 0);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_use) {
dpb.insertByte(isc_dpb_no_reserve,
tdgbl->ALICE_data.ua_use ? 1 : 0);
2001-05-23 15:26:42 +02:00
}
2001-05-23 15:26:42 +02:00
else if (switches & sw_mode) {
dpb.insertByte(isc_dpb_set_db_readonly,
tdgbl->ALICE_data.ua_read_only ? 1 : 0);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_shut) {
2004-12-10 23:54:16 +01:00
UCHAR b = 0;
2001-05-23 15:26:42 +02:00
if (switches & sw_attach)
b |= isc_dpb_shut_attachment;
2001-05-23 15:26:42 +02:00
else if (switches & sw_cache)
b |= isc_dpb_shut_cache;
2001-05-23 15:26:42 +02:00
else if (switches & sw_force)
b |= isc_dpb_shut_force;
2001-05-23 15:26:42 +02:00
else if (switches & sw_tran)
b |= isc_dpb_shut_transaction;
switch (tdgbl->ALICE_data.ua_shutdown_mode) {
case SHUT_NORMAL:
b |= isc_dpb_shut_normal;
break;
case SHUT_SINGLE:
b |= isc_dpb_shut_single;
break;
case SHUT_MULTI:
b |= isc_dpb_shut_multi;
break;
case SHUT_FULL:
b |= isc_dpb_shut_full;
break;
default:
break;
}
dpb.insertByte(isc_dpb_shutdown, b);
// SSHORT is used for timeouts inside engine,
// therefore convert larger values to MAX_SSHORT
SLONG timeout = tdgbl->ALICE_data.ua_shutdown_delay;
if (timeout > MAX_SSHORT)
{
timeout = MAX_SSHORT;
}
dpb.insertInt(isc_dpb_shutdown_delay, timeout);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_online) {
2004-12-10 23:54:16 +01:00
UCHAR b = 0;
switch (tdgbl->ALICE_data.ua_shutdown_mode) {
case SHUT_NORMAL:
b |= isc_dpb_shut_normal;
break;
case SHUT_SINGLE:
b |= isc_dpb_shut_single;
break;
case SHUT_MULTI:
b |= isc_dpb_shut_multi;
break;
case SHUT_FULL:
b |= isc_dpb_shut_full;
break;
default:
break;
}
dpb.insertByte(isc_dpb_online, b);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_disable) {
dpb.insertTag(isc_dpb_disable_wal);
2001-05-23 15:26:42 +02:00
}
else if (switches & (sw_list | sw_commit | sw_rollback | sw_two_phase)) {
dpb.insertTag(isc_dpb_no_garbage_collect);
2001-05-23 15:26:42 +02:00
}
else if (switches & sw_set_db_dialect) {
dpb.insertInt(isc_dpb_set_db_sql_dialect,
tdgbl->ALICE_data.ua_db_SQL_dialect);
2001-05-23 15:26:42 +02:00
}
if (tdgbl->ALICE_data.ua_user) {
dpb.insertString(isc_dpb_user_name,
tdgbl->ALICE_data.ua_user,
strlen(tdgbl->ALICE_data.ua_user));
2001-05-23 15:26:42 +02:00
}
if (tdgbl->ALICE_data.ua_password) {
2008-01-16 06:58:53 +01:00
dpb.insertString(tdgbl->uSvc->isService() ? isc_dpb_password_enc :
isc_dpb_password,
tdgbl->ALICE_data.ua_password,
strlen(tdgbl->ALICE_data.ua_password));
2001-05-23 15:26:42 +02:00
}
2006-12-08 19:38:15 +01:00
if (tdgbl->ALICE_data.ua_tr_user) {
2008-01-16 06:58:53 +01:00
tdgbl->uSvc->checkService();
dpb.insertString(isc_dpb_trusted_auth,
tdgbl->ALICE_data.ua_tr_user,
strlen(tdgbl->ALICE_data.ua_tr_user));
2006-12-08 19:38:15 +01:00
}
2008-01-16 06:58:53 +01:00
if (tdgbl->ALICE_data.ua_tr_role) {
tdgbl->uSvc->checkService();
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
}
#ifdef TRUSTED_AUTH
if (tdgbl->ALICE_data.ua_trusted) {
if (!dpb.find(isc_dpb_trusted_auth)) {
dpb.insertTag(isc_dpb_trusted_auth);
}
}
#endif
2001-05-23 15:26:42 +02:00
}
//____________________________________________________________
//
2001-05-23 15:26:42 +02:00
// Extract database info from string
//
2001-05-23 15:26:42 +02:00
static void extract_db_info(const UCHAR* db_info_buffer, size_t buf_size)
2001-05-23 15:26:42 +02:00
{
2004-07-02 12:02:46 +02:00
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
2001-05-23 15:26:42 +02:00
const UCHAR* p = db_info_buffer;
const UCHAR* const end = p + buf_size;
2001-05-23 15:26:42 +02:00
UCHAR item;
while ((item = *p++) != isc_info_end && p < end - 1)
{
const SLONG length = gds__vax_integer(p, 2);
2001-05-23 15:26:42 +02:00
p += 2;
// TMN: Here we should really have the following assert
2003-11-04 00:59:24 +01:00
// fb_assert(length <= MAX_SSHORT);
// for all cases that use 'length' as input to 'gds__vax_integer'
// Remember to keep this list in sync with the val_errors array.
2007-09-10 02:45:40 +02:00
switch (item)
{
2001-05-23 15:26:42 +02:00
case isc_info_page_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_PAGE_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_record_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_RECORD_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_bpage_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_BLOB_PAGE_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_dpage_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_DATA_PAGE_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_ipage_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_INDEX_PAGE_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_ppage_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_POINTER_PAGE_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_tpage_errors:
tdgbl->ALICE_data.ua_val_errors[VAL_TIP_PAGE_ERRORS] =
gds__vax_integer(p, (SSHORT) length);
2001-05-23 15:26:42 +02:00
break;
case isc_info_error:
/* has to be a < V4 database. */
tdgbl->ALICE_data.ua_val_errors[VAL_INVALID_DB_VERSION] = 1;
return;
default:
fb_assert(false);
2001-05-23 15:26:42 +02:00
}
2007-09-10 02:45:40 +02:00
p += length;
2001-05-23 15:26:42 +02:00
}
}