2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
2003-09-25 13:49:12 +02:00
|
|
|
* MODULE: jrd.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: User visible entrypoints
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-07-02 11:49:19 +02:00
|
|
|
*
|
2001-07-10 19:35:13 +02:00
|
|
|
* 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
|
|
|
|
* conditionals, as the engine now fully supports
|
|
|
|
* readonly databases.
|
2002-07-02 11:49:19 +02:00
|
|
|
* 2001.07.09 Sean Leyne - Restore default setting to Force Write = "On", for
|
|
|
|
* Windows NT platform, for new database files. This was changed
|
|
|
|
* with IB 6.0 to OFF and has introduced many reported database
|
|
|
|
* corruptions.
|
2002-10-30 07:40:58 +01:00
|
|
|
*
|
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "firebird.h"
|
2004-03-22 12:38:23 +01:00
|
|
|
#include "../jrd/common.h"
|
2004-04-29 00:43:34 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "../jrd/common.h"
|
2008-01-16 10:29:37 +01:00
|
|
|
#include "../jrd/ThreadStart.h"
|
2002-11-11 19:28:35 +01:00
|
|
|
#include "../jrd/os/thd_priority.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <stdarg.h>
|
2002-08-26 14:18:16 +02:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <unistd.h>
|
2002-08-26 14:18:16 +02:00
|
|
|
#endif
|
2003-02-19 07:14:39 +01:00
|
|
|
#ifdef HAVE_PWD_H
|
2002-04-04 09:10:40 +02:00
|
|
|
#include <pwd.h>
|
2001-12-24 03:51:06 +01:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <errno.h>
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
#include "../jrd/ibase.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/jrd.h"
|
|
|
|
#include "../jrd/irq.h"
|
|
|
|
#include "../jrd/isc.h"
|
|
|
|
#include "../jrd/drq.h"
|
|
|
|
#include "../jrd/req.h"
|
|
|
|
#include "../jrd/tra.h"
|
|
|
|
#include "../jrd/blb.h"
|
|
|
|
#include "../jrd/lck.h"
|
2005-11-22 00:33:20 +01:00
|
|
|
#include "../jrd/nbak.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/scl.h"
|
2003-07-14 12:35:49 +02:00
|
|
|
#include "../jrd/os/pio.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/ods.h"
|
|
|
|
#include "../jrd/exe.h"
|
|
|
|
#include "../jrd/val.h"
|
|
|
|
#include "../jrd/rse.h"
|
|
|
|
#include "../jrd/all.h"
|
2006-02-23 06:08:26 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/log.h"
|
2006-02-23 06:08:26 +01:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/fil.h"
|
2007-05-27 00:08:13 +02:00
|
|
|
#include "../jrd/intl.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/sbm.h"
|
|
|
|
#include "../jrd/svc.h"
|
|
|
|
#include "../jrd/sdw.h"
|
|
|
|
#include "../jrd/lls.h"
|
|
|
|
#include "../jrd/cch.h"
|
|
|
|
#include "../jrd/iberr.h"
|
|
|
|
#include "../intl/charsets.h"
|
2003-12-22 11:00:59 +01:00
|
|
|
#include "../jrd/sort.h"
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/blb_proto.h"
|
|
|
|
#include "../jrd/cch_proto.h"
|
|
|
|
#include "../jrd/cmp_proto.h"
|
|
|
|
#include "../jrd/dbg_proto.h"
|
|
|
|
#include "../jrd/dyn_proto.h"
|
|
|
|
#include "../jrd/err_proto.h"
|
|
|
|
#include "../jrd/exe_proto.h"
|
|
|
|
#include "../jrd/ext_proto.h"
|
|
|
|
#include "../jrd/fun_proto.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/iberr_proto.h"
|
|
|
|
#include "../jrd/inf_proto.h"
|
|
|
|
#include "../jrd/ini_proto.h"
|
|
|
|
#include "../jrd/intl_proto.h"
|
|
|
|
#include "../jrd/isc_f_proto.h"
|
|
|
|
#include "../jrd/isc_proto.h"
|
|
|
|
#include "../jrd/jrd_proto.h"
|
|
|
|
|
|
|
|
#include "../jrd/lck_proto.h"
|
|
|
|
#include "../jrd/log_proto.h"
|
|
|
|
#include "../jrd/met_proto.h"
|
|
|
|
#include "../jrd/mov_proto.h"
|
|
|
|
#include "../jrd/pag_proto.h"
|
|
|
|
#include "../jrd/par_proto.h"
|
2003-07-14 12:35:49 +02:00
|
|
|
#include "../jrd/os/pio_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/sch_proto.h"
|
|
|
|
#include "../jrd/scl_proto.h"
|
|
|
|
#include "../jrd/sdw_proto.h"
|
|
|
|
#include "../jrd/shut_proto.h"
|
|
|
|
#include "../jrd/sort_proto.h"
|
2004-05-18 00:30:09 +02:00
|
|
|
#include "../jrd/thread_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/tra_proto.h"
|
|
|
|
#include "../jrd/val_proto.h"
|
2007-01-06 07:52:43 +01:00
|
|
|
#include "../jrd/vio_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/file_params.h"
|
|
|
|
#include "../jrd/event_proto.h"
|
2005-08-21 17:52:30 +02:00
|
|
|
#include "../jrd/why_proto.h"
|
2002-09-19 18:02:58 +02:00
|
|
|
#include "../jrd/flags.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-11-06 16:13:02 +01:00
|
|
|
#include "../common/config/config.h"
|
2006-05-31 10:53:00 +02:00
|
|
|
#include "../common/config/dir_list.h"
|
2002-09-24 02:27:23 +02:00
|
|
|
#include "../jrd/plugin_manager.h"
|
2003-08-06 18:30:49 +02:00
|
|
|
#include "../jrd/db_alias.h"
|
2005-05-28 00:45:31 +02:00
|
|
|
#include "../jrd/IntlManager.h"
|
2004-05-03 01:06:37 +02:00
|
|
|
#include "../common/classes/fb_tls.h"
|
2004-11-24 19:26:24 +01:00
|
|
|
#include "../common/classes/ClumpletReader.h"
|
2006-10-30 21:58:06 +01:00
|
|
|
#include "../jrd/DebugInterface.h"
|
2001-08-21 11:41:00 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
using namespace Jrd;
|
|
|
|
|
2004-05-07 00:11:24 +02:00
|
|
|
const SSHORT WAIT_PERIOD = -1;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-10-01 07:48:00 +02:00
|
|
|
#ifdef SUPPORT_RAW_DEVICES
|
|
|
|
#define unlink PIO_unlink
|
|
|
|
#endif
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
#ifdef DEV_BUILD
|
|
|
|
int debug;
|
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-02-28 09:40:27 +01:00
|
|
|
namespace
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
Database* databases = NULL;
|
2008-02-05 09:21:18 +01:00
|
|
|
Firebird::GlobalPtr<Firebird::Mutex> databases_rec_mutex;
|
2008-02-06 01:43:54 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
inline void dbMutexLock()
|
|
|
|
{
|
|
|
|
databases_rec_mutex->enter();
|
|
|
|
}
|
2008-02-06 01:43:54 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
inline void dbMutexUnlock()
|
|
|
|
{
|
|
|
|
databases_rec_mutex->leave();
|
|
|
|
}
|
2007-02-28 09:40:27 +01:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
class EngineStartup
|
2007-02-28 09:40:27 +01:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
static void init()
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
IntlManager::initialize();
|
|
|
|
PluginManager::load_engine_plugins();
|
2007-02-28 09:40:27 +01:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
#if defined(WIN_NT) && !defined(SERVER_SHUTDOWN)
|
|
|
|
setup_NT_handlers();
|
|
|
|
#endif
|
2007-02-28 09:40:27 +01:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
static void cleanup() {}
|
2007-02-28 09:40:27 +01:00
|
|
|
};
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
Firebird::InitMutex<EngineStartup> engineStartup;
|
2007-02-28 09:40:27 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
class DbMutexGuard
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbMutexGuard()
|
|
|
|
{
|
|
|
|
dbMutexLock();
|
|
|
|
}
|
|
|
|
|
|
|
|
~DbMutexGuard()
|
|
|
|
{
|
2008-02-05 09:21:18 +01:00
|
|
|
try {
|
|
|
|
dbMutexUnlock();
|
|
|
|
}
|
2008-02-06 01:43:54 +01:00
|
|
|
catch (const Firebird::Exception&)
|
2008-02-05 09:21:18 +01:00
|
|
|
{
|
|
|
|
Firebird::MutexLockGuard::onDtorException();
|
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// copying is prohibited
|
|
|
|
DbMutexGuard(const DbMutexGuard&);
|
|
|
|
DbMutexGuard& operator=(const DbMutexGuard&);
|
|
|
|
};
|
|
|
|
|
2008-02-02 18:04:06 +01:00
|
|
|
inline void validateHandle(thread_db* tdbb, Attachment* const attachment)
|
2008-01-26 14:51:33 +01:00
|
|
|
{
|
|
|
|
if (!attachment->checkHandle() ||
|
|
|
|
!attachment->att_database->checkHandle())
|
|
|
|
{
|
|
|
|
Firebird::status_exception::raise(isc_bad_db_handle, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Database* const dbb = attachment->att_database;
|
|
|
|
|
|
|
|
const Attachment* attach = dbb->dbb_attachments;
|
2008-02-02 18:04:06 +01:00
|
|
|
while (attach && attach != attachment)
|
|
|
|
attach = attach->att_next;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
if (!attach)
|
|
|
|
Firebird::status_exception::raise(isc_bad_db_handle, 0);
|
|
|
|
|
|
|
|
tdbb->setAttachment(attachment);
|
|
|
|
tdbb->setDatabase(dbb);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void validateHandle(thread_db* tdbb, jrd_tra* transaction)
|
|
|
|
{
|
|
|
|
if (!transaction->checkHandle())
|
|
|
|
Firebird::status_exception::raise(isc_bad_trans_handle, 0);
|
|
|
|
|
|
|
|
validateHandle(tdbb, transaction->tra_attachment);
|
|
|
|
|
|
|
|
tdbb->setTransaction(transaction);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void validateHandle(thread_db* tdbb, jrd_req* request)
|
|
|
|
{
|
|
|
|
if (!request->checkHandle())
|
|
|
|
Firebird::status_exception::raise(isc_bad_req_handle, 0);
|
|
|
|
|
|
|
|
validateHandle(tdbb, request->req_attachment);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void validateHandle(thread_db* tdbb, blb* blob)
|
|
|
|
{
|
|
|
|
if (!blob->checkHandle())
|
|
|
|
Firebird::status_exception::raise(isc_bad_segstr_handle, 0);
|
|
|
|
|
|
|
|
validateHandle(tdbb, blob->blb_transaction);
|
|
|
|
validateHandle(tdbb, blob->blb_attachment);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void validateHandle(Service* service)
|
|
|
|
{
|
|
|
|
if (!service->checkHandle())
|
|
|
|
Firebird::status_exception::raise(isc_bad_svc_handle, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
class DatabaseContextHolder : public Jrd::ContextPoolHolder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DatabaseContextHolder(thread_db* arg)
|
|
|
|
: Jrd::ContextPoolHolder(arg, arg->getDatabase()->dbb_permanent),
|
|
|
|
tdbb(arg)
|
|
|
|
{
|
|
|
|
Database* dbb = tdbb->getDatabase();
|
|
|
|
dbb->dbb_sync.lock();
|
|
|
|
++dbb->dbb_use_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
~DatabaseContextHolder()
|
|
|
|
{
|
|
|
|
Database* dbb = tdbb->getDatabase();
|
|
|
|
if (dbb->checkHandle())
|
|
|
|
{
|
|
|
|
--dbb->dbb_use_count;
|
|
|
|
dbb->dbb_sync.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// copying is prohibited
|
|
|
|
DatabaseContextHolder(const DatabaseContextHolder&);
|
|
|
|
DatabaseContextHolder& operator=(const DatabaseContextHolder&);
|
|
|
|
|
|
|
|
thread_db* tdbb;
|
|
|
|
};
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
} // anonymous
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
#include <windows.h>
|
2006-07-21 03:35:17 +02:00
|
|
|
// these should stop a most annoying warning
|
2001-05-23 15:26:42 +02:00
|
|
|
#undef TEXT
|
|
|
|
#define TEXT SCHAR
|
|
|
|
#endif // WIN_NT
|
|
|
|
|
2004-04-19 17:29:29 +02:00
|
|
|
void Jrd::Trigger::compile(thread_db* tdbb)
|
2002-10-24 13:16:59 +02:00
|
|
|
{
|
2007-01-06 14:43:41 +01:00
|
|
|
if (!request /*&& !compile_in_progress*/)
|
2002-10-24 13:16:59 +02:00
|
|
|
{
|
2004-03-11 06:04:26 +01:00
|
|
|
SET_TDBB(tdbb);
|
2002-09-19 18:02:58 +02:00
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2007-01-06 14:43:41 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
Database::CheckoutLockGuard guard(dbb, dbb->dbb_sp_rec_mutex);
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2007-01-06 14:43:41 +01:00
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
compile_in_progress = true;
|
2004-03-20 15:57:40 +01:00
|
|
|
// Allocate statement memory pool
|
2008-01-29 11:11:52 +01:00
|
|
|
MemoryPool* new_pool = dbb->createPool();
|
2002-09-19 18:02:58 +02:00
|
|
|
// Trigger request is not compiled yet. Lets do it now
|
2005-03-28 23:52:55 +02:00
|
|
|
USHORT par_flags = (USHORT)
|
|
|
|
(flags & TRG_ignore_perm) ? csb_ignore_perm : 0;
|
|
|
|
if (type & 1)
|
|
|
|
par_flags |= csb_pre_trigger;
|
|
|
|
else
|
|
|
|
par_flags |= csb_post_trigger;
|
|
|
|
|
2006-11-03 10:42:42 +01:00
|
|
|
CompilerScratch* csb = NULL;
|
2002-09-26 20:13:02 +02:00
|
|
|
try {
|
2004-08-30 20:11:08 +02:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
2006-10-30 21:58:06 +01:00
|
|
|
|
2006-11-03 10:42:42 +01:00
|
|
|
csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5);
|
2006-10-30 21:58:06 +01:00
|
|
|
csb->csb_g_flags |= par_flags;
|
2007-01-20 15:18:18 +01:00
|
|
|
|
|
|
|
if (!dbg_blob_id.isEmpty())
|
|
|
|
DBG_parse_debug_info(tdbb, &dbg_blob_id, csb->csb_dbg_info);
|
2006-10-30 21:58:06 +01:00
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
PAR_blr(tdbb, relation, blr.begin(), NULL, &csb, &request, (relation ? true : false),
|
2005-03-28 23:52:55 +02:00
|
|
|
par_flags);
|
2006-10-30 21:58:06 +01:00
|
|
|
|
|
|
|
delete csb;
|
2002-10-24 13:16:59 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception&) {
|
2004-01-03 11:59:52 +01:00
|
|
|
compile_in_progress = false;
|
2006-11-03 10:42:42 +01:00
|
|
|
if (csb) {
|
|
|
|
delete csb;
|
|
|
|
csb = NULL;
|
|
|
|
}
|
2002-09-28 00:59:24 +02:00
|
|
|
if (request) {
|
2004-11-24 10:22:07 +01:00
|
|
|
CMP_release(tdbb, request);
|
2002-09-28 00:59:24 +02:00
|
|
|
request = NULL;
|
2004-01-28 08:50:41 +01:00
|
|
|
}
|
|
|
|
else {
|
2008-01-29 11:11:52 +01:00
|
|
|
dbb->deletePool(new_pool);
|
2002-10-24 13:16:59 +02:00
|
|
|
}
|
2007-01-06 14:43:41 +01:00
|
|
|
|
2002-09-26 20:13:02 +02:00
|
|
|
throw;
|
|
|
|
}
|
2002-09-19 18:02:58 +02:00
|
|
|
|
2006-01-03 12:28:24 +01:00
|
|
|
request->req_trg_name = name;
|
|
|
|
|
2002-09-19 18:02:58 +02:00
|
|
|
if (sys_trigger)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2002-10-24 13:16:59 +02:00
|
|
|
request->req_flags |= req_sys_trigger;
|
2004-04-19 17:29:29 +02:00
|
|
|
}
|
2002-09-19 18:02:58 +02:00
|
|
|
if (flags & TRG_ignore_perm)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2002-10-24 13:16:59 +02:00
|
|
|
request->req_flags |= req_ignore_perm;
|
2004-04-19 17:29:29 +02:00
|
|
|
}
|
2002-10-24 13:16:59 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
compile_in_progress = false;
|
2002-09-19 18:02:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-19 17:29:29 +02:00
|
|
|
void Jrd::Trigger::release(thread_db* tdbb)
|
2002-10-24 13:16:59 +02:00
|
|
|
{
|
2008-01-29 02:36:41 +01:00
|
|
|
if (blr.getCount() == 0 || //sys_trigger
|
|
|
|
!request || CMP_clone_is_active(request))
|
2004-03-28 11:10:30 +02:00
|
|
|
{
|
2004-03-11 06:04:26 +01:00
|
|
|
return; // FALSE;
|
2002-10-24 13:16:59 +02:00
|
|
|
}
|
2002-09-28 00:59:24 +02:00
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
CMP_release(tdbb, request);
|
2002-10-24 13:16:59 +02:00
|
|
|
request = NULL;
|
2004-03-11 06:04:26 +01:00
|
|
|
return; // TRUE;
|
2002-09-19 18:02:58 +02:00
|
|
|
}
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Option block for database parameter block
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
class DatabaseOptions
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
public:
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dpb_wal_action;
|
|
|
|
SLONG dpb_sweep_interval;
|
|
|
|
ULONG dpb_page_buffers;
|
2004-02-20 07:43:27 +01:00
|
|
|
bool dpb_set_page_buffers;
|
2001-05-23 15:26:42 +02:00
|
|
|
ULONG dpb_buffers;
|
|
|
|
USHORT dpb_debug;
|
|
|
|
USHORT dpb_verify;
|
|
|
|
USHORT dpb_sweep;
|
|
|
|
USHORT dpb_trace;
|
|
|
|
USHORT dpb_disable;
|
|
|
|
USHORT dpb_dbkey_scope;
|
|
|
|
USHORT dpb_page_size;
|
2003-12-05 11:35:47 +01:00
|
|
|
bool dpb_activate_shadow;
|
|
|
|
bool dpb_delete_shadow;
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dpb_no_garbage;
|
2004-01-06 11:33:18 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
bool dpb_quit_log;
|
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dpb_shutdown;
|
|
|
|
SSHORT dpb_shutdown_delay;
|
|
|
|
USHORT dpb_online;
|
|
|
|
SSHORT dpb_force_write;
|
|
|
|
UCHAR dpb_set_force_write;
|
|
|
|
UCHAR dpb_no_reserve;
|
|
|
|
UCHAR dpb_set_no_reserve;
|
|
|
|
SSHORT dpb_interp;
|
|
|
|
USHORT dpb_single_user;
|
2004-02-20 07:43:27 +01:00
|
|
|
bool dpb_overwrite;
|
|
|
|
bool dpb_sec_attach;
|
|
|
|
bool dpb_disable_wal;
|
2004-11-07 15:50:53 +01:00
|
|
|
bool dpb_gsec_attach;
|
2001-05-23 15:26:42 +02:00
|
|
|
SLONG dpb_connect_timeout;
|
|
|
|
SLONG dpb_dummy_packet_interval;
|
2004-02-20 07:43:27 +01:00
|
|
|
bool dpb_db_readonly;
|
|
|
|
bool dpb_set_db_readonly;
|
|
|
|
bool dpb_gfix_attach;
|
|
|
|
bool dpb_gstat_attach;
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dpb_sql_dialect;
|
|
|
|
USHORT dpb_set_db_sql_dialect;
|
2006-09-14 15:47:31 +02:00
|
|
|
SLONG dpb_remote_pid;
|
2006-11-05 19:30:36 +01:00
|
|
|
bool dpb_no_db_triggers;
|
2007-10-24 09:03:37 +02:00
|
|
|
bool dpb_gbak_attach;
|
2008-01-16 10:29:37 +01:00
|
|
|
bool dpb_trusted_role;
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
// here begin compound objects
|
|
|
|
// for constructor to work properly dpb_sys_user_name
|
|
|
|
// MUST be FIRST
|
|
|
|
Firebird::string dpb_sys_user_name;
|
|
|
|
Firebird::string dpb_user_name;
|
|
|
|
Firebird::string dpb_password;
|
|
|
|
Firebird::string dpb_password_enc;
|
|
|
|
Firebird::string dpb_role_name;
|
|
|
|
Firebird::string dpb_journal;
|
|
|
|
Firebird::string dpb_key;
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2004-11-25 17:09:12 +01:00
|
|
|
Firebird::PathName dpb_log;
|
2004-11-24 19:26:24 +01:00
|
|
|
#endif
|
2004-11-25 17:09:12 +01:00
|
|
|
Firebird::PathName dpb_lc_messages;
|
2004-11-24 19:26:24 +01:00
|
|
|
Firebird::string dpb_lc_ctype;
|
|
|
|
Firebird::PathName dpb_working_directory;
|
|
|
|
Firebird::string dpb_set_db_charset;
|
2004-11-26 02:01:27 +01:00
|
|
|
Firebird::string dpb_network_protocol;
|
|
|
|
Firebird::string dpb_remote_address;
|
2006-12-08 19:38:15 +01:00
|
|
|
Firebird::string dpb_trusted_login;
|
2007-05-16 09:54:33 +02:00
|
|
|
Firebird::PathName dpb_remote_process;
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
public:
|
|
|
|
DatabaseOptions()
|
|
|
|
{
|
|
|
|
memset(this, 0,
|
|
|
|
reinterpret_cast<char*>(&this->dpb_sys_user_name) -
|
|
|
|
reinterpret_cast<char*>(this));
|
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
void get(const UCHAR*, USHORT, bool&);
|
2004-05-24 19:31:47 +02:00
|
|
|
};
|
|
|
|
|
2006-07-10 05:12:10 +02:00
|
|
|
#ifndef SUPERSERVER
|
|
|
|
static int blocking_ast_dsql_cache(void*);
|
|
|
|
#endif
|
2008-01-26 14:51:33 +01:00
|
|
|
static void check_database(thread_db* tdbb);
|
|
|
|
static void check_transaction(thread_db*, jrd_tra*);
|
2004-01-03 11:59:52 +01:00
|
|
|
static ISC_STATUS commit(ISC_STATUS*, jrd_tra**, const bool);
|
2007-01-20 15:18:18 +01:00
|
|
|
static ISC_STATUS compile_request(ISC_STATUS*, Attachment**, jrd_req**, SSHORT, const SCHAR*, USHORT, const char*, USHORT, const UCHAR*);
|
2008-01-16 10:29:37 +01:00
|
|
|
static bool drop_files(const jrd_file*);
|
|
|
|
static void find_intl_charset(thread_db*, Attachment*, const DatabaseOptions*);
|
2008-01-26 14:51:33 +01:00
|
|
|
static jrd_tra* find_transaction(thread_db*, ISC_STATUS);
|
2008-01-16 10:29:37 +01:00
|
|
|
static void init_database_locks(thread_db*, Database*);
|
|
|
|
static ISC_STATUS handle_error(ISC_STATUS*, ISC_STATUS);
|
|
|
|
static void run_commit_triggers(thread_db* tdbb, jrd_tra* transaction);
|
|
|
|
static void verify_request_synchronization(jrd_req*& request, SSHORT level);
|
2007-07-25 15:21:59 +02:00
|
|
|
static unsigned int purge_transactions(thread_db*, Attachment*, const bool, const ULONG);
|
2004-11-07 15:50:53 +01:00
|
|
|
namespace {
|
|
|
|
enum vdnResult {vdnFail, vdnOk, vdnSecurity};
|
|
|
|
}
|
|
|
|
static vdnResult verify_database_name(const Firebird::PathName&, ISC_STATUS*);
|
2008-01-16 10:29:37 +01:00
|
|
|
static ISC_STATUS unwindAttach(const Firebird::Exception& ex,
|
|
|
|
ISC_STATUS* userStatus,
|
|
|
|
thread_db* tdbb,
|
|
|
|
Attachment* attachment,
|
|
|
|
Database* dbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
#if defined (WIN_NT)
|
2003-03-01 19:04:21 +01:00
|
|
|
#ifdef SERVER_SHUTDOWN
|
2003-11-01 11:26:43 +01:00
|
|
|
static void ExtractDriveLetter(const TEXT*, ULONG*);
|
2003-03-01 19:04:21 +01:00
|
|
|
#else // SERVER_SHUTDOWN
|
2001-05-23 15:26:42 +02:00
|
|
|
static void setup_NT_handlers(void);
|
|
|
|
static BOOLEAN handler_NT(SSHORT);
|
2003-03-01 19:04:21 +01:00
|
|
|
#endif // SERVER_SHUTDOWN
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif // WIN_NT
|
|
|
|
|
2004-03-14 14:34:43 +01:00
|
|
|
static Database* init(thread_db*, ISC_STATUS*, const Firebird::PathName&, bool);
|
2008-01-26 14:51:33 +01:00
|
|
|
static void prepare(thread_db*, jrd_tra*, USHORT, const UCHAR*);
|
|
|
|
static void release_attachment(thread_db*, Attachment*);
|
2007-06-15 11:28:56 +02:00
|
|
|
static void detachLocksFromAttachment(Attachment*);
|
2008-01-26 14:51:33 +01:00
|
|
|
static ISC_STATUS rollback(ISC_STATUS*, jrd_tra**, const bool);
|
2004-03-07 08:58:55 +01:00
|
|
|
static void shutdown_database(Database*, const bool);
|
2004-11-24 19:26:24 +01:00
|
|
|
static void strip_quotes(Firebird::string&);
|
2004-03-18 06:56:06 +01:00
|
|
|
static void purge_attachment(thread_db*, ISC_STATUS*, Attachment*, const bool);
|
2008-01-26 18:33:57 +01:00
|
|
|
static void getUserInfo(Database*, UserId&, const DatabaseOptions&);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// check whether we need to perform an autocommit;
|
|
|
|
// do it here to prevent committing every record update
|
|
|
|
// in a statement
|
|
|
|
//
|
2004-03-11 06:04:26 +01:00
|
|
|
static void check_autocommit(jrd_req* request, thread_db* tdbb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2006-07-21 03:35:17 +02:00
|
|
|
// dimitr: we should ignore autocommit for requests
|
|
|
|
// created by EXECUTE STATEMENT
|
2003-02-26 12:57:36 +01:00
|
|
|
if (request->req_transaction->tra_callback_count > 0)
|
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (request->req_transaction->tra_flags & TRA_perform_autocommit)
|
|
|
|
{
|
2007-12-03 16:46:39 +01:00
|
|
|
if (!(tdbb->getAttachment()->att_flags & ATT_no_db_triggers) &&
|
2006-12-30 02:26:50 +01:00
|
|
|
!(request->req_transaction->tra_flags & TRA_prepared))
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
|
|
|
// run ON TRANSACTION COMMIT triggers
|
2006-12-30 02:26:50 +01:00
|
|
|
run_commit_triggers(tdbb, request->req_transaction);
|
2006-11-05 19:30:36 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
request->req_transaction->tra_flags &= ~TRA_perform_autocommit;
|
2003-11-01 11:26:43 +01:00
|
|
|
TRA_commit(tdbb, request->req_transaction, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-06 20:09:24 +02:00
|
|
|
const int SWEEP_INTERVAL = 20000;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-06 20:09:24 +02:00
|
|
|
const char DBL_QUOTE = '\042';
|
|
|
|
const char SINGLE_QUOTE = '\'';
|
|
|
|
const int BUFFER_LENGTH128 = 128;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#define GDS_ATTACH_DATABASE jrd8_attach_database
|
|
|
|
#define GDS_BLOB_INFO jrd8_blob_info
|
|
|
|
#define GDS_CANCEL_BLOB jrd8_cancel_blob
|
|
|
|
#define GDS_CANCEL_EVENTS jrd8_cancel_events
|
|
|
|
#define GDS_CANCEL_OPERATION jrd8_cancel_operation
|
|
|
|
#define GDS_CLOSE_BLOB jrd8_close_blob
|
|
|
|
#define GDS_COMMIT jrd8_commit_transaction
|
|
|
|
#define GDS_COMMIT_RETAINING jrd8_commit_retaining
|
|
|
|
#define GDS_COMPILE jrd8_compile_request
|
|
|
|
#define GDS_CREATE_BLOB2 jrd8_create_blob2
|
|
|
|
#define GDS_CREATE_DATABASE jrd8_create_database
|
|
|
|
#define GDS_DATABASE_INFO jrd8_database_info
|
|
|
|
#define GDS_DDL jrd8_ddl
|
|
|
|
#define GDS_DETACH jrd8_detach_database
|
|
|
|
#define GDS_DROP_DATABASE jrd8_drop_database
|
2005-08-21 17:52:30 +02:00
|
|
|
#define GDS_INTL_FUNCTION jrd8_intl_function
|
2006-07-10 05:12:10 +02:00
|
|
|
#define GDS_DSQL_CACHE jrd8_dsql_cache
|
2007-01-20 15:18:18 +01:00
|
|
|
#define GDS_INTERNAL_COMPILE jrd8_internal_compile_request
|
2001-05-23 15:26:42 +02:00
|
|
|
#define GDS_GET_SEGMENT jrd8_get_segment
|
|
|
|
#define GDS_GET_SLICE jrd8_get_slice
|
|
|
|
#define GDS_OPEN_BLOB2 jrd8_open_blob2
|
|
|
|
#define GDS_PREPARE jrd8_prepare_transaction
|
|
|
|
#define GDS_PUT_SEGMENT jrd8_put_segment
|
|
|
|
#define GDS_PUT_SLICE jrd8_put_slice
|
|
|
|
#define GDS_QUE_EVENTS jrd8_que_events
|
|
|
|
#define GDS_RECONNECT jrd8_reconnect_transaction
|
|
|
|
#define GDS_RECEIVE jrd8_receive
|
|
|
|
#define GDS_RELEASE_REQUEST jrd8_release_request
|
|
|
|
#define GDS_REQUEST_INFO jrd8_request_info
|
|
|
|
#define GDS_ROLLBACK jrd8_rollback_transaction
|
|
|
|
#define GDS_ROLLBACK_RETAINING jrd8_rollback_retaining
|
|
|
|
#define GDS_SEEK_BLOB jrd8_seek_blob
|
|
|
|
#define GDS_SEND jrd8_send
|
|
|
|
#define GDS_SERVICE_ATTACH jrd8_service_attach
|
|
|
|
#define GDS_SERVICE_DETACH jrd8_service_detach
|
|
|
|
#define GDS_SERVICE_QUERY jrd8_service_query
|
|
|
|
#define GDS_SERVICE_START jrd8_service_start
|
|
|
|
#define GDS_START_AND_SEND jrd8_start_and_send
|
|
|
|
#define GDS_START jrd8_start_request
|
|
|
|
#define GDS_START_MULTIPLE jrd8_start_multiple
|
|
|
|
#define GDS_START_TRANSACTION jrd8_start_transaction
|
|
|
|
#define GDS_TRANSACT_REQUEST jrd8_transact_request
|
|
|
|
#define GDS_TRANSACTION_INFO jrd8_transaction_info
|
|
|
|
#define GDS_UNWIND jrd8_unwind_request
|
|
|
|
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// External hook definitions
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-09 11:05:07 +01:00
|
|
|
/* dimitr: just uncomment the following line to use this feature.
|
|
|
|
Requires support from the PIO modules. Only Win32 is 100% ready
|
|
|
|
for this so far. Note that the database encryption code in the
|
|
|
|
PIO layer seems to be incompatible with the SUPERSERVER_V2 code.
|
|
|
|
2003.02.09 */
|
|
|
|
//#define ISC_DATABASE_ENCRYPTION
|
|
|
|
|
|
|
|
static const char* CRYPT_IMAGE = "fbcrypt";
|
|
|
|
static const char* ENCRYPT = "encrypt";
|
|
|
|
static const char* DECRYPT = "decrypt";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2006-07-01 10:50:21 +02:00
|
|
|
void JRD_print_pools(const char* filename)
|
|
|
|
{
|
|
|
|
FILE* out = fopen(filename, "w");
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
ALL_print_memory_pool_info(out, databases);
|
|
|
|
fclose(out);
|
|
|
|
}
|
2004-10-25 07:14:12 +02:00
|
|
|
}
|
|
|
|
|
2004-10-28 07:23:16 +02:00
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
2005-09-30 18:16:39 +02:00
|
|
|
SSHORT _file_length,
|
|
|
|
const TEXT* _file_name,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT dpb_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const UCHAR* dpb,
|
2005-09-30 18:16:39 +02:00
|
|
|
const TEXT* _expanded_filename)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ a t t a c h _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Attach a moldy, grungy, old database
|
|
|
|
* sullied by user data.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (*handle) {
|
2008-01-16 10:29:37 +01:00
|
|
|
return handle_error(user_status, isc_bad_db_handle);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2005-09-30 18:16:39 +02:00
|
|
|
Firebird::PathName file_name(_file_name,
|
|
|
|
_file_length ? _file_length : strlen(_file_name));
|
|
|
|
Firebird::PathName expanded_name(file_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Resolve given alias name
|
2003-10-29 11:53:47 +01:00
|
|
|
const bool is_alias = ResolveDatabaseAlias(expanded_name, expanded_name);
|
2003-08-17 21:56:53 +02:00
|
|
|
if (is_alias)
|
2004-11-07 15:50:53 +01:00
|
|
|
{
|
|
|
|
ISC_expand_filename(expanded_name, false);
|
|
|
|
}
|
2003-08-17 21:56:53 +02:00
|
|
|
else
|
2004-11-07 15:50:53 +01:00
|
|
|
{
|
2005-09-30 18:16:39 +02:00
|
|
|
expanded_name = _expanded_filename;
|
2004-11-07 15:50:53 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Check database against conf file.
|
2004-11-11 06:37:52 +01:00
|
|
|
const vdnResult vdn = verify_database_name(expanded_name, user_status);
|
2004-11-07 15:50:53 +01:00
|
|
|
if (!is_alias && vdn == vdnFail)
|
|
|
|
{
|
2003-08-17 21:56:53 +02:00
|
|
|
return user_status[1];
|
2004-11-11 06:37:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Unless we're already attached, do some initialization
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = init(tdbb, user_status, expanded_name, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!dbb) {
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2001-05-23 15:26:42 +02:00
|
|
|
return user_status[1];
|
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
tdbb->setDatabase(dbb);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2004-08-30 20:11:08 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_flags |= DBB_being_opened;
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Initialize special error handling
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
ISC_STATUS* const status = user_status;
|
2007-12-03 16:46:39 +01:00
|
|
|
Attachment* attachment = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-21 09:57:12 +02:00
|
|
|
bool initing_security = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Process database parameter block
|
2008-01-26 14:51:33 +01:00
|
|
|
bool invalid_client_SQL_dialect = false;
|
2004-11-24 19:26:24 +01:00
|
|
|
DatabaseOptions options;
|
2008-01-26 14:51:33 +01:00
|
|
|
options.get(dpb, dpb_length, invalid_client_SQL_dialect);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
// First check for correct credentials supplied
|
|
|
|
UserId userId;
|
2008-01-26 18:33:57 +01:00
|
|
|
getUserInfo(dbb, userId, options);
|
2007-06-08 12:24:57 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifndef NO_NFS
|
2006-07-21 03:35:17 +02:00
|
|
|
// Don't check nfs if single user
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!options.dpb_single_user)
|
|
|
|
#endif
|
|
|
|
{
|
2006-07-21 03:35:17 +02:00
|
|
|
// Check to see if the database is truly local or if it just looks
|
|
|
|
// that way
|
2001-08-21 11:41:00 +02:00
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
if (ISC_check_if_remote(expanded_name, true)) {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_unavailable, 0);
|
2003-04-06 11:08:58 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-11-08 09:01:26 +01:00
|
|
|
/* If database to be opened is SecurityDatabase, then only
|
2004-11-07 15:50:53 +01:00
|
|
|
gsec or SecurityDatabase may open it. This protects from use
|
|
|
|
of old gsec to write wrong password hashes into it. */
|
|
|
|
if (vdn == vdnSecurity && !options.dpb_gsec_attach && !options.dpb_sec_attach)
|
|
|
|
{
|
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "direct",
|
|
|
|
isc_arg_string, "security database",
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2004-11-07 15:50:53 +01:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Worry about encryption key
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (dbb->dbb_decrypt) {
|
2004-05-27 18:26:52 +02:00
|
|
|
if (dbb->dbb_filename.hasData() &&
|
2004-11-24 19:26:24 +01:00
|
|
|
(dbb->dbb_encrypt_key.hasData() || options.dpb_key.hasData()))
|
2004-05-27 18:26:52 +02:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
if ((dbb->dbb_encrypt_key.hasData() && options.dpb_key.isEmpty()) ||
|
|
|
|
(dbb->dbb_encrypt_key.empty() && options.dpb_key.hasData()) ||
|
2004-03-14 14:34:43 +01:00
|
|
|
(dbb->dbb_encrypt_key != options.dpb_key))
|
2003-10-29 11:53:47 +01:00
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "encryption",
|
|
|
|
isc_arg_string, "database",
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2001-07-29 19:42:23 +02:00
|
|
|
0);
|
2003-10-29 11:53:47 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2004-11-24 19:26:24 +01:00
|
|
|
else if (options.dpb_key.hasData())
|
2004-05-27 18:26:52 +02:00
|
|
|
{
|
2004-03-14 14:34:43 +01:00
|
|
|
dbb->dbb_encrypt_key = options.dpb_key;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
tdbb->setAttachment((attachment = FB_NEW(*dbb->dbb_permanent) Attachment(dbb)));
|
2007-02-08 15:14:54 +01:00
|
|
|
attachment->att_filename = is_alias ? file_name : expanded_name;
|
2004-11-26 02:01:27 +01:00
|
|
|
attachment->att_network_protocol = options.dpb_network_protocol;
|
|
|
|
attachment->att_remote_address = options.dpb_remote_address;
|
2006-09-14 15:47:31 +02:00
|
|
|
attachment->att_remote_pid = options.dpb_remote_pid;
|
2007-05-16 09:54:33 +02:00
|
|
|
attachment->att_remote_process = options.dpb_remote_process;
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_next = dbb->dbb_attachments;
|
2006-09-15 04:14:46 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_attachments = attachment;
|
|
|
|
dbb->dbb_flags &= ~DBB_being_opened;
|
|
|
|
dbb->dbb_sys_trans->tra_attachment = attachment;
|
|
|
|
|
|
|
|
attachment->att_charset = options.dpb_interp;
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options.dpb_lc_messages.hasData()) {
|
2004-03-14 14:34:43 +01:00
|
|
|
attachment->att_lc_messages = options.dpb_lc_messages;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (options.dpb_no_garbage)
|
|
|
|
attachment->att_flags |= ATT_no_cleanup;
|
|
|
|
|
2007-10-24 08:26:31 +02:00
|
|
|
if (options.dpb_gbak_attach)
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags |= ATT_gbak_attachment;
|
|
|
|
|
|
|
|
if (options.dpb_gstat_attach)
|
|
|
|
attachment->att_flags |= ATT_gstat_attachment;
|
|
|
|
|
|
|
|
if (options.dpb_gfix_attach)
|
|
|
|
attachment->att_flags |= ATT_gfix_attachment;
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options.dpb_working_directory.hasData()) {
|
2004-03-14 14:34:43 +01:00
|
|
|
attachment->att_working_directory = options.dpb_working_directory;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// If we're a not a secondary attachment, initialize some stuff
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
bool first = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
LCK_init(tdbb, LCK_OWNER_attachment); // For the attachment
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags |= ATT_lck_init_done;
|
2004-05-27 18:26:52 +02:00
|
|
|
if (dbb->dbb_filename.empty())
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
first = true;
|
2004-03-14 14:34:43 +01:00
|
|
|
dbb->dbb_filename = expanded_name;
|
2004-11-11 06:37:52 +01:00
|
|
|
|
|
|
|
// NS: Use alias as database ID only if accessing database using file name is not possible.
|
|
|
|
//
|
|
|
|
// This way we:
|
|
|
|
// 1. Ensure uniqueness of ID even in presence of multiple processes
|
|
|
|
// 2. Make sure that ID value can be used to connect back to database
|
|
|
|
//
|
2007-02-26 17:17:00 +01:00
|
|
|
if (is_alias && vdn == vdnFail)
|
2005-09-30 18:16:39 +02:00
|
|
|
dbb->dbb_database_name = file_name;
|
2004-11-11 06:37:52 +01:00
|
|
|
else
|
|
|
|
dbb->dbb_database_name = expanded_name;
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Extra LCK_init() done to keep the lock table until the
|
|
|
|
// database is shutdown() after the last detach.
|
2001-05-23 15:26:42 +02:00
|
|
|
LCK_init(tdbb, LCK_OWNER_database);
|
|
|
|
dbb->dbb_flags |= DBB_lck_init_done;
|
2006-07-19 08:19:56 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
INI_init();
|
2006-05-22 00:07:35 +02:00
|
|
|
|
|
|
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
|
|
|
pageSpace->file =
|
2007-03-09 08:59:05 +01:00
|
|
|
PIO_open(dbb, expanded_name, options.dpb_trace != 0, file_name, false);
|
2008-01-26 14:51:33 +01:00
|
|
|
SHUT_init(tdbb);
|
2007-03-09 09:55:07 +01:00
|
|
|
PAG_header_init();
|
2001-05-23 15:26:42 +02:00
|
|
|
INI_init2();
|
|
|
|
PAG_init();
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_set_page_buffers) {
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_page_buffers = options.dpb_page_buffers;
|
|
|
|
}
|
2006-04-29 07:42:43 +02:00
|
|
|
CCH_init(tdbb, options.dpb_buffers);
|
2006-10-07 12:53:01 +02:00
|
|
|
|
|
|
|
// Initialize locks
|
|
|
|
init_database_locks(tdbb, dbb);
|
|
|
|
|
2003-08-06 18:30:49 +02:00
|
|
|
// Initialize backup difference subsystem. This must be done before WAL and shadowing
|
|
|
|
// is enabled because nbackup it is a lower level subsystem
|
2005-11-22 00:33:20 +01:00
|
|
|
dbb->dbb_backup_manager = FB_NEW(*dbb->dbb_permanent) BackupManager(tdbb, dbb, nbak_state_unknown);
|
2007-03-09 09:55:07 +01:00
|
|
|
|
|
|
|
PAG_init2(0);
|
|
|
|
PAG_header(false);
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2003-08-17 21:56:53 +02:00
|
|
|
LOG_init(expanded_name, length_expanded);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// initialize shadowing as soon as the database is ready for it
|
|
|
|
// but before any real work is done
|
2001-05-23 15:26:42 +02:00
|
|
|
SDW_init(options.dpb_activate_shadow,
|
2007-01-20 15:45:45 +01:00
|
|
|
options.dpb_delete_shadow);
|
2003-03-23 10:05:35 +01:00
|
|
|
|
|
|
|
/* dimitr: disabled due to unreliable behaviour of minor ODS upgrades
|
|
|
|
a) in the case of any failure it's impossible to attach the database
|
|
|
|
b) there's no way to handle failures properly, because upgrade is
|
|
|
|
being made in the context of system transaction which doesn't use
|
|
|
|
the backout logic
|
2001-05-23 15:26:42 +02:00
|
|
|
INI_update_database();
|
2003-03-23 10:05:35 +01:00
|
|
|
*/
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Attachments to a ReadOnly database need NOT do garbage collection
|
2001-12-24 03:51:06 +01:00
|
|
|
if (dbb->dbb_flags & DBB_read_only) {
|
2001-07-12 07:46:06 +02:00
|
|
|
attachment->att_flags |= ATT_no_cleanup;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-07-12 07:46:06 +02:00
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_disable_wal) {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2001-07-29 19:42:23 +02:00
|
|
|
0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_buffers && !dbb->dbb_page_buffers) {
|
2006-04-29 07:42:43 +02:00
|
|
|
CCH_expand(tdbb, options.dpb_buffers);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!options.dpb_verify && CCH_exclusive(tdbb, LCK_PW, LCK_NO_WAIT))
|
|
|
|
{
|
|
|
|
TRA_cleanup(tdbb);
|
|
|
|
}
|
|
|
|
|
2003-09-21 09:57:12 +02:00
|
|
|
initing_security = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (invalid_client_SQL_dialect)
|
|
|
|
{
|
|
|
|
ERR_post(isc_inv_client_dialect_specified, isc_arg_number,
|
|
|
|
options.dpb_sql_dialect,
|
|
|
|
isc_arg_gds, isc_valid_client_dialects,
|
2005-10-14 06:12:36 +02:00
|
|
|
isc_arg_string, "1, 2 or 3", 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2007-06-13 15:21:40 +02:00
|
|
|
if (userId.usr_sql_role_name.hasData())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
switch (options.dpb_sql_dialect)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
2006-07-21 03:35:17 +02:00
|
|
|
// V6 Client --> V6 Server, dummy client SQL dialect 0 was passed
|
|
|
|
// It means that client SQL dialect was not set by user
|
|
|
|
// and takes DB SQL dialect as client SQL dialect
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original)
|
|
|
|
>= ODS_10_0)
|
2003-12-03 09:19:24 +01:00
|
|
|
{
|
|
|
|
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3) {
|
2006-07-21 03:35:17 +02:00
|
|
|
// DB created in IB V6.0 by client SQL dialect 3
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_sql_dialect = SQL_DIALECT_V6;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
|
|
|
else {
|
2006-07-21 03:35:17 +02:00
|
|
|
// old DB was gbaked in IB V6.0
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_sql_dialect = SQL_DIALECT_V5;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_sql_dialect = SQL_DIALECT_V5;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 99:
|
2006-07-21 03:35:17 +02:00
|
|
|
// V5 Client --> V6 Server, old client has no concept of dialect
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_sql_dialect = SQL_DIALECT_V5;
|
|
|
|
break;
|
|
|
|
default:
|
2006-07-21 03:35:17 +02:00
|
|
|
// V6 Client --> V6 Server, but client SQL dialect was set
|
|
|
|
// by user and was passed.
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (options.dpb_sql_dialect)
|
|
|
|
{
|
|
|
|
case SQL_DIALECT_V5:
|
|
|
|
{
|
2007-06-13 15:21:40 +02:00
|
|
|
strip_quotes(userId.usr_sql_role_name);
|
|
|
|
userId.usr_sql_role_name.upper();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SQL_DIALECT_V6_TRANSITION:
|
|
|
|
case SQL_DIALECT_V6:
|
|
|
|
{
|
2007-06-13 15:21:40 +02:00
|
|
|
if (userId.usr_sql_role_name.hasData() &&
|
|
|
|
(userId.usr_sql_role_name[0] == DBL_QUOTE ||
|
|
|
|
userId.usr_sql_role_name[0] == SINGLE_QUOTE))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2007-06-13 15:21:40 +02:00
|
|
|
const char end_quote = userId.usr_sql_role_name[0];
|
2006-07-21 03:35:17 +02:00
|
|
|
// remove the delimited quotes and escape quote
|
|
|
|
// from ROLE name
|
2007-06-13 15:21:40 +02:00
|
|
|
userId.usr_sql_role_name.erase(0, 1);
|
2004-11-24 19:26:24 +01:00
|
|
|
for (Firebird::string::iterator p =
|
2007-06-13 15:21:40 +02:00
|
|
|
userId.usr_sql_role_name.begin();
|
|
|
|
p < userId.usr_sql_role_name.end(); ++p)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
if (*p == end_quote)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2007-06-13 15:21:40 +02:00
|
|
|
if (++p < userId.usr_sql_role_name.end() &&
|
2004-11-24 19:26:24 +01:00
|
|
|
*p == end_quote)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
// skip the escape quote here
|
2007-06-13 15:21:40 +02:00
|
|
|
userId.usr_sql_role_name.erase(p--);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
// delimited done
|
2007-06-13 15:21:40 +02:00
|
|
|
userId.usr_sql_role_name.erase(--p,
|
|
|
|
userId.usr_sql_role_name.end());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-06-13 15:21:40 +02:00
|
|
|
userId.usr_sql_role_name.upper();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
options.dpb_sql_dialect = 0;
|
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
SCL_init(false, userId, tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-21 09:57:12 +02:00
|
|
|
initing_security = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
if (options.dpb_shutdown)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2008-01-26 14:51:33 +01:00
|
|
|
if (!SHUT_database(tdbb, options.dpb_shutdown,
|
|
|
|
options.dpb_shutdown_delay))
|
2004-02-25 02:50:40 +01:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2004-02-25 02:50:40 +01:00
|
|
|
if (user_status[1] != FB_SUCCESS)
|
|
|
|
ERR_punt();
|
|
|
|
else
|
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "shutdown or online",
|
|
|
|
isc_arg_string, "database",
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2004-02-25 02:50:40 +01:00
|
|
|
0);
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (options.dpb_online)
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2008-01-26 14:51:33 +01:00
|
|
|
if (!SHUT_online(tdbb, options.dpb_online))
|
2004-02-25 02:50:40 +01:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2002-11-14 09:33:08 +01:00
|
|
|
if (user_status[1] != FB_SUCCESS)
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_punt();
|
|
|
|
else
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "shutdown or online",
|
|
|
|
isc_arg_string, "database",
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2001-07-29 19:42:23 +02:00
|
|
|
0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
2001-07-10 19:35:13 +02:00
|
|
|
/* Check if another attachment has or is requesting exclusive database access.
|
2001-05-23 15:26:42 +02:00
|
|
|
If this is an implicit attachment for the security (password) database, don't
|
2001-07-10 19:35:13 +02:00
|
|
|
try to get exclusive attachment to avoid a deadlock condition which happens
|
2001-05-23 15:26:42 +02:00
|
|
|
when a client tries to connect to the security database itself. */
|
|
|
|
|
|
|
|
if (!options.dpb_sec_attach) {
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2004-06-12 03:06:05 +02:00
|
|
|
bool attachment_succeeded = true;
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_single)
|
|
|
|
attachment_succeeded = CCH_exclusive_attachment(tdbb, LCK_none, -1);
|
|
|
|
else
|
|
|
|
CCH_exclusive_attachment(tdbb, LCK_none, LCK_WAIT);
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2005-07-24 20:48:45 +02:00
|
|
|
if (attachment->att_flags & ATT_shutdown) {
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown) {
|
|
|
|
ERR_post(isc_shutdown, isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name), 0);
|
2005-07-24 20:48:45 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
ERR_post(isc_att_shutdown, 0);
|
|
|
|
}
|
|
|
|
}
|
2004-06-12 03:06:05 +02:00
|
|
|
if (!attachment_succeeded) {
|
|
|
|
ERR_post(isc_shutdown, isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name), 0);
|
2004-06-12 03:06:05 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// If database is shutdown then kick 'em out.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (dbb->dbb_ast_flags & (DBB_shut_attach | DBB_shut_tran))
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_shutinprog, isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name), 0);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown) {
|
|
|
|
// Allow only SYSDBA/owner to access database that is shut down
|
2006-08-16 17:15:58 +02:00
|
|
|
bool allow_access = attachment->locksmith();
|
2004-02-25 02:50:40 +01:00
|
|
|
// Handle special shutdown modes
|
|
|
|
if (allow_access) {
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_full) {
|
|
|
|
// Full shutdown. Deny access always
|
|
|
|
allow_access = false;
|
|
|
|
}
|
|
|
|
else if (dbb->dbb_ast_flags & DBB_shutdown_single) {
|
|
|
|
// Single user maintenance. Allow access only if we were able to take exclusive lock
|
|
|
|
// Note that logic below this exclusive lock differs for SS and CS builds:
|
|
|
|
// - CS keeps PW database lock from releasing in AST in single-user maintenance mode
|
|
|
|
// - for SS this code effectively checks that no other attachments are present
|
|
|
|
// at call point, ATT_exclusive bit is released just before this procedure exits
|
|
|
|
// Things are done this way to handle return to online mode nicely.
|
|
|
|
allow_access = CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!allow_access) {
|
|
|
|
// Note we throw exception here when entering full-shutdown mode
|
|
|
|
ERR_post(isc_shutdown, isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name), 0);
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2001-12-24 03:51:06 +01:00
|
|
|
if (options.dpb_quit_log) {
|
2001-05-23 15:26:42 +02:00
|
|
|
LOG_disable();
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Figure out what character set & collation this attachment prefers
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
find_intl_charset(tdbb, attachment, &options);
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (options.dpb_verify)
|
|
|
|
{
|
|
|
|
if (!CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD)) {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_content, isc_arg_gds, isc_cant_validate, 0);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef GARBAGE_THREAD
|
2006-07-21 03:35:17 +02:00
|
|
|
// Can't allow garbage collection during database validation.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
VIO_fini(tdbb);
|
|
|
|
#endif
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!VAL_validate(tdbb, options.dpb_verify)) {
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_punt();
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options.dpb_journal.hasData()) {
|
2004-01-06 11:33:18 +01:00
|
|
|
ERR_post(isc_bad_dpb_content,
|
|
|
|
isc_arg_gds, isc_cant_start_journal,
|
|
|
|
0);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (options.dpb_wal_action)
|
|
|
|
{
|
2005-05-02 11:10:06 +02:00
|
|
|
// No WAL anymore. We deleted it.
|
2004-01-06 11:33:18 +01:00
|
|
|
ERR_post(isc_no_wal, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-11-05 19:30:36 +01:00
|
|
|
* if the attachment is through gbak and this attachment is not by owner
|
2003-03-23 10:05:35 +01:00
|
|
|
* or sysdba then return error. This has been added here to allow for the
|
2001-05-23 15:26:42 +02:00
|
|
|
* GBAK security feature of only allowing the owner or sysdba to backup a
|
|
|
|
* database. smistry 10/5/98
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (((attachment->att_flags & ATT_gbak_attachment) ||
|
|
|
|
(attachment->att_flags & ATT_gfix_attachment) ||
|
|
|
|
(attachment->att_flags & ATT_gstat_attachment)) &&
|
2006-08-16 17:15:58 +02:00
|
|
|
!attachment->locksmith())
|
2003-10-29 11:53:47 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_post(isc_adm_task_denied, 0);
|
|
|
|
}
|
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
if (((attachment->att_flags & ATT_gfix_attachment) ||
|
|
|
|
(attachment->att_flags & ATT_gstat_attachment)))
|
|
|
|
{
|
|
|
|
options.dpb_no_db_triggers = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options.dpb_no_db_triggers)
|
|
|
|
{
|
|
|
|
if (attachment->locksmith())
|
|
|
|
attachment->att_flags |= ATT_no_db_triggers;
|
|
|
|
else
|
|
|
|
ERR_post(isc_adm_task_denied, 0);
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_log) {
|
|
|
|
if (first) {
|
2004-01-06 11:33:18 +01:00
|
|
|
if (!CCH_exclusive(tdbb, LCK_EX, WAIT_PERIOD)) {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2001-07-29 19:42:23 +02:00
|
|
|
0);
|
2004-01-06 11:33:18 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
LOG_enable(options.dpb_log, strlen(options.dpb_log));
|
|
|
|
}
|
2001-07-29 19:42:23 +02:00
|
|
|
else {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_content, isc_arg_gds,
|
|
|
|
isc_cant_start_logging, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_set_db_sql_dialect) {
|
2001-05-23 15:26:42 +02:00
|
|
|
PAG_set_db_SQL_dialect(dbb, options.dpb_set_db_sql_dialect);
|
|
|
|
}
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_sweep_interval != -1) {
|
2001-05-23 15:26:42 +02:00
|
|
|
PAG_sweep_interval(options.dpb_sweep_interval);
|
|
|
|
dbb->dbb_sweep_interval = options.dpb_sweep_interval;
|
|
|
|
}
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_set_force_write) {
|
2001-05-23 15:26:42 +02:00
|
|
|
PAG_set_force_write(dbb, options.dpb_force_write);
|
|
|
|
}
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_set_no_reserve) {
|
2001-05-23 15:26:42 +02:00
|
|
|
PAG_set_no_reserve(dbb, options.dpb_no_reserve);
|
|
|
|
}
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_set_page_buffers) {
|
2001-05-23 15:26:42 +02:00
|
|
|
PAG_set_page_buffers(options.dpb_page_buffers);
|
|
|
|
}
|
|
|
|
|
2003-02-03 14:34:16 +01:00
|
|
|
if (options.dpb_set_db_readonly) {
|
|
|
|
if (!CCH_exclusive(tdbb, LCK_EX, WAIT_PERIOD)) {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name),
|
2003-02-03 14:34:16 +01:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
PAG_set_db_readonly(dbb, options.dpb_db_readonly);
|
|
|
|
}
|
2001-07-12 07:46:06 +02:00
|
|
|
|
2006-07-24 17:56:50 +02:00
|
|
|
PAG_attachment_id(tdbb);
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2006-07-21 03:35:17 +02:00
|
|
|
// don't record the attach until now in case the log is added during the attach
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-09-30 18:16:39 +02:00
|
|
|
LOG_call(log_attach2, file_name, *handle, dpb_length, dpb,
|
2001-05-23 15:26:42 +02:00
|
|
|
expanded_filename);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GARBAGE_THREAD
|
|
|
|
VIO_init(tdbb);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CCH_release_exclusive(tdbb);
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// if there was an error, the status vector is all set
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
if (options.dpb_sweep & isc_dpb_records)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2001-12-24 03:51:06 +01:00
|
|
|
if (!(TRA_sweep(tdbb, 0)))
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_punt();
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_dbkey_scope) {
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_dbkey_trans = TRA_start(tdbb, 0, 0);
|
|
|
|
}
|
|
|
|
|
2003-08-06 18:30:49 +02:00
|
|
|
// Recover database after crash during backup difference file merge
|
2006-07-21 03:35:17 +02:00
|
|
|
dbb->dbb_backup_manager->end_backup(tdbb, true); // true = do recovery
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
if (!(attachment->att_flags & ATT_no_db_triggers))
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = NULL;
|
2006-11-05 19:30:36 +01:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// start a transaction to execute ON CONNECT triggers
|
|
|
|
transaction = TRA_start(tdbb, 0, NULL);
|
|
|
|
|
|
|
|
// load all database triggers
|
|
|
|
MET_load_db_triggers(tdbb, DB_TRIGGER_CONNECT);
|
|
|
|
MET_load_db_triggers(tdbb, DB_TRIGGER_DISCONNECT);
|
|
|
|
MET_load_db_triggers(tdbb, DB_TRIGGER_TRANS_START);
|
|
|
|
MET_load_db_triggers(tdbb, DB_TRIGGER_TRANS_COMMIT);
|
|
|
|
MET_load_db_triggers(tdbb, DB_TRIGGER_TRANS_ROLLBACK);
|
|
|
|
|
|
|
|
// run ON CONNECT triggers
|
2008-02-02 18:04:06 +01:00
|
|
|
EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_connect);
|
2006-11-05 19:30:36 +01:00
|
|
|
|
|
|
|
// and commit the transaction
|
|
|
|
TRA_commit(tdbb, transaction, false);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
2006-11-12 22:19:50 +01:00
|
|
|
if (!(dbb->dbb_flags & DBB_bugcheck) && transaction)
|
2006-11-10 09:38:55 +01:00
|
|
|
TRA_rollback(tdbb, transaction, false, false);
|
2006-11-05 19:30:36 +01:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2007-12-19 15:12:31 +01:00
|
|
|
|
|
|
|
*handle = attachment;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_handle_returned, *handle);
|
2003-08-06 18:30:49 +02:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
} // try
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const DelayFailedLogin& ex)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
ISC_STATUS s = unwindAttach(ex, user_status, tdbb, attachment, dbb);
|
|
|
|
ex.sleep();
|
|
|
|
return s;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
return unwindAttach(ex, user_status, tdbb, attachment, dbb);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_BLOB_INFO(ISC_STATUS* user_status,
|
2004-02-20 07:43:27 +01:00
|
|
|
blb** blob_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT item_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const SCHAR* items,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT buffer_length,
|
|
|
|
SCHAR* buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ b l o b _ i n f o
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Provide information on blob object.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_blob_info2, *blob_handle, item_length, items, buffer_length);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try {
|
2008-01-26 14:51:33 +01:00
|
|
|
blb* blob = *blob_handle;
|
|
|
|
validateHandle(tdbb, blob);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
INF_blob_info(blob, items, item_length, buffer, buffer_length);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
ISC_STATUS GDS_CANCEL_BLOB(ISC_STATUS * user_status, blb** blob_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c a n c e l _ b l o b
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abort a partially completed blob.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2008-01-26 14:51:33 +01:00
|
|
|
LOG_call(log_cancel_blob, *blob_handle);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try {
|
|
|
|
blb* blob = *blob_handle;
|
|
|
|
validateHandle(tdbb, blob);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
BLB_cancel(tdbb, blob);
|
|
|
|
*blob_handle = NULL;
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SLONG* id)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c a n c e l _ e v e n t s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Cancel an outstanding event.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_cancel_events, *handle, *id);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
validateHandle(tdbb, *handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
EVENT_cancel(*id);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
ISC_STATUS GDS_CANCEL_OPERATION(ISC_STATUS* user_status,
|
|
|
|
Attachment** handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT option)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c a n c e l _ o p e r a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Try to cancel an operation.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
switch (option) {
|
|
|
|
case CANCEL_disable:
|
|
|
|
attachment->att_flags |= ATT_cancel_disable;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
case CANCEL_enable:
|
|
|
|
attachment->att_flags &= ~ATT_cancel_disable;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
case CANCEL_raise:
|
|
|
|
attachment->att_flags |= ATT_cancel_raise;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
ISC_STATUS GDS_CLOSE_BLOB(ISC_STATUS * user_status, blb** blob_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c l o s e _ b l o b
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abort a partially completed blob.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_close_blob, *blob_handle);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
blb* blob = *blob_handle;
|
|
|
|
validateHandle(tdbb, blob);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
BLB_close(tdbb, blob);
|
|
|
|
*blob_handle = NULL;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
ISC_STATUS GDS_COMMIT(ISC_STATUS * user_status, jrd_tra** tra_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c o m m i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Commit a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (commit(user_status, tra_handle, false) == FB_SUCCESS)
|
|
|
|
*tra_handle = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
ISC_STATUS GDS_COMMIT_RETAINING(ISC_STATUS * user_status, jrd_tra** tra_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c o m m i t _ r e t a i n i n g
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Commit a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
return commit(user_status, tra_handle, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_COMPILE(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT blr_length,
|
2003-11-07 09:06:35 +01:00
|
|
|
const SCHAR* blr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c o m p i l e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
*
|
|
|
|
**************************************/
|
2007-01-20 15:18:18 +01:00
|
|
|
return compile_request(user_status, db_handle, req_handle, blr_length, blr, 0, NULL, 0, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_CREATE_BLOB2(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2004-02-20 07:43:27 +01:00
|
|
|
blb** blob_handle,
|
|
|
|
bid* blob_id,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT bpb_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const UCHAR* bpb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c r e a t e _ b l o b
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2004-03-11 06:04:26 +01:00
|
|
|
* Create a new blob.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_create_blob2, *db_handle, *tra_handle, *blob_handle, blob_id,
|
|
|
|
bpb_length, bpb);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (*blob_handle)
|
|
|
|
Firebird::status_exception::raise(isc_bad_segstr_handle, 0);
|
|
|
|
|
|
|
|
validateHandle(tdbb, *db_handle);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_segstr_wrong_db);
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
blb* blob = BLB_create2(tdbb, transaction, blob_id, bpb_length, bpb);
|
2002-04-04 09:10:40 +02:00
|
|
|
*blob_handle = blob;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2002-04-04 09:10:40 +02:00
|
|
|
LOG_call(log_handle_returned, *blob_handle);
|
2004-01-21 08:18:30 +01:00
|
|
|
LOG_call(log_handle_returned, blob_id->bid_stuff.bid_temp_id);
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
2005-09-30 18:16:39 +02:00
|
|
|
USHORT _file_length,
|
|
|
|
const TEXT* _file_name,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT dpb_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const UCHAR* dpb,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT db_type,
|
2005-09-30 18:16:39 +02:00
|
|
|
const TEXT* _expanded_filename)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ c r e a t e _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Create a nice, squeeky clean database, uncorrupted by user data.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (*handle)
|
2005-09-30 18:16:39 +02:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
return handle_error(user_status, isc_bad_db_handle);
|
2005-09-30 18:16:39 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-09-30 18:16:39 +02:00
|
|
|
Firebird::PathName file_name(_file_name,
|
|
|
|
_file_length ? _file_length : strlen(_file_name));
|
|
|
|
Firebird::PathName expanded_name(file_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Resolve given alias name
|
2003-10-29 11:53:47 +01:00
|
|
|
const bool is_alias = ResolveDatabaseAlias(expanded_name, expanded_name);
|
2003-08-17 21:56:53 +02:00
|
|
|
if (is_alias)
|
2004-11-07 15:50:53 +01:00
|
|
|
{
|
|
|
|
ISC_expand_filename(expanded_name, false);
|
|
|
|
}
|
2003-08-17 21:56:53 +02:00
|
|
|
else
|
2004-11-07 15:50:53 +01:00
|
|
|
{
|
2005-09-30 18:16:39 +02:00
|
|
|
expanded_name = _expanded_filename;
|
2004-11-07 15:50:53 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Check database against conf file.
|
2004-12-20 18:44:25 +01:00
|
|
|
const vdnResult vdn = verify_database_name(expanded_name, user_status);
|
|
|
|
if (!is_alias && vdn == vdnFail)
|
|
|
|
{
|
|
|
|
return user_status[1];
|
|
|
|
}
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = init(tdbb, user_status, expanded_name, false);
|
2003-12-03 09:19:24 +01:00
|
|
|
if (!dbb) {
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexUnlock();
|
2001-05-23 15:26:42 +02:00
|
|
|
return user_status[1];
|
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
tdbb->setDatabase(dbb);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2004-08-30 20:11:08 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_flags |= DBB_being_opened;
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
ISC_STATUS* const status = user_status;
|
|
|
|
Attachment* attachment = NULL;
|
|
|
|
|
2003-09-21 09:57:12 +02:00
|
|
|
bool initing_security = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Process database parameter block
|
2008-01-26 14:51:33 +01:00
|
|
|
bool invalid_client_SQL_dialect = false;
|
2004-11-24 19:26:24 +01:00
|
|
|
DatabaseOptions options;
|
2008-01-26 14:51:33 +01:00
|
|
|
options.get(dpb, dpb_length, invalid_client_SQL_dialect);
|
2004-02-20 07:43:27 +01:00
|
|
|
if (!invalid_client_SQL_dialect && options.dpb_sql_dialect == 99) {
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_sql_dialect = 0;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
// First check for correct credentials supplied
|
|
|
|
UserId userId;
|
2008-01-26 18:33:57 +01:00
|
|
|
getUserInfo(dbb, userId, options);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifndef NO_NFS
|
2006-07-21 03:35:17 +02:00
|
|
|
// Don't check nfs if single user
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!options.dpb_single_user)
|
|
|
|
#endif
|
|
|
|
{
|
2006-07-21 03:35:17 +02:00
|
|
|
// Check to see if the database is truly local or if it just looks
|
|
|
|
// that way
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-09-07 09:03:25 +02:00
|
|
|
if (ISC_check_if_remote(expanded_name, true))
|
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_unavailable, 0);
|
2003-03-31 19:43:02 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options.dpb_key.hasData())
|
2004-09-07 09:03:25 +02:00
|
|
|
{
|
2004-03-14 14:34:43 +01:00
|
|
|
dbb->dbb_encrypt_key = options.dpb_key;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
tdbb->setAttachment((attachment = FB_NEW(*dbb->dbb_permanent) Attachment(dbb)));
|
2007-02-08 15:14:54 +01:00
|
|
|
attachment->att_filename = is_alias ? file_name : expanded_name;
|
2004-11-26 02:01:27 +01:00
|
|
|
attachment->att_network_protocol = options.dpb_network_protocol;
|
|
|
|
attachment->att_remote_address = options.dpb_remote_address;
|
2006-09-14 15:47:31 +02:00
|
|
|
attachment->att_remote_pid = options.dpb_remote_pid;
|
2007-05-16 09:54:33 +02:00
|
|
|
attachment->att_remote_process = options.dpb_remote_process;
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_next = dbb->dbb_attachments;
|
2006-09-15 04:14:46 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_attachments = attachment;
|
|
|
|
dbb->dbb_flags &= ~DBB_being_opened;
|
|
|
|
dbb->dbb_sys_trans->tra_attachment = attachment;
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options.dpb_working_directory.hasData()) {
|
2004-03-14 14:34:43 +01:00
|
|
|
attachment->att_working_directory = options.dpb_working_directory;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-10-24 08:26:31 +02:00
|
|
|
if (options.dpb_gbak_attach) {
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags |= ATT_gbak_attachment;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
if (options.dpb_no_db_triggers)
|
|
|
|
attachment->att_flags |= ATT_no_db_triggers;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (options.dpb_sql_dialect) {
|
|
|
|
case 0:
|
2004-11-24 19:26:24 +01:00
|
|
|
// This can be issued by QLI, GDEF and old BDE clients.
|
|
|
|
// In this case assume dialect 1
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_sql_dialect = SQL_DIALECT_V5;
|
|
|
|
case SQL_DIALECT_V5:
|
|
|
|
break;
|
|
|
|
case SQL_DIALECT_V6:
|
|
|
|
dbb->dbb_flags |= DBB_DB_SQL_dialect_3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR_post(isc_database_create_failed, isc_arg_string,
|
2004-03-16 18:35:03 +01:00
|
|
|
expanded_name.c_str(), isc_arg_gds, isc_inv_dialect_specified,
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_arg_number, options.dpb_sql_dialect, isc_arg_gds,
|
|
|
|
isc_valid_db_dialects, isc_arg_string, "1 and 3", 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
attachment->att_charset = options.dpb_interp;
|
2003-08-26 09:20:33 +02:00
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options.dpb_lc_messages.hasData()) {
|
2004-03-14 14:34:43 +01:00
|
|
|
attachment->att_lc_messages = options.dpb_lc_messages;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-03 09:19:24 +01:00
|
|
|
if (!options.dpb_page_size) {
|
2001-05-23 15:26:42 +02:00
|
|
|
options.dpb_page_size = DEFAULT_PAGE_SIZE;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-19 17:16:14 +02:00
|
|
|
USHORT page_size = MIN_NEW_PAGE_SIZE;
|
|
|
|
for (; page_size < MAX_PAGE_SIZE; page_size <<= 1)
|
2003-12-03 09:19:24 +01:00
|
|
|
{
|
2003-09-13 14:03:11 +02:00
|
|
|
if (options.dpb_page_size < page_size << 1)
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
dbb->dbb_page_size =
|
|
|
|
(page_size > MAX_PAGE_SIZE) ? MAX_PAGE_SIZE : page_size;
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
LCK_init(tdbb, LCK_OWNER_attachment); // For the attachment
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags |= ATT_lck_init_done;
|
2006-07-21 03:35:17 +02:00
|
|
|
// Extra LCK_init() done to keep the lock table until the
|
|
|
|
// database is shutdown() after the last detach.
|
2001-05-23 15:26:42 +02:00
|
|
|
LCK_init(tdbb, LCK_OWNER_database);
|
|
|
|
dbb->dbb_flags |= DBB_lck_init_done;
|
2006-07-19 08:19:56 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
INI_init();
|
|
|
|
PAG_init();
|
2003-09-21 09:57:12 +02:00
|
|
|
initing_security = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
SCL_init(true, userId, tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-21 09:57:12 +02:00
|
|
|
initing_security = false;
|
2005-04-13 03:06:24 +02:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
2005-04-13 03:06:24 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// try to create with overwrite = false
|
2007-03-09 08:59:05 +01:00
|
|
|
pageSpace->file = PIO_create(dbb, expanded_name, false, false, false);
|
2005-04-13 03:06:24 +02:00
|
|
|
}
|
|
|
|
catch (Firebird::status_exception)
|
|
|
|
{
|
|
|
|
if (options.dpb_overwrite)
|
|
|
|
{
|
2005-09-30 18:16:39 +02:00
|
|
|
if (GDS_ATTACH_DATABASE(user_status, _file_length, _file_name, handle,
|
|
|
|
dpb_length, dpb, _expanded_filename) == isc_adm_task_denied)
|
2005-04-13 03:06:24 +02:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
2005-05-01 16:58:21 +02:00
|
|
|
bool allow_overwrite = false;
|
2005-04-13 03:06:24 +02:00
|
|
|
|
2005-05-01 16:58:21 +02:00
|
|
|
if (*handle)
|
|
|
|
{
|
2006-08-16 17:15:58 +02:00
|
|
|
allow_overwrite = (*handle)->att_user->locksmith();
|
2005-05-01 16:58:21 +02:00
|
|
|
GDS_DETACH(user_status, handle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// clear status after failed attach
|
|
|
|
user_status[0] = 0;
|
|
|
|
allow_overwrite = true;
|
|
|
|
}
|
2005-04-13 03:06:24 +02:00
|
|
|
|
|
|
|
if (allow_overwrite)
|
|
|
|
{
|
|
|
|
// file is a database and the user (SYSDBA or owner) has right to overwrite
|
2006-05-22 00:07:35 +02:00
|
|
|
pageSpace->file =
|
2007-03-09 08:59:05 +01:00
|
|
|
PIO_create(dbb, expanded_name, options.dpb_overwrite, false, false);
|
2005-04-13 03:06:24 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "overwrite",
|
|
|
|
isc_arg_string, "database",
|
|
|
|
isc_arg_string,
|
|
|
|
ERR_cstring(expanded_name.c_str()), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
const jrd_file* first_dbb_file = pageSpace->file;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (options.dpb_set_page_buffers)
|
|
|
|
dbb->dbb_page_buffers = options.dpb_page_buffers;
|
2006-04-29 07:42:43 +02:00
|
|
|
CCH_init(tdbb, options.dpb_buffers);
|
2006-10-07 12:53:01 +02:00
|
|
|
|
|
|
|
// Initialize locks
|
|
|
|
init_database_locks(tdbb, dbb);
|
|
|
|
|
2003-08-06 18:30:49 +02:00
|
|
|
// Initialize backup difference subsystem. This must be done before WAL and shadowing
|
|
|
|
// is enabled because nbackup it is a lower level subsystem
|
2005-11-22 00:33:20 +01:00
|
|
|
dbb->dbb_backup_manager = FB_NEW(*dbb->dbb_permanent) BackupManager(tdbb, dbb, nbak_state_normal);
|
2003-08-06 18:30:49 +02:00
|
|
|
|
2007-04-24 16:05:46 +02:00
|
|
|
dbb->dbb_backup_manager->dbCreating = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
PAG_format_header();
|
|
|
|
INI_init2();
|
|
|
|
PAG_format_log();
|
2006-05-22 00:07:35 +02:00
|
|
|
PAG_format_pip(tdbb, *pageSpace);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (options.dpb_set_page_buffers)
|
|
|
|
PAG_set_page_buffers(options.dpb_page_buffers);
|
|
|
|
|
|
|
|
if (options.dpb_set_no_reserve)
|
|
|
|
PAG_set_no_reserve(dbb, options.dpb_no_reserve);
|
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
INI_format(attachment->att_user->usr_user_name.c_str(),
|
2004-11-24 19:26:24 +01:00
|
|
|
options.dpb_set_db_charset.c_str());
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
// There is no point to move database online at database creation since it is online by default.
|
|
|
|
// We do not allow to create database that is fully shut down.
|
|
|
|
if (options.dpb_online || (options.dpb_shutdown & isc_dpb_shut_mode_mask) == isc_dpb_shut_full)
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_post(isc_bad_shutdown_mode, isc_arg_string, ERR_string(file_name), 0);
|
2004-02-25 02:50:40 +01:00
|
|
|
|
|
|
|
if (options.dpb_shutdown) {
|
2008-01-26 14:51:33 +01:00
|
|
|
if (!SHUT_database(tdbb, options.dpb_shutdown,
|
|
|
|
options.dpb_shutdown_delay))
|
2004-07-30 07:56:35 +02:00
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "shutdown or online",
|
|
|
|
isc_arg_string, "database",
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string(file_name), 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2004-02-25 02:50:40 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (options.dpb_sweep_interval != -1) {
|
|
|
|
PAG_sweep_interval(options.dpb_sweep_interval);
|
|
|
|
dbb->dbb_sweep_interval = options.dpb_sweep_interval;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options.dpb_set_force_write)
|
|
|
|
PAG_set_force_write(dbb, options.dpb_force_write);
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// initialize shadowing semaphore as soon as the database is ready for it
|
|
|
|
// but before any real work is done
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-06 11:33:18 +01:00
|
|
|
SDW_init(options.dpb_activate_shadow, options.dpb_delete_shadow);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef GARBAGE_THREAD
|
|
|
|
VIO_init(tdbb);
|
|
|
|
#endif
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
if (options.dpb_set_db_readonly) {
|
2001-07-10 19:35:13 +02:00
|
|
|
if (!CCH_exclusive (tdbb, LCK_EX, WAIT_PERIOD))
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post (isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
|
|
|
isc_arg_string,
|
2005-09-30 18:16:39 +02:00
|
|
|
ERR_string (file_name),
|
2001-07-29 19:42:23 +02:00
|
|
|
0);
|
|
|
|
|
2001-07-10 19:35:13 +02:00
|
|
|
PAG_set_db_readonly (dbb, options.dpb_db_readonly);
|
2001-07-29 19:42:23 +02:00
|
|
|
}
|
2001-07-10 19:35:13 +02:00
|
|
|
|
2006-07-24 17:56:50 +02:00
|
|
|
PAG_attachment_id(tdbb);
|
|
|
|
|
|
|
|
CCH_release_exclusive(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Figure out what character set & collation this attachment prefers
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
find_intl_charset(tdbb, attachment, &options);
|
|
|
|
|
2002-07-02 11:49:19 +02:00
|
|
|
#ifdef WIN_NT
|
2004-03-14 14:34:43 +01:00
|
|
|
dbb->dbb_filename.assign(first_dbb_file->fil_string,
|
2002-07-02 11:49:19 +02:00
|
|
|
first_dbb_file->fil_length);
|
|
|
|
#else
|
2004-03-14 14:34:43 +01:00
|
|
|
dbb->dbb_filename = expanded_name;
|
2002-07-02 11:49:19 +02:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-11-11 06:37:52 +01:00
|
|
|
// NS: Use alias as database ID only if accessing database using file name is not possible.
|
|
|
|
//
|
|
|
|
// This way we:
|
|
|
|
// 1. Ensure uniqueness of ID even in presence of multiple processes
|
|
|
|
// 2. Make sure that ID value can be used to connect back to database
|
|
|
|
//
|
|
|
|
if (is_alias && vdn == vdnFail)
|
2005-09-30 18:16:39 +02:00
|
|
|
dbb->dbb_database_name = file_name;
|
2004-11-11 06:37:52 +01:00
|
|
|
else
|
|
|
|
dbb->dbb_database_name = dbb->dbb_filename;
|
|
|
|
|
2004-05-14 20:43:34 +02:00
|
|
|
CCH_flush(tdbb, FLUSH_FINI, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-04-24 16:05:46 +02:00
|
|
|
dbb->dbb_backup_manager->dbCreating = false;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
dbMutexUnlock();
|
|
|
|
|
|
|
|
*handle = attachment;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
} // try
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const DelayFailedLogin& ex)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
ISC_STATUS s = unwindAttach(ex, user_status, tdbb, attachment, dbb);
|
|
|
|
ex.sleep();
|
|
|
|
return s;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
return unwindAttach(ex, user_status, tdbb, attachment, dbb);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_DATABASE_INFO(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT item_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const SCHAR* items,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT buffer_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
SCHAR* buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ d a t a b a s e _ i n f o
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Provide information on database object.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_database_info2, *handle, item_length, items, buffer_length);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
INF_database_info(items, item_length, buffer, buffer_length);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
ISC_STATUS GDS_DDL(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT ddl_length,
|
2003-11-05 10:02:33 +01:00
|
|
|
const SCHAR* ddl)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ d d l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_ddl, *db_handle, *tra_handle, ddl_length, ddl);
|
|
|
|
#endif
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *db_handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_segstr_wrong_db);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
DYN_ddl(attachment, transaction, ddl_length,
|
2003-11-05 10:02:33 +01:00
|
|
|
reinterpret_cast<const UCHAR*>(ddl));
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Perform an auto commit for autocommit transactions.
|
|
|
|
// This is slightly tricky. If the commit retain works,
|
|
|
|
// all is well. If TRA_commit() fails, we perform
|
|
|
|
// a rollback_retain(). This will backout the
|
|
|
|
// effects of the transaction, mark it dead and
|
|
|
|
// start a new transaction.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (transaction->tra_flags & TRA_perform_autocommit)
|
|
|
|
{
|
|
|
|
transaction->tra_flags &= ~TRA_perform_autocommit;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-02 07:10:26 +01:00
|
|
|
try {
|
2008-01-26 14:51:33 +01:00
|
|
|
TRA_commit(tdbb, transaction, true);
|
2003-11-02 07:10:26 +01:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception&) {
|
2008-01-26 14:51:33 +01:00
|
|
|
ISC_STATUS_ARRAY temp_status;
|
|
|
|
tdbb->tdbb_status_vector = temp_status;
|
|
|
|
try {
|
|
|
|
TRA_rollback(tdbb, transaction, true, false);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{} // no-op
|
|
|
|
tdbb->tdbb_status_vector = user_status;
|
|
|
|
throw;
|
2003-11-02 07:10:26 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2004-11-07 11:47:20 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const Firebird::Exception& ex) {
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
ISC_STATUS GDS_DETACH(ISC_STATUS* user_status, Attachment** handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ d e t a c h
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close down a database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
DbMutexGuard guard;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// if this is the last attachment, mark dbb as not in use
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->dbb_attachments == attachment &&
|
|
|
|
!attachment->att_next &&
|
|
|
|
!(dbb->dbb_flags & DBB_being_opened))
|
|
|
|
{
|
|
|
|
dbb->dbb_flags |= DBB_not_in_use;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2008-01-26 14:51:33 +01:00
|
|
|
LOG_call(log_detach, *handle);
|
|
|
|
LOG_call(log_statistics, dbb->dbb_reads, dbb->dbb_writes,
|
|
|
|
dbb->dbb_max_memory);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Purge attachment, don't rollback open transactions
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
attachment->att_flags |= ATT_cancel_disable;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
purge_attachment(tdbb, user_status, attachment, false);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
*handle = NULL;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex) {
|
2008-01-26 14:51:33 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2008-01-29 11:36:49 +01:00
|
|
|
if (dbb)
|
|
|
|
{
|
|
|
|
dbb->dbb_flags &= ~DBB_not_in_use;
|
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
ISC_STATUS GDS_DROP_DATABASE(ISC_STATUS* user_status, Attachment** handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ d r o p _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close down and purge a database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2004-08-30 20:11:08 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
DbMutexGuard guard;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2004-08-30 20:11:08 +02:00
|
|
|
LOG_call(log_drop_database, *handle);
|
|
|
|
LOG_call(log_statistics, dbb->dbb_reads, dbb->dbb_writes,
|
2008-01-26 14:51:33 +01:00
|
|
|
dbb->dbb_max_memory);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
2008-01-26 14:51:33 +01:00
|
|
|
const Firebird::PathName& file_name = attachment->att_filename;
|
2005-07-24 20:48:45 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (!attachment->locksmith())
|
2008-01-29 02:36:41 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
ERR_post(isc_no_priv,
|
|
|
|
isc_arg_string, "drop",
|
|
|
|
isc_arg_string, "database",
|
|
|
|
isc_arg_string, ERR_cstring(file_name), 0);
|
2008-01-29 02:36:41 +01:00
|
|
|
}
|
2003-01-18 17:31:23 +01:00
|
|
|
|
2008-01-29 02:36:41 +01:00
|
|
|
if (attachment->att_flags & ATT_shutdown)
|
|
|
|
{
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown)
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
ERR_post(isc_shutdown, isc_arg_string,
|
|
|
|
ERR_cstring(file_name), 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ERR_post(isc_att_shutdown, 0);
|
2005-07-24 20:48:45 +02:00
|
|
|
}
|
2004-08-30 20:11:08 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (!CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD))
|
2008-01-29 02:36:41 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
ERR_post(isc_lock_timeout,
|
|
|
|
isc_arg_gds, isc_obj_in_use,
|
|
|
|
isc_arg_string, ERR_cstring(file_name), 0);
|
2008-01-29 02:36:41 +01:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Check if same process has more attachments
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->dbb_attachments && dbb->dbb_attachments->att_next) {
|
|
|
|
ERR_post(isc_no_meta_update, isc_arg_gds, isc_obj_in_use,
|
|
|
|
isc_arg_string, "DATABASE", 0);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Forced release of all transactions
|
|
|
|
purge_transactions(tdbb, attachment, true, attachment->att_flags);
|
2007-07-25 15:21:59 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
attachment->att_flags |= ATT_cancel_disable;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Here we have database locked in exclusive mode.
|
|
|
|
// Just mark the header page with an 0 ods version so that no other
|
|
|
|
// process can attach to this database once we release our exclusive
|
|
|
|
// lock and start dropping files.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
WIN window(HEADER_PAGE_NUMBER);
|
|
|
|
Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
|
|
|
CCH_MARK_MUST_WRITE(tdbb, &window);
|
|
|
|
header->hdr_ods_version = 0;
|
|
|
|
CCH_RELEASE(tdbb, &window);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// This point on database is useless
|
|
|
|
// mark the dbb unusable
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
dbb->dbb_flags |= DBB_not_in_use;
|
|
|
|
*handle = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
|
|
|
const jrd_file* file = pageSpace->file;
|
2004-08-30 20:11:08 +02:00
|
|
|
const Shadow* shadow = dbb->dbb_shadow;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Unlink attachment from database
|
2008-01-26 14:51:33 +01:00
|
|
|
release_attachment(tdbb, attachment);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
shutdown_database(dbb, false);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// drop the files here
|
|
|
|
bool err = drop_files(file);
|
2004-08-30 20:11:08 +02:00
|
|
|
for (; shadow; shadow = shadow->sdw_next)
|
|
|
|
{
|
|
|
|
err = err || drop_files(shadow->sdw_file);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
tdbb->setDatabase(NULL);
|
2008-01-29 18:32:42 +01:00
|
|
|
Database::deleteDbb(dbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (err) {
|
|
|
|
user_status[0] = isc_arg_gds;
|
|
|
|
user_status[1] = isc_drdb_completed_with_errs;
|
|
|
|
user_status[2] = isc_arg_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex) {
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-21 17:52:30 +02:00
|
|
|
ISC_STATUS GDS_INTL_FUNCTION(ISC_STATUS* user_status, Attachment** handle,
|
2007-05-27 00:08:13 +02:00
|
|
|
USHORT function, UCHAR charSetNumber, USHORT strLen, const UCHAR* str, void* result)
|
2005-08-21 17:52:30 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ i n t l _ f u n c t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Return INTL informations.
|
|
|
|
* (candidate for removal when engine functions can be called by DSQL)
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2005-08-21 17:52:30 +02:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2005-08-21 17:52:30 +02:00
|
|
|
CharSet* charSet = INTL_charset_lookup(tdbb, charSetNumber);
|
|
|
|
|
|
|
|
switch (function)
|
|
|
|
{
|
|
|
|
case INTL_FUNCTION_CHAR_LENGTH:
|
|
|
|
{
|
|
|
|
ULONG offendingPos;
|
|
|
|
|
|
|
|
if (!charSet->wellFormed(strLen, str, &offendingPos))
|
|
|
|
{
|
|
|
|
ERR_post(isc_sqlerr,
|
|
|
|
isc_arg_number, (SLONG) - 104,
|
|
|
|
isc_arg_gds, isc_malformed_string, 0);
|
|
|
|
}
|
|
|
|
else
|
2007-05-27 00:08:13 +02:00
|
|
|
*static_cast<USHORT*>(result) = charSet->length(strLen, str, true);
|
2005-08-21 17:52:30 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-05-27 00:08:13 +02:00
|
|
|
case INTL_FUNCTION_CONV_TO_METADATA:
|
|
|
|
{
|
|
|
|
Firebird::UCharBuffer* buffer = static_cast<Firebird::UCharBuffer*>(result);
|
|
|
|
buffer->resize(INTL_convert_bytes(tdbb, CS_METADATA, buffer->getBuffer(strLen * 4),
|
|
|
|
strLen * 4, charSetNumber, str, strLen, ERR_post));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-08-21 17:52:30 +02:00
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2005-08-21 17:52:30 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2005-08-21 17:52:30 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2005-08-21 17:52:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-10 05:12:10 +02:00
|
|
|
ISC_STATUS GDS_DSQL_CACHE(ISC_STATUS* user_status, Attachment** handle,
|
|
|
|
USHORT operation, int type, const char* name, bool* obsolete)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ d s q l _ c a c h e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Manage DSQL cache locks.
|
|
|
|
* (candidate for removal when engine functions can be called by DSQL)
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2006-07-10 05:12:10 +02:00
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
2006-07-12 17:13:22 +02:00
|
|
|
if (obsolete)
|
|
|
|
*obsolete = false;
|
2006-07-10 05:12:10 +02:00
|
|
|
#else
|
2006-07-12 17:13:22 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2006-07-10 05:12:10 +02:00
|
|
|
|
|
|
|
Firebird::string key((char*)&type, sizeof(type));
|
|
|
|
key.append(name);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
DSqlCacheItem* item = attachment->att_dsql_cache.put(key);
|
2007-07-25 15:21:59 +02:00
|
|
|
if (item)
|
2006-07-10 05:12:10 +02:00
|
|
|
{
|
|
|
|
item->obsolete = false;
|
|
|
|
item->locked = false;
|
|
|
|
item->lock = FB_NEW_RPT(*dbb->dbb_permanent, key.length()) Lock();
|
|
|
|
|
|
|
|
item->lock->lck_type = LCK_dsql_cache;
|
|
|
|
item->lock->lck_owner_handle = LCK_get_owner_handle(tdbb, item->lock->lck_type);
|
|
|
|
item->lock->lck_parent = dbb->dbb_lock;
|
|
|
|
item->lock->lck_dbb = dbb;
|
|
|
|
item->lock->lck_object = (blk*)item;
|
|
|
|
item->lock->lck_ast = blocking_ast_dsql_cache;
|
|
|
|
item->lock->lck_length = key.length();
|
|
|
|
memcpy(item->lock->lck_key.lck_string, key.c_str(), key.length());
|
2007-07-25 15:21:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
item = &attachment->att_dsql_cache.current()->second;
|
2006-07-10 05:12:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (obsolete)
|
|
|
|
*obsolete = item->obsolete;
|
|
|
|
|
|
|
|
if (operation == DSQL_CACHE_USE && !item->locked)
|
|
|
|
{
|
|
|
|
// lock to be notified by others when we should mark as obsolete
|
|
|
|
LCK_lock(tdbb, item->lock, LCK_SR, LCK_WAIT);
|
|
|
|
item->locked = true;
|
|
|
|
}
|
|
|
|
else if (operation == DSQL_CACHE_RELEASE)
|
|
|
|
{
|
|
|
|
// notify others through AST to mark as obsolete
|
|
|
|
LCK_lock(tdbb, item->lock, LCK_EX, LCK_WAIT);
|
|
|
|
|
|
|
|
// release lock
|
|
|
|
LCK_release(tdbb, item->lock);
|
|
|
|
item->locked = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->obsolete = false;
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2006-07-10 05:12:10 +02:00
|
|
|
}
|
2006-07-12 17:13:22 +02:00
|
|
|
#endif // SUPERSERVER
|
2006-07-10 05:12:10 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2006-07-10 05:12:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-20 15:18:18 +01:00
|
|
|
ISC_STATUS GDS_INTERNAL_COMPILE(ISC_STATUS* user_status,
|
|
|
|
Attachment** db_handle,
|
|
|
|
jrd_req** req_handle,
|
|
|
|
SSHORT blr_length,
|
|
|
|
const SCHAR* blr,
|
|
|
|
USHORT string_length, const char* string,
|
|
|
|
USHORT dbginfo_length, const UCHAR* dbginfo)
|
2006-07-17 19:44:18 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2007-01-20 15:18:18 +01:00
|
|
|
* g d s _ $ i n t e r n a l _ c o m p i l e
|
2006-07-17 19:44:18 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2007-01-20 15:18:18 +01:00
|
|
|
* Compile a request passing the SQL text and debug information.
|
2006-07-17 19:44:18 +02:00
|
|
|
* (candidate for removal when engine functions can be called by DSQL)
|
|
|
|
*
|
|
|
|
**************************************/
|
2007-01-20 15:18:18 +01:00
|
|
|
return compile_request(user_status, db_handle, req_handle, blr_length, blr,
|
|
|
|
string_length, string, dbginfo_length, dbginfo);
|
2006-07-17 19:44:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_GET_SEGMENT(ISC_STATUS * user_status,
|
2004-02-20 07:43:27 +01:00
|
|
|
blb** blob_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT * length,
|
|
|
|
USHORT buffer_length,
|
|
|
|
UCHAR * buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ g e t _ s e g m e n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abort a partially completed blob.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_get_segment2, *blob_handle, length, buffer_length);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
blb* blob = *blob_handle;
|
|
|
|
validateHandle(tdbb, blob);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
*length = BLB_get_segment(tdbb, blob, buffer, buffer_length);
|
2008-01-26 14:51:33 +01:00
|
|
|
user_status[0] = isc_arg_gds;
|
|
|
|
user_status[2] = isc_arg_end;
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
if (blob->blb_flags & BLB_eof) {
|
2008-01-26 14:51:33 +01:00
|
|
|
user_status[1] = isc_segstr_eof;
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
else if (blob->blb_fragment_size) {
|
|
|
|
user_status[1] = isc_segment;
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-03 09:19:24 +01:00
|
|
|
ISC_STATUS GDS_GET_SLICE(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2004-02-24 06:34:44 +01:00
|
|
|
ISC_QUAD* array_id,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT sdl_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const UCHAR* sdl,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT param_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const UCHAR* param,
|
2003-10-03 03:53:34 +02:00
|
|
|
SLONG slice_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
UCHAR* slice,
|
|
|
|
SLONG* return_length)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ g e t _ s l i c e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Snatch a slice of an array.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_get_slice2, *db_handle, *tra_handle, *array_id, sdl_length,
|
|
|
|
sdl, param_length, param, slice_length);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
validateHandle(tdbb, *db_handle);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_segstr_wrong_db);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
2004-02-24 06:34:44 +01:00
|
|
|
if (!array_id->gds_quad_low && !array_id->gds_quad_high) {
|
2002-04-04 09:10:40 +02:00
|
|
|
MOVE_CLEAR(slice, slice_length);
|
|
|
|
*return_length = 0;
|
|
|
|
}
|
2007-11-01 18:19:54 +01:00
|
|
|
else {
|
2002-04-04 09:10:40 +02:00
|
|
|
*return_length = BLB_get_slice(tdbb,
|
2001-05-23 15:26:42 +02:00
|
|
|
transaction,
|
2004-02-20 07:43:27 +01:00
|
|
|
reinterpret_cast<bid*>(array_id),
|
2001-05-23 15:26:42 +02:00
|
|
|
sdl,
|
|
|
|
param_length,
|
2007-11-01 18:19:54 +01:00
|
|
|
param,
|
2001-05-23 15:26:42 +02:00
|
|
|
slice_length, slice);
|
2007-11-01 18:19:54 +01:00
|
|
|
}
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_OPEN_BLOB2(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2004-02-20 07:43:27 +01:00
|
|
|
blb** blob_handle,
|
|
|
|
bid* blob_id,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT bpb_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const UCHAR* bpb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ o p e n _ b l o b 2
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open an existing blob.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_open_blob2, *db_handle, *tra_handle, *blob_handle, blob_id,
|
|
|
|
bpb_length, bpb);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (*blob_handle)
|
|
|
|
Firebird::status_exception::raise(isc_bad_segstr_handle, 0);
|
|
|
|
|
|
|
|
validateHandle(tdbb, *db_handle);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_segstr_wrong_db);
|
|
|
|
|
2007-05-22 04:14:20 +02:00
|
|
|
blb* blob = BLB_open2(tdbb, transaction, blob_id, bpb_length, bpb, true);
|
2002-04-04 09:10:40 +02:00
|
|
|
*blob_handle = blob;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2002-04-04 09:10:40 +02:00
|
|
|
LOG_call(log_handle_returned, *blob_handle);
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_PREPARE(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT length,
|
2006-02-23 06:08:26 +01:00
|
|
|
const UCHAR* msg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ p r e p a r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Prepare a transaction for commit. First phase of a two
|
|
|
|
* phase commit.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_prepare2, *tra_handle, length, msg);
|
|
|
|
#endif
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
jrd_tra* transaction = *tra_handle;
|
|
|
|
validateHandle(tdbb, transaction);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
prepare(tdbb, transaction, length, msg);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_PUT_SEGMENT(ISC_STATUS* user_status,
|
2004-02-20 07:43:27 +01:00
|
|
|
blb** blob_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT buffer_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const UCHAR* buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ p u t _ s e g m e n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abort a partially completed blob.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_put_segment, *blob_handle, buffer_length, buffer);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
blb* blob = *blob_handle;
|
|
|
|
validateHandle(tdbb, blob);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
BLB_put_segment(tdbb, blob, buffer, buffer_length);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-03 09:19:24 +01:00
|
|
|
ISC_STATUS GDS_PUT_SLICE(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2004-02-24 06:34:44 +01:00
|
|
|
ISC_QUAD* array_id,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT sdl_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const UCHAR* sdl,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT param_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const UCHAR* param,
|
2003-10-03 03:53:34 +02:00
|
|
|
SLONG slice_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
UCHAR* slice)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ p u t _ s l i c e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Snatch a slice of an array.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_put_slice, *db_handle, *tra_handle, *array_id, sdl_length,
|
|
|
|
sdl, param_length, param, slice_length, slice);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
validateHandle(tdbb, *db_handle);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_segstr_wrong_db);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
BLB_put_slice(tdbb,
|
2001-05-23 15:26:42 +02:00
|
|
|
transaction,
|
2004-02-20 07:43:27 +01:00
|
|
|
reinterpret_cast<bid*>(array_id),
|
2001-05-23 15:26:42 +02:00
|
|
|
sdl,
|
|
|
|
param_length,
|
2004-01-12 07:58:27 +01:00
|
|
|
reinterpret_cast<const SLONG*>(param), slice_length, slice);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
ISC_STATUS GDS_QUE_EVENTS(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
SLONG* id,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const UCHAR* items,
|
2003-12-22 11:00:59 +01:00
|
|
|
FPTR_EVENT_CALLBACK ast,
|
2003-11-28 07:48:34 +01:00
|
|
|
void* arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ q u e _ e v e n t s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Que a request for event notification.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_que_events, *handle, length, items);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2004-03-18 06:56:06 +01:00
|
|
|
Lock* lock = dbb->dbb_lock;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
if (!attachment->att_event_session &&
|
|
|
|
!(attachment->att_event_session = EVENT_create_session(user_status)))
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
*id = EVENT_que(user_status,
|
|
|
|
attachment->att_event_session,
|
|
|
|
lock->lck_length,
|
2008-01-26 14:51:33 +01:00
|
|
|
(const TEXT*) &lock->lck_key, length, items, ast, arg);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2002-04-04 09:10:40 +02:00
|
|
|
LOG_call(log_handle_returned, *id);
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_RECEIVE(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT msg_type,
|
|
|
|
USHORT msg_length,
|
|
|
|
SCHAR * msg,
|
|
|
|
SSHORT level
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef SCROLLABLE_CURSORS
|
2003-10-03 03:53:34 +02:00
|
|
|
, USHORT direction,
|
|
|
|
ULONG offset
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ r e c e i v e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get a record from the host program.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_receive2, *req_handle, msg_type, msg_length, level);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
check_transaction(tdbb, request->req_transaction);
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
verify_request_synchronization(request, level);
|
2007-09-05 09:18:37 +02:00
|
|
|
|
2006-01-28 05:12:42 +01:00
|
|
|
#ifdef SCROLLABLE_CURSORS
|
2002-04-04 09:10:40 +02:00
|
|
|
if (direction)
|
|
|
|
EXE_seek(tdbb, request, direction, offset);
|
2006-01-28 05:12:42 +01:00
|
|
|
#endif
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
EXE_receive(tdbb, request, msg_type, msg_length,
|
2007-03-24 04:00:22 +01:00
|
|
|
reinterpret_cast<UCHAR*>(msg), true);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
check_autocommit(request, tdbb);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (request->req_flags & req_warning)
|
2002-04-04 09:10:40 +02:00
|
|
|
request->req_flags &= ~req_warning;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
ISC_STATUS GDS_RECONNECT(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT length,
|
2003-11-01 11:26:43 +01:00
|
|
|
const UCHAR* id)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ r e c o n n e c t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Connect to a transaction in limbo.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_reconnect, *db_handle, *tra_handle, length, id);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (*tra_handle)
|
|
|
|
Firebird::status_exception::raise(isc_bad_trans_handle, 0);
|
|
|
|
|
|
|
|
Attachment* attachment = *db_handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
jrd_tra* transaction = TRA_reconnect(tdbb, id, length);
|
2002-04-04 09:10:40 +02:00
|
|
|
*tra_handle = transaction;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2002-04-04 09:10:40 +02:00
|
|
|
LOG_call(log_handle_returned, *tra_handle);
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
ISC_STATUS GDS_RELEASE_REQUEST(ISC_STATUS * user_status, jrd_req** req_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ r e l e a s e _ r e q u e s t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Release a request.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_release_request, *req_handle);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
CMP_release(tdbb, request);
|
|
|
|
*req_handle = NULL;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_REQUEST_INFO(ISC_STATUS* user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT level,
|
|
|
|
SSHORT item_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const SCHAR* items,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT buffer_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
SCHAR* buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ r e q u e s t _ i n f o
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Provide information on blob object.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_request_info2, *req_handle, level, item_length, items,
|
|
|
|
buffer_length);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
verify_request_synchronization(request, level);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
INF_request_info(request, items, item_length, buffer, buffer_length);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_ROLLBACK_RETAINING(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ r o l l b a c k _ r e t a i n i n g
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abort a transaction but keep the environment valid
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
return rollback(user_status, tra_handle, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
ISC_STATUS GDS_ROLLBACK(ISC_STATUS * user_status, jrd_tra** tra_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ r o l l b a c k
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abort a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
if (rollback(user_status, tra_handle, false) == FB_SUCCESS)
|
|
|
|
*tra_handle = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_SEEK_BLOB(ISC_STATUS * user_status,
|
2004-02-20 07:43:27 +01:00
|
|
|
blb** blob_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT mode,
|
|
|
|
SLONG offset,
|
|
|
|
SLONG * result)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s e e k _ b l o b
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Seek a stream blob.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_blob_seek, *blob_handle, mode, offset);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
blb* blob = *blob_handle;
|
|
|
|
validateHandle(tdbb, blob);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
*result = BLB_lseek(blob, mode, offset);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_SEND(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT msg_type,
|
|
|
|
USHORT msg_length,
|
|
|
|
SCHAR * msg,
|
|
|
|
SSHORT level)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s e n d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get a record from the host program.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_send, *req_handle, msg_type, msg_length, msg, level);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
check_transaction(tdbb, request->req_transaction);
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
verify_request_synchronization(request, level);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
EXE_send(tdbb, request, msg_type, msg_length,
|
2003-10-07 12:43:20 +02:00
|
|
|
reinterpret_cast<UCHAR*>(msg));
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
check_autocommit(request, tdbb);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (request->req_flags & req_warning)
|
2002-04-04 09:10:40 +02:00
|
|
|
request->req_flags &= ~req_warning;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-03 09:19:24 +01:00
|
|
|
ISC_STATUS GDS_SERVICE_ATTACH(ISC_STATUS* user_status,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT service_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const TEXT* service_name,
|
2004-03-18 06:56:06 +01:00
|
|
|
Service** svc_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT spb_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const SCHAR* spb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s e r v i c e _ a t t a c h
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2007-02-11 10:04:54 +01:00
|
|
|
* Connect to a Firebird service.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
if (*svc_handle)
|
|
|
|
Firebird::status_exception::raise(isc_bad_svc_handle, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-02-02 19:33:37 +01:00
|
|
|
*svc_handle = new Service(service_length, service_name, spb_length, spb);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const DelayFailedLogin& ex)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
ex.sleep();
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
ISC_STATUS GDS_SERVICE_DETACH(ISC_STATUS* user_status, Service** svc_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s e r v i c e _ d e t a c h
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close down a service.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Service* service = *svc_handle;
|
|
|
|
validateHandle(service);
|
|
|
|
|
2008-02-02 19:33:37 +01:00
|
|
|
service->detach();
|
2002-04-04 09:10:40 +02:00
|
|
|
*svc_handle = NULL;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_SERVICE_QUERY(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Service** svc_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
ULONG* reserved,
|
|
|
|
USHORT send_item_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const SCHAR* send_items,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT recv_item_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const SCHAR* recv_items,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT buffer_length,
|
|
|
|
SCHAR* buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s e r v i c e _ q u e r y
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Provide information on service object.
|
|
|
|
*
|
|
|
|
* NOTE: The parameter RESERVED must not be used
|
|
|
|
* for any purpose as there are networking issues
|
|
|
|
* involved (as with any handle that goes over the
|
2001-07-10 19:35:13 +02:00
|
|
|
* network). This parameter will be implemented at
|
2001-05-23 15:26:42 +02:00
|
|
|
* a later date.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Service* service = *svc_handle;
|
|
|
|
validateHandle(service);
|
|
|
|
|
2008-02-02 19:33:37 +01:00
|
|
|
if (service->getVersion() == isc_spb_version1) {
|
|
|
|
service->query(send_item_length, send_items, recv_item_length,
|
2002-04-04 09:10:40 +02:00
|
|
|
recv_items, buffer_length, buffer);
|
2008-01-26 14:51:33 +01:00
|
|
|
}
|
2002-04-04 09:10:40 +02:00
|
|
|
else {
|
2006-07-21 03:35:17 +02:00
|
|
|
// For SVC_query2, we are going to completly dismantle user_status (since at this point it is
|
|
|
|
// meaningless anyway). The status vector returned by this function can hold information about
|
|
|
|
// the call to query the service manager and/or a service thread that may have been running.
|
|
|
|
|
2008-02-02 19:33:37 +01:00
|
|
|
service->query2(tdbb, send_item_length, send_items,
|
2002-04-04 09:10:40 +02:00
|
|
|
recv_item_length, recv_items, buffer_length, buffer);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// If there is a status vector from a service thread, copy it into the thread status
|
2003-11-01 11:26:43 +01:00
|
|
|
int len, warning;
|
2008-02-02 19:33:37 +01:00
|
|
|
PARSE_STATUS(service->getStatus(), len, warning);
|
2002-04-04 09:10:40 +02:00
|
|
|
if (len) {
|
2008-02-02 19:33:37 +01:00
|
|
|
memcpy(tdbb->tdbb_status_vector, service->getStatus(), sizeof(ISC_STATUS) * len);
|
2006-07-21 03:35:17 +02:00
|
|
|
// Empty out the service status vector
|
2008-02-02 19:33:37 +01:00
|
|
|
memset(service->getStatus(), 0, sizeof(ISC_STATUS_ARRAY));
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_SERVICE_START(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Service** svc_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
ULONG* reserved,
|
|
|
|
USHORT spb_length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* spb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ s e r v i c e _ s t a r t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Start the specified service
|
|
|
|
*
|
|
|
|
* NOTE: The parameter RESERVED must not be used
|
|
|
|
* for any purpose as there are networking issues
|
|
|
|
* involved (as with any handle that goes over the
|
2001-07-10 19:35:13 +02:00
|
|
|
* network). This parameter will be implemented at
|
2001-05-23 15:26:42 +02:00
|
|
|
* a later date.
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Service* service = *svc_handle;
|
|
|
|
validateHandle(service);
|
|
|
|
|
2008-02-02 19:33:37 +01:00
|
|
|
service->start(spb_length, spb);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
2008-02-02 19:33:37 +01:00
|
|
|
if (service->getStatus()[1]) {
|
|
|
|
ISC_STATUS* svc_status = service->getStatus();
|
2003-04-10 08:49:16 +02:00
|
|
|
ISC_STATUS* tdbb_status = tdbb->tdbb_status_vector;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
while (*svc_status) {
|
|
|
|
*tdbb_status++ = *svc_status++;
|
|
|
|
}
|
|
|
|
*tdbb_status = isc_arg_end;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-03 09:19:24 +01:00
|
|
|
ISC_STATUS GDS_START_AND_SEND(ISC_STATUS* user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT msg_type,
|
|
|
|
USHORT msg_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
SCHAR* msg,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT level)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s t a r t _ a n d _ s e n d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get a record from the host program.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_start_and_send, *req_handle, *tra_handle, msg_type,
|
|
|
|
msg_length, msg, level);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
check_transaction(tdbb, request->req_transaction);
|
|
|
|
|
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_req_wrong_db);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
if (level)
|
2003-11-09 10:51:02 +01:00
|
|
|
request = CMP_clone_request(tdbb, request, level, false);
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
EXE_unwind(tdbb, request);
|
|
|
|
EXE_start(tdbb, request, transaction);
|
|
|
|
EXE_send(tdbb, request, msg_type, msg_length,
|
2003-10-07 12:43:20 +02:00
|
|
|
reinterpret_cast<UCHAR*>(msg));
|
2002-04-04 09:10:40 +02:00
|
|
|
|
|
|
|
check_autocommit(request, tdbb);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (request->req_flags & req_warning)
|
2002-04-04 09:10:40 +02:00
|
|
|
request->req_flags &= ~req_warning;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_START(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT level)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s t a r t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get a record from the host program.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_start, *req_handle, *tra_handle, level);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
check_transaction(tdbb, request->req_transaction);
|
|
|
|
|
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_req_wrong_db);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
if (level)
|
2003-11-09 10:51:02 +01:00
|
|
|
request = CMP_clone_request(tdbb, request, level, false);
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
EXE_unwind(tdbb, request);
|
|
|
|
EXE_start(tdbb, request, transaction);
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
check_autocommit(request, tdbb);
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
if (request->req_flags & req_warning)
|
2002-04-04 09:10:40 +02:00
|
|
|
request->req_flags &= ~req_warning;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_START_MULTIPLE(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT count,
|
|
|
|
TEB * vector)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s t a r t _ m u l t i p l e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Start a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
jrd_tra* prior = NULL;
|
|
|
|
jrd_tra* transaction = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
if (*tra_handle)
|
|
|
|
Firebird::status_exception::raise(isc_bad_trans_handle, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (count < 1 || count > MAX_DB_PER_TRANS)
|
|
|
|
{
|
|
|
|
Firebird::status_exception::raise(isc_max_db_per_trans_allowed,
|
|
|
|
isc_arg_number, MAX_DB_PER_TRANS,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (TEB* v = vector; v < vector + count; v++)
|
2006-10-10 08:41:36 +02:00
|
|
|
{
|
|
|
|
Attachment* attachment = *v->teb_database;
|
2008-01-26 14:51:33 +01:00
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2006-10-10 08:41:36 +02:00
|
|
|
LOG_call(log_start_multiple, *tra_handle, count, vector);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2006-10-10 08:41:36 +02:00
|
|
|
transaction = TRA_start(tdbb, v->teb_tpb_length, v->teb_tpb);
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2006-10-10 08:41:36 +02:00
|
|
|
transaction->tra_sibling = prior;
|
|
|
|
prior = transaction;
|
2006-11-05 19:30:36 +01:00
|
|
|
|
|
|
|
// run ON TRANSACTION START triggers
|
2008-01-26 14:51:33 +01:00
|
|
|
EXE_execute_db_triggers(tdbb, transaction,
|
|
|
|
jrd_req::req_trigger_trans_start);
|
2006-10-10 08:41:36 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
*tra_handle = transaction;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2008-01-26 14:51:33 +01:00
|
|
|
LOG_call(log_handle_returned, *tra_handle);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
2008-01-26 14:51:33 +01:00
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
|
|
|
if (prior)
|
|
|
|
{
|
|
|
|
ISC_STATUS_ARRAY temp_status;
|
|
|
|
rollback(temp_status, &prior, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_START_TRANSACTION(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT count,
|
|
|
|
...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ s t a r t _ t r a n s a c t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Start a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2006-10-14 03:29:36 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (count < 1 || USHORT(count) > MAX_DB_PER_TRANS)
|
|
|
|
{
|
|
|
|
Firebird::status_exception::raise(isc_max_db_per_trans_allowed,
|
|
|
|
isc_arg_number, MAX_DB_PER_TRANS,
|
|
|
|
0);
|
|
|
|
}
|
2006-10-14 03:29:36 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::HalfStaticArray<TEB, 16> tebs;
|
|
|
|
tebs.grow(count);
|
2006-10-14 03:29:36 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
va_list ptr;
|
|
|
|
va_start(ptr, count);
|
2006-10-14 03:29:36 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
for (TEB* teb_iter = tebs.begin(); teb_iter < tebs.end(); teb_iter++) {
|
|
|
|
teb_iter->teb_database = va_arg(ptr, Attachment**);
|
|
|
|
teb_iter->teb_tpb_length = va_arg(ptr, int);
|
|
|
|
teb_iter->teb_tpb = va_arg(ptr, UCHAR*);
|
|
|
|
}
|
2006-10-14 03:29:36 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
va_end(ptr);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
GDS_START_MULTIPLE(user_status, tra_handle, count, tebs.begin());
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_TRANSACT_REQUEST(ISC_STATUS* user_status,
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment** db_handle,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT blr_length,
|
2003-12-03 09:19:24 +01:00
|
|
|
const SCHAR* blr,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT in_msg_length,
|
|
|
|
SCHAR* in_msg,
|
|
|
|
USHORT out_msg_length,
|
|
|
|
SCHAR* out_msg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ t r a n s a c t _ r e q u e s t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Execute a procedure.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_transact_request, *db_handle, *tra_handle,
|
|
|
|
blr_length, blr, in_msg_length, in_msg, out_msg_length);
|
|
|
|
#endif
|
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Attachment* attachment = *db_handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
validateHandle(tdbb, *tra_handle);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-29 11:11:52 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = find_transaction(tdbb, isc_req_wrong_db);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_nod* in_message = NULL;
|
|
|
|
jrd_nod* out_message = NULL;
|
|
|
|
|
2008-01-29 11:11:52 +01:00
|
|
|
jrd_req* request = NULL;
|
|
|
|
MemoryPool* new_pool = dbb->createPool();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
CompilerScratch* csb =
|
|
|
|
PAR_parse(tdbb, reinterpret_cast<const UCHAR*>(blr), FALSE);
|
|
|
|
request = CMP_make_request(tdbb, csb);
|
|
|
|
CMP_verify_access(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_nod* node;
|
|
|
|
for (size_t i = 0; i < csb->csb_rpt.getCount(); i++)
|
2004-08-30 20:11:08 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if ( (node = csb->csb_rpt[i].csb_message) )
|
2004-08-30 20:11:08 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if ((int) (IPTR) node->nod_arg[e_msg_number] == 0)
|
|
|
|
{
|
|
|
|
in_message = node;
|
|
|
|
}
|
|
|
|
else if ((int) (IPTR) node->nod_arg[e_msg_number] == 1)
|
|
|
|
{
|
|
|
|
out_message = node;
|
|
|
|
}
|
2004-08-30 20:11:08 +02:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-29 11:11:52 +01:00
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
if (request)
|
|
|
|
CMP_release(tdbb, request);
|
|
|
|
else
|
|
|
|
dbb->deletePool(new_pool);
|
|
|
|
|
|
|
|
throw;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
request->req_attachment = attachment;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
USHORT len;
|
|
|
|
if (in_msg_length)
|
|
|
|
{
|
|
|
|
if (in_message) {
|
|
|
|
const Format* format = (Format*) in_message->nod_arg[e_msg_format];
|
|
|
|
len = format->fmt_length;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in_msg_length != len)
|
|
|
|
{
|
|
|
|
ERR_post(isc_port_len,
|
|
|
|
isc_arg_number, (SLONG) in_msg_length,
|
|
|
|
isc_arg_number, (SLONG) len,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2008-02-02 18:04:06 +01:00
|
|
|
memcpy((SCHAR*) request + in_message->nod_impure, in_msg, in_msg_length);
|
2008-01-26 14:51:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
EXE_start(tdbb, request, transaction);
|
|
|
|
|
|
|
|
if (out_message) {
|
|
|
|
const Format* format = (Format*) out_message->nod_arg[e_msg_format];
|
2001-05-23 15:26:42 +02:00
|
|
|
len = format->fmt_length;
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
else {
|
2001-05-23 15:26:42 +02:00
|
|
|
len = 0;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
if (out_msg_length != len) {
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_port_len,
|
2008-01-26 14:51:33 +01:00
|
|
|
isc_arg_number, (SLONG) out_msg_length,
|
2003-11-08 17:40:17 +01:00
|
|
|
isc_arg_number, (SLONG) len, 0);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (out_msg_length) {
|
|
|
|
memcpy(out_msg, (SCHAR*) request + out_message->nod_impure,
|
|
|
|
out_msg_length);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
check_autocommit(request, tdbb);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
CMP_release(tdbb, request);
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
ISC_STATUS GDS_TRANSACTION_INFO(ISC_STATUS* user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_tra** tra_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT item_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
const SCHAR* items,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT buffer_length,
|
2003-10-29 11:53:47 +01:00
|
|
|
SCHAR* buffer)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ t r a n s a c t i o n _ i n f o
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Provide information on blob object.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_transaction_info2, *tra_handle, item_length, items,
|
|
|
|
buffer_length);
|
|
|
|
#endif
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = *tra_handle;
|
|
|
|
validateHandle(tdbb, transaction);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
INF_transaction_info(transaction, items, item_length, buffer,
|
2001-05-23 15:26:42 +02:00
|
|
|
buffer_length);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2002-04-04 09:10:40 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
ISC_STATUS GDS_UNWIND(ISC_STATUS * user_status,
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_req** req_handle,
|
2003-10-03 03:53:34 +02:00
|
|
|
SSHORT level)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g d s _ $ u n w i n d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Unwind a running request. This is potentially nasty since it can
|
|
|
|
* be called asynchronously.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_unwind, *req_handle, level);
|
|
|
|
#endif
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
jrd_req* request = *req_handle;
|
|
|
|
validateHandle(tdbb, request);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Pick up and validate request level
|
2003-11-05 10:02:33 +01:00
|
|
|
verify_request_synchronization(request, level);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Unwind request. This just tweaks some bits.
|
2003-11-05 10:02:33 +01:00
|
|
|
EXE_unwind(tdbb, request);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const Firebird::Exception& ex)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
2004-03-14 14:34:43 +01:00
|
|
|
bool JRD_getdir(Firebird::PathName& buf)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* J R D _ g e t d i r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Current working directory is cached in the attachment
|
2008-01-16 10:29:37 +01:00
|
|
|
* block. Get it out. This function could be called before
|
2001-05-23 15:26:42 +02:00
|
|
|
* an attachment is created. In such a case thread specific
|
2001-07-10 19:35:13 +02:00
|
|
|
* data (t_data) will hold the user name which will be used
|
2001-05-23 15:26:42 +02:00
|
|
|
* to get the users home directory.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-01 11:26:43 +01:00
|
|
|
char* t_data = NULL;
|
2004-03-14 14:34:43 +01:00
|
|
|
char b[MAXPATHLEN];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
ThreadData::getSpecificData((void**) &t_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (t_data) {
|
|
|
|
#ifdef WIN_NT
|
2004-03-14 14:34:43 +01:00
|
|
|
GetCurrentDirectory(MAXPATHLEN, b);
|
|
|
|
buf = b;
|
2001-05-23 15:26:42 +02:00
|
|
|
#else
|
2003-11-01 11:26:43 +01:00
|
|
|
const struct passwd* pwd;
|
2004-03-14 14:34:43 +01:00
|
|
|
strcpy(b, t_data);
|
|
|
|
pwd = getpwnam(b);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (pwd)
|
2004-03-14 14:34:43 +01:00
|
|
|
buf = pwd->pw_dir;
|
2006-07-21 03:35:17 +02:00
|
|
|
else // No home dir for this users here. Default to server dir
|
2004-03-14 14:34:43 +01:00
|
|
|
return fb_getcwd(buf);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-05-23 05:18:10 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-19 20:14:29 +02:00
|
|
|
/** If the server has not done a JRD_set_thread_data prior to this call
|
2004-03-11 06:04:26 +01:00
|
|
|
(which will be the case when connecting via IPC), thread_db will
|
2001-05-23 15:26:42 +02:00
|
|
|
be NULL so do not attempt to get the attachment handle from
|
2004-03-14 14:34:43 +01:00
|
|
|
thread_db. Just return false as described below.
|
|
|
|
NOTE: The only time
|
2001-05-23 15:26:42 +02:00
|
|
|
this code is entered via IPC is if the database name = "".
|
|
|
|
**/
|
|
|
|
|
2004-05-19 20:14:29 +02:00
|
|
|
/** In case of backup/restore APIs, JRD_set_thread_data has been done but
|
2001-05-23 15:26:42 +02:00
|
|
|
the thread's context is a 'gbak' specific, so don't try extract
|
|
|
|
attachment from there.
|
|
|
|
**/
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment* attachment;
|
2004-08-30 20:11:08 +02:00
|
|
|
if (tdbb && (tdbb->getType() == ThreadData::tddDBB))
|
2007-12-03 16:46:39 +01:00
|
|
|
attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2004-03-14 14:34:43 +01:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-07-10 19:35:13 +02:00
|
|
|
/**
|
2001-05-23 15:26:42 +02:00
|
|
|
An older version of client will not be sending isc_dpb_working directory
|
2001-07-10 19:35:13 +02:00
|
|
|
so in all probabilities attachment->att_working_directory will be null.
|
2004-03-14 14:34:43 +01:00
|
|
|
return false so that ISC_expand_filename will create the file in fbserver's dir
|
2001-05-23 15:26:42 +02:00
|
|
|
**/
|
2004-05-27 18:26:52 +02:00
|
|
|
if (!attachment || attachment->att_working_directory.empty())
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2004-03-14 14:34:43 +01:00
|
|
|
return false;
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2004-03-14 14:34:43 +01:00
|
|
|
buf = attachment->att_working_directory;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-14 14:34:43 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-07-21 03:35:17 +02:00
|
|
|
#endif // SUPERSERVER
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_PROCS
|
2004-03-11 06:04:26 +01:00
|
|
|
void JRD_print_procedure_info(thread_db* tdbb, const char* mesg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/*****************************************************
|
|
|
|
*
|
|
|
|
* J R D _ p r i n t _ p r o c e d u r e _ i n f o
|
|
|
|
*
|
|
|
|
*****************************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2001-07-10 19:35:13 +02:00
|
|
|
* print name , use_count of all procedures in
|
2001-05-23 15:26:42 +02:00
|
|
|
* cache
|
|
|
|
*
|
|
|
|
******************************************************/
|
|
|
|
TEXT fname[MAXPATHLEN];
|
|
|
|
|
|
|
|
gds__prefix(fname, "proc_info.log");
|
2004-04-29 00:43:34 +02:00
|
|
|
FILE* fptr = fopen(fname, "a+");
|
2003-11-01 11:26:43 +01:00
|
|
|
if (!fptr) {
|
2006-07-01 10:50:21 +02:00
|
|
|
char buff[MAXPATHLEN + 25];
|
2001-05-23 15:26:42 +02:00
|
|
|
sprintf(buff, "Failed to open %s\n", fname);
|
|
|
|
gds__log(buff, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mesg)
|
2004-04-29 00:43:34 +02:00
|
|
|
fputs(mesg, fptr);
|
|
|
|
fprintf(fptr,
|
2001-05-23 15:26:42 +02:00
|
|
|
"Prc Name , prc id , flags , Use Count , Alter Count\n");
|
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
vec<jrd_prc*>* procedures = tdbb->getDatabase()->dbb_procedures;
|
2003-11-01 11:26:43 +01:00
|
|
|
if (procedures) {
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_prc*>::iterator ptr, end;
|
2001-12-24 03:51:06 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end();
|
2006-02-10 04:28:43 +01:00
|
|
|
ptr < end; ++ptr)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
const jrd_prc* procedure = *ptr;
|
2003-11-01 11:26:43 +01:00
|
|
|
if (procedure)
|
2004-04-29 00:43:34 +02:00
|
|
|
fprintf(fptr, "%s , %d, %X, %d, %d\n",
|
2004-06-05 11:37:18 +02:00
|
|
|
(procedure->prc_name->hasData()) ?
|
|
|
|
procedure->prc_name->c_str() : "NULL",
|
2003-11-01 11:26:43 +01:00
|
|
|
procedure->prc_id,
|
|
|
|
procedure->prc_flags, procedure->prc_use_count,
|
2006-02-23 06:08:26 +01:00
|
|
|
0); // procedure->prc_alter_count
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2004-04-29 00:43:34 +02:00
|
|
|
fprintf(fptr, "No Cached Procedures\n");
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-04-29 00:43:34 +02:00
|
|
|
fclose(fptr);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
}
|
2006-07-21 03:35:17 +02:00
|
|
|
#endif // DEBUG_PROCS
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* J R D _ r e s c h e d u l e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Somebody has kindly offered to relinquish
|
|
|
|
* control so that somebody else may run.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->dbb_sync.hasContention())
|
|
|
|
{
|
|
|
|
Database::Checkout dcoHolder(dbb);
|
2004-05-15 02:58:46 +02:00
|
|
|
THREAD_YIELD();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-10-30 13:39:08 +01:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
// Test various flags and unwind/throw if required.
|
|
|
|
// But do that only if we're not in the verb cleanup state,
|
|
|
|
// which should never be interrupted.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
if (!(tdbb->tdbb_flags & TDBB_verb_cleanup))
|
2005-07-24 20:48:45 +02:00
|
|
|
{
|
2007-12-10 08:18:54 +01:00
|
|
|
// If database has been shutdown then get out
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
Attachment* attachment = tdbb->getAttachment();
|
|
|
|
jrd_tra* transaction = tdbb->getTransaction();
|
|
|
|
jrd_req* request = tdbb->getRequest();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
if (attachment)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2007-12-10 08:18:54 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown &&
|
|
|
|
attachment->att_flags & ATT_shutdown)
|
|
|
|
{
|
|
|
|
const Firebird::PathName& file_name = attachment->att_filename;
|
|
|
|
if (punt) {
|
|
|
|
CCH_unwind(tdbb, false);
|
|
|
|
ERR_post(isc_shutdown, isc_arg_string,
|
|
|
|
ERR_cstring(file_name), 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ISC_STATUS* status = tdbb->tdbb_status_vector;
|
|
|
|
*status++ = isc_arg_gds;
|
|
|
|
*status++ = isc_shutdown;
|
|
|
|
*status++ = isc_arg_string;
|
|
|
|
*status++ = (ISC_STATUS) ERR_cstring(file_name);
|
|
|
|
*status++ = isc_arg_end;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (attachment->att_flags & ATT_shutdown &&
|
|
|
|
!(tdbb->tdbb_flags & TDBB_shutdown_manager))
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (punt) {
|
2004-02-20 07:43:27 +01:00
|
|
|
CCH_unwind(tdbb, false);
|
2007-12-10 08:18:54 +01:00
|
|
|
ERR_post(isc_att_shutdown, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-11-01 11:26:43 +01:00
|
|
|
ISC_STATUS* status = tdbb->tdbb_status_vector;
|
2001-05-23 15:26:42 +02:00
|
|
|
*status++ = isc_arg_gds;
|
2007-12-10 08:18:54 +01:00
|
|
|
*status++ = isc_att_shutdown;
|
2001-05-23 15:26:42 +02:00
|
|
|
*status++ = isc_arg_end;
|
2004-03-11 06:04:26 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2007-12-10 08:18:54 +01:00
|
|
|
|
|
|
|
// If a cancel has been raised, defer its acknowledgement
|
|
|
|
// when executing in the context of an internal request or
|
|
|
|
// the system transaction.
|
|
|
|
|
|
|
|
if ((attachment->att_flags & ATT_cancel_raise) &&
|
|
|
|
!(attachment->att_flags & ATT_cancel_disable))
|
|
|
|
{
|
|
|
|
if ((!request ||
|
|
|
|
!(request->req_flags & (req_internal | req_sys_trigger))) &&
|
|
|
|
(!transaction || !(transaction->tra_flags & TRA_system)))
|
|
|
|
{
|
|
|
|
attachment->att_flags &= ~ATT_cancel_raise;
|
|
|
|
if (punt) {
|
|
|
|
CCH_unwind(tdbb, false);
|
|
|
|
ERR_post(isc_cancelled, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ISC_STATUS* status = tdbb->tdbb_status_vector;
|
|
|
|
*status++ = isc_arg_gds;
|
|
|
|
*status++ = isc_cancelled;
|
|
|
|
*status++ = isc_arg_end;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-12-04 22:36:29 +01:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
// Handle request cancellation
|
2006-12-04 22:36:29 +01:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
if (transaction && (transaction->tra_flags & TRA_cancel_request))
|
|
|
|
{
|
|
|
|
transaction->tra_flags &= ~TRA_cancel_request;
|
|
|
|
tdbb->tdbb_flags |= TDBB_sys_error;
|
2006-12-04 22:36:29 +01:00
|
|
|
|
2007-12-10 08:18:54 +01:00
|
|
|
if (punt) {
|
|
|
|
CCH_unwind(tdbb, false);
|
|
|
|
ERR_post(isc_cancelled, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ISC_STATUS* status = tdbb->tdbb_status_vector;
|
|
|
|
*status++ = isc_arg_gds;
|
|
|
|
*status++ = isc_cancelled;
|
|
|
|
*status++ = isc_arg_end;
|
|
|
|
return true;
|
|
|
|
}
|
2006-12-04 22:36:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// Enable signal handler for the monitoring stuff
|
|
|
|
|
|
|
|
if (dbb->dbb_ast_flags & DBB_monitor_off) {
|
|
|
|
dbb->dbb_ast_flags &= ~DBB_monitor_off;
|
|
|
|
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
tdbb->tdbb_quantum = (tdbb->tdbb_quantum <= 0) ?
|
|
|
|
(quantum ? quantum : QUANTUM) : tdbb->tdbb_quantum;
|
|
|
|
|
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void jrd_vtof(const char* string, char* field, SSHORT length)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* j r d _ v t o f
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Move a null terminated string to a fixed length
|
|
|
|
* field.
|
|
|
|
* If the length of the string pointed to by 'field'
|
|
|
|
* is less than 'length', this function pads the
|
|
|
|
* destination string with space upto 'length' bytes.
|
|
|
|
*
|
|
|
|
* The call is primarily generated by the preprocessor.
|
|
|
|
*
|
|
|
|
* This is the same code as gds__vtof but is used internally.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
while (*string) {
|
|
|
|
*field++ = *string++;
|
|
|
|
if (--length <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length) {
|
2006-02-23 06:08:26 +01:00
|
|
|
memset(field, ' ', length);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-10 05:12:10 +02:00
|
|
|
#ifndef SUPERSERVER
|
|
|
|
static int blocking_ast_dsql_cache(void* ast_object)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* b l o c k i n g _ a s t _ d s q l _ c a c h e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Someone is trying to drop a item from the DSQL cache.
|
|
|
|
* Mark the symbol as obsolete and release the lock.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
DSqlCacheItem* item = static_cast<DSqlCacheItem*>(ast_object);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Database* dbb = item->lock->lck_dbb;
|
|
|
|
Database::SyncGuard dsGuard(dbb, true);
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb;
|
2006-07-10 05:12:10 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
tdbb->setDatabase(dbb);
|
2007-12-03 16:46:39 +01:00
|
|
|
tdbb->setAttachment(item->lock->lck_attachment);
|
2006-07-10 05:12:10 +02:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, 0);
|
|
|
|
|
|
|
|
item->obsolete = true;
|
|
|
|
item->locked = false;
|
|
|
|
LCK_release(tdbb, item->lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif // SUPERSERVER
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static void check_database(thread_db* tdbb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* c h e c k _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-01-26 14:51:33 +01:00
|
|
|
* Check an attachment for validity.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
|
|
|
Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->dbb_flags & DBB_bugcheck)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
2008-02-02 18:04:06 +01:00
|
|
|
static const char string[] = "can't continue after bugcheck";
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::status_exception::raise(isc_bug_check,
|
|
|
|
isc_arg_string, string,
|
|
|
|
0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (attachment->att_flags & ATT_shutdown ||
|
2004-02-25 02:50:40 +01:00
|
|
|
((dbb->dbb_ast_flags & DBB_shutdown) &&
|
|
|
|
((dbb->dbb_ast_flags & DBB_shutdown_full) ||
|
2006-08-16 17:15:58 +02:00
|
|
|
!attachment->locksmith())))
|
2003-10-29 11:53:47 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown)
|
|
|
|
{
|
|
|
|
const Firebird::PathName& filename = attachment->att_filename;
|
|
|
|
Firebird::status_exception::raise(isc_shutdown,
|
|
|
|
isc_arg_string, ERR_cstring(filename),
|
|
|
|
0);
|
2005-07-24 20:48:45 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Firebird::status_exception::raise(isc_att_shutdown, 0);
|
2005-07-24 20:48:45 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((attachment->att_flags & ATT_cancel_raise) &&
|
2003-10-29 11:53:47 +01:00
|
|
|
!(attachment->att_flags & ATT_cancel_disable))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags &= ~ATT_cancel_raise;
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::status_exception::raise(isc_cancelled, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2006-10-30 13:39:08 +01:00
|
|
|
// Enable signal handler for the monitoring stuff
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_monitor_off)
|
|
|
|
{
|
2006-10-30 13:39:08 +01:00
|
|
|
dbb->dbb_ast_flags &= ~DBB_monitor_off;
|
|
|
|
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static void check_transaction(thread_db* tdbb, jrd_tra* transaction)
|
2007-09-05 09:18:37 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* c h e c k _ t r a n s a c t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Check transaction for not being interrupted
|
|
|
|
* in the meantime.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
|
|
|
if (transaction && (transaction->tra_flags & TRA_cancel_request))
|
|
|
|
{
|
|
|
|
transaction->tra_flags &= ~TRA_cancel_request;
|
|
|
|
tdbb->tdbb_flags |= TDBB_sys_error;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::status_exception::raise(isc_cancelled, 0);
|
2007-09-05 09:18:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
static ISC_STATUS commit(ISC_STATUS* user_status,
|
|
|
|
jrd_tra** tra_handle,
|
|
|
|
const bool retaining_flag)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* c o m m i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Commit a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call((retaining_flag) ? log_commit_retaining : log_commit,
|
|
|
|
*tra_handle);
|
|
|
|
#endif
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = *tra_handle;
|
|
|
|
validateHandle(tdbb, transaction);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2008-02-02 18:04:06 +01:00
|
|
|
if (transaction->tra_sibling && !(transaction->tra_flags & TRA_prepared))
|
2008-01-26 14:51:33 +01:00
|
|
|
{
|
|
|
|
prepare(tdbb, transaction, 0, NULL);
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
const Attachment* const attachment = tdbb->getAttachment();
|
|
|
|
|
|
|
|
if (!(attachment->att_flags & ATT_no_db_triggers) &&
|
|
|
|
!(transaction->tra_flags & TRA_prepared))
|
|
|
|
{
|
|
|
|
// run ON TRANSACTION COMMIT triggers
|
|
|
|
run_commit_triggers(tdbb, transaction);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* next = transaction;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
while ( (transaction = next) )
|
|
|
|
{
|
|
|
|
next = transaction->tra_sibling;
|
|
|
|
validateHandle(tdbb, transaction->tra_attachment);
|
|
|
|
tdbb->setTransaction(transaction);
|
|
|
|
check_database(tdbb);
|
|
|
|
TRA_commit(tdbb, transaction, retaining_flag);
|
|
|
|
}
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex) {
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-20 15:18:18 +01:00
|
|
|
ISC_STATUS compile_request(ISC_STATUS* user_status,
|
|
|
|
Attachment** db_handle,
|
|
|
|
jrd_req** req_handle,
|
|
|
|
SSHORT blr_length,
|
|
|
|
const SCHAR* blr,
|
|
|
|
USHORT string_length, const char* string,
|
|
|
|
USHORT dbginfo_length, const UCHAR* dbginfo)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* compile_request
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2007-01-20 15:18:18 +01:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_compile, *db_handle, *req_handle, blr_length, blr);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (*req_handle)
|
|
|
|
Firebird::status_exception::raise(isc_bad_req_handle, 0);
|
|
|
|
|
|
|
|
Attachment* attachment = *db_handle;
|
|
|
|
validateHandle(tdbb, attachment);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
|
|
|
|
|
|
|
jrd_req* request =
|
|
|
|
CMP_compile2(tdbb, reinterpret_cast<const UCHAR*>(blr), FALSE,
|
|
|
|
dbginfo_length, dbginfo);
|
2007-01-20 15:18:18 +01:00
|
|
|
|
|
|
|
request->req_attachment = attachment;
|
|
|
|
request->req_request = attachment->att_requests;
|
|
|
|
attachment->att_requests = request;
|
|
|
|
|
2007-01-28 13:17:17 +01:00
|
|
|
request->req_sql_text.assign(string, string_length);
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2007-01-20 15:18:18 +01:00
|
|
|
*req_handle = request;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2007-01-20 15:18:18 +01:00
|
|
|
LOG_call(log_handle_returned, *req_handle);
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2007-01-20 15:18:18 +01:00
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2007-01-20 15:18:18 +01:00
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2007-01-20 15:18:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
static bool drop_files(const jrd_file* file)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d r o p _ f i l e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* drop a linked list of files
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-11-14 09:33:08 +01:00
|
|
|
status[1] = FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
for (; file; file = file->fil_next)
|
|
|
|
{
|
|
|
|
if (unlink(file->fil_string))
|
|
|
|
{
|
|
|
|
IBERR_build_status(status, isc_io_error,
|
2003-11-08 17:40:17 +01:00
|
|
|
isc_arg_string, "unlink",
|
|
|
|
isc_arg_string,
|
2003-01-18 17:31:23 +01:00
|
|
|
ERR_cstring(file->fil_string),
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_arg_gds, isc_io_delete_err,
|
|
|
|
SYS_ERR, errno,
|
|
|
|
0);
|
2004-05-23 05:18:10 +02:00
|
|
|
Database* dbb = GET_DBB();
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
|
|
|
gds__log_status(pageSpace->file->fil_string, status);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
return status[1] ? true : false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static jrd_tra* find_transaction(thread_db* tdbb, ISC_STATUS error_code)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* f i n d _ t r a n s a c t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Find the element of a possible multiple database transaction
|
|
|
|
* that corresponds to the current database.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
const Attachment* const attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-02-02 18:04:06 +01:00
|
|
|
for (jrd_tra* transaction = tdbb->getTransaction(); transaction;
|
|
|
|
transaction = transaction->tra_sibling)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
if (transaction->tra_attachment == attachment)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
return transaction;
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::status_exception::raise(error_code, 0);
|
|
|
|
return NULL; // Added to remove compiler warnings
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
static void find_intl_charset(thread_db* tdbb, Attachment* attachment, const DatabaseOptions* options)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* f i n d _ i n t l _ c h a r s e t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Attachment has declared it's prefered character set
|
|
|
|
* as part of LC_CTYPE, passed over with the attachment
|
|
|
|
* block. Now let's resolve that to an internal subtype id.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (options->dpb_lc_ctype.isEmpty()) {
|
2006-07-21 03:35:17 +02:00
|
|
|
// No declaration of character set, act like 3.x Interbase
|
2003-01-23 04:33:53 +01:00
|
|
|
attachment->att_charset = DEFAULT_ATTACHMENT_CHARSET;
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-04-05 18:34:18 +02:00
|
|
|
USHORT id;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-11-27 07:51:58 +01:00
|
|
|
const UCHAR* lc_ctype =
|
|
|
|
reinterpret_cast<const UCHAR*>(options->dpb_lc_ctype.c_str());
|
|
|
|
|
2005-05-28 00:45:31 +02:00
|
|
|
if (MET_get_char_coll_subtype(tdbb, &id, lc_ctype, options->dpb_lc_ctype.length()) &&
|
2005-06-14 05:16:54 +02:00
|
|
|
INTL_defined_type(tdbb, id & 0xFF) &&
|
2005-05-28 00:45:31 +02:00
|
|
|
((id & 0xFF) != CS_BINARY))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
attachment->att_charset = id & 0xFF;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-07-21 03:35:17 +02:00
|
|
|
// Report an error - we can't do what user has requested
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_content,
|
|
|
|
isc_arg_gds, isc_charset_not_found,
|
|
|
|
isc_arg_string, ERR_cstring(options->dpb_lc_ctype),
|
2001-05-23 15:26:42 +02:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_client_SQL_dialect)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2008-01-16 10:29:37 +01:00
|
|
|
* D a t a b a s e O p t i o n s : : g e t
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Parse database parameter block picking up options and things.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SSHORT num_old_files = 0;
|
|
|
|
|
2004-05-23 05:18:10 +02:00
|
|
|
Database* dbb = GET_DBB();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
ULONG page_cache_size = Config::getDefaultDbCachePages();
|
|
|
|
if (page_cache_size < MIN_PAGE_BUFFERS)
|
|
|
|
page_cache_size = MIN_PAGE_BUFFERS;
|
|
|
|
if (page_cache_size > MAX_PAGE_BUFFERS)
|
|
|
|
page_cache_size = MAX_PAGE_BUFFERS;
|
|
|
|
|
|
|
|
dpb_buffers = page_cache_size;
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_sweep_interval = -1;
|
2005-04-09 20:44:50 +02:00
|
|
|
dpb_overwrite = false;
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_sql_dialect = 99;
|
2004-02-20 07:43:27 +01:00
|
|
|
invalid_client_SQL_dialect = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (dpb_length == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (dpb == NULL)
|
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_form, 0);
|
2004-11-24 19:26:24 +01:00
|
|
|
}
|
|
|
|
|
2005-11-27 21:53:09 +01:00
|
|
|
Firebird::ClumpletReader rdr(Firebird::ClumpletReader::Tagged, dpb, dpb_length);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (rdr.getBufferTag() != isc_dpb_version1)
|
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_form, isc_arg_gds, isc_wrodpbver, 0);
|
2004-11-24 19:26:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
for (; !(rdr.isEof()); rdr.moveNext())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
switch (rdr.getClumpTag())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
case isc_dpb_working_directory:
|
|
|
|
{
|
2004-11-25 17:09:12 +01:00
|
|
|
rdr.getPath(dpb_working_directory);
|
2004-11-24 19:26:24 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
// CLASSIC have no thread data. Init to zero.
|
|
|
|
char* t_data = 0;
|
2004-08-30 20:11:08 +02:00
|
|
|
ThreadData::getSpecificData((void **) &t_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Null value for working_directory implies remote database. So get
|
|
|
|
// the users HOME directory
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifndef WIN_NT
|
2004-11-25 17:09:12 +01:00
|
|
|
if (dpb_working_directory.isEmpty()) {
|
2003-08-28 15:16:03 +02:00
|
|
|
struct passwd *passwd = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (t_data)
|
|
|
|
passwd = getpwnam(t_data);
|
2004-11-24 19:26:24 +01:00
|
|
|
if (passwd)
|
|
|
|
{
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_working_directory = passwd->pw_dir;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-07-21 03:35:17 +02:00
|
|
|
else { // No home dir for this users here. Default to server dir
|
2004-11-25 17:09:12 +01:00
|
|
|
fb_getcwd(dpb_working_directory);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (t_data)
|
|
|
|
{
|
|
|
|
free(t_data);
|
|
|
|
t_data = NULL;
|
|
|
|
}
|
2006-07-21 03:35:17 +02:00
|
|
|
// Null out the thread local data so that further references will fail
|
2004-08-30 20:11:08 +02:00
|
|
|
ThreadData::putSpecificData(0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_set_page_buffers:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_page_buffers = rdr.getInt();
|
|
|
|
if (dpb_page_buffers &&
|
|
|
|
(dpb_page_buffers < MIN_PAGE_BUFFERS ||
|
|
|
|
dpb_page_buffers > MAX_PAGE_BUFFERS))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_content, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_set_page_buffers = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_num_buffers:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_buffers = rdr.getInt();
|
|
|
|
if (dpb_buffers < 10)
|
2004-11-24 19:26:24 +01:00
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_bad_dpb_content, 0);
|
2004-11-24 19:26:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_page_size:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_page_size = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_debug:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_debug = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_sweep:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_sweep = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_sweep_interval:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_sweep_interval = rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_verify:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_verify = (USHORT) rdr.getInt();
|
|
|
|
if (dpb_verify & isc_dpb_ignore)
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_flags |= DBB_damaged;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_trace:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_trace = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_damaged:
|
2004-11-24 19:26:24 +01:00
|
|
|
if (rdr.getInt() & 1)
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_flags |= DBB_damaged;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_enable_journal:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_journal);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_wal_backup_dir:
|
2004-11-25 17:09:12 +01:00
|
|
|
// ignore, skip
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_drop_walfile:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_wal_action = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_old_dump_id:
|
|
|
|
case isc_dpb_online_dump:
|
|
|
|
case isc_dpb_old_file_size:
|
|
|
|
case isc_dpb_old_num_files:
|
|
|
|
case isc_dpb_old_start_page:
|
|
|
|
case isc_dpb_old_start_seqno:
|
|
|
|
case isc_dpb_old_start_file:
|
2004-11-25 17:09:12 +01:00
|
|
|
// ignore, skip
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_old_file:
|
2004-01-06 11:33:18 +01:00
|
|
|
//if (num_old_files >= MAX_OLD_FILES) complain here, for now.
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_num_old_files, 0);
|
2004-11-24 19:26:24 +01:00
|
|
|
// following code is never executed now !
|
2001-05-23 15:26:42 +02:00
|
|
|
num_old_files++;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_wal_chkptlen:
|
|
|
|
case isc_dpb_wal_numbufs:
|
|
|
|
case isc_dpb_wal_bufsize:
|
|
|
|
case isc_dpb_wal_grp_cmt_wait:
|
2004-11-25 17:09:12 +01:00
|
|
|
// ignore, skip
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_dbkey_scope:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_dbkey_scope = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_sys_user_name:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_sys_user_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_sql_role_name:
|
2008-01-16 10:29:37 +01:00
|
|
|
if (! dpb_trusted_role)
|
|
|
|
{
|
|
|
|
rdr.getString(dpb_role_name);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_user_name:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_user_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_password:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_password);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_password_enc:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_password_enc);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2006-12-08 19:38:15 +01:00
|
|
|
case isc_dpb_trusted_auth:
|
|
|
|
rdr.getString(dpb_trusted_login);
|
|
|
|
break;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
case isc_dpb_trusted_role:
|
|
|
|
dpb_trusted_role = true;
|
|
|
|
rdr.getString(dpb_role_name);
|
|
|
|
break;
|
2006-12-08 19:38:15 +01:00
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_encrypt_key:
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef ISC_DATABASE_ENCRYPTION
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_key);
|
2001-05-23 15:26:42 +02:00
|
|
|
#else
|
2006-07-21 03:35:17 +02:00
|
|
|
// Just in case there WAS a customer using this unsupported
|
|
|
|
// feature - post an error when they try to access it in 4.0
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_uns_ext, isc_arg_gds, isc_random,
|
|
|
|
isc_arg_string, "Encryption not supported", 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_no_garbage_collect:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_no_garbage = TRUE;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_disable_journal:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_disable = TRUE;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_activate_shadow:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_activate_shadow = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_delete_shadow:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_delete_shadow = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_force_write:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_set_force_write = TRUE;
|
|
|
|
dpb_force_write = (SSHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_begin_log:
|
2004-01-06 11:33:18 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2004-11-25 17:09:12 +01:00
|
|
|
rdr.getPath(dpb_log);
|
2004-01-06 11:33:18 +01:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_quit_log:
|
2004-01-06 11:33:18 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_quit_log = true;
|
2004-01-06 11:33:18 +01:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_no_reserve:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_set_no_reserve = TRUE;
|
|
|
|
dpb_no_reserve = (UCHAR) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_interp:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_interp = (SSHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_lc_messages:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getPath(dpb_lc_messages);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_lc_ctype:
|
2007-10-24 08:26:31 +02:00
|
|
|
rdr.getString(dpb_lc_ctype);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_shutdown:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_shutdown = (USHORT) rdr.getInt();
|
2004-02-25 02:50:40 +01:00
|
|
|
// Enforce default
|
2004-11-25 17:09:12 +01:00
|
|
|
if ((dpb_shutdown & isc_dpb_shut_mode_mask) == isc_dpb_shut_default)
|
|
|
|
dpb_shutdown |= isc_dpb_shut_multi;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_shutdown_delay:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_shutdown_delay = (SSHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_online:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_online = (USHORT) rdr.getInt();
|
2004-02-25 02:50:40 +01:00
|
|
|
// Enforce default
|
2004-11-25 17:09:12 +01:00
|
|
|
if ((dpb_online & isc_dpb_shut_mode_mask) == isc_dpb_shut_default)
|
2004-11-24 19:26:24 +01:00
|
|
|
{
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_online |= isc_dpb_shut_normal;
|
2004-11-24 19:26:24 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_reserved:
|
2003-10-29 11:53:47 +01:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
Firebird::string single;
|
|
|
|
rdr.getString(single);
|
2007-10-24 08:26:31 +02:00
|
|
|
if (single == "YES")
|
2004-11-24 19:26:24 +01:00
|
|
|
{
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_single_user = TRUE;
|
2004-11-24 19:26:24 +01:00
|
|
|
}
|
2003-10-29 11:53:47 +01:00
|
|
|
}
|
2004-11-24 19:26:24 +01:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
case isc_dpb_overwrite:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_overwrite = rdr.getInt() != 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_sec_attach:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_sec_attach = rdr.getInt() != 0;
|
|
|
|
dpb_buffers = 50;
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_flags |= DBB_security_db;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_gbak_attach:
|
2007-10-24 08:26:31 +02:00
|
|
|
{
|
|
|
|
Firebird::string gbakStr;
|
|
|
|
rdr.getString(gbakStr);
|
|
|
|
dpb_gbak_attach = gbakStr.hasData();
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_gstat_attach:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_gstat_attach = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_gfix_attach:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_gfix_attach = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2004-11-07 15:50:53 +01:00
|
|
|
case isc_dpb_gsec_attach:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_gsec_attach = rdr.getBoolean();
|
2004-11-07 15:50:53 +01:00
|
|
|
break;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case isc_dpb_disable_wal:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_disable_wal = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_connect_timeout:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_connect_timeout = rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dpb_dummy_packet_interval:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_dummy_packet_interval = rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_sql_dialect:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_sql_dialect = (USHORT) rdr.getInt();
|
|
|
|
if (dpb_sql_dialect > SQL_DIALECT_V6)
|
2008-01-26 14:51:33 +01:00
|
|
|
invalid_client_SQL_dialect = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_set_db_sql_dialect:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_set_db_sql_dialect = (USHORT) rdr.getInt();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-01-23 04:33:53 +01:00
|
|
|
case isc_dpb_set_db_readonly:
|
2004-11-25 17:09:12 +01:00
|
|
|
dpb_set_db_readonly = true;
|
|
|
|
dpb_db_readonly = rdr.getInt() != 0;
|
2003-01-23 04:33:53 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dpb_set_db_charset:
|
2004-11-25 17:09:12 +01:00
|
|
|
rdr.getString(dpb_set_db_charset);
|
2003-01-23 04:33:53 +01:00
|
|
|
break;
|
2001-07-12 07:46:06 +02:00
|
|
|
|
2006-10-14 03:29:36 +02:00
|
|
|
case isc_dpb_address_path:
|
|
|
|
{
|
|
|
|
Firebird::ClumpletReader address_stack(Firebird::ClumpletReader::UnTagged,
|
|
|
|
rdr.getBytes(), rdr.getClumpLength());
|
|
|
|
while (!address_stack.isEof()) {
|
|
|
|
if (address_stack.getClumpTag() != isc_dpb_address) {
|
|
|
|
address_stack.moveNext();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Firebird::ClumpletReader address(Firebird::ClumpletReader::UnTagged,
|
|
|
|
address_stack.getBytes(), address_stack.getClumpLength());
|
|
|
|
while (!address.isEof()) {
|
|
|
|
switch (address.getClumpTag()) {
|
|
|
|
case isc_dpb_addr_protocol:
|
|
|
|
address.getString(dpb_network_protocol);
|
|
|
|
break;
|
|
|
|
case isc_dpb_addr_endpoint:
|
|
|
|
address.getString(dpb_remote_address);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
address.moveNext();
|
2004-11-26 02:01:27 +01:00
|
|
|
}
|
2006-10-14 03:29:36 +02:00
|
|
|
break;
|
2004-11-26 02:01:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-05-16 09:54:33 +02:00
|
|
|
case isc_dpb_process_id:
|
2006-09-14 15:47:31 +02:00
|
|
|
dpb_remote_pid = rdr.getInt();
|
|
|
|
break;
|
|
|
|
|
2007-05-16 09:54:33 +02:00
|
|
|
case isc_dpb_process_name:
|
|
|
|
rdr.getPath(dpb_remote_process);
|
|
|
|
break;
|
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
case isc_dpb_no_db_triggers:
|
|
|
|
dpb_no_db_triggers = rdr.getInt() != 0;
|
|
|
|
break;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
default:
|
2004-11-24 19:26:24 +01:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (! rdr.isEof())
|
2002-07-02 11:49:19 +02:00
|
|
|
{
|
2004-11-24 19:26:24 +01:00
|
|
|
ERR_post(isc_bad_dpb_form, 0);
|
2002-07-02 11:49:19 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
static ISC_STATUS handle_error(ISC_STATUS* user_status, ISC_STATUS code)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* h a n d l e _ e r r o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* An invalid handle has been passed in. If there is a user status
|
|
|
|
* vector, make it reflect the error. If not, emulate the routine
|
|
|
|
* "error" and abort.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-01 11:26:43 +01:00
|
|
|
ISC_STATUS* vector = user_status;
|
2003-11-08 17:40:17 +01:00
|
|
|
*vector++ = isc_arg_gds;
|
2001-05-23 15:26:42 +02:00
|
|
|
*vector++ = code;
|
2003-11-08 17:40:17 +01:00
|
|
|
*vector = isc_arg_end;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (WIN_NT) && !defined(SERVER_SHUTDOWN)
|
|
|
|
static BOOLEAN handler_NT(SSHORT controlAction)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* h a n d l e r _ N T
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* For some actions, get NT to issue a popup asking
|
|
|
|
* the user to delay.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
switch (controlAction) {
|
|
|
|
case CTRL_CLOSE_EVENT:
|
|
|
|
case CTRL_LOGOFF_EVENT:
|
|
|
|
case CTRL_SHUTDOWN_EVENT:
|
2006-07-21 03:35:17 +02:00
|
|
|
return TRUE; // NT will issue popup
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
case CTRL_C_EVENT:
|
|
|
|
case CTRL_BREAK_EVENT:
|
2006-07-21 03:35:17 +02:00
|
|
|
return FALSE; // let it go
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-07-21 03:35:17 +02:00
|
|
|
// So, what are we to return here?!
|
|
|
|
return FALSE; // let it go
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static Database* init(thread_db* tdbb,
|
2003-04-10 08:49:16 +02:00
|
|
|
ISC_STATUS* user_status,
|
2004-03-14 14:34:43 +01:00
|
|
|
const Firebird::PathName& expanded_filename,
|
2003-12-03 09:19:24 +01:00
|
|
|
bool attach_flag)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i n i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Initialize for database access. First call from both CREATE and
|
|
|
|
* OPEN.
|
|
|
|
*
|
|
|
|
**************************************/
|
2007-06-06 14:37:24 +02:00
|
|
|
Firebird::Mutex temp_mutx[DBB_MUTX_max];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2007-02-26 02:01:17 +01:00
|
|
|
// Initialize standard random generator.
|
|
|
|
// MSVC (at least since version 7) have per-thread random seed.
|
2007-03-01 01:44:14 +01:00
|
|
|
// As we don't know who uses per-thread seed, this should work for both cases.
|
2007-02-26 02:01:17 +01:00
|
|
|
static bool first_rand = true;
|
|
|
|
static int first_rand_value = rand();
|
|
|
|
|
|
|
|
if (first_rand || (rand() == first_rand_value))
|
|
|
|
srand(time(NULL));
|
|
|
|
|
|
|
|
first_rand = false;
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
engineStartup.init();
|
2007-02-26 03:13:42 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
try {
|
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Check to see if the database is already actively attached
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb;
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef SUPERSERVER
|
2004-03-07 08:58:55 +01:00
|
|
|
for (dbb = databases; dbb; dbb = dbb->dbb_next)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-03-07 08:58:55 +01:00
|
|
|
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use)) &&
|
2004-03-14 14:34:43 +01:00
|
|
|
(dbb->dbb_filename == expanded_filename))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-03-07 08:58:55 +01:00
|
|
|
return (attach_flag) ? dbb : NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2003-01-18 22:45:24 +01:00
|
|
|
#ifdef SUPERSERVER
|
2004-03-26 00:12:50 +01:00
|
|
|
Firebird::MemoryStats temp_stats;
|
2008-01-29 11:11:52 +01:00
|
|
|
MemoryPool* perm = MemoryPool::createPool(NULL, temp_stats);
|
|
|
|
dbb = Database::newDbb(perm);
|
2004-03-26 00:12:50 +01:00
|
|
|
perm->setStatsGroup(dbb->dbb_memory_stats);
|
2003-01-18 22:45:24 +01:00
|
|
|
#else
|
2008-01-29 11:11:52 +01:00
|
|
|
MemoryPool* perm = MemoryPool::createPool(NULL);
|
|
|
|
dbb = Database::newDbb(perm);
|
2003-01-18 22:45:24 +01:00
|
|
|
#endif
|
2004-03-07 08:58:55 +01:00
|
|
|
dbb->dbb_mutexes = temp_mutx;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
tdbb->setDatabase(dbb);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-29 11:11:52 +01:00
|
|
|
dbb->dbb_bufferpool = dbb->createPool();
|
2006-05-25 12:20:31 +02:00
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
// provide context pool for the rest stuff
|
|
|
|
Jrd::ContextPoolHolder context(tdbb, perm);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef SUPERSERVER
|
2004-03-07 08:58:55 +01:00
|
|
|
dbb->dbb_next = databases;
|
|
|
|
databases = dbb;
|
2008-01-26 14:51:33 +01:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-06-06 14:37:24 +02:00
|
|
|
dbb->dbb_mutexes = FB_NEW(*dbb->dbb_permanent) Firebird::Mutex[DBB_MUTX_max];
|
2005-12-02 08:35:34 +01:00
|
|
|
dbb->dbb_internal = vec<jrd_req*>::newVector(*dbb->dbb_permanent, irq_MAX);
|
|
|
|
dbb->dbb_dyn_req = vec<jrd_req*>::newVector(*dbb->dbb_permanent, drq_MAX);
|
2004-03-07 08:58:55 +01:00
|
|
|
dbb->dbb_flags |= DBB_exclusive;
|
|
|
|
dbb->dbb_sweep_interval = SWEEP_INTERVAL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-10-30 13:39:08 +01:00
|
|
|
GenerateGuid(&dbb->dbb_guid);
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// set a garbage collection policy
|
2004-11-09 13:59:37 +01:00
|
|
|
|
|
|
|
if ((dbb->dbb_flags & (DBB_gc_cooperative | DBB_gc_background)) == 0)
|
|
|
|
{
|
2004-11-11 00:02:31 +01:00
|
|
|
Firebird::string gc_policy = Config::getGCPolicy();
|
2004-11-11 11:17:16 +01:00
|
|
|
gc_policy.lower();
|
2004-11-11 00:02:31 +01:00
|
|
|
if (gc_policy == GCPolicyCooperative) {
|
2004-11-09 13:59:37 +01:00
|
|
|
dbb->dbb_flags |= DBB_gc_cooperative;
|
|
|
|
}
|
2004-11-11 00:02:31 +01:00
|
|
|
else if (gc_policy == GCPolicyBackground) {
|
2004-11-09 13:59:37 +01:00
|
|
|
dbb->dbb_flags |= DBB_gc_background;
|
|
|
|
}
|
2004-11-11 00:02:31 +01:00
|
|
|
else if (gc_policy == GCPolicyCombined) {
|
2004-11-09 13:59:37 +01:00
|
|
|
dbb->dbb_flags |= DBB_gc_cooperative | DBB_gc_background;
|
|
|
|
}
|
|
|
|
else // config value is invalid, use default
|
2004-11-11 00:02:31 +01:00
|
|
|
{
|
2004-11-11 11:17:16 +01:00
|
|
|
if (GCPolicyDefault == GCPolicyCooperative) {
|
2004-11-09 13:59:37 +01:00
|
|
|
dbb->dbb_flags |= DBB_gc_cooperative;
|
|
|
|
}
|
2004-11-11 11:17:16 +01:00
|
|
|
else if (GCPolicyDefault == GCPolicyBackground) {
|
2004-11-09 13:59:37 +01:00
|
|
|
dbb->dbb_flags |= DBB_gc_background;
|
|
|
|
}
|
2004-11-11 11:17:16 +01:00
|
|
|
else if (GCPolicyDefault == GCPolicyCombined) {
|
2004-11-09 13:59:37 +01:00
|
|
|
dbb->dbb_flags |= DBB_gc_cooperative | DBB_gc_background;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fb_assert(false);
|
2004-11-11 00:02:31 +01:00
|
|
|
}
|
2004-11-10 06:19:20 +01:00
|
|
|
}
|
2004-11-09 13:59:37 +01:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Initialize a number of subsystems
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
TRA_init(tdbb);
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Lookup some external "hooks"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-09 11:05:07 +01:00
|
|
|
PluginManager::Plugin crypt_lib =
|
2004-03-14 14:34:43 +01:00
|
|
|
PluginManager::enginePluginManager().findPlugin(CRYPT_IMAGE);
|
2003-02-09 11:05:07 +01:00
|
|
|
if (crypt_lib) {
|
2003-02-10 08:38:31 +01:00
|
|
|
Firebird::string encrypt_entrypoint(ENCRYPT);
|
|
|
|
Firebird::string decrypt_entrypoint(DECRYPT);
|
2004-03-07 08:58:55 +01:00
|
|
|
dbb->dbb_encrypt =
|
|
|
|
(Database::crypt_routine) crypt_lib.lookupSymbol(encrypt_entrypoint);
|
|
|
|
dbb->dbb_decrypt =
|
|
|
|
(Database::crypt_routine) crypt_lib.lookupSymbol(decrypt_entrypoint);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
INTL_init(tdbb);
|
|
|
|
|
2003-02-03 14:34:16 +01:00
|
|
|
SecurityDatabase::initialize();
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
return dbb;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
} // try
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex) {
|
2004-03-01 04:35:23 +01:00
|
|
|
Firebird::stuff_exception(user_status, ex);
|
2001-12-24 03:51:06 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-19 08:19:56 +02:00
|
|
|
static void init_database_locks(thread_db* tdbb, Database* dbb)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i n i t _ d a t a b a s e _ l o c k s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Initialize secondary database locks.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
|
|
|
fb_assert(dbb);
|
|
|
|
|
2007-09-05 09:18:37 +02:00
|
|
|
// Lock shared by all dbb owners, used to signal other processes
|
2006-10-30 13:39:08 +01:00
|
|
|
// to dump their monitoring data and synchronize operations
|
2007-09-05 09:18:37 +02:00
|
|
|
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
|
2006-10-07 12:53:01 +02:00
|
|
|
dbb->dbb_monitor_lock = lock;
|
|
|
|
lock->lck_type = LCK_monitor;
|
|
|
|
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
|
|
|
|
lock->lck_parent = dbb->dbb_lock;
|
|
|
|
lock->lck_length = sizeof(SLONG);
|
|
|
|
lock->lck_dbb = dbb;
|
|
|
|
lock->lck_object = reinterpret_cast<blk*>(dbb);
|
2006-10-30 13:39:08 +01:00
|
|
|
lock->lck_ast = DatabaseSnapshot::blockingAst;
|
|
|
|
LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT);
|
|
|
|
|
|
|
|
// Lock that identifies a dbb instance
|
|
|
|
const size_t key_length = sizeof(FB_GUID);
|
|
|
|
lock = FB_NEW_RPT(*dbb->dbb_permanent, key_length) Lock();
|
|
|
|
dbb->dbb_instance_lock = lock;
|
|
|
|
lock->lck_type = LCK_instance;
|
|
|
|
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
|
|
|
|
lock->lck_length = key_length;
|
|
|
|
memcpy(lock->lck_key.lck_string, &dbb->dbb_guid, key_length);
|
|
|
|
lock->lck_dbb = dbb;
|
2006-10-07 12:53:01 +02:00
|
|
|
LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT);
|
2006-07-19 08:19:56 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-20 05:14:15 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static void prepare(thread_db* tdbb,
|
|
|
|
jrd_tra* transaction,
|
|
|
|
USHORT length,
|
|
|
|
const UCHAR* msg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* p r e p a r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-01-26 14:51:33 +01:00
|
|
|
* Attempt to prepare a transaction.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
if (!(transaction->tra_flags & TRA_prepared))
|
|
|
|
{
|
|
|
|
// run ON TRANSACTION COMMIT triggers
|
2007-01-07 00:54:23 +01:00
|
|
|
run_commit_triggers(tdbb, transaction);
|
2006-11-05 19:30:36 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
for (; transaction; transaction = transaction->tra_sibling) {
|
2008-01-26 14:51:33 +01:00
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
check_database(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
TRA_prepare(tdbb, transaction, length, msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static void release_attachment(thread_db* tdbb, Attachment* attachment)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* r e l e a s e _ a t t a c h m e n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Disconnect attachment block from database block.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
SET_TDBB(tdbb);
|
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
CHECK_DBB(dbb);
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (!attachment)
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
#ifdef SUPERSERVER
|
2007-01-27 16:40:12 +01:00
|
|
|
if (dbb->dbb_relations)
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
2007-01-27 16:40:12 +01:00
|
|
|
vec<jrd_rel*>& rels = *dbb->dbb_relations;
|
|
|
|
for (size_t i = 1; i < rels.count(); i++)
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
2007-01-27 16:40:12 +01:00
|
|
|
jrd_rel* relation = rels[i];
|
|
|
|
if (relation && (relation->rel_flags & REL_temp_conn) &&
|
|
|
|
!(relation->rel_flags & (REL_deleted | REL_deleting)) )
|
|
|
|
{
|
|
|
|
relation->delPages(tdbb);
|
|
|
|
}
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (attachment->att_event_session)
|
|
|
|
EVENT_delete_session(attachment->att_event_session);
|
|
|
|
|
|
|
|
if (attachment->att_id_lock)
|
|
|
|
LCK_release(tdbb, attachment->att_id_lock);
|
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
#ifndef SUPERSERVER
|
|
|
|
if (attachment->att_temp_pg_lock)
|
|
|
|
LCK_release(tdbb, attachment->att_temp_pg_lock);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2007-07-25 15:21:59 +02:00
|
|
|
for (bool getResult = attachment->att_dsql_cache.getFirst(); getResult;
|
|
|
|
getResult = attachment->att_dsql_cache.getNext())
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
2007-07-25 15:21:59 +02:00
|
|
|
LCK_release(tdbb, attachment->att_dsql_cache.current()->second.lock);
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
2006-05-22 00:07:35 +02:00
|
|
|
#endif
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
for (vcl** vector = attachment->att_counts;
|
2001-05-23 15:26:42 +02:00
|
|
|
vector < attachment->att_counts + DBB_max_count; ++vector)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (*vector)
|
2005-01-25 07:33:07 +01:00
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
delete *vector;
|
2005-01-25 07:33:07 +01:00
|
|
|
*vector = 0;
|
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
// Release any validation error vector allocated
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (attachment->att_val_errors) {
|
2001-12-24 03:51:06 +01:00
|
|
|
delete attachment->att_val_errors;
|
2003-09-01 09:58:04 +02:00
|
|
|
attachment->att_val_errors = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2007-06-15 11:28:56 +02:00
|
|
|
detachLocksFromAttachment(attachment);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-02 09:01:33 +02:00
|
|
|
if (attachment->att_flags & ATT_lck_init_done) {
|
2006-07-21 03:35:17 +02:00
|
|
|
LCK_fini(tdbb, LCK_OWNER_attachment); // For the attachment
|
2005-05-02 09:01:33 +02:00
|
|
|
attachment->att_flags &= ~ATT_lck_init_done;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (attachment->att_compatibility_table)
|
2001-12-24 03:51:06 +01:00
|
|
|
delete attachment->att_compatibility_table;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// remove the attachment block from the dbb linked list
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
for (Attachment** ptr = &dbb->dbb_attachments; *ptr; ptr = &(*ptr)->att_next) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (*ptr == attachment) {
|
|
|
|
*ptr = attachment->att_next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-15 11:28:56 +02:00
|
|
|
static void detachLocksFromAttachment(Attachment* attachment)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e t a c h L o c k s F r o m A t t a c h m e n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Bug #7781, need to null out the attachment pointer of all locks which
|
|
|
|
* were hung off this attachment block, to ensure that the attachment
|
|
|
|
* block doesn't get dereferenced after it is released
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
Lock* long_lock = attachment->att_long_locks;
|
|
|
|
while (long_lock) {
|
|
|
|
Lock* next = long_lock->lck_next;
|
|
|
|
long_lock->lck_attachment = NULL;
|
|
|
|
long_lock->lck_next = NULL;
|
|
|
|
long_lock->lck_prior = NULL;
|
|
|
|
long_lock = next;
|
|
|
|
}
|
|
|
|
attachment->att_long_locks = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Jrd::Attachment::~Attachment()
|
|
|
|
{
|
|
|
|
// For normal attachments that happens release_attachment(),
|
|
|
|
// but for special ones like GC should be done also in dtor -
|
|
|
|
// they do not (and should not) call release_attachment().
|
|
|
|
// It's no danger calling detachLocksFromAttachment()
|
|
|
|
// once more here because it nulls att_long_locks.
|
|
|
|
// AP 2007
|
|
|
|
detachLocksFromAttachment(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static ISC_STATUS rollback(ISC_STATUS* user_status,
|
|
|
|
jrd_tra** tra_handle,
|
|
|
|
const bool retaining_flag)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2008-01-26 14:51:33 +01:00
|
|
|
* r o l l b a c k
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-01-26 14:51:33 +01:00
|
|
|
* Abort a transaction.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
ThreadContextHolder tdbb(user_status);
|
2008-02-02 15:36:06 +01:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
LOG_call(log_rollback, *tra_handle);
|
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = *tra_handle;
|
|
|
|
validateHandle(tdbb, transaction);
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* next = transaction;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
while ( (transaction = next) )
|
|
|
|
{
|
|
|
|
next = transaction->tra_sibling;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
validateHandle(tdbb, transaction->tra_attachment);
|
|
|
|
check_database(tdbb);
|
2006-11-10 09:12:07 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
const Database* const dbb = tdbb->getDatabase();
|
|
|
|
const Attachment* const attachment = tdbb->getAttachment();
|
|
|
|
|
|
|
|
if (!(attachment->att_flags & ATT_no_db_triggers))
|
2006-11-10 09:12:07 +01:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
ISC_STATUS_ARRAY temp_status = {0};
|
|
|
|
tdbb->tdbb_status_vector = temp_status;
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
// run ON TRANSACTION ROLLBACK triggers
|
2008-02-03 03:32:39 +01:00
|
|
|
EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_rollback);
|
2008-01-26 14:51:33 +01:00
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
if (dbb->dbb_flags & DBB_bugcheck)
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
tdbb->tdbb_status_vector = user_status;
|
|
|
|
tdbb->setTransaction(transaction);
|
|
|
|
TRA_rollback(tdbb, transaction, retaining_flag, false);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& ex) {
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
user_status = local_status;
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const Firebird::Exception& ex)
|
|
|
|
{
|
|
|
|
Firebird::stuff_exception(user_status, ex);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return user_status[1];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (WIN_NT) && !defined(SERVER_SHUTDOWN)
|
|
|
|
static void setup_NT_handlers()
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s e t u p _ N T _ h a n d l e r s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Set up Windows NT console control handlers for
|
|
|
|
* things that can happen. The handler used for
|
|
|
|
* all cases, handler_NT(), will flush and close
|
|
|
|
* any open database files.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-08-28 15:16:03 +02:00
|
|
|
SetConsoleCtrlHandler((PHANDLER_ROUTINE) handler_NT, TRUE);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2007-10-26 15:21:16 +02:00
|
|
|
bool Database::onRawDevice()
|
|
|
|
{
|
|
|
|
#ifdef SUPPORT_RAW_DEVICES
|
|
|
|
return PIO_on_raw_device(dbb_filename);
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
static void shutdown_database(Database* dbb, const bool release_pools)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s h u t d o w n _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Shutdown physical database environment.
|
|
|
|
* NOTE: This routine assumes that upon entry,
|
|
|
|
* mutex databases_mutex will be locked.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-05-23 05:18:10 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Shutdown file and/or remote connection
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef SUPERSERVER_V2
|
2006-07-21 03:35:17 +02:00
|
|
|
TRA_header_write(tdbb, dbb, 0L); // Update transaction info on header page.
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GARBAGE_THREAD
|
|
|
|
VIO_fini(tdbb);
|
|
|
|
#endif
|
|
|
|
CMP_fini(tdbb);
|
|
|
|
CCH_fini(tdbb);
|
2005-11-22 00:33:20 +01:00
|
|
|
if (dbb->dbb_backup_manager)
|
|
|
|
dbb->dbb_backup_manager->shutdown(tdbb);
|
2004-11-29 12:15:09 +01:00
|
|
|
// FUN_fini(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-10-30 13:39:08 +01:00
|
|
|
if (dbb->dbb_instance_lock)
|
|
|
|
LCK_release(tdbb, dbb->dbb_instance_lock);
|
|
|
|
|
2006-10-07 12:53:01 +02:00
|
|
|
if (dbb->dbb_monitor_lock)
|
|
|
|
LCK_release(tdbb, dbb->dbb_monitor_lock);
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (dbb->dbb_shadow_lock)
|
|
|
|
LCK_release(tdbb, dbb->dbb_shadow_lock);
|
|
|
|
|
|
|
|
if (dbb->dbb_retaining_lock)
|
|
|
|
LCK_release(tdbb, dbb->dbb_retaining_lock);
|
|
|
|
|
2007-07-25 15:21:59 +02:00
|
|
|
// temporal measure to avoid unstable state of lock file -
|
|
|
|
// this is anyway called in ~Database()
|
|
|
|
dbb->destroyIntlObjects();
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
|
|
|
|
if (dbb->dbb_log)
|
|
|
|
LOG_fini();
|
|
|
|
#endif
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Shut down any extern relations
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (dbb->dbb_relations)
|
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_rel*>* vector = dbb->dbb_relations;
|
|
|
|
vec<jrd_rel*>::iterator ptr = vector->begin(), end = vector->end();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
for (; ptr < end; ++ptr)
|
|
|
|
{
|
2007-10-26 12:53:47 +02:00
|
|
|
jrd_rel* relation = *ptr;
|
|
|
|
if (relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2007-10-26 12:53:47 +02:00
|
|
|
if (relation->rel_file)
|
|
|
|
{
|
|
|
|
EXT_fini(*ptr, false);
|
|
|
|
}
|
|
|
|
|
2008-01-28 18:27:03 +01:00
|
|
|
for (IndexLock* index_lock = relation->rel_index_locks; index_lock;
|
|
|
|
index_lock = index_lock->idl_next)
|
|
|
|
{
|
|
|
|
if (index_lock->idl_lock)
|
|
|
|
LCK_release(tdbb, index_lock->idl_lock);
|
|
|
|
}
|
|
|
|
|
2007-10-26 12:53:47 +02:00
|
|
|
for (IndexBlock* index_block = relation->rel_index_blocks; index_block;
|
|
|
|
index_block = index_block->idb_next)
|
|
|
|
{
|
|
|
|
if (index_block->idb_lock)
|
|
|
|
LCK_release(tdbb, index_block->idb_lock);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-26 12:53:47 +02:00
|
|
|
if (dbb->dbb_lock)
|
|
|
|
LCK_release(tdbb, dbb->dbb_lock);
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
Database** d_ptr; // Intentionally left outside loop (HP/UX compiler)
|
2001-05-23 15:26:42 +02:00
|
|
|
for (d_ptr = &databases; *(d_ptr); d_ptr = &(*d_ptr)->dbb_next) {
|
|
|
|
if (*d_ptr == dbb) {
|
|
|
|
*d_ptr = dbb->dbb_next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dbb->dbb_flags & DBB_lck_init_done) {
|
2007-09-18 16:50:51 +02:00
|
|
|
dbb->dbb_page_manager.releaseLocks();
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
LCK_fini(tdbb, LCK_OWNER_database); // For the database
|
2001-05-23 15:26:42 +02:00
|
|
|
dbb->dbb_flags &= ~DBB_lck_init_done;
|
|
|
|
}
|
|
|
|
|
2004-06-08 15:41:08 +02:00
|
|
|
delete[] dbb->dbb_mutexes;
|
2006-02-23 06:08:26 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (release_pools) {
|
2007-12-03 16:46:39 +01:00
|
|
|
tdbb->setDatabase(NULL);
|
2008-01-29 11:36:49 +01:00
|
|
|
Database::deleteDbb(dbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-02-03 14:34:16 +01:00
|
|
|
|
|
|
|
SecurityDatabase::shutdown();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
static void strip_quotes(Firebird::string& out)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s t r i p _ q u o t e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get rid of quotes around strings
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-11-24 19:26:24 +01:00
|
|
|
if (out.isEmpty())
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-11-24 19:26:24 +01:00
|
|
|
if (out[0] == DBL_QUOTE || out[0] == SINGLE_QUOTE)
|
|
|
|
{
|
|
|
|
// Skip any initial quote
|
2004-11-27 07:51:58 +01:00
|
|
|
const char quote = out[0];
|
2004-11-24 19:26:24 +01:00
|
|
|
out.erase(0, 1);
|
|
|
|
// Search for same quote
|
|
|
|
size_t pos = out.find(quote);
|
|
|
|
if (pos != Firebird::string::npos)
|
|
|
|
{
|
|
|
|
out.erase(pos);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static bool shutdown_dbb(thread_db* tdbb, Database* dbb, Attachment** released)
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s h u t d o w n _ d b b
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* rollback every transaction,
|
|
|
|
* release every attachment,
|
|
|
|
* and shutdown database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:51:33 +01:00
|
|
|
tdbb->setDatabase(dbb);
|
|
|
|
tdbb->tdbb_flags |= TDBB_shutdown_manager;
|
|
|
|
DatabaseContextHolder dbbHolder(tdbb);
|
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use | DBB_security_db)) &&
|
|
|
|
!(dbb->dbb_ast_flags & DBB_shutdown &&
|
|
|
|
dbb->dbb_ast_flags & DBB_shutdown_locks))
|
|
|
|
{
|
|
|
|
Attachment* att_next;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
for (Attachment* attach = dbb->dbb_attachments; attach; attach = att_next)
|
|
|
|
{
|
|
|
|
att_next = attach->att_next;
|
2007-12-03 16:46:39 +01:00
|
|
|
tdbb->setAttachment(attach);
|
2007-01-20 15:45:45 +01:00
|
|
|
|
|
|
|
// purge_attachment() below can do an ERR_post
|
2008-01-26 14:51:33 +01:00
|
|
|
ISC_STATUS_ARRAY temp_status;
|
|
|
|
tdbb->tdbb_status_vector = temp_status;
|
2007-01-20 15:45:45 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
try
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
|
|
|
// purge attachment, rollback any open transactions
|
2008-01-26 14:51:33 +01:00
|
|
|
purge_attachment(tdbb, temp_status, attach, true);
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
catch (const Firebird::Exception&)
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
|
|
|
if (released)
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
*released = NULL;
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
return false;
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// attach became invalid pointer
|
2007-01-26 02:24:48 +01:00
|
|
|
// if we have someone interested in that fact, inform him
|
2007-01-20 15:45:45 +01:00
|
|
|
if (released)
|
|
|
|
{
|
|
|
|
*released++ = attach;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
if (released)
|
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
*released = NULL;
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
return true;
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
static bool shutdown_all()
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s h u t d o w n _ a l l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* rollback every transaction,
|
|
|
|
* release every attachment,
|
|
|
|
* and shutdown every database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb;
|
2007-01-20 15:45:45 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
try {
|
|
|
|
DbMutexGuard guard;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
Database* dbb_next;
|
|
|
|
for (Database* dbb = databases; dbb; dbb = dbb_next)
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
2008-02-05 09:21:18 +01:00
|
|
|
dbb_next = dbb->dbb_next;
|
|
|
|
|
|
|
|
if (!shutdown_dbb(tdbb, dbb, NULL))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
|
|
|
}
|
2008-02-05 09:21:18 +01:00
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2007-01-20 15:45:45 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
return true;
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef SERVER_SHUTDOWN
|
2003-10-29 11:53:47 +01:00
|
|
|
TEXT* JRD_num_attachments(TEXT* const buf, USHORT buf_len, USHORT flag,
|
2006-10-30 13:39:08 +01:00
|
|
|
ULONG* atts, ULONG* dbs)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* J R D _ n u m _ a t t a c h m e n t s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Count the number of active databases and
|
|
|
|
* attachments. If flag is set then put
|
|
|
|
* what it says into buf, if it fits. If it does not fit
|
|
|
|
* then allocate local buffer, put info into there, and
|
|
|
|
* return pointer to caller (in this case a caller must
|
|
|
|
* release memory allocated for local buffer).
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// protect against NULL value for buf
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
TEXT* lbuf = buf;
|
2003-10-29 11:53:47 +01:00
|
|
|
if (!lbuf)
|
|
|
|
buf_len = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef WIN_NT
|
2006-07-21 03:35:17 +02:00
|
|
|
// Check that the buffer is big enough for the requested
|
|
|
|
// information. If not, unset the flag
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
if (flag == JRD_info_drivemask) {
|
|
|
|
if (buf_len < sizeof(ULONG)) {
|
|
|
|
lbuf = (TEXT*) gds__alloc((SLONG) (sizeof(ULONG)));
|
|
|
|
if (!lbuf)
|
2001-05-23 15:26:42 +02:00
|
|
|
flag = 0;
|
2003-10-29 11:53:47 +01:00
|
|
|
}
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2006-10-30 13:39:08 +01:00
|
|
|
ULONG num_dbs = 0;
|
|
|
|
ULONG num_att = 0;
|
2006-02-23 06:08:26 +01:00
|
|
|
ULONG drive_mask = 0L;
|
2007-02-26 17:17:00 +01:00
|
|
|
USHORT total = 0;
|
|
|
|
Firebird::HalfStaticArray<Firebird::PathName, 8> dbFiles;
|
2006-02-23 06:08:26 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
try {
|
2008-01-26 14:51:33 +01:00
|
|
|
dbMutexLock();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
// Zip through the list of databases and count the number of local
|
|
|
|
// connections. If buf is not NULL then copy all the database names
|
|
|
|
// that will fit into it.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
for (Database* dbb = databases; dbb; dbb = dbb->dbb_next)
|
|
|
|
{
|
|
|
|
Database::SyncGuard dsGuard(dbb);
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef WIN_NT
|
2006-07-21 03:35:17 +02:00
|
|
|
// Get drive letters for db files
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (flag == JRD_info_drivemask)
|
2004-02-20 07:43:27 +01:00
|
|
|
{
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
|
|
|
for (jrd_file* files = pageSpace->file; files; files = files->fil_next)
|
2001-05-23 15:26:42 +02:00
|
|
|
ExtractDriveLetter(files->fil_string, &drive_mask);
|
2004-02-20 07:43:27 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2003-02-03 14:34:16 +01:00
|
|
|
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use | DBB_security_db)) &&
|
2001-05-23 15:26:42 +02:00
|
|
|
!(dbb->dbb_ast_flags & DBB_shutdown
|
2004-02-20 07:43:27 +01:00
|
|
|
&& dbb->dbb_ast_flags & DBB_shutdown_locks))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
num_dbs++;
|
|
|
|
if (flag == JRD_info_dbnames) {
|
2007-02-26 17:17:00 +01:00
|
|
|
dbFiles.push(dbb->dbb_database_name);
|
|
|
|
total += sizeof(USHORT) + dbb->dbb_database_name.length();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
for (const Attachment* attach = dbb->dbb_attachments; attach;
|
2003-11-01 11:26:43 +01:00
|
|
|
attach = attach->att_next)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
num_att++;
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
2006-07-21 03:35:17 +02:00
|
|
|
// Get drive letters for temp directories
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (flag == JRD_info_drivemask) {
|
2006-05-31 10:53:00 +02:00
|
|
|
const Firebird::TempDirectoryList dirList;
|
|
|
|
for (size_t i = 0; i < dirList.getCount(); i++) {
|
|
|
|
const Firebird::PathName& path = dirList[i];
|
|
|
|
ExtractDriveLetter(path.c_str(), &drive_mask);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
dbMutexUnlock();
|
2008-02-05 09:21:18 +01:00
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
// Here we ignore possible errors from databases_rec_mutex.
|
|
|
|
// They were always silently ignored, and for this function
|
|
|
|
// we really have no way to notify world about mutex problem.
|
|
|
|
// AP. 2008.
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
*atts = num_att;
|
|
|
|
*dbs = num_dbs;
|
|
|
|
|
2007-02-26 17:17:00 +01:00
|
|
|
if (dbFiles.getCount() > 0)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (flag == JRD_info_dbnames)
|
|
|
|
{
|
2003-10-29 11:53:47 +01:00
|
|
|
if (buf_len < (sizeof(USHORT) + total))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
lbuf = (TEXT *) gds__alloc((SLONG) (sizeof(USHORT) + total));
|
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
TEXT* lbufp = lbuf;
|
|
|
|
if (lbufp)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/* Put db info into buffer. Format is as follows:
|
|
|
|
|
|
|
|
number of dbases sizeof (USHORT)
|
|
|
|
1st db name length sizeof (USHORT)
|
|
|
|
1st db name sizeof (TEXT) * length
|
|
|
|
2nd db name length
|
|
|
|
2nd db name
|
|
|
|
...
|
|
|
|
last db name length
|
|
|
|
last db name
|
|
|
|
*/
|
|
|
|
|
|
|
|
lbufp += sizeof(USHORT);
|
|
|
|
total = 0;
|
2007-02-26 17:17:00 +01:00
|
|
|
for (size_t n = 0; n < dbFiles.getCount(); ++n) {
|
|
|
|
*lbufp++ = (TEXT) dbFiles[n].length();
|
|
|
|
*lbufp++ = (TEXT) (dbFiles[n].length() >> 8);
|
2008-02-03 11:41:44 +01:00
|
|
|
memcpy(lbufp, dbFiles[n].c_str(), dbFiles[n].length());
|
2007-02-26 17:17:00 +01:00
|
|
|
lbufp += dbFiles[n].length();
|
2001-05-23 15:26:42 +02:00
|
|
|
total++;
|
|
|
|
}
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(total == num_dbs);
|
2001-05-23 15:26:42 +02:00
|
|
|
lbufp = lbuf;
|
|
|
|
*lbufp++ = (TEXT) total;
|
2007-02-26 17:17:00 +01:00
|
|
|
*lbufp++ = (TEXT) (total >> 8);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
if (flag == JRD_info_drivemask)
|
|
|
|
*(ULONG *) lbuf = drive_mask;
|
|
|
|
#endif
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
// CVC: Apparently, the original condition will leak memory, because flag
|
|
|
|
// may be JRD_info_drivemask and memory could be allocated for that purpose,
|
|
|
|
// as few as sizeof(ULONG), but a leak is a leak! I added the ifdef below.
|
2001-05-23 15:26:42 +02:00
|
|
|
if (num_dbs == 0)
|
2003-10-29 11:53:47 +01:00
|
|
|
{
|
|
|
|
#ifdef WIN_NT
|
|
|
|
if (flag == JRD_info_drivemask && lbuf != buf)
|
|
|
|
gds__free(lbuf);
|
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
lbuf = NULL;
|
2003-10-29 11:53:47 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return lbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
2003-11-01 11:26:43 +01:00
|
|
|
static void ExtractDriveLetter(const TEXT* file_name, ULONG* drive_mask)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E x t r a c t D r i v e L e t t e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Determine the drive letter of file_name
|
|
|
|
* and set the proper bit in the bit mask.
|
|
|
|
* bit 0 = drive A
|
|
|
|
* bit 1 = drive B and so on...
|
|
|
|
* This function is used to determine drive
|
|
|
|
* usage for use with Plug and Play for
|
|
|
|
* MS Windows 4.0.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
ULONG mask = 1;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const SHORT shift = (*file_name - 'A');
|
2001-05-23 15:26:42 +02:00
|
|
|
mask <<= shift;
|
|
|
|
*drive_mask |= mask;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
|
|
|
|
{
|
2005-04-11 17:33:18 +02:00
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s h u t d o w n _ t h r e a d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Shutdown SuperServer. If hangs, server
|
|
|
|
* is forcely & dirty closed after timeout.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
*static_cast<int*>(arg) = shutdown_all();
|
2005-04-11 17:33:18 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-24 13:14:51 +02:00
|
|
|
void JRD_shutdown_all(bool asyncMode)
|
2005-04-11 17:33:18 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* J R D _ s h u t d o w n _ a l l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2005-06-25 11:34:59 +02:00
|
|
|
* Rollback every transaction, release
|
|
|
|
* every attachment, and shutdown every
|
|
|
|
* database. Can be called in either a
|
|
|
|
* blocking mode or as a request for
|
|
|
|
* asynchronous shutdown.
|
2005-04-11 17:33:18 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int flShutdownComplete = 0;
|
2005-06-24 13:14:51 +02:00
|
|
|
|
|
|
|
if (asyncMode)
|
2005-04-11 17:33:18 +02:00
|
|
|
{
|
2005-06-24 13:14:51 +02:00
|
|
|
gds__thread_start(shutdown_thread, &flShutdownComplete,
|
|
|
|
THREAD_medium, 0, 0);
|
|
|
|
int timeout = 10; // seconds
|
|
|
|
while (timeout--)
|
|
|
|
{
|
|
|
|
if (flShutdownComplete)
|
|
|
|
break;
|
|
|
|
THREAD_SLEEP(1 * 1000);
|
|
|
|
}
|
2005-04-11 17:33:18 +02:00
|
|
|
}
|
2005-06-24 13:14:51 +02:00
|
|
|
else // sync mode
|
2005-04-11 17:33:18 +02:00
|
|
|
{
|
2008-01-26 14:51:33 +01:00
|
|
|
flShutdownComplete = shutdown_all();
|
2005-04-11 17:33:18 +02:00
|
|
|
}
|
2005-06-24 13:14:51 +02:00
|
|
|
|
|
|
|
if (!flShutdownComplete)
|
2005-04-11 17:33:18 +02:00
|
|
|
{
|
|
|
|
gds__log("Forced server shutdown - not all databases closed");
|
|
|
|
}
|
|
|
|
}
|
2007-01-20 15:45:45 +01:00
|
|
|
|
|
|
|
#else // SERVER_SHUTDOWN
|
|
|
|
|
|
|
|
// This conditional compilation, though sitting under not
|
|
|
|
// defined SERVER_SHUTDOWN, performs full or partial shutdown
|
|
|
|
// of database. SERVER_SHUTDOWN defined controls some other
|
|
|
|
// aspects of operation, therefore was left "as is".
|
2007-01-26 02:24:48 +01:00
|
|
|
// Who wants to invent better name for it, please do it.
|
2007-01-20 15:45:45 +01:00
|
|
|
|
|
|
|
void JRD_process_close()
|
|
|
|
{
|
|
|
|
shutdown_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
void JRD_database_close(Attachment** handle, Attachment** released)
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
ThreadContextHolder tdbb;
|
2007-01-20 15:45:45 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
try {
|
|
|
|
DbMutexGuard guard;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
Database* dbb = databases;
|
|
|
|
for (; dbb; dbb = dbb->dbb_next)
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
2008-02-05 09:21:18 +01:00
|
|
|
for (Attachment* attach = dbb->dbb_attachments; attach; attach = attach->att_next)
|
2007-01-20 15:45:45 +01:00
|
|
|
{
|
2008-02-05 09:21:18 +01:00
|
|
|
if (attach == *handle)
|
|
|
|
{
|
|
|
|
// got dbb to be closed
|
|
|
|
shutdown_dbb(tdbb, dbb, released);
|
|
|
|
return;
|
|
|
|
}
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-05 09:21:18 +01:00
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
// This function is called from yValve as a last attempt to help
|
|
|
|
// when terminate signal is sent to firebird server.
|
|
|
|
// Ignore possible mutex problems.
|
|
|
|
}
|
2007-01-20 15:45:45 +01:00
|
|
|
}
|
|
|
|
|
2006-07-21 03:35:17 +02:00
|
|
|
#endif // SERVER_SHUTDOWN
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2007-07-25 15:21:59 +02:00
|
|
|
static unsigned int purge_transactions(thread_db* tdbb,
|
|
|
|
Attachment* attachment,
|
|
|
|
const bool force_flag,
|
|
|
|
const ULONG att_flags)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* p u r g e _ t r a n s a c t i o n s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* commit or rollback all transactions
|
|
|
|
* from an attachment
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
Database* dbb = attachment->att_database;
|
|
|
|
jrd_tra* trans_dbk = attachment->att_dbkey_trans;
|
|
|
|
|
|
|
|
unsigned int count = 0;
|
|
|
|
jrd_tra* next;
|
2007-07-26 03:23:18 +02:00
|
|
|
|
2007-07-25 15:21:59 +02:00
|
|
|
for (jrd_tra* transaction = attachment->att_transactions;
|
|
|
|
transaction;
|
|
|
|
transaction = next)
|
|
|
|
{
|
|
|
|
next = transaction->tra_next;
|
|
|
|
if (transaction != trans_dbk)
|
|
|
|
{
|
2007-07-26 03:23:18 +02:00
|
|
|
if ((transaction->tra_flags & TRA_prepared) ||
|
|
|
|
(dbb->dbb_ast_flags & DBB_shutdown) ||
|
|
|
|
(att_flags & ATT_shutdown))
|
2007-07-25 15:21:59 +02:00
|
|
|
{
|
|
|
|
TRA_release_transaction(tdbb, transaction);
|
|
|
|
}
|
|
|
|
else if (force_flag)
|
|
|
|
TRA_rollback(tdbb, transaction, false, true);
|
|
|
|
else
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count)
|
|
|
|
{
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there's a side transaction for db-key scope, get rid of it
|
|
|
|
if (trans_dbk)
|
|
|
|
{
|
|
|
|
attachment->att_dbkey_trans = NULL;
|
2007-07-26 03:23:18 +02:00
|
|
|
if ((dbb->dbb_ast_flags & DBB_shutdown) ||
|
|
|
|
(att_flags & ATT_shutdown))
|
2007-07-25 15:21:59 +02:00
|
|
|
{
|
|
|
|
TRA_release_transaction(tdbb, trans_dbk);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TRA_commit(tdbb, trans_dbk, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static void purge_attachment(thread_db* tdbb,
|
2003-04-10 08:49:16 +02:00
|
|
|
ISC_STATUS* user_status,
|
2008-01-16 10:29:37 +01:00
|
|
|
Attachment* attachment,
|
|
|
|
const bool force_flag)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* p u r g e _ a t t a c h m e n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Zap an attachment, shutting down the database
|
|
|
|
* if it is the last one.
|
|
|
|
* NOTE: This routine assumes that upon entry,
|
|
|
|
* mutex databases_mutex will be locked.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = attachment->att_database;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2006-12-12 15:21:17 +01:00
|
|
|
if (!(dbb->dbb_flags & DBB_bugcheck))
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
ISC_STATUS* const original_status = tdbb->tdbb_status_vector;
|
2006-12-13 15:28:57 +01:00
|
|
|
|
2006-12-12 15:21:17 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
if (!(attachment->att_flags & ATT_no_db_triggers) &&
|
|
|
|
!(attachment->att_flags & ATT_shutdown))
|
|
|
|
{
|
|
|
|
ISC_STATUS_ARRAY temp_status = {0};
|
|
|
|
tdbb->tdbb_status_vector = temp_status;
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
jrd_tra* transaction = NULL;
|
|
|
|
|
2006-12-12 15:21:17 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// start a transaction to execute ON DISCONNECT triggers
|
|
|
|
transaction = TRA_start(tdbb, 0, NULL);
|
|
|
|
|
|
|
|
// run ON DISCONNECT triggers
|
2008-01-26 14:51:33 +01:00
|
|
|
EXE_execute_db_triggers(tdbb, transaction,
|
|
|
|
jrd_req::req_trigger_disconnect);
|
2006-12-12 15:21:17 +01:00
|
|
|
|
|
|
|
// and commit the transaction
|
|
|
|
TRA_commit(tdbb, transaction, false);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
if (dbb->dbb_flags & DBB_bugcheck)
|
|
|
|
throw;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (transaction)
|
|
|
|
TRA_rollback(tdbb, transaction, false, false);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
if (dbb->dbb_flags & DBB_bugcheck)
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
2006-12-13 15:28:57 +01:00
|
|
|
tdbb->tdbb_status_vector = original_status;
|
2006-12-12 15:21:17 +01:00
|
|
|
attachment->att_flags |= ATT_shutdown;
|
|
|
|
throw;
|
|
|
|
}
|
2006-12-13 15:28:57 +01:00
|
|
|
|
|
|
|
tdbb->tdbb_status_vector = original_status;
|
2006-12-12 15:21:17 +01:00
|
|
|
}
|
|
|
|
|
2005-07-24 20:48:45 +02:00
|
|
|
const ULONG att_flags = attachment->att_flags;
|
|
|
|
attachment->att_flags |= ATT_shutdown;
|
|
|
|
|
2006-12-12 15:21:17 +01:00
|
|
|
if (!(dbb->dbb_flags & DBB_bugcheck))
|
|
|
|
{
|
2005-06-24 13:14:51 +02:00
|
|
|
// Check for any pending transactions
|
2007-07-25 15:21:59 +02:00
|
|
|
unsigned int count = purge_transactions(tdbb, attachment, force_flag, att_flags);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (count)
|
|
|
|
{
|
2007-07-25 15:21:59 +02:00
|
|
|
ERR_post(isc_open_trans, isc_arg_number, (SLONG) count, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SORT_shutdown(attachment);
|
|
|
|
}
|
|
|
|
|
2005-06-24 13:14:51 +02:00
|
|
|
// Unlink attachment from database
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
release_attachment(tdbb, attachment);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-06-24 13:14:51 +02:00
|
|
|
// If there are still attachments, do a partial shutdown
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->checkHandle())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (dbb->dbb_attachments || (dbb->dbb_flags & DBB_being_opened))
|
|
|
|
{
|
2003-11-10 10:16:38 +01:00
|
|
|
// There are still attachments so do a partial shutdown
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-10 10:16:38 +01:00
|
|
|
// Both CMP_release() and SCL_release() do advance the pointer
|
|
|
|
// before the deallocation.
|
2003-11-01 11:26:43 +01:00
|
|
|
jrd_req* request;
|
2001-12-24 03:51:06 +01:00
|
|
|
while ( (request = attachment->att_requests) ) {
|
2001-05-23 15:26:42 +02:00
|
|
|
CMP_release(tdbb, request);
|
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
SecurityClass* sec_class;
|
2003-11-01 11:26:43 +01:00
|
|
|
while ( (sec_class = attachment->att_security_classes) ) {
|
|
|
|
SCL_release(sec_class);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-26 14:51:33 +01:00
|
|
|
|
|
|
|
delete attachment->att_user;
|
2001-12-24 03:51:06 +01:00
|
|
|
delete attachment;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
shutdown_database(dbb, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
|
2006-12-30 02:26:50 +01:00
|
|
|
static void run_commit_triggers(thread_db* tdbb, jrd_tra* transaction)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* r u n _ c o m m i t _ t r i g g e r s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Run ON TRANSACTION COMMIT triggers of a transaction.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2007-12-03 16:46:39 +01:00
|
|
|
if (transaction == tdbb->getDatabase()->dbb_sys_trans)
|
2007-01-07 00:54:23 +01:00
|
|
|
return;
|
|
|
|
|
2006-12-30 02:26:50 +01:00
|
|
|
// start a savepoint to rollback changes of all triggers
|
|
|
|
VIO_start_save_point(tdbb, transaction);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// run ON TRANSACTION COMMIT triggers
|
2008-01-26 14:51:33 +01:00
|
|
|
EXE_execute_db_triggers(tdbb, transaction,
|
|
|
|
jrd_req::req_trigger_trans_commit);
|
2007-01-07 00:54:23 +01:00
|
|
|
VIO_verb_cleanup(tdbb, transaction);
|
2006-12-30 02:26:50 +01:00
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
2007-12-03 16:46:39 +01:00
|
|
|
if (!(tdbb->getDatabase()->dbb_flags & DBB_bugcheck))
|
2006-12-30 02:26:50 +01:00
|
|
|
{
|
|
|
|
// rollbacks the created savepoint
|
|
|
|
++transaction->tra_save_point->sav_verb_count;
|
|
|
|
VIO_verb_cleanup(tdbb, transaction);
|
|
|
|
}
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
// verify_request_synchronization
|
|
|
|
//
|
2006-11-24 01:25:13 +01:00
|
|
|
// @brief Finds the sub-requests at the given level and replaces it with the
|
2003-11-05 10:02:33 +01:00
|
|
|
// original passed request (note the pointer by reference). If that specific
|
|
|
|
// sub-request is not found, throw the dreaded "request synchronization error".
|
|
|
|
// Notice that at this time, the calling function's "request" pointer has been
|
|
|
|
// set to null, so remember that if you write a debugging routine.
|
|
|
|
// This function replaced a chunk of code repeated four times.
|
|
|
|
//
|
|
|
|
// @param request The incoming, parent request to be replaced.
|
|
|
|
// @param level The level of the sub-request we need to find.
|
|
|
|
static void verify_request_synchronization(jrd_req*& request, SSHORT level)
|
|
|
|
{
|
|
|
|
const USHORT lev = level;
|
|
|
|
if (lev) {
|
2005-12-02 08:35:34 +01:00
|
|
|
const vec<jrd_req*>* vector = request->req_sub_requests;
|
2003-11-05 10:02:33 +01:00
|
|
|
if (!vector || lev >= vector->count() ||
|
2005-12-02 08:35:34 +01:00
|
|
|
!(request = (*vector)[lev]))
|
2003-11-05 10:02:33 +01:00
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
ERR_post(isc_req_sync, 0);
|
2003-11-05 10:02:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-31 19:43:02 +02:00
|
|
|
/**
|
|
|
|
|
|
|
|
verify_database_name
|
|
|
|
|
|
|
|
@brief Verify database name for open/create
|
|
|
|
against given in conf file list of available directories
|
2006-08-16 17:15:58 +02:00
|
|
|
and security database name
|
2003-03-31 19:43:02 +02:00
|
|
|
|
|
|
|
@param name
|
|
|
|
@param status
|
|
|
|
|
|
|
|
**/
|
2004-11-07 15:50:53 +01:00
|
|
|
static vdnResult verify_database_name(const Firebird::PathName& name, ISC_STATUS* status)
|
2003-03-31 19:43:02 +02:00
|
|
|
{
|
2005-02-24 13:24:38 +01:00
|
|
|
// Check for security2.fdb
|
2003-03-31 19:43:02 +02:00
|
|
|
static TEXT SecurityNameBuffer[MAXPATHLEN] = "";
|
2004-08-16 14:28:43 +02:00
|
|
|
static Firebird::PathName ExpandedSecurityNameBuffer(*getDefaultMemoryPool());
|
2003-03-31 19:43:02 +02:00
|
|
|
if (! SecurityNameBuffer[0]) {
|
|
|
|
SecurityDatabase::getPath(SecurityNameBuffer);
|
2004-11-07 15:50:53 +01:00
|
|
|
ExpandedSecurityNameBuffer = SecurityNameBuffer;
|
|
|
|
ISC_expand_filename(ExpandedSecurityNameBuffer, false);
|
2003-03-31 19:43:02 +02:00
|
|
|
}
|
2004-11-07 15:50:53 +01:00
|
|
|
if (name == SecurityNameBuffer || name == ExpandedSecurityNameBuffer)
|
|
|
|
return vdnSecurity;
|
2008-01-26 14:51:33 +01:00
|
|
|
|
2003-03-31 19:43:02 +02:00
|
|
|
// Check for .conf
|
2003-04-06 17:01:30 +02:00
|
|
|
if (!ISC_verify_database_access(name)) {
|
2003-11-08 17:40:17 +01:00
|
|
|
status[0] = isc_arg_gds;
|
|
|
|
status[1] = isc_conf_access_denied;
|
|
|
|
status[2] = isc_arg_string;
|
2003-10-29 11:53:47 +01:00
|
|
|
// CVC: Using STATUS to hold pointer to literal string!
|
2003-10-07 12:43:20 +02:00
|
|
|
status[3] = reinterpret_cast<ISC_STATUS>("database");
|
2003-11-08 17:40:17 +01:00
|
|
|
status[4] = isc_arg_string;
|
2004-03-14 14:34:43 +01:00
|
|
|
status[5] = (ISC_STATUS)(U_IPTR) ERR_cstring(name.c_str());
|
2003-11-08 17:40:17 +01:00
|
|
|
status[6] = isc_arg_end;
|
2004-11-07 15:50:53 +01:00
|
|
|
return vdnFail;
|
2003-03-31 19:43:02 +02:00
|
|
|
}
|
2004-11-07 15:50:53 +01:00
|
|
|
return vdnOk;
|
2003-03-31 19:43:02 +02:00
|
|
|
}
|
2006-08-16 17:15:58 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
Attachment::locksmith
|
|
|
|
|
|
|
|
@brief Validate - is attached user locksmith?
|
|
|
|
|
|
|
|
**/
|
|
|
|
bool Attachment::locksmith() const
|
|
|
|
{
|
|
|
|
return att_user->locksmith();
|
|
|
|
}
|
2007-06-08 12:24:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
getUserInfo
|
|
|
|
|
|
|
|
@brief Checks the userinfo database to validate
|
|
|
|
password to that passed in.
|
2007-06-09 06:06:26 +02:00
|
|
|
Takes into account possible trusted authentication.
|
2007-06-08 12:24:57 +02:00
|
|
|
Fills UserId structure with resulting values.
|
|
|
|
|
|
|
|
@param user
|
|
|
|
@param options
|
|
|
|
|
|
|
|
**/
|
2008-01-26 18:33:57 +01:00
|
|
|
static void getUserInfo(Database* dbb, UserId& user, const DatabaseOptions& options)
|
2007-06-08 12:24:57 +02:00
|
|
|
{
|
2008-01-26 18:33:57 +01:00
|
|
|
Database::Checkout dcoHolder(dbb);
|
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
int id = -1, group = -1; // CVC: This var contained trash
|
2007-11-19 17:18:59 +01:00
|
|
|
int node_id = 0;
|
|
|
|
Firebird::string name;
|
2007-06-08 12:24:57 +02:00
|
|
|
|
2007-06-09 11:25:40 +02:00
|
|
|
#ifdef BOOT_BUILD
|
2007-06-08 12:24:57 +02:00
|
|
|
bool wheel = true;
|
|
|
|
#else
|
|
|
|
bool wheel = false;
|
2008-01-16 10:29:37 +01:00
|
|
|
if (options.dpb_trusted_login.hasData())
|
2007-06-08 12:24:57 +02:00
|
|
|
{
|
2008-01-16 13:29:45 +01:00
|
|
|
name = options.dpb_trusted_login;
|
2007-06-08 12:24:57 +02:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
else
|
2007-06-08 12:24:57 +02:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
if (options.dpb_user_name.isEmpty())
|
2007-06-08 12:24:57 +02:00
|
|
|
{
|
2008-01-16 13:29:45 +01:00
|
|
|
wheel = ISC_get_user(&name, &id, &group,
|
2008-01-16 10:29:37 +01:00
|
|
|
options.dpb_sys_user_name.nullStr());
|
2007-06-08 12:24:57 +02:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
if (options.dpb_user_name.hasData() || (id == -1))
|
2007-06-08 12:24:57 +02:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
Firebird::string remote = options.dpb_network_protocol +
|
|
|
|
(options.dpb_network_protocol.isEmpty() || options.dpb_remote_address.isEmpty() ? "" : "/") +
|
|
|
|
options.dpb_remote_address;
|
|
|
|
|
|
|
|
SecurityDatabase::verifyUser(name,
|
|
|
|
options.dpb_user_name.nullStr(),
|
|
|
|
options.dpb_password.nullStr(),
|
|
|
|
options.dpb_password_enc.nullStr(),
|
|
|
|
&id, &group, &node_id, remote);
|
2007-06-08 12:24:57 +02:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
2007-06-08 12:24:57 +02:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
// if the name from the user database is defined as SYSDBA,
|
|
|
|
// we define that user id as having system privileges
|
2007-06-08 12:24:57 +02:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
if (name == SYSDBA_USER_NAME)
|
|
|
|
{
|
|
|
|
wheel = true;
|
2007-06-08 12:24:57 +02:00
|
|
|
}
|
2007-06-09 11:25:40 +02:00
|
|
|
#endif // BOOT_BUILD
|
2007-06-08 12:24:57 +02:00
|
|
|
|
|
|
|
// In case we became WHEEL on an OS that didn't require name SYSDBA,
|
|
|
|
// (Like Unix) force the effective Database User name to be SYSDBA
|
|
|
|
|
|
|
|
if (wheel)
|
|
|
|
{
|
2007-11-19 17:18:59 +01:00
|
|
|
name = SYSDBA_USER_NAME;
|
2007-06-08 12:24:57 +02:00
|
|
|
}
|
|
|
|
|
2007-11-19 17:18:59 +01:00
|
|
|
if (name.length() > USERNAME_LENGTH)
|
2007-11-15 13:48:24 +01:00
|
|
|
{
|
|
|
|
Firebird::status_exception::raise(isc_long_login,
|
2007-11-19 17:18:59 +01:00
|
|
|
isc_arg_number, name.length(),
|
2008-01-26 14:51:33 +01:00
|
|
|
isc_arg_number, USERNAME_LENGTH,
|
|
|
|
0);
|
2007-11-15 13:48:24 +01:00
|
|
|
}
|
|
|
|
|
2007-06-08 12:24:57 +02:00
|
|
|
user.usr_user_name = name;
|
2007-11-19 17:18:59 +01:00
|
|
|
user.usr_project_name = "";
|
|
|
|
user.usr_org_name = "";
|
2007-06-08 12:24:57 +02:00
|
|
|
user.usr_sql_role_name = options.dpb_role_name;
|
|
|
|
user.usr_user_id = id;
|
|
|
|
user.usr_group_id = group;
|
|
|
|
user.usr_node_id = node_id;
|
|
|
|
if (wheel)
|
|
|
|
{
|
|
|
|
user.usr_flags |= USR_locksmith;
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
if (options.dpb_trusted_role)
|
|
|
|
{
|
|
|
|
user.usr_flags |= USR_trole;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ISC_STATUS unwindAttach(const Firebird::Exception& ex,
|
|
|
|
ISC_STATUS* userStatus,
|
|
|
|
thread_db* tdbb,
|
|
|
|
Attachment* attachment,
|
|
|
|
Database* dbb)
|
|
|
|
{
|
|
|
|
ISC_STATUS_ARRAY temp_status;
|
|
|
|
ISC_STATUS* const save_status = tdbb->tdbb_status_vector;
|
|
|
|
tdbb->tdbb_status_vector = temp_status;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
dbb->dbb_flags &= ~DBB_being_opened;
|
2008-01-26 14:51:33 +01:00
|
|
|
release_attachment(tdbb, attachment);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
if (dbb->checkHandle())
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
if (!dbb->dbb_attachments)
|
|
|
|
{
|
|
|
|
shutdown_database(dbb, true);
|
|
|
|
}
|
|
|
|
else if (attachment)
|
|
|
|
{
|
|
|
|
delete attachment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
tdbb->tdbb_status_vector = save_status;
|
|
|
|
dbMutexUnlock();
|
|
|
|
|
2008-01-26 14:51:33 +01:00
|
|
|
Firebird::stuff_exception(userStatus, ex);
|
|
|
|
return userStatus[1];
|
2007-06-08 12:24:57 +02:00
|
|
|
}
|
2007-12-03 16:46:39 +01:00
|
|
|
|
|
|
|
void thread_db::setTransaction(jrd_tra* val)
|
|
|
|
{
|
|
|
|
transaction = val;
|
|
|
|
traStat = val ? &val->tra_stats : RuntimeStatistics::getDummy();
|
|
|
|
}
|
|
|
|
|
|
|
|
void thread_db::setRequest(jrd_req* val)
|
|
|
|
{
|
|
|
|
request = val;
|
|
|
|
reqStat = val ? &val->req_stats : RuntimeStatistics::getDummy();
|
|
|
|
}
|
2008-02-08 17:54:10 +01:00
|
|
|
|
|
|
|
Database::~Database()
|
|
|
|
{
|
|
|
|
delete dbb_sys_trans;
|
|
|
|
|
|
|
|
destroyIntlObjects();
|
|
|
|
|
|
|
|
fb_assert(dbb_pools[0] == dbb_permanent);
|
|
|
|
for (size_t i = 1; i < dbb_pools.getCount(); ++i)
|
|
|
|
{
|
|
|
|
MemoryPool::deletePool(dbb_pools[i]);
|
|
|
|
}
|
|
|
|
}
|