~ubuntu-branches/ubuntu/karmic/firebird2.1/karmic

« back to all changes in this revision

Viewing changes to src/alice/exe.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2008-05-26 23:59:25 UTC
  • Revision ID: james.westby@ubuntu.com-20080526235925-2pnqj6nxpppoeaer
Tags: upstream-2.1.0.17798-0.ds2
ImportĀ upstreamĀ versionĀ 2.1.0.17798-0.ds2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//____________________________________________________________
 
2
//
 
3
//              PROGRAM:        Alice (All Else) Utility
 
4
//              MODULE:         exe.cpp
 
5
//              DESCRIPTION:    Does the database calls
 
6
//
 
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
 
11
//
 
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.
 
16
//
 
17
//  The Original Code was created by Inprise Corporation
 
18
//  and its predecessors. Portions created by Inprise Corporation are
 
19
//  Copyright (C) Inprise Corporation.
 
20
//
 
21
//  All Rights Reserved.
 
22
//  Contributor(s): ______________________________________.
 
23
//
 
24
//
 
25
//____________________________________________________________
 
26
//
 
27
//
 
28
// 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
 
29
//                         conditionals, as the engine now fully supports
 
30
//                         readonly databases.
 
31
//
 
32
// 2002.10.30 Sean Leyne - Removed obsolete "PC_PLATFORM" define
 
33
//
 
34
 
 
35
#include "firebird.h"
 
36
#include <stdio.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
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"
 
51
 
 
52
 
 
53
static void buildDpb(Firebird::ClumpletWriter&, const ULONG);
 
54
static void extract_db_info(const UCHAR*, size_t);
 
55
 
 
56
// Keep always in sync with function extract_db_info()
 
57
static const TEXT val_errors[] =
 
58
{
 
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
 
62
};
 
63
 
 
64
 
 
65
//____________________________________________________________
 
66
//
 
67
//
 
68
 
 
69
int EXE_action(const TEXT* database, const ULONG switches)
 
70
{
 
71
        bool error = false;
 
72
        AliceAutoPool newPool(AliceMemoryPool::createPool());
 
73
        {
 
74
                AliceGlobals* tdgbl = AliceGlobals::getSpecific();
 
75
                AliceContextPoolHolder context(tdgbl, newPool);
 
76
 
 
77
                for (USHORT i = 0; i < MAX_VAL_ERRORS; i++)
 
78
                {
 
79
                        tdgbl->ALICE_data.ua_val_errors[i] = 0;
 
80
                }
 
81
 
 
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);
 
86
 
 
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()));
 
91
 
 
92
                tdgbl->service_blk->svc_started();
 
93
 
 
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)
 
97
                )
 
98
                {
 
99
                        error = true;
 
100
                }
 
101
                
 
102
                if (tdgbl->status[2] == isc_arg_warning)
 
103
                {
 
104
                        ALICE_print_status(tdgbl->status);
 
105
                }
 
106
 
 
107
                if (handle != 0) 
 
108
                {
 
109
                        UCHAR error_string[128];
 
110
                        if ((switches & sw_validate) && (tdgbl->status[1] != isc_bug_check))
 
111
                        {
 
112
                                isc_database_info(tdgbl->status, &handle, sizeof(val_errors),
 
113
                                                           val_errors, sizeof(error_string),
 
114
                                                           reinterpret_cast<char*>(error_string));
 
115
 
 
116
                                extract_db_info(error_string, sizeof(error_string));
 
117
                        }
 
118
 
 
119
                        if (switches & sw_disable)
 
120
                        {
 
121
                                MET_disable_wal(tdgbl->status, handle);
 
122
                        }
 
123
 
 
124
                        isc_detach_database(tdgbl->status, &handle);
 
125
                }
 
126
        }
 
127
 
 
128
        return ((error) ? FINI_ERROR : FINI_OK);
 
129
}
 
130
 
 
131
 
 
132
//____________________________________________________________
 
133
//
 
134
//
 
135
 
 
136
int EXE_two_phase(const TEXT* database, const ULONG switches)
 
137
{
 
138
        bool error = false;
 
139
        AliceAutoPool newPool(AliceMemoryPool::createPool());
 
140
        {
 
141
                AliceGlobals* tdgbl = AliceGlobals::getSpecific();
 
142
                AliceContextPoolHolder context(tdgbl, newPool);
 
143
 
 
144
                for (USHORT i = 0; i < MAX_VAL_ERRORS; i++)
 
145
                {
 
146
                        tdgbl->ALICE_data.ua_val_errors[i] = 0;
 
147
                }
 
148
 
 
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);
 
153
 
 
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()));
 
158
 
 
159
                tdgbl->service_blk->svc_started();
 
160
 
 
161
                if (tdgbl->status[1])
 
162
                {
 
163
                        error = true;
 
164
                }
 
165
                else if (switches & sw_list)
 
166
                {
 
167
                        TDR_list_limbo((handle), database, switches);
 
168
                }
 
169
                else if (switches & (sw_commit | sw_rollback | sw_two_phase))
 
170
                {
 
171
                        error = TDR_reconnect_multiple((handle),
 
172
                                                                           tdgbl->ALICE_data.ua_transaction, database,
 
173
                                                                           switches);
 
174
                }
 
175
 
 
176
                if (handle)
 
177
                {
 
178
                        isc_detach_database(tdgbl->status, &handle);
 
179
                }
 
180
        }
 
181
 
 
182
        return (error ? FINI_ERROR : FINI_OK);
 
183
}
 
184
 
 
185
//____________________________________________________________
 
186
//
 
187
//
 
188
//  generate the database parameter block for the attach,
 
189
//  based on the various switches
 
190
//
 
191
 
 
192
static void buildDpb(Firebird::ClumpletWriter& dpb, const ULONG switches)
 
193
{
 
194
        AliceGlobals* tdgbl = AliceGlobals::getSpecific();
 
195
        dpb.reset(isc_dpb_version1);
 
196
        dpb.insertTag(isc_dpb_gfix_attach);
 
197
 
 
198
        if (switches & sw_sweep) {
 
199
                dpb.insertByte(isc_dpb_sweep, isc_dpb_records);
 
200
        }
 
201
        else if (switches & sw_activate) {
 
202
                dpb.insertTag(isc_dpb_activate_shadow);
 
203
        }
 
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)
 
211
                        b |= isc_dpb_repair;
 
212
                if (switches & sw_ignore)
 
213
                        b |= isc_dpb_ignore;
 
214
                dpb.insertByte(isc_dpb_verify, b);
 
215
        }
 
216
        else if (switches & sw_housekeeping) {
 
217
                dpb.insertInt(isc_dpb_sweep_interval, 
 
218
                                          tdgbl->ALICE_data.ua_sweep_interval);
 
219
        }
 
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));
 
224
        }
 
225
        else if (switches & sw_buffers) {
 
226
                dpb.insertInt(isc_dpb_set_page_buffers, 
 
227
                                          tdgbl->ALICE_data.ua_page_buffers);
 
228
        }
 
229
        else if (switches & sw_quit_log) {
 
230
                dpb.insertTag(isc_dpb_quit_log);
 
231
        }
 
232
        else if (switches & sw_kill) {
 
233
                dpb.insertTag(isc_dpb_delete_shadow);
 
234
        }
 
235
        else if (switches & sw_write) {
 
236
                dpb.insertByte(isc_dpb_force_write, 
 
237
                                           tdgbl->ALICE_data.ua_force ? 1 : 0);
 
238
        }
 
239
        else if (switches & sw_use) {
 
240
                dpb.insertByte(isc_dpb_no_reserve, 
 
241
                                           tdgbl->ALICE_data.ua_use ? 1 : 0);
 
242
        }
 
243
 
 
244
        else if (switches & sw_mode) {
 
245
                dpb.insertByte(isc_dpb_set_db_readonly,
 
246
                                           tdgbl->ALICE_data.ua_read_only ? 1 : 0);
 
247
        }
 
248
        else if (switches & sw_shut) {
 
249
                UCHAR b = 0;
 
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) {
 
259
                case SHUT_NORMAL:
 
260
                        b |= isc_dpb_shut_normal;
 
261
                        break;
 
262
                case SHUT_SINGLE:
 
263
                        b |= isc_dpb_shut_single;
 
264
                        break;
 
265
                case SHUT_MULTI:
 
266
                        b |= isc_dpb_shut_multi;
 
267
                        break;
 
268
                case SHUT_FULL:
 
269
                        b |= isc_dpb_shut_full;
 
270
                        break;
 
271
                default:                        
 
272
                        break;
 
273
                }
 
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)
 
279
                {
 
280
                        timeout = MAX_SSHORT;
 
281
                }
 
282
                dpb.insertInt(isc_dpb_shutdown_delay, timeout);
 
283
        }
 
284
        else if (switches & sw_online) {
 
285
                UCHAR b = 0;
 
286
                switch (tdgbl->ALICE_data.ua_shutdown_mode) {
 
287
                case SHUT_NORMAL:
 
288
                        b |= isc_dpb_shut_normal;
 
289
                        break;
 
290
                case SHUT_SINGLE:
 
291
                        b |= isc_dpb_shut_single;
 
292
                        break;
 
293
                case SHUT_MULTI:
 
294
                        b |= isc_dpb_shut_multi;
 
295
                        break;
 
296
                case SHUT_FULL:
 
297
                        b |= isc_dpb_shut_full;
 
298
                        break;
 
299
                default:
 
300
                        break;
 
301
                }
 
302
                dpb.insertByte(isc_dpb_online, b);
 
303
        }
 
304
        else if (switches & sw_disable) {
 
305
                dpb.insertTag(isc_dpb_disable_wal);
 
306
        }
 
307
        else if (switches & (sw_list | sw_commit | sw_rollback | sw_two_phase)) {
 
308
                dpb.insertTag(isc_dpb_no_garbage_collect);
 
309
        }
 
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);
 
313
        }
 
314
 
 
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));
 
319
        }
 
320
        if (tdgbl->ALICE_data.ua_password) {
 
321
                dpb.insertString(tdgbl->sw_service ? isc_dpb_password_enc :
 
322
                                                 isc_dpb_password,
 
323
                                                 tdgbl->ALICE_data.ua_password, 
 
324
                                                 strlen(tdgbl->ALICE_data.ua_password));
 
325
        }
 
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));
 
331
        }
 
332
#endif
 
333
#ifdef TRUSTED_AUTH
 
334
        if (tdgbl->ALICE_data.ua_trusted) {
 
335
                if (!dpb.find(isc_dpb_trusted_auth)) {
 
336
                        dpb.insertTag(isc_dpb_trusted_auth);
 
337
                }
 
338
        }
 
339
#endif
 
340
}
 
341
 
 
342
 
 
343
//____________________________________________________________
 
344
//
 
345
//              Extract database info from string
 
346
//
 
347
 
 
348
static void extract_db_info(const UCHAR* db_info_buffer, size_t buf_size)
 
349
{
 
350
        AliceGlobals* tdgbl = AliceGlobals::getSpecific();
 
351
 
 
352
        const UCHAR* p = db_info_buffer;
 
353
        const UCHAR* const end = p + buf_size;
 
354
 
 
355
        UCHAR item;
 
356
        while ((item = *p++) != isc_info_end && p < end - 1)
 
357
        {
 
358
                const SLONG length = gds__vax_integer(p, 2);
 
359
                p += 2;
 
360
 
 
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.
 
365
                switch (item)
 
366
                {
 
367
                case isc_info_page_errors:
 
368
                        tdgbl->ALICE_data.ua_val_errors[VAL_PAGE_ERRORS] =
 
369
                                gds__vax_integer(p, (SSHORT) length);
 
370
                        break;
 
371
 
 
372
                case isc_info_record_errors:
 
373
                        tdgbl->ALICE_data.ua_val_errors[VAL_RECORD_ERRORS] =
 
374
                                gds__vax_integer(p, (SSHORT) length);
 
375
                        break;
 
376
 
 
377
                case isc_info_bpage_errors:
 
378
                        tdgbl->ALICE_data.ua_val_errors[VAL_BLOB_PAGE_ERRORS] =
 
379
                                gds__vax_integer(p, (SSHORT) length);
 
380
                        break;
 
381
 
 
382
                case isc_info_dpage_errors:
 
383
                        tdgbl->ALICE_data.ua_val_errors[VAL_DATA_PAGE_ERRORS] =
 
384
                                gds__vax_integer(p, (SSHORT) length);
 
385
                        break;
 
386
 
 
387
                case isc_info_ipage_errors:
 
388
                        tdgbl->ALICE_data.ua_val_errors[VAL_INDEX_PAGE_ERRORS] =
 
389
                                gds__vax_integer(p, (SSHORT) length);
 
390
                        break;
 
391
 
 
392
                case isc_info_ppage_errors:
 
393
                        tdgbl->ALICE_data.ua_val_errors[VAL_POINTER_PAGE_ERRORS] =
 
394
                                gds__vax_integer(p, (SSHORT) length);
 
395
                        break;
 
396
 
 
397
                case isc_info_tpage_errors:
 
398
                        tdgbl->ALICE_data.ua_val_errors[VAL_TIP_PAGE_ERRORS] =
 
399
                                gds__vax_integer(p, (SSHORT) length);
 
400
                        break;
 
401
 
 
402
                case isc_info_error:
 
403
                        /* has to be a < V4 database. */
 
404
 
 
405
                        tdgbl->ALICE_data.ua_val_errors[VAL_INVALID_DB_VERSION] = 1;
 
406
                        return;
 
407
 
 
408
                default:
 
409
                        fb_assert(false);
 
410
                }
 
411
 
 
412
                p += length;
 
413
        }
 
414
}