1
//____________________________________________________________
3
// PROGRAM: Alice (All Else) Utility
5
// DESCRIPTION: Does the database calls
7
// The contents of this file are subject to the Interbase Public
8
// License Version 1.0 (the "License"); you may not use this file
9
// except in compliance with the License. You may obtain a copy
10
// of the License at http://www.Inprise.com/IPL.html
12
// Software distributed under the License is distributed on an
13
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
14
// or implied. See the License for the specific language governing
15
// rights and limitations under the License.
17
// The Original Code was created by Inprise Corporation
18
// and its predecessors. Portions created by Inprise Corporation are
19
// Copyright (C) Inprise Corporation.
21
// All Rights Reserved.
22
// Contributor(s): ______________________________________.
25
//____________________________________________________________
28
// 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
29
// conditionals, as the engine now fully supports
30
// readonly databases.
32
// 2002.10.30 Sean Leyne - Removed obsolete "PC_PLATFORM" define
39
#include "../jrd/ibase.h"
40
#include "../jrd/common.h"
41
#include "../alice/alice.h"
42
#include "../alice/alice_proto.h"
43
#include "../alice/aliceswi.h"
44
#include "../alice/all.h"
45
#include "../alice/all_proto.h"
46
#include "../alice/alice_meta.h"
47
#include "../alice/tdr_proto.h"
48
#include "../jrd/gds_proto.h"
49
#include "../jrd/thd.h"
50
#include "../common/classes/ClumpletWriter.h"
53
static void buildDpb(Firebird::ClumpletWriter&, const ULONG);
54
static void extract_db_info(const UCHAR*, size_t);
56
// Keep always in sync with function extract_db_info()
57
static const TEXT val_errors[] =
59
isc_info_page_errors, isc_info_record_errors, isc_info_bpage_errors,
60
isc_info_dpage_errors, isc_info_ipage_errors, isc_info_ppage_errors,
61
isc_info_tpage_errors, isc_info_end
65
//____________________________________________________________
69
int EXE_action(const TEXT* database, const ULONG switches)
72
AliceAutoPool newPool(AliceMemoryPool::createPool());
74
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
75
AliceContextPoolHolder context(tdgbl, newPool);
77
for (USHORT i = 0; i < MAX_VAL_ERRORS; i++)
79
tdgbl->ALICE_data.ua_val_errors[i] = 0;
82
// generate the database parameter block for the attach,
83
// based on the various switches
84
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE);
85
buildDpb(dpb, switches);
87
FB_API_HANDLE handle = 0;
88
isc_attach_database(tdgbl->status, 0, database, &handle,
89
dpb.getBufferLength(),
90
reinterpret_cast<const SCHAR*>(dpb.getBuffer()));
92
tdgbl->service_blk->svc_started();
94
if (tdgbl->status[1] &&
95
// Ignore isc_shutdown error produced when we switch to full shutdown mode. It is expected.
96
(tdgbl->status[1] != isc_shutdown || !(switches & sw_shut) || tdgbl->ALICE_data.ua_shutdown_mode != SHUT_FULL)
102
if (tdgbl->status[2] == isc_arg_warning)
104
ALICE_print_status(tdgbl->status);
109
UCHAR error_string[128];
110
if ((switches & sw_validate) && (tdgbl->status[1] != isc_bug_check))
112
isc_database_info(tdgbl->status, &handle, sizeof(val_errors),
113
val_errors, sizeof(error_string),
114
reinterpret_cast<char*>(error_string));
116
extract_db_info(error_string, sizeof(error_string));
119
if (switches & sw_disable)
121
MET_disable_wal(tdgbl->status, handle);
124
isc_detach_database(tdgbl->status, &handle);
128
return ((error) ? FINI_ERROR : FINI_OK);
132
//____________________________________________________________
136
int EXE_two_phase(const TEXT* database, const ULONG switches)
139
AliceAutoPool newPool(AliceMemoryPool::createPool());
141
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
142
AliceContextPoolHolder context(tdgbl, newPool);
144
for (USHORT i = 0; i < MAX_VAL_ERRORS; i++)
146
tdgbl->ALICE_data.ua_val_errors[i] = 0;
149
// generate the database parameter block for the attach,
150
// based on the various switches
151
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE);
152
buildDpb(dpb, switches);
154
FB_API_HANDLE handle = 0;
155
isc_attach_database(tdgbl->status, 0, database, &handle,
156
dpb.getBufferLength(),
157
reinterpret_cast<const SCHAR*>(dpb.getBuffer()));
159
tdgbl->service_blk->svc_started();
161
if (tdgbl->status[1])
165
else if (switches & sw_list)
167
TDR_list_limbo((handle), database, switches);
169
else if (switches & (sw_commit | sw_rollback | sw_two_phase))
171
error = TDR_reconnect_multiple((handle),
172
tdgbl->ALICE_data.ua_transaction, database,
178
isc_detach_database(tdgbl->status, &handle);
182
return (error ? FINI_ERROR : FINI_OK);
185
//____________________________________________________________
188
// generate the database parameter block for the attach,
189
// based on the various switches
192
static void buildDpb(Firebird::ClumpletWriter& dpb, const ULONG switches)
194
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
195
dpb.reset(isc_dpb_version1);
196
dpb.insertTag(isc_dpb_gfix_attach);
198
if (switches & sw_sweep) {
199
dpb.insertByte(isc_dpb_sweep, isc_dpb_records);
201
else if (switches & sw_activate) {
202
dpb.insertTag(isc_dpb_activate_shadow);
204
else if (switches & sw_validate) {
205
UCHAR b = isc_dpb_pages;
206
if (switches & sw_full)
207
b |= isc_dpb_records;
208
if (switches & sw_no_update)
209
b |= isc_dpb_no_update;
210
if (switches & sw_mend)
212
if (switches & sw_ignore)
214
dpb.insertByte(isc_dpb_verify, b);
216
else if (switches & sw_housekeeping) {
217
dpb.insertInt(isc_dpb_sweep_interval,
218
tdgbl->ALICE_data.ua_sweep_interval);
220
else if (switches & sw_begin_log) {
221
dpb.insertString(isc_dpb_begin_log,
222
tdgbl->ALICE_data.ua_log_file,
223
strlen(tdgbl->ALICE_data.ua_log_file));
225
else if (switches & sw_buffers) {
226
dpb.insertInt(isc_dpb_set_page_buffers,
227
tdgbl->ALICE_data.ua_page_buffers);
229
else if (switches & sw_quit_log) {
230
dpb.insertTag(isc_dpb_quit_log);
232
else if (switches & sw_kill) {
233
dpb.insertTag(isc_dpb_delete_shadow);
235
else if (switches & sw_write) {
236
dpb.insertByte(isc_dpb_force_write,
237
tdgbl->ALICE_data.ua_force ? 1 : 0);
239
else if (switches & sw_use) {
240
dpb.insertByte(isc_dpb_no_reserve,
241
tdgbl->ALICE_data.ua_use ? 1 : 0);
244
else if (switches & sw_mode) {
245
dpb.insertByte(isc_dpb_set_db_readonly,
246
tdgbl->ALICE_data.ua_read_only ? 1 : 0);
248
else if (switches & sw_shut) {
250
if (switches & sw_attach)
251
b |= isc_dpb_shut_attachment;
252
else if (switches & sw_cache)
253
b |= isc_dpb_shut_cache;
254
else if (switches & sw_force)
255
b |= isc_dpb_shut_force;
256
else if (switches & sw_tran)
257
b |= isc_dpb_shut_transaction;
258
switch (tdgbl->ALICE_data.ua_shutdown_mode) {
260
b |= isc_dpb_shut_normal;
263
b |= isc_dpb_shut_single;
266
b |= isc_dpb_shut_multi;
269
b |= isc_dpb_shut_full;
274
dpb.insertByte(isc_dpb_shutdown, b);
275
// SSHORT is used for timeouts inside engine,
276
// therefore convert larger values to MAX_SSHORT
277
SLONG timeout = tdgbl->ALICE_data.ua_shutdown_delay;
278
if (timeout > MAX_SSHORT)
280
timeout = MAX_SSHORT;
282
dpb.insertInt(isc_dpb_shutdown_delay, timeout);
284
else if (switches & sw_online) {
286
switch (tdgbl->ALICE_data.ua_shutdown_mode) {
288
b |= isc_dpb_shut_normal;
291
b |= isc_dpb_shut_single;
294
b |= isc_dpb_shut_multi;
297
b |= isc_dpb_shut_full;
302
dpb.insertByte(isc_dpb_online, b);
304
else if (switches & sw_disable) {
305
dpb.insertTag(isc_dpb_disable_wal);
307
else if (switches & (sw_list | sw_commit | sw_rollback | sw_two_phase)) {
308
dpb.insertTag(isc_dpb_no_garbage_collect);
310
else if (switches & sw_set_db_dialect) {
311
dpb.insertInt(isc_dpb_set_db_sql_dialect,
312
tdgbl->ALICE_data.ua_db_SQL_dialect);
315
if (tdgbl->ALICE_data.ua_user) {
316
dpb.insertString(isc_dpb_user_name,
317
tdgbl->ALICE_data.ua_user,
318
strlen(tdgbl->ALICE_data.ua_user));
320
if (tdgbl->ALICE_data.ua_password) {
321
dpb.insertString(tdgbl->sw_service ? isc_dpb_password_enc :
323
tdgbl->ALICE_data.ua_password,
324
strlen(tdgbl->ALICE_data.ua_password));
326
#ifdef TRUSTED_SERVICES
327
if (tdgbl->ALICE_data.ua_tr_user) {
328
dpb.insertString(isc_dpb_trusted_auth,
329
tdgbl->ALICE_data.ua_tr_user,
330
strlen(tdgbl->ALICE_data.ua_tr_user));
334
if (tdgbl->ALICE_data.ua_trusted) {
335
if (!dpb.find(isc_dpb_trusted_auth)) {
336
dpb.insertTag(isc_dpb_trusted_auth);
343
//____________________________________________________________
345
// Extract database info from string
348
static void extract_db_info(const UCHAR* db_info_buffer, size_t buf_size)
350
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
352
const UCHAR* p = db_info_buffer;
353
const UCHAR* const end = p + buf_size;
356
while ((item = *p++) != isc_info_end && p < end - 1)
358
const SLONG length = gds__vax_integer(p, 2);
361
// TMN: Here we should really have the following assert
362
// fb_assert(length <= MAX_SSHORT);
363
// for all cases that use 'length' as input to 'gds__vax_integer'
364
// Remember to keep this list in sync with the val_errors array.
367
case isc_info_page_errors:
368
tdgbl->ALICE_data.ua_val_errors[VAL_PAGE_ERRORS] =
369
gds__vax_integer(p, (SSHORT) length);
372
case isc_info_record_errors:
373
tdgbl->ALICE_data.ua_val_errors[VAL_RECORD_ERRORS] =
374
gds__vax_integer(p, (SSHORT) length);
377
case isc_info_bpage_errors:
378
tdgbl->ALICE_data.ua_val_errors[VAL_BLOB_PAGE_ERRORS] =
379
gds__vax_integer(p, (SSHORT) length);
382
case isc_info_dpage_errors:
383
tdgbl->ALICE_data.ua_val_errors[VAL_DATA_PAGE_ERRORS] =
384
gds__vax_integer(p, (SSHORT) length);
387
case isc_info_ipage_errors:
388
tdgbl->ALICE_data.ua_val_errors[VAL_INDEX_PAGE_ERRORS] =
389
gds__vax_integer(p, (SSHORT) length);
392
case isc_info_ppage_errors:
393
tdgbl->ALICE_data.ua_val_errors[VAL_POINTER_PAGE_ERRORS] =
394
gds__vax_integer(p, (SSHORT) length);
397
case isc_info_tpage_errors:
398
tdgbl->ALICE_data.ua_val_errors[VAL_TIP_PAGE_ERRORS] =
399
gds__vax_integer(p, (SSHORT) length);
403
/* has to be a < V4 database. */
405
tdgbl->ALICE_data.ua_val_errors[VAL_INVALID_DB_VERSION] = 1;