2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
2003-12-31 06:36:12 +01:00
|
|
|
* MODULE: shut.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Database shutdown handler
|
|
|
|
*
|
|
|
|
* 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): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/jrd.h"
|
|
|
|
#include "../jrd/scl.h"
|
2005-11-22 00:33:20 +01:00
|
|
|
#include "../jrd/nbak.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/ods.h"
|
|
|
|
#include "../jrd/cch_proto.h"
|
|
|
|
#include "../jrd/cmp_proto.h"
|
|
|
|
#include "../jrd/err_proto.h"
|
|
|
|
|
|
|
|
#include "../jrd/lck_proto.h"
|
|
|
|
#include "../jrd/rlck_proto.h"
|
|
|
|
#include "../jrd/shut_proto.h"
|
|
|
|
#include "../jrd/tra_proto.h"
|
2008-11-28 00:06:48 +01:00
|
|
|
#include "../jrd/extds/ExtDS.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 16:33:30 +01:00
|
|
|
using namespace Jrd;
|
2008-08-27 14:20:47 +02:00
|
|
|
using namespace Firebird;
|
2004-03-20 16:33:30 +01:00
|
|
|
|
2004-05-07 00:11:24 +02:00
|
|
|
const SSHORT SHUT_WAIT_TIME = 5;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
// Shutdown lock data
|
2008-12-13 10:26:00 +01:00
|
|
|
union shutdown_data
|
|
|
|
{
|
2004-03-28 11:10:30 +02:00
|
|
|
struct {
|
|
|
|
SSHORT flag;
|
|
|
|
SSHORT delay;
|
|
|
|
} data_items;
|
|
|
|
SLONG data_long;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
// Define this to true if you need to allow no-op behavior when requested shutdown mode
|
2004-02-25 02:50:40 +01:00
|
|
|
// matches current. Logic of jrd8_create_database may need attention in this case too
|
2004-05-07 00:11:24 +02:00
|
|
|
const bool IGNORE_SAME_MODE = false;
|
2004-02-25 02:50:40 +01:00
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
static void bad_mode(Database* dbb)
|
|
|
|
{
|
|
|
|
ERR_post(Arg::Gds(isc_bad_shutdown_mode) << Arg::Str(dbb->dbb_database_name));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void same_mode(Database* dbb)
|
|
|
|
{
|
|
|
|
if (!IGNORE_SAME_MODE)
|
|
|
|
bad_mode(dbb);
|
|
|
|
}
|
|
|
|
|
2007-03-09 09:27:34 +01:00
|
|
|
static void check_backup_state(thread_db*);
|
2012-12-18 14:54:18 +01:00
|
|
|
static bool notify_shutdown(thread_db*, SSHORT, SSHORT, Sync*);
|
2015-11-04 07:06:26 +01:00
|
|
|
static bool shutdown(thread_db*, SSHORT, bool);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2015-11-04 07:06:26 +01:00
|
|
|
bool SHUT_blocking_ast(thread_db* tdbb, bool ast)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* S H U T _ b l o c k i n g _ a s t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Read data from database lock for
|
|
|
|
* shutdown instructions.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:17:19 +01:00
|
|
|
SET_TDBB(tdbb);
|
2013-03-17 13:14:25 +01:00
|
|
|
Database* const dbb = tdbb->getDatabase();
|
2008-01-26 14:17:19 +01:00
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
shutdown_data data;
|
2008-01-26 14:17:19 +01:00
|
|
|
data.data_long = LCK_read_data(tdbb, dbb->dbb_lock);
|
2004-02-20 07:43:27 +01:00
|
|
|
const SSHORT flag = data.data_items.flag;
|
|
|
|
const SSHORT delay = data.data_items.delay;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-02-05 08:01:37 +01:00
|
|
|
const int shut_mode = flag & isc_dpb_shut_mode_mask;
|
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
// Delay of -1 means we're going online
|
2013-03-17 13:14:25 +01:00
|
|
|
|
2009-06-27 08:23:36 +02:00
|
|
|
if (delay == -1)
|
|
|
|
{
|
2010-02-05 08:01:37 +01:00
|
|
|
dbb->dbb_ast_flags &= ~(DBB_shut_attach | DBB_shut_tran | DBB_shut_force);
|
|
|
|
|
|
|
|
if (shut_mode)
|
2008-12-13 10:26:00 +01:00
|
|
|
{
|
2010-02-05 08:01:37 +01:00
|
|
|
dbb->dbb_ast_flags &= ~(DBB_shutdown | DBB_shutdown_single | DBB_shutdown_full);
|
|
|
|
|
|
|
|
switch (shut_mode)
|
|
|
|
{
|
|
|
|
case isc_dpb_shut_normal:
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_multi:
|
|
|
|
dbb->dbb_ast_flags |= DBB_shutdown;
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_single:
|
|
|
|
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_single;
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_full:
|
|
|
|
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_full;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2015-11-04 07:06:26 +01:00
|
|
|
return false;
|
2013-03-17 13:14:25 +01:00
|
|
|
}
|
2013-03-17 21:36:56 +01:00
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
if ((flag & isc_dpb_shut_force) && !delay)
|
2015-11-04 07:06:26 +01:00
|
|
|
return shutdown(tdbb, flag, ast);
|
2008-01-16 10:48:41 +01:00
|
|
|
|
|
|
|
if (flag & isc_dpb_shut_attachment)
|
|
|
|
dbb->dbb_ast_flags |= DBB_shut_attach;
|
|
|
|
if (flag & isc_dpb_shut_force)
|
|
|
|
dbb->dbb_ast_flags |= DBB_shut_force;
|
|
|
|
if (flag & isc_dpb_shut_transaction)
|
|
|
|
dbb->dbb_ast_flags |= DBB_shut_tran;
|
2015-11-04 07:06:26 +01:00
|
|
|
|
|
|
|
return false;
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
void SHUT_database(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard)
|
2004-02-25 02:50:40 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* S H U T _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Schedule database for shutdown
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:17:19 +01:00
|
|
|
SET_TDBB(tdbb);
|
2011-10-10 15:51:10 +02:00
|
|
|
Database* const dbb = tdbb->getDatabase();
|
|
|
|
Jrd::Attachment* const attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
// Only platform's user locksmith can shutdown or bring online a database
|
2004-02-25 02:50:40 +01:00
|
|
|
|
2016-05-31 19:07:08 +02:00
|
|
|
if (!attachment->locksmith(tdbb, CHANGE_SHUTDOWN_MODE))
|
2006-08-16 17:15:58 +02:00
|
|
|
{
|
2015-08-18 17:04:04 +02:00
|
|
|
ERR_post_nothrow(Arg::Gds(isc_no_priv) << "shutdown" << "database" << dbb->dbb_filename);
|
2016-12-30 17:28:37 +01:00
|
|
|
if (attachment->att_user && attachment->att_user->testFlag(USR_mapdown))
|
2015-08-18 17:04:04 +02:00
|
|
|
ERR_post_nothrow(Arg::Gds(isc_map_down));
|
|
|
|
ERR_punt();
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
|
|
|
|
2007-05-08 10:31:48 +02:00
|
|
|
const int shut_mode = flag & isc_dpb_shut_mode_mask;
|
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
// Check if requested shutdown mode is valid
|
|
|
|
// Note that if we are already in requested mode we just return true.
|
2008-12-05 02:20:14 +01:00
|
|
|
// This is required to ensure backward compatible behavior (gbak relies on that,
|
2004-02-25 02:50:40 +01:00
|
|
|
// user-written scripts may rely on this behaviour too)
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (shut_mode)
|
|
|
|
{
|
2004-02-25 02:50:40 +01:00
|
|
|
case isc_dpb_shut_full:
|
2008-12-05 02:20:14 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_full)
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb);
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2004-02-25 02:50:40 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_multi:
|
2014-03-26 20:11:32 +01:00
|
|
|
if (dbb->dbb_ast_flags & (DBB_shutdown_full | DBB_shutdown_single))
|
2004-02-25 02:50:40 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb);
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown)
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb);
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2004-02-25 02:50:40 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_single:
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_full)
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb);
|
2009-01-11 13:04:30 +01:00
|
|
|
}
|
2004-02-25 02:50:40 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_single)
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb);
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2004-02-25 02:50:40 +01:00
|
|
|
break;
|
2008-12-05 02:20:14 +01:00
|
|
|
case isc_dpb_shut_normal:
|
2004-02-25 02:50:40 +01:00
|
|
|
if (!(dbb->dbb_ast_flags & DBB_shutdown))
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb);
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb);
|
2004-02-25 02:50:40 +01:00
|
|
|
default:
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb); // unexpected mode
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2007-03-09 09:27:34 +01:00
|
|
|
// Reject exclusive and single-user shutdown attempts
|
|
|
|
// for a physically locked database
|
|
|
|
|
2008-12-13 10:26:00 +01:00
|
|
|
if (shut_mode == isc_dpb_shut_full || shut_mode == isc_dpb_shut_single)
|
2007-03-09 09:27:34 +01:00
|
|
|
{
|
|
|
|
check_backup_state(tdbb);
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags |= ATT_shutdown_manager;
|
|
|
|
|
2009-11-23 10:13:38 +01:00
|
|
|
// Database is being shutdown. First notification gives shutdown type and delay in seconds.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
bool exclusive = notify_shutdown(tdbb, flag, delay, guard);
|
2011-10-10 15:51:10 +02:00
|
|
|
bool successful = exclusive;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-23 10:13:38 +01:00
|
|
|
// Try to get exclusive database lock periodically up to specified delay. If we
|
|
|
|
// haven't gotten it report shutdown error for weaker forms. For forced shutdown
|
|
|
|
// keep notifying until successful.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-03-17 13:20:29 +01:00
|
|
|
SSHORT timeout = delay ? delay - 1 : 0;
|
2005-06-15 11:11:52 +02:00
|
|
|
|
|
|
|
if (!exclusive)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
do
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2011-10-10 15:51:10 +02:00
|
|
|
if (!(dbb->dbb_ast_flags & (DBB_shut_attach | DBB_shut_tran | DBB_shut_force)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ((flag & isc_dpb_shut_transaction) && !TRA_active_transactions(tdbb, dbb))
|
2005-06-15 11:11:52 +02:00
|
|
|
{
|
2011-10-10 15:51:10 +02:00
|
|
|
successful = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
if (timeout && CCH_exclusive(tdbb, LCK_PW, -1, guard))
|
2011-10-10 15:51:10 +02:00
|
|
|
{
|
|
|
|
exclusive = true;
|
2005-06-15 11:11:52 +02:00
|
|
|
break;
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2013-03-17 13:14:25 +01:00
|
|
|
while (timeout--);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-10-27 03:04:14 +02:00
|
|
|
if (!exclusive && !successful &&
|
2014-03-22 21:51:24 +01:00
|
|
|
(timeout > 0 || (flag & (isc_dpb_shut_attachment | isc_dpb_shut_transaction))))
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2012-12-18 14:54:18 +01:00
|
|
|
notify_shutdown(tdbb, 0, -1, guard); // Tell everyone we're giving up
|
2001-05-23 15:26:42 +02:00
|
|
|
attachment->att_flags &= ~ATT_shutdown_manager;
|
2008-08-27 14:20:47 +02:00
|
|
|
ERR_post(Arg::Gds(isc_shutfail));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
if (!exclusive && !notify_shutdown(tdbb, shut_mode | isc_dpb_shut_force, 0, guard))
|
2009-06-27 08:23:36 +02:00
|
|
|
{
|
2012-12-18 14:54:18 +01:00
|
|
|
if (!CCH_exclusive(tdbb, LCK_PW, LCK_WAIT, guard))
|
2011-10-10 15:51:10 +02:00
|
|
|
{
|
2012-12-18 14:54:18 +01:00
|
|
|
notify_shutdown(tdbb, 0, -1, guard); // Tell everyone we're giving up
|
2011-10-10 15:51:10 +02:00
|
|
|
attachment->att_flags &= ~ATT_shutdown_manager;
|
|
|
|
ERR_post(Arg::Gds(isc_shutfail));
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
dbb->dbb_ast_flags &= ~(DBB_shut_force | DBB_shut_attach | DBB_shut_tran);
|
2011-10-10 15:51:10 +02:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
WIN window(HEADER_PAGE_NUMBER);
|
2011-10-10 15:51:10 +02:00
|
|
|
Ods::header_page* const header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
2001-05-23 15:26:42 +02:00
|
|
|
CCH_MARK_MUST_WRITE(tdbb, &window);
|
2004-02-25 02:50:40 +01:00
|
|
|
// Set appropriate shutdown mode in database header
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags &= ~Ods::hdr_shutdown_mask;
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (shut_mode)
|
|
|
|
{
|
2004-02-25 02:50:40 +01:00
|
|
|
case isc_dpb_shut_normal:
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_multi:
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags |= Ods::hdr_shutdown_multi;
|
2004-02-25 02:50:40 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_single:
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags |= Ods::hdr_shutdown_single;
|
2004-02-25 02:50:40 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_full:
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags |= Ods::hdr_shutdown_full;
|
2004-02-25 02:50:40 +01:00
|
|
|
break;
|
2007-05-08 10:31:48 +02:00
|
|
|
default:
|
|
|
|
fb_assert(false);
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
CCH_RELEASE(tdbb, &window);
|
2011-10-10 15:51:10 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
CCH_release_exclusive(tdbb);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-25 13:38:03 +02:00
|
|
|
void SHUT_init(thread_db* tdbb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* S H U T _ i n i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Read data from database lock for
|
|
|
|
* shutdown instructions.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
SHUT_blocking_ast(tdbb, false);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
void SHUT_online(thread_db* tdbb, SSHORT flag, Sync* guard)
|
2004-03-07 08:58:55 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* S H U T _ o n l i n e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Move database to "more online" state
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-26 14:17:19 +01:00
|
|
|
SET_TDBB(tdbb);
|
2011-10-10 15:51:10 +02:00
|
|
|
Database* const dbb = tdbb->getDatabase();
|
|
|
|
Jrd::Attachment* const attachment = tdbb->getAttachment();
|
2004-03-07 08:58:55 +01:00
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
// Only platform's user locksmith can shutdown or bring online a database
|
2004-03-07 08:58:55 +01:00
|
|
|
|
2016-12-30 17:28:37 +01:00
|
|
|
if (!attachment->locksmith(tdbb, CHANGE_SHUTDOWN_MODE))
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2015-08-18 17:04:04 +02:00
|
|
|
ERR_post_nothrow(Arg::Gds(isc_no_priv) << "bring online" << "database" << dbb->dbb_filename);
|
2016-12-30 17:28:37 +01:00
|
|
|
if (attachment->att_user && attachment->att_user->testFlag(USR_mapdown))
|
2015-08-18 17:04:04 +02:00
|
|
|
ERR_post_nothrow(Arg::Gds(isc_map_down));
|
|
|
|
ERR_punt();
|
2004-03-07 08:58:55 +01:00
|
|
|
}
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2007-05-08 10:31:48 +02:00
|
|
|
const int shut_mode = flag & isc_dpb_shut_mode_mask;
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
// Check if requested shutdown mode is valid
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (shut_mode)
|
|
|
|
{
|
2004-03-07 08:58:55 +01:00
|
|
|
case isc_dpb_shut_normal:
|
2008-12-05 02:20:14 +01:00
|
|
|
if (!(dbb->dbb_ast_flags & DBB_shutdown))
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb); // normal -> normal
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2004-03-07 08:58:55 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_multi:
|
|
|
|
if (!(dbb->dbb_ast_flags & DBB_shutdown))
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb); // normal -> multi
|
2009-01-11 13:04:30 +01:00
|
|
|
}
|
2008-12-13 10:26:00 +01:00
|
|
|
if (!(dbb->dbb_ast_flags & DBB_shutdown_full) && !(dbb->dbb_ast_flags & DBB_shutdown_single))
|
2004-03-07 08:58:55 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb); // multi -> multi
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
2004-03-07 08:58:55 +01:00
|
|
|
}
|
|
|
|
break;
|
2008-12-05 02:20:14 +01:00
|
|
|
case isc_dpb_shut_single:
|
2004-03-07 08:58:55 +01:00
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_single)
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb); //single -> single
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2004-03-07 08:58:55 +01:00
|
|
|
if (!(dbb->dbb_ast_flags & DBB_shutdown_full))
|
2009-01-11 13:04:30 +01:00
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb); // !full -> single
|
2009-01-11 13:04:30 +01:00
|
|
|
}
|
2008-12-05 02:20:14 +01:00
|
|
|
break;
|
2004-03-07 08:58:55 +01:00
|
|
|
case isc_dpb_shut_full:
|
|
|
|
if (dbb->dbb_ast_flags & DBB_shutdown_full)
|
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
same_mode(dbb); // full -> full
|
2009-01-11 13:04:30 +01:00
|
|
|
return;
|
2004-03-07 08:58:55 +01:00
|
|
|
}
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb);
|
2004-03-07 08:58:55 +01:00
|
|
|
default: // isc_dpb_shut_full
|
2013-03-17 13:14:25 +01:00
|
|
|
bad_mode(dbb); // unexpected mode
|
2004-03-07 08:58:55 +01:00
|
|
|
}
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2007-03-09 09:27:34 +01:00
|
|
|
// Reject exclusive and single-user shutdown attempts
|
|
|
|
// for a physically locked database
|
|
|
|
|
2008-12-13 10:26:00 +01:00
|
|
|
if (shut_mode == isc_dpb_shut_full || shut_mode == isc_dpb_shut_single)
|
2007-03-09 09:27:34 +01:00
|
|
|
{
|
|
|
|
check_backup_state(tdbb);
|
|
|
|
}
|
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
// Reset shutdown flag on database header page
|
2004-03-07 08:58:55 +01:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
WIN window(HEADER_PAGE_NUMBER);
|
2011-10-10 15:51:10 +02:00
|
|
|
Ods::header_page* const header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
2004-03-07 08:58:55 +01:00
|
|
|
CCH_MARK_MUST_WRITE(tdbb, &window);
|
|
|
|
// Set appropriate shutdown mode in database header
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags &= ~Ods::hdr_shutdown_mask;
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (shut_mode)
|
|
|
|
{
|
2004-03-07 08:58:55 +01:00
|
|
|
case isc_dpb_shut_normal:
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_multi:
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags |= Ods::hdr_shutdown_multi;
|
2004-03-07 08:58:55 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_single:
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags |= Ods::hdr_shutdown_single;
|
2004-03-07 08:58:55 +01:00
|
|
|
break;
|
|
|
|
case isc_dpb_shut_full:
|
2004-05-01 00:47:16 +02:00
|
|
|
header->hdr_flags |= Ods::hdr_shutdown_full;
|
2004-03-07 08:58:55 +01:00
|
|
|
break;
|
2007-05-08 10:31:48 +02:00
|
|
|
default:
|
|
|
|
fb_assert(false);
|
2004-03-07 08:58:55 +01:00
|
|
|
}
|
|
|
|
CCH_RELEASE(tdbb, &window);
|
|
|
|
|
2011-10-10 15:51:10 +02:00
|
|
|
// Notify existing database clients that a currently scheduled shutdown is cancelled
|
2004-03-07 08:58:55 +01:00
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
if (notify_shutdown(tdbb, shut_mode, -1, guard))
|
2004-03-07 08:58:55 +01:00
|
|
|
CCH_release_exclusive(tdbb);
|
2009-01-11 13:04:30 +01:00
|
|
|
}
|
2004-03-07 08:58:55 +01:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2007-03-09 09:27:34 +01:00
|
|
|
static void check_backup_state(thread_db* tdbb)
|
|
|
|
{
|
2013-03-17 13:14:25 +01:00
|
|
|
Database* const dbb = tdbb->getDatabase();
|
2007-03-09 09:27:34 +01:00
|
|
|
|
2009-03-17 08:39:55 +01:00
|
|
|
BackupManager::StateReadGuard stateGuard(tdbb);
|
2007-03-09 09:27:34 +01:00
|
|
|
|
2014-09-30 16:21:44 +02:00
|
|
|
if (dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal)
|
2008-04-16 10:46:13 +02:00
|
|
|
{
|
2008-08-27 14:20:47 +02:00
|
|
|
ERR_post(Arg::Gds(isc_bad_shutdown_mode) << Arg::Str(dbb->dbb_filename));
|
2007-03-09 09:27:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
static bool notify_shutdown(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* n o t i f y _ s h u t d o w n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Notify database users that shutdown
|
|
|
|
* status of a database is changing.
|
|
|
|
* Pulse database lock and pass shutdown
|
|
|
|
* flags and delay via lock data.
|
|
|
|
*
|
|
|
|
**************************************/
|
2011-10-10 15:51:10 +02:00
|
|
|
Database* const dbb = tdbb->getDatabase();
|
2014-06-10 09:13:34 +02:00
|
|
|
StableAttachmentPart* const sAtt = tdbb->getAttachment()->getStable();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
shutdown_data data;
|
2001-05-23 15:26:42 +02:00
|
|
|
data.data_items.flag = flag;
|
|
|
|
data.data_items.delay = delay;
|
|
|
|
|
2008-01-26 14:17:19 +01:00
|
|
|
LCK_write_data(tdbb, dbb->dbb_lock, data.data_long);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-11-14 11:26:29 +01:00
|
|
|
{ // scope
|
|
|
|
// Checkout before calling AST function
|
2014-06-10 09:13:34 +02:00
|
|
|
MutexUnlockGuard uguard(*(sAtt->getMutex()), FB_FUNCTION);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-11-14 11:26:29 +01:00
|
|
|
// Notify local attachments
|
|
|
|
SHUT_blocking_ast(tdbb, true);
|
|
|
|
}
|
2005-06-15 11:11:52 +02:00
|
|
|
|
2011-10-10 15:51:10 +02:00
|
|
|
// Send blocking ASTs to other database users
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2012-12-18 14:54:18 +01:00
|
|
|
return CCH_exclusive(tdbb, LCK_PW, -1, guard);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-04 07:06:26 +01:00
|
|
|
static bool shutdown(thread_db* tdbb, SSHORT flag, bool force)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2011-10-10 15:51:10 +02:00
|
|
|
* s h u t d o w n
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2011-10-10 15:51:10 +02:00
|
|
|
* Initiate database shutdown.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2011-10-10 15:51:10 +02:00
|
|
|
Database* const dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
// Mark database and all active attachments as shutdown
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-25 02:50:40 +01:00
|
|
|
dbb->dbb_ast_flags &= ~(DBB_shutdown | DBB_shutdown_single | DBB_shutdown_full);
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (flag & isc_dpb_shut_mode_mask)
|
|
|
|
{
|
2007-05-08 10:31:48 +02:00
|
|
|
case isc_dpb_shut_normal:
|
|
|
|
break;
|
2004-02-25 02:50:40 +01:00
|
|
|
case isc_dpb_shut_multi:
|
|
|
|
dbb->dbb_ast_flags |= DBB_shutdown;
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_single:
|
|
|
|
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_single;
|
|
|
|
break;
|
|
|
|
case isc_dpb_shut_full:
|
|
|
|
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_full;
|
|
|
|
break;
|
2007-05-08 10:31:48 +02:00
|
|
|
default:
|
|
|
|
fb_assert(false);
|
2004-02-25 02:50:40 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
if (force)
|
2003-09-13 14:03:11 +02:00
|
|
|
{
|
2013-06-30 17:20:58 +02:00
|
|
|
bool found = false;
|
2013-03-17 13:14:25 +01:00
|
|
|
for (Jrd::Attachment* attachment = dbb->dbb_attachments;
|
|
|
|
attachment; attachment = attachment->att_next)
|
|
|
|
{
|
2014-06-10 09:13:34 +02:00
|
|
|
StableAttachmentPart* const sAtt = attachment->getStable();
|
|
|
|
MutexLockGuard guard(*(sAtt->getMutex(true)), FB_FUNCTION);
|
2013-08-19 20:50:28 +02:00
|
|
|
|
2013-03-17 13:14:25 +01:00
|
|
|
if (!(attachment->att_flags & ATT_shutdown_manager))
|
2013-06-30 17:20:58 +02:00
|
|
|
{
|
|
|
|
if (!(attachment->att_flags & ATT_shutdown))
|
|
|
|
{
|
2017-02-22 13:30:57 +01:00
|
|
|
attachment->signalShutdown(isc_att_shut_db_down);
|
2013-06-30 17:20:58 +02:00
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
2013-03-17 13:14:25 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-06-30 17:20:58 +02:00
|
|
|
if (found)
|
|
|
|
JRD_shutdown_attachments(dbb);
|
2015-11-04 07:06:26 +01:00
|
|
|
|
|
|
|
return true;
|
2013-03-17 13:14:25 +01:00
|
|
|
}
|
2015-11-04 07:06:26 +01:00
|
|
|
|
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|