mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 05:23:03 +01:00
1) Make NBACKUP happy on Win32 CS too.
2) Fix tracking of OWN_hung in Win32 CS lock manager (lock-up debugging aid) 3) Fix possible unsynchronized access to memory manager in Win32 CS builds and client library. Have shown itself as a very rare crash of Win32 CS manager process during its startup. 4) Reduce warnings a little Points 2 and 3 need to be backported to B1_5_Release
This commit is contained in:
parent
473a94cb1b
commit
ce78ed1f1d
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\alice_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\alice_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -85,7 +85,7 @@
|
||||
ProgramDataBaseFileName=".\..\..\..\temp\release\build_msg/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\burp_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\burp_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -32,7 +32,7 @@
|
||||
ProgramDataBaseFileName=".\..\..\..\temp\debug\codes/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\engine_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -81,7 +81,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\engine_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -81,7 +81,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\engine_es/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -77,7 +77,7 @@
|
||||
ProgramDataBaseFileName=".\..\..\..\temp\debug\fbclient_static/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -91,7 +91,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\fbudf/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -153,6 +153,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\isc.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\locks.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header files"
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\ipserver/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\lock_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\lock_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\remote_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\remote_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\utilities_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\utilities_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\wal_ss/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -80,7 +80,7 @@
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\wal_cs/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
|
@ -321,7 +321,7 @@ MemoryPool* MemoryPool::internal_create(size_t instance_size, int *cur_mem, int
|
||||
void MemoryPool::deletePool(MemoryPool* pool) {
|
||||
/* dimitr: I think we need an abstract base class or a global macro
|
||||
in locks.h to avoid these architecture checks. */
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef MULTI_THREAD
|
||||
pool->lock.~Spinlock();
|
||||
#else
|
||||
pool->lock.~SharedSpinlock();
|
||||
|
@ -113,7 +113,7 @@ private:
|
||||
Vector<void*,MAX_TREE_DEPTH+1> spareNodes;
|
||||
bool needSpare;
|
||||
PendingFreeBlock *pendingFree;
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef MULTI_THREAD
|
||||
Spinlock lock;
|
||||
#else
|
||||
SharedSpinlock lock;
|
||||
@ -241,11 +241,11 @@ inline void* operator new[](size_t s, Firebird::MemoryPool& pool, char* file, in
|
||||
#define FB_NEW(pool) new(pool,__FILE__,__LINE__)
|
||||
#define FB_NEW_RPT(pool,count) new(pool,count,__FILE__,__LINE__)
|
||||
#else
|
||||
inline void* operator new(size_t s, Firebird::MemoryPool& pool) throw(std::bad_alloc) {
|
||||
inline void* operator new(size_t s, Firebird::MemoryPool& pool) {
|
||||
return pool.allocate(s);
|
||||
// return pool.calloc(s);
|
||||
}
|
||||
inline void* operator new[](size_t s, Firebird::MemoryPool& pool) throw(std::bad_alloc) {
|
||||
inline void* operator new[](size_t s, Firebird::MemoryPool& pool) {
|
||||
return pool.allocate(s);
|
||||
// return pool.calloc(s);
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef WIN_NT
|
||||
|
||||
#define MISS_SPIN_COUNT ((tSetCriticalSectionSpinCount *)(-1))
|
||||
@ -60,6 +59,5 @@ Spinlock::Spinlock() {
|
||||
}
|
||||
|
||||
#endif // WIN_NT
|
||||
#endif // SUPERSERVER
|
||||
|
||||
} // namespace Firebird
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef MULTI_THREAD
|
||||
#ifdef WIN_NT
|
||||
// It is relatively easy to avoid using this header. Maybe do the same stuff like
|
||||
// in thd.h ? This is Windows platform maintainers choice
|
||||
@ -41,11 +41,11 @@
|
||||
#include <thread.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif /* SUPERSERVER */
|
||||
#endif /* MULTI_THREAD */
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef MULTI_THREAD
|
||||
#ifdef WIN_NT
|
||||
|
||||
/* Process-local spinlock. Used to manage memory heaps in threaded environment. */
|
||||
@ -126,7 +126,7 @@ public:
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* SUPERSERVER */
|
||||
#endif /* MULTI_THREAD */
|
||||
|
||||
// Spinlock in shared memory. Not implemented yet !
|
||||
class SharedSpinlock {
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
|
||||
#else
|
||||
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef MULTI_THREAD
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
@ -171,7 +171,7 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif /*SUPERSERVER*/
|
||||
#endif /*MULTI_THREAD*/
|
||||
|
||||
#endif /*!WIN_NT*/
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
* John Bellardo <bellardo@cs.ucsd.edu>
|
||||
*
|
||||
*
|
||||
* $Id: firebird.h,v 1.12 2003-03-09 02:23:56 brodsom Exp $
|
||||
* $Id: firebird.h,v 1.13 2003-08-10 15:43:21 skidder Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -65,4 +65,10 @@
|
||||
#define SERVER_SHUTDOWN 1
|
||||
#endif
|
||||
|
||||
// Check if we need thread synchronization
|
||||
#if defined(SUPERSERVER) || defined(SUPERCLIENT) || \
|
||||
defined(WIN_NT) || defined(SOLARIS_MT) || defined (VMS)
|
||||
#define MULTI_THREAD 1
|
||||
#endif
|
||||
|
||||
#endif /* INCLUDE_Firebird */
|
||||
|
@ -1201,14 +1201,7 @@ static bool begin_backup( TDBB tdbb,
|
||||
case 2:
|
||||
return true;
|
||||
case 3:
|
||||
if (!dbb->backup_manager->begin_backup())
|
||||
{
|
||||
ERR_post(gds_no_meta_update,
|
||||
gds_arg_gds, gds_lock_timeout,
|
||||
gds_arg_gds, gds_obj_in_use,
|
||||
gds_arg_string, "BACKUP STATE",
|
||||
0); /*!!!FIXME!!!*/
|
||||
}
|
||||
dbb->backup_manager->begin_backup();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1241,14 +1234,7 @@ static bool end_backup( TDBB tdbb,
|
||||
case 2:
|
||||
return true;
|
||||
case 3:
|
||||
if (!dbb->backup_manager->end_backup(false/*end backup normally*/))
|
||||
{
|
||||
ERR_post(gds_no_meta_update,
|
||||
gds_arg_gds, gds_lock_timeout,
|
||||
gds_arg_gds, gds_obj_in_use,
|
||||
gds_arg_string, "BACKUP STATE",
|
||||
0); /*!!!FIXME!!!*/
|
||||
}
|
||||
dbb->backup_manager->end_backup(false/*end backup normally*/);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -550,8 +550,6 @@ const TEXT* DLL_EXPORT ERR_string(const TEXT* in_string, int length)
|
||||
#endif
|
||||
jrd_failures_ptr = jrd_failures;
|
||||
|
||||
#pragma FB_COMPILER_MESSAGE("Fix! Can we change the API to take the real type?")
|
||||
// ugly but currently necessary cast
|
||||
gds__register_cleanup(cleanup, 0);
|
||||
}
|
||||
|
||||
|
@ -495,7 +495,6 @@ SLONG LCK_get_owner_handle(TDBB tdbb, enum lck_t lock_type)
|
||||
case LCK_range_relation:
|
||||
case LCK_backup_state:
|
||||
case LCK_backup_alloc:
|
||||
case LCK_backup_merge:
|
||||
return LCK_OWNER_HANDLE_DBB;
|
||||
case LCK_attachment:
|
||||
case LCK_relation:
|
||||
|
@ -45,8 +45,7 @@ enum lck_t {
|
||||
LCK_range_relation, /* Relation refresh range lock */
|
||||
LCK_update_shadow, /* shadow update sync lock */
|
||||
LCK_backup_state, /* Lock to synchronize for objects depending on backup status*/
|
||||
LCK_backup_alloc, /* Lock for page allocation table in backup spare file */
|
||||
LCK_backup_merge /* Lock for backup delta merge process */
|
||||
LCK_backup_alloc /* Lock for page allocation table in backup spare file */
|
||||
};
|
||||
|
||||
/* Lock owner types */
|
||||
|
144
src/jrd/nbak.cpp
144
src/jrd/nbak.cpp
@ -60,7 +60,14 @@ void BackupManager::lock_state_write(bool thread_exit) {
|
||||
state_lock->beginWrite();
|
||||
if (thread_exit) THREAD_ENTER;
|
||||
#else
|
||||
ast_flags |= NBAK_state_in_use; // Prevent ASTs from releasing the lock
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
// Release shared lock to prevent possible deadlocks
|
||||
if (state_lock->lck_physical != LCK_none)
|
||||
if (LCK_convert(tdbb, state_lock, LCK_EX, LCK_NO_WAIT))
|
||||
return;
|
||||
else
|
||||
LCK_release(tdbb, state_lock);
|
||||
if (!LCK_lock(tdbb, state_lock, LCK_EX, LCK_WAIT))
|
||||
// This is OK because state changing code expect it
|
||||
ERR_post(gds_lock_conflict, 0);
|
||||
@ -72,7 +79,21 @@ bool BackupManager::try_lock_state_write() {
|
||||
return state_lock->tryBeginWrite();
|
||||
#else
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
return LCK_lock(tdbb, state_lock, LCK_EX, LCK_NO_WAIT);
|
||||
ast_flags |= NBAK_state_in_use; // Prevent ASTs from releasing the lock
|
||||
bool result;
|
||||
if (state_lock->lck_physical == LCK_none)
|
||||
result = LCK_lock(tdbb, state_lock, LCK_EX, LCK_NO_WAIT);
|
||||
else
|
||||
result = LCK_convert(tdbb, state_lock, LCK_EX, LCK_NO_WAIT);
|
||||
if (!result) {
|
||||
if (ast_flags & NBAK_state_blocking) {
|
||||
LCK_release(tdbb, state_lock);
|
||||
ast_flags &= ~NBAK_state_blocking;
|
||||
backup_state = nbak_state_unknown; // We know state only as long we lock it
|
||||
}
|
||||
ast_flags &= ~NBAK_state_in_use;
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -83,6 +104,7 @@ void BackupManager::unlock_state_write() {
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
LCK_release(tdbb, state_lock);
|
||||
backup_state = nbak_state_unknown; // We know state only as long we lock it
|
||||
ast_flags &= ~NBAK_state_in_use;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -93,7 +115,14 @@ bool BackupManager::lock_alloc_write(bool thread_exit) {
|
||||
if (thread_exit) THREAD_ENTER;
|
||||
return true;
|
||||
#else
|
||||
ast_flags |= NBAK_alloc_in_use; // Prevent ASTs from releasing the lock
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
// Release shared lock to prevent possible deadlocks
|
||||
if (alloc_lock->lck_physical != LCK_none)
|
||||
if (LCK_convert(tdbb, alloc_lock, LCK_EX, LCK_NO_WAIT))
|
||||
return true;
|
||||
else
|
||||
LCK_release(tdbb, alloc_lock);
|
||||
return LCK_lock(tdbb, alloc_lock, LCK_EX, LCK_WAIT);
|
||||
#endif
|
||||
}
|
||||
@ -109,23 +138,34 @@ void BackupManager::unlock_alloc_write() {
|
||||
ast_flags |= NBAK_alloc_dirty;
|
||||
} else
|
||||
LCK_convert(tdbb, alloc_lock, LCK_SR, LCK_WAIT);
|
||||
ast_flags &= ~NBAK_alloc_in_use;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Initialize and open difference file for writing
|
||||
bool BackupManager::begin_backup() {
|
||||
void BackupManager::begin_backup() {
|
||||
TRACE("begin_backup");
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
lock_state_write(true);
|
||||
TRACE("state locked");
|
||||
|
||||
// Lock header page first to prevent possible deadlock
|
||||
WIN window;
|
||||
window.win_page = HEADER_PAGE;
|
||||
window.win_flags = 0;
|
||||
HDR header = (HDR) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||
bool state_locked = false, header_locked = true;
|
||||
try {
|
||||
lock_state_write(true);
|
||||
state_locked = true;
|
||||
TRACE("state locked");
|
||||
|
||||
if (!actualize_state(tdbb->tdbb_status_vector))
|
||||
ERR_punt();
|
||||
// Check state
|
||||
if (backup_state != nbak_state_normal) {
|
||||
TRACE1("end backup - invalid state %d", backup_state);
|
||||
unlock_state_write();
|
||||
return false;
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
return;
|
||||
}
|
||||
// Create file
|
||||
TRACE1("Creating difference file %s", diff_name);
|
||||
@ -145,23 +185,18 @@ bool BackupManager::begin_backup() {
|
||||
TRACE("Set backup state in header");
|
||||
FB_GUID guid;
|
||||
GenerateGuid(&guid);
|
||||
// Flush buffers to prevent the amount of allocated pages from increasing
|
||||
// Before lock we'll write only header then. This may not change the number of
|
||||
// pages in file.
|
||||
tdbb->tdbb_flags |= TDBB_set_backup_state;
|
||||
CCH_flush(tdbb, FLUSH_ALL, 0);
|
||||
// Set state in database header page. All changes are written to main database file yet.
|
||||
WIN window;
|
||||
HDR header;
|
||||
window.win_page = HEADER_PAGE;
|
||||
window.win_flags = 0;
|
||||
header = (HDR) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||
CCH_MARK_MUST_WRITE(tdbb, &window);
|
||||
int newState = nbak_state_stalled;
|
||||
header->hdr_flags = (header->hdr_flags & ~hdr_backup_mask) | newState;
|
||||
// This number may be smaller than actual because some pages may be not flushed to
|
||||
// disk yet. This is not a problem as it can cause only a slight performance degradation
|
||||
backup_pages = header->hdr_backup_pages = PIO_act_alloc(database);
|
||||
ULONG adjusted_scn = ++header->hdr_header.pag_scn(); // Generate new SCN
|
||||
PAG_replace_entry_first(header, HDR_backup_guid, sizeof(guid), (UCHAR*)&guid);
|
||||
|
||||
header_locked = false;
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
CCH_flush(tdbb, FLUSH_ALL, 0);
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
@ -172,11 +207,13 @@ bool BackupManager::begin_backup() {
|
||||
// We already modified state in header, error here is not very important
|
||||
actualize_alloc(tdbb->tdbb_status_vector);
|
||||
unlock_state_write();
|
||||
return true;
|
||||
} catch (const std::exception&) {
|
||||
unlock_state_write();
|
||||
backup_state = nbak_state_unknown;
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
if (state_locked)
|
||||
unlock_state_write();
|
||||
if (header_locked)
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -184,20 +221,31 @@ bool BackupManager::begin_backup() {
|
||||
// Merge difference file to main files (if needed) and unlink() difference
|
||||
// file then. If merge is already in progress method silently returns and
|
||||
// does nothing (so it can be used for recovery on database startup).
|
||||
bool BackupManager::end_backup(bool recover) {
|
||||
void BackupManager::end_backup(bool recover) {
|
||||
TRACE("end_backup");
|
||||
TDBB tdbb = GET_THREAD_DATA;
|
||||
ULONG adjusted_scn; // We use this value to prevent race conditions.
|
||||
// They are possible because we release state lock
|
||||
// for some instants and anything is possible at
|
||||
// that times.
|
||||
if (recover) {
|
||||
if (!try_lock_state_write())
|
||||
return false;
|
||||
} else
|
||||
lock_state_write(true);
|
||||
TRACE("state locked");
|
||||
|
||||
// Lock header page first to prevent possible deadlock
|
||||
WIN window;
|
||||
window.win_page = HEADER_PAGE;
|
||||
window.win_flags = 0;
|
||||
HDR header = (HDR) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||
bool state_locked = false, header_locked = true;
|
||||
|
||||
try {
|
||||
if (recover) {
|
||||
if (!try_lock_state_write()) {
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
lock_state_write(true);
|
||||
state_locked = true;
|
||||
TRACE("state locked");
|
||||
// Check state
|
||||
if (!actualize_state(tdbb->tdbb_status_vector))
|
||||
ERR_punt();
|
||||
@ -205,7 +253,8 @@ bool BackupManager::end_backup(bool recover) {
|
||||
if (backup_state == nbak_state_normal || (recover && backup_state != nbak_state_merge)) {
|
||||
TRACE1("invalid state %d", backup_state);
|
||||
unlock_state_write();
|
||||
return false;
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
return;
|
||||
}
|
||||
TRACE1("difference file %s", diff_name);
|
||||
// Set state in database header
|
||||
@ -213,12 +262,7 @@ bool BackupManager::end_backup(bool recover) {
|
||||
TRACE1("Current backup state is %d", backup_state);
|
||||
backup_state = nbak_state_merge;
|
||||
adjusted_scn = ++current_scn;
|
||||
WIN window;
|
||||
HDR header;
|
||||
window.win_page = HEADER_PAGE;
|
||||
window.win_flags = 0;
|
||||
TRACE1("New state is getting to become %d", backup_state);
|
||||
header = (HDR) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||
CCH_MARK_MUST_WRITE(tdbb, &window);
|
||||
TRACE1("New state is getting to become after fetches %d", backup_state);
|
||||
// Generate new SCN
|
||||
@ -226,16 +270,20 @@ bool BackupManager::end_backup(bool recover) {
|
||||
TRACE1("new SCN=%d is getting written to header", adjusted_scn);
|
||||
// Adjust state
|
||||
header->hdr_flags = (header->hdr_flags & ~hdr_backup_mask) | backup_state;
|
||||
header_locked = false;
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
CCH_flush(tdbb, FLUSH_ALL, 0); // This is to adjust header in main database file
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
TRACE1("Set state %d in header page", backup_state);
|
||||
} catch (const std::exception&) {
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
unlock_state_write();
|
||||
backup_state = nbak_state_unknown;
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
if (state_locked)
|
||||
unlock_state_write();
|
||||
if (header_locked)
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Here comes the dirty work. We need to reapply all changes from difference file to database
|
||||
@ -253,7 +301,7 @@ bool BackupManager::end_backup(bool recover) {
|
||||
if (backup_state != nbak_state_merge || current_scn != adjusted_scn) {
|
||||
/* Handle the case when somebody finalized merge for us */
|
||||
unlock_state();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
TRACE("Status OK.");
|
||||
if (!actualize_alloc(tdbb->tdbb_status_vector))
|
||||
@ -284,28 +332,31 @@ bool BackupManager::end_backup(bool recover) {
|
||||
}
|
||||
|
||||
// We finished. We need to reflect it in our database header page
|
||||
lock_state_write(true);
|
||||
window.win_page = HEADER_PAGE;
|
||||
window.win_flags = 0;
|
||||
header = (HDR) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||
state_locked = false;
|
||||
header_locked = true;
|
||||
try {
|
||||
lock_state_write(true);
|
||||
state_locked = true;
|
||||
// Check state
|
||||
if (!actualize_state(tdbb->tdbb_status_vector))
|
||||
ERR_punt();
|
||||
if (backup_state != nbak_state_merge || current_scn != adjusted_scn) {
|
||||
/* Handle the case when somebody finalized merge for us */
|
||||
unlock_state_write();
|
||||
return false;
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
return;
|
||||
}
|
||||
// Set state in database header
|
||||
tdbb->tdbb_flags |= TDBB_set_backup_state;
|
||||
backup_state = nbak_state_normal;
|
||||
WIN window;
|
||||
HDR header;
|
||||
window.win_page = HEADER_PAGE;
|
||||
window.win_flags = 0;
|
||||
header = (HDR) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||
CCH_MARK_MUST_WRITE(tdbb, &window);
|
||||
// Adjust state
|
||||
header->hdr_flags = (header->hdr_flags & ~hdr_backup_mask) | backup_state;
|
||||
TRACE1("Set state %d in header page", backup_state);
|
||||
header_locked = false;
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
CCH_flush(tdbb, FLUSH_ALL, 0); // This is to adjust header in main database file
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
@ -324,12 +375,15 @@ bool BackupManager::end_backup(bool recover) {
|
||||
unlock_state_write();
|
||||
TRACE("backup ended");
|
||||
} catch (const std::exception&) {
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
unlock_state_write();
|
||||
backup_state = nbak_state_unknown;
|
||||
tdbb->tdbb_flags &= ~TDBB_set_backup_state;
|
||||
if (state_locked)
|
||||
unlock_state_write();
|
||||
if (header_locked)
|
||||
CCH_RELEASE(tdbb, &window);
|
||||
throw;
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool BackupManager::actualize_alloc(ISC_STATUS* status) {
|
||||
@ -485,7 +539,7 @@ BackupManager::BackupManager(DBB _database, int ini_state) :
|
||||
state_lock->lck_ast = backup_state_ast;
|
||||
|
||||
alloc_lock = FB_NEW_RPT(*database->dbb_permanent, 0) lck();
|
||||
alloc_lock->lck_type = LCK_backup_merge;
|
||||
alloc_lock->lck_type = LCK_backup_alloc;
|
||||
alloc_lock->lck_owner_handle = LCK_get_owner_handle(tdbb, alloc_lock->lck_type);
|
||||
alloc_lock->lck_parent = database->dbb_lock;
|
||||
alloc_lock->lck_length = 0;
|
||||
@ -805,7 +859,7 @@ int BackupManager::alloc_table_ast(void *ast_object)
|
||||
|
||||
TRACE("alloc_table_ast");
|
||||
|
||||
if (new_dbb->backup_manager->ast_flags & NBAK_alloc_in_use || lock->lck_physical != LCK_SR)
|
||||
if (new_dbb->backup_manager->ast_flags & NBAK_alloc_in_use)
|
||||
new_dbb->backup_manager->ast_flags |= NBAK_alloc_blocking;
|
||||
else {
|
||||
new_dbb->backup_manager->ast_flags |= NBAK_alloc_dirty;
|
||||
|
@ -80,12 +80,12 @@ public:
|
||||
}
|
||||
|
||||
// Initialize and open difference file for writing
|
||||
bool begin_backup();
|
||||
void begin_backup();
|
||||
|
||||
// Merge difference file to main files (if needed) and unlink() difference
|
||||
// file then. If merge is already in progress method silently returns false and
|
||||
// does nothing (so it can be used for recovery on database startup).
|
||||
bool end_backup(bool recover);
|
||||
void end_backup(bool recover);
|
||||
|
||||
// Prevent allocation table from modification by other threads/processes
|
||||
// You may or may not call unlock function in case this functions fail
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
$Id: thd.h,v 1.12 2003-03-24 13:35:28 brodsom Exp $
|
||||
$Id: thd.h,v 1.13 2003-08-10 15:43:22 skidder Exp $
|
||||
*/
|
||||
|
||||
#ifndef _JRD_THD_H_
|
||||
@ -35,7 +35,6 @@ $Id: thd.h,v 1.12 2003-03-24 13:35:28 brodsom Exp $
|
||||
#ifdef SOLARIS
|
||||
#ifdef SOLARIS_MT
|
||||
#include <thread.h>
|
||||
#define MULTI_THREAD 1
|
||||
#define THD_MUTEX_STRUCT mutex_t
|
||||
#define THD_COND_STRUCT cond_t
|
||||
#define THD_RWLOCK_STRUCT rwlock_t
|
||||
@ -45,17 +44,14 @@ $Id: thd.h,v 1.12 2003-03-24 13:35:28 brodsom Exp $
|
||||
/* RITTER - changed HP10 to HPUX in the line below */
|
||||
#if (defined(HPUX) && defined(SUPERSERVER))
|
||||
#define POSIX_THREADS 1
|
||||
#define MULTI_THREAD 1
|
||||
#endif
|
||||
|
||||
#if (defined(LINUX) && defined(SUPERSERVER))
|
||||
#define POSIX_THREADS 1
|
||||
#define MULTI_THREAD 1
|
||||
#endif
|
||||
|
||||
#if (defined(FREEBSD) && defined(SUPERSERVER))
|
||||
#define POSIX_THREADS 1
|
||||
#define MULTI_THREAD 1
|
||||
#endif
|
||||
|
||||
/* The following ifdef was added to build thread safe gds shared
|
||||
@ -67,16 +63,13 @@ $Id: thd.h,v 1.12 2003-03-24 13:35:28 brodsom Exp $
|
||||
*/
|
||||
#if (defined(LINUX) && defined(SUPERCLIENT))
|
||||
#define POSIX_THREADS 1
|
||||
#define MULTI_THREAD 1
|
||||
#endif
|
||||
|
||||
#if (defined(DARWIN) && defined(SUPERSERVER))
|
||||
#define POSIX_THREADS 1
|
||||
#define MULTI_THREAD 1
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#define MULTI_THREAD 1
|
||||
/*
|
||||
#define POSIX_THREADS 1
|
||||
*/
|
||||
@ -85,7 +78,6 @@ $Id: thd.h,v 1.12 2003-03-24 13:35:28 brodsom Exp $
|
||||
#endif
|
||||
|
||||
#ifdef WIN_NT
|
||||
#define MULTI_THREAD 1
|
||||
#define THD_MUTEX_STRUCT struct IB_RTL_CRITICAL_SECTION
|
||||
|
||||
/* The following code fragment has been extracted from <winnt.h>.
|
||||
|
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
$Id: lock.cpp,v 1.60 2003-08-09 22:36:26 brodsom Exp $
|
||||
$Id: lock.cpp,v 1.61 2003-08-10 15:43:23 skidder Exp $
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
@ -1467,7 +1467,7 @@ static void acquire( PTR owner_offset)
|
||||
LOCK_post_manager = FALSE;
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLOCKING_SIGNALS
|
||||
#ifndef SUPERSERVER
|
||||
if (LOCK_owner) {
|
||||
LOCK_owner->own_ast_hung_flags &= ~OWN_hung; /* Can't be hung by OS if we got here */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user