mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:03:02 +01:00
1) Globally named per-database shmem regions.
2) Slightly reworked monitoring internals. 3) Encapsulated the event manager, many internal changes there. 4) Various cleanup, etc.
This commit is contained in:
parent
bb59a30d0f
commit
1b3927b026
@ -54,6 +54,28 @@ namespace Jrd
|
||||
#endif
|
||||
}
|
||||
|
||||
const Firebird::string& Database::getUniqueFileId() const
|
||||
{
|
||||
static Firebird::GlobalPtr<Firebird::string> file_id;
|
||||
|
||||
if (file_id->empty())
|
||||
{
|
||||
const PageSpace* const pageSpace = dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
|
||||
Firebird::UCharBuffer buffer;
|
||||
PIO_get_unique_file_id(pageSpace->file, buffer);
|
||||
|
||||
for (size_t i = 0; i < buffer.getCount(); i++)
|
||||
{
|
||||
TEXT hex[3];
|
||||
sprintf(hex, "%02x", (int) buffer[i]);
|
||||
file_id->append(hex);
|
||||
}
|
||||
}
|
||||
|
||||
return file_id;
|
||||
}
|
||||
|
||||
Database::~Database()
|
||||
{
|
||||
delete dbb_sys_trans;
|
||||
@ -66,9 +88,14 @@ namespace Jrd
|
||||
MemoryPool::deletePool(dbb_pools[i]);
|
||||
}
|
||||
|
||||
delete dbb_monitoring_data;
|
||||
|
||||
dbb_flags |= DBB_destroying;
|
||||
|
||||
Checkout dcoHolder(this);
|
||||
dbb_lock_mgr->release();
|
||||
// This line decrements the usage counter and may cause the destructor to be called.
|
||||
// It should happen with the dbb_sync unlocked.
|
||||
dbb_lock_mgr = NULL;
|
||||
}
|
||||
|
||||
void Database::deletePool(MemoryPool* pool)
|
||||
|
@ -57,19 +57,20 @@
|
||||
#include "../common/classes/PublicHandle.h"
|
||||
#include "../common/classes/semaphore.h"
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../jrd/DatabaseSnapshot.h"
|
||||
#include "../jrd/RandomGenerator.h"
|
||||
#include "../jrd/os/guid.h"
|
||||
#include "../jrd/sbm.h"
|
||||
#include "../jrd/flu.h"
|
||||
#include "../jrd/RuntimeStatistics.h"
|
||||
#include "../lock/lock_proto.h"
|
||||
#include "../jrd/os/thd_priority.h"
|
||||
#include "../jrd/event_proto.h"
|
||||
#include "../lock/lock_proto.h"
|
||||
|
||||
class CharSetContainer;
|
||||
|
||||
namespace Jrd
|
||||
{
|
||||
|
||||
class Trigger;
|
||||
template <typename T> class vec;
|
||||
class jrd_prc;
|
||||
@ -326,10 +327,10 @@ public:
|
||||
return TypedHandle<type_dbb>::checkHandle();
|
||||
}
|
||||
|
||||
mutable Sync* dbb_sync; // Database sync primitive
|
||||
Firebird::Reference dbb_sync_ref; // Database reference to dbb_sync
|
||||
mutable Firebird::RefPtr<Sync> dbb_sync; // Database sync primitive
|
||||
|
||||
LockManager* dbb_lock_mgr;
|
||||
Firebird::RefPtr<LockManager> dbb_lock_mgr;
|
||||
Firebird::RefPtr<EventManager> dbb_event_mgr;
|
||||
|
||||
Database* dbb_next; // Next database block in system
|
||||
Attachment* dbb_attachments; // Active attachments
|
||||
@ -342,10 +343,8 @@ public:
|
||||
SLONG dbb_sh_counter_curr; // current value of shared counter lock
|
||||
SLONG dbb_sh_counter_max; // maximum cached value of shared counter lock
|
||||
jrd_tra* dbb_sys_trans; // system transaction
|
||||
// jrd_file* dbb_file; // files for I/O operations
|
||||
Shadow* dbb_shadow; // shadow control block
|
||||
Lock* dbb_shadow_lock; // lock for synchronizing addition of shadows
|
||||
//SLONG dbb_shadow_sync_count; // to synchronize changes to shadows
|
||||
Lock* dbb_retaining_lock; // lock for preserving commit retaining snapshot
|
||||
Lock* dbb_monitor_lock; // lock for monitoring purposes
|
||||
PageManager dbb_page_manager;
|
||||
@ -354,6 +353,8 @@ public:
|
||||
BlobFilter* dbb_blob_filters; // known blob filters
|
||||
trig_vec* dbb_triggers[DB_TRIGGER_MAX];
|
||||
|
||||
DatabaseSnapshot::SharedData* dbb_monitoring_data; // monitoring data
|
||||
|
||||
DatabaseModules dbb_modules; // external function/filter modules
|
||||
|
||||
Firebird::Mutex dbb_meta_mutex; // Mutex to protect metadata changes while dbb_sync is unlocked
|
||||
@ -447,6 +448,9 @@ public:
|
||||
// returns true if primary file is located on raw device
|
||||
bool onRawDevice() const;
|
||||
|
||||
// returns an unique ID string for a database file
|
||||
const Firebird::string& getUniqueFileId() const;
|
||||
|
||||
MemoryPool* createPool()
|
||||
{
|
||||
MemoryPool* const pool = MemoryPool::createPool(dbb_permanent, dbb_memory_stats);
|
||||
@ -459,7 +463,6 @@ public:
|
||||
private:
|
||||
explicit Database(MemoryPool* p)
|
||||
: dbb_sync(FB_NEW(*getDefaultMemoryPool()) Sync),
|
||||
dbb_sync_ref(*dbb_sync),
|
||||
dbb_page_manager(*p),
|
||||
dbb_modules(*p),
|
||||
dbb_filename(*p),
|
||||
|
@ -72,35 +72,40 @@ const UCHAR TAG_RECORD = MAX_UCHAR;
|
||||
|
||||
// SharedMemory class
|
||||
|
||||
const ULONG DatabaseSnapshot::SharedMemory::VERSION = 2;
|
||||
const ULONG DatabaseSnapshot::SharedMemory::DEFAULT_SIZE = 1048576;
|
||||
|
||||
|
||||
DatabaseSnapshot::SharedMemory::SharedMemory()
|
||||
DatabaseSnapshot::SharedData::SharedData(const Database* dbb)
|
||||
: process_id(getpid()), local_id(dbb->dbb_monitoring_id)
|
||||
{
|
||||
TEXT filename[MAXPATHLEN];
|
||||
gds__prefix_lock(filename, MONITOR_FILE);
|
||||
Firebird::string name;
|
||||
name.printf(MONITOR_FILE, dbb->getUniqueFileId().c_str());
|
||||
|
||||
ISC_STATUS_ARRAY statusVector;
|
||||
base = (Header*) ISC_map_file(statusVector, filename, init, this, DEFAULT_SIZE, &handle);
|
||||
base = (Header*) ISC_map_file(statusVector, name.c_str(), init, this, DEFAULT_SIZE, &handle);
|
||||
if (!base)
|
||||
{
|
||||
iscLogStatus("Cannot initialize the shared memory region", statusVector);
|
||||
status_exception::raise(statusVector);
|
||||
}
|
||||
|
||||
fb_assert(base->version == VERSION);
|
||||
fb_assert(base->version == MONITOR_VERSION);
|
||||
}
|
||||
|
||||
|
||||
DatabaseSnapshot::SharedMemory::~SharedMemory()
|
||||
DatabaseSnapshot::SharedData::~SharedData()
|
||||
{
|
||||
cleanup();
|
||||
|
||||
#ifdef WIN_NT
|
||||
ISC_mutex_fini(&mutex);
|
||||
#else
|
||||
ISC_mutex_fini(&base->mutex);
|
||||
#endif
|
||||
|
||||
ISC_STATUS_ARRAY statusVector;
|
||||
ISC_unmap_file(statusVector, &handle);
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::acquire()
|
||||
void DatabaseSnapshot::SharedData::acquire()
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
checkMutex("lock", ISC_mutex_lock(&mutex));
|
||||
@ -123,7 +128,7 @@ void DatabaseSnapshot::SharedMemory::acquire()
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::release()
|
||||
void DatabaseSnapshot::SharedData::release()
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
checkMutex("unlock", ISC_mutex_unlock(&mutex));
|
||||
@ -133,13 +138,8 @@ void DatabaseSnapshot::SharedMemory::release()
|
||||
}
|
||||
|
||||
|
||||
UCHAR* DatabaseSnapshot::SharedMemory::readData(thread_db* tdbb, MemoryPool& pool, ULONG& resultSize)
|
||||
UCHAR* DatabaseSnapshot::SharedData::read(MemoryPool& pool, ULONG& resultSize)
|
||||
{
|
||||
fb_assert(tdbb);
|
||||
|
||||
const Database* const dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
|
||||
DumpGuard guard(this);
|
||||
|
||||
ULONG self_dbb_offset = 0;
|
||||
@ -157,7 +157,7 @@ UCHAR* DatabaseSnapshot::SharedMemory::readData(thread_db* tdbb, MemoryPool& poo
|
||||
const Element* const element = (Element*) ptr;
|
||||
const ULONG length = sizeof(Element) + element->length;
|
||||
|
||||
if (element->processId == getpid() && element->localId == dbb->dbb_monitoring_id)
|
||||
if (element->processId == process_id && element->localId == local_id)
|
||||
{
|
||||
self_dbb_offset = offset;
|
||||
}
|
||||
@ -206,17 +206,12 @@ UCHAR* DatabaseSnapshot::SharedMemory::readData(thread_db* tdbb, MemoryPool& poo
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::writeData(thread_db* tdbb, ULONG length, const UCHAR* buffer)
|
||||
void DatabaseSnapshot::SharedData::write(ULONG length, const UCHAR* buffer)
|
||||
{
|
||||
fb_assert(tdbb);
|
||||
|
||||
const Database* const dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
|
||||
DumpGuard guard(this);
|
||||
|
||||
// Remove old copies of our element, if any
|
||||
doCleanup(dbb);
|
||||
cleanup();
|
||||
|
||||
// Do we need to extend the allocated memory?
|
||||
while (base->used + sizeof(Element) + length > base->allocated)
|
||||
@ -227,37 +222,24 @@ void DatabaseSnapshot::SharedMemory::writeData(thread_db* tdbb, ULONG length, co
|
||||
// Put an up-to-date element at the tail
|
||||
UCHAR* const ptr = (UCHAR*) base + base->used;
|
||||
Element* const element = (Element*) ptr;
|
||||
element->processId = getpid();
|
||||
element->localId = dbb->dbb_monitoring_id;
|
||||
element->processId = process_id;
|
||||
element->localId = local_id;
|
||||
element->length = length;
|
||||
memcpy(ptr + sizeof(Element), buffer, length);
|
||||
base->used += sizeof(Element) + length;
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::cleanup(thread_db* tdbb)
|
||||
void DatabaseSnapshot::SharedData::cleanup()
|
||||
{
|
||||
fb_assert(tdbb);
|
||||
|
||||
const Database* const dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
|
||||
DumpGuard guard(this);
|
||||
|
||||
// Remove information about our dbb
|
||||
doCleanup(dbb);
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::doCleanup(const Database* const dbb)
|
||||
{
|
||||
for (ULONG offset = sizeof(Header); offset < base->used;)
|
||||
{
|
||||
UCHAR* const ptr = (UCHAR*) base + offset;
|
||||
const Element* const element = (Element*) ptr;
|
||||
const ULONG length = sizeof(Element) + element->length;
|
||||
|
||||
if (element->processId == getpid() && element->localId == dbb->dbb_monitoring_id)
|
||||
if (element->processId == process_id && element->localId == local_id)
|
||||
{
|
||||
fb_assert(base->used >= offset + length);
|
||||
memmove(ptr, ptr + length, base->used - offset - length);
|
||||
@ -271,7 +253,7 @@ void DatabaseSnapshot::SharedMemory::doCleanup(const Database* const dbb)
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::extend()
|
||||
void DatabaseSnapshot::SharedData::extend()
|
||||
{
|
||||
const ULONG newSize = handle.sh_mem_length_mapped + DEFAULT_SIZE;
|
||||
|
||||
@ -289,7 +271,7 @@ void DatabaseSnapshot::SharedMemory::extend()
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::checkMutex(const TEXT* string, int state)
|
||||
void DatabaseSnapshot::SharedData::checkMutex(const TEXT* string, int state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
@ -304,15 +286,13 @@ void DatabaseSnapshot::SharedMemory::checkMutex(const TEXT* string, int state)
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool initialize)
|
||||
void DatabaseSnapshot::SharedData::init(void* arg, SH_MEM_T* shmemData, bool initialize)
|
||||
{
|
||||
SharedMemory* const shmem = (SharedMemory*) arg;
|
||||
SharedData* const shmem = (SharedData*) arg;
|
||||
fb_assert(shmem);
|
||||
|
||||
#ifdef WIN_NT
|
||||
char buffer[MAXPATHLEN];
|
||||
gds__prefix_lock(buffer, MONITOR_FILE);
|
||||
checkMutex("init", ISC_mutex_init(&shmem->mutex, buffer));
|
||||
checkMutex("init", ISC_mutex_init(&shmem->mutex, shmemData->sh_mem_name));
|
||||
#endif
|
||||
|
||||
if (!initialize)
|
||||
@ -320,7 +300,7 @@ void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool i
|
||||
|
||||
// Initialize the shared data header
|
||||
Header* const header = (Header*) shmemData->sh_mem_address;
|
||||
header->version = VERSION;
|
||||
header->version = MONITOR_VERSION;
|
||||
header->used = sizeof(Header);
|
||||
header->allocated = shmemData->sh_mem_length_mapped;
|
||||
|
||||
@ -332,9 +312,6 @@ void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool i
|
||||
|
||||
// DatabaseSnapshot class
|
||||
|
||||
DatabaseSnapshot::SharedMemory* DatabaseSnapshot::dump = NULL;
|
||||
InitMutex<DatabaseSnapshot> DatabaseSnapshot::startup;
|
||||
|
||||
|
||||
DatabaseSnapshot* DatabaseSnapshot::create(thread_db* tdbb)
|
||||
{
|
||||
@ -355,17 +332,6 @@ DatabaseSnapshot* DatabaseSnapshot::create(thread_db* tdbb)
|
||||
}
|
||||
|
||||
|
||||
void DatabaseSnapshot::cleanup(thread_db* tdbb)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
if (dump)
|
||||
{
|
||||
dump->cleanup(tdbb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int DatabaseSnapshot::blockingAst(void* ast_object)
|
||||
{
|
||||
Database* dbb = static_cast<Database*>(ast_object);
|
||||
@ -458,9 +424,9 @@ DatabaseSnapshot::DatabaseSnapshot(thread_db* tdbb, MemoryPool& pool)
|
||||
dbb->dbb_ast_flags |= DBB_monitor_off;
|
||||
|
||||
// Read the shared memory
|
||||
fb_assert(dump);
|
||||
fb_assert(dbb->dbb_monitoring_data);
|
||||
ULONG dataSize = 0;
|
||||
AutoPtr<UCHAR, ArrayDelete<UCHAR> > data(dump->readData(tdbb, pool, dataSize));
|
||||
AutoPtr<UCHAR, ArrayDelete<UCHAR> > data(dbb->dbb_monitoring_data->read(pool, dataSize));
|
||||
fb_assert(dataSize);
|
||||
|
||||
ClumpletReader reader(ClumpletReader::WideUnTagged, data, dataSize);
|
||||
@ -899,10 +865,12 @@ void DatabaseSnapshot::dumpData(thread_db* tdbb)
|
||||
}
|
||||
}
|
||||
|
||||
startup.init();
|
||||
if (!dbb->dbb_monitoring_data)
|
||||
{
|
||||
dbb->dbb_monitoring_data = FB_NEW(*dbb->dbb_permanent) SharedData(dbb);
|
||||
}
|
||||
|
||||
fb_assert(dump);
|
||||
dump->writeData(tdbb, writer.getBufferLength(), writer.getBuffer());
|
||||
dbb->dbb_monitoring_data->write(writer.getBufferLength(), writer.getBuffer());
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,11 @@
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
// forward declarations
|
||||
class jrd_rel;
|
||||
class RecordBuffer;
|
||||
class RuntimeStatistics;
|
||||
|
||||
class DatabaseSnapshot
|
||||
{
|
||||
struct RelationData
|
||||
@ -38,10 +43,18 @@ class DatabaseSnapshot
|
||||
RecordBuffer* data;
|
||||
};
|
||||
|
||||
class SharedMemory
|
||||
struct Element
|
||||
{
|
||||
static const ULONG VERSION;
|
||||
static const ULONG DEFAULT_SIZE;
|
||||
SLONG processId;
|
||||
SLONG localId;
|
||||
ULONG length;
|
||||
};
|
||||
|
||||
public:
|
||||
class SharedData
|
||||
{
|
||||
static const ULONG MONITOR_VERSION = 2;
|
||||
static const ULONG DEFAULT_SIZE = 1048576;
|
||||
|
||||
struct Header
|
||||
{
|
||||
@ -56,42 +69,40 @@ class DatabaseSnapshot
|
||||
class DumpGuard
|
||||
{
|
||||
public:
|
||||
explicit DumpGuard(SharedMemory* ptr)
|
||||
: dump(ptr)
|
||||
explicit DumpGuard(SharedData* ptr)
|
||||
: data(ptr)
|
||||
{
|
||||
dump->acquire();
|
||||
data->acquire();
|
||||
}
|
||||
|
||||
~DumpGuard()
|
||||
{
|
||||
dump->release();
|
||||
data->release();
|
||||
}
|
||||
|
||||
private:
|
||||
DumpGuard(const DumpGuard&);
|
||||
DumpGuard& operator=(const DumpGuard&);
|
||||
|
||||
SharedMemory* dump;
|
||||
SharedData* const data;
|
||||
};
|
||||
|
||||
public:
|
||||
SharedMemory();
|
||||
~SharedMemory();
|
||||
explicit SharedData(const Database*);
|
||||
~SharedData();
|
||||
|
||||
void acquire();
|
||||
void release();
|
||||
|
||||
UCHAR* readData(thread_db*, MemoryPool&, ULONG&);
|
||||
void writeData(thread_db*, ULONG, const UCHAR*);
|
||||
|
||||
void cleanup(thread_db*);
|
||||
UCHAR* read(MemoryPool&, ULONG&);
|
||||
void write(ULONG, const UCHAR*);
|
||||
|
||||
private:
|
||||
// copying is prohibited
|
||||
SharedMemory(const SharedMemory&);
|
||||
SharedMemory& operator =(const SharedMemory&);
|
||||
SharedData(const SharedData&);
|
||||
SharedData& operator =(const SharedData&);
|
||||
|
||||
void doCleanup(const Database* const dbb);
|
||||
void cleanup();
|
||||
void extend();
|
||||
|
||||
static void checkMutex(const TEXT*, int);
|
||||
@ -102,29 +113,18 @@ class DatabaseSnapshot
|
||||
struct mtx mutex;
|
||||
#endif
|
||||
Header* base;
|
||||
|
||||
const SLONG process_id;
|
||||
const SLONG local_id;
|
||||
};
|
||||
|
||||
struct Element
|
||||
{
|
||||
SLONG processId;
|
||||
SLONG localId;
|
||||
ULONG length;
|
||||
};
|
||||
|
||||
public:
|
||||
~DatabaseSnapshot();
|
||||
|
||||
RecordBuffer* getData(const jrd_rel*) const;
|
||||
|
||||
static DatabaseSnapshot* create(thread_db*);
|
||||
static void cleanup(thread_db*);
|
||||
static int blockingAst(void*);
|
||||
|
||||
static void init()
|
||||
{
|
||||
dump = FB_NEW(*getDefaultMemoryPool()) SharedMemory;
|
||||
}
|
||||
|
||||
protected:
|
||||
DatabaseSnapshot(thread_db*, MemoryPool&);
|
||||
|
||||
@ -147,9 +147,6 @@ private:
|
||||
static void putContextVars(Firebird::StringMap&, Firebird::ClumpletWriter&, int, bool);
|
||||
static void putMemoryUsage(const Firebird::MemoryStats&, Firebird::ClumpletWriter&, int, int);
|
||||
|
||||
static SharedMemory* dump;
|
||||
static Firebird::InitMutex<DatabaseSnapshot> startup;
|
||||
|
||||
Firebird::Array<RelationData> snapshot;
|
||||
Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<SINT64, SLONG> > > idMap;
|
||||
int idCounter;
|
||||
|
@ -634,8 +634,12 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
|
||||
switch (work->dfw_type)
|
||||
{
|
||||
case dfw_post_event:
|
||||
EVENT_post(lock->lck_length, (const TEXT*) &lock->lck_key,
|
||||
work->dfw_name.length(), work->dfw_name.c_str(), work->dfw_count);
|
||||
EventManager::init(dbb);
|
||||
|
||||
dbb->dbb_event_mgr->postEvent(lock->lck_length, (const TEXT*) &lock->lck_key,
|
||||
work->dfw_name.length(), work->dfw_name.c_str(),
|
||||
work->dfw_count);
|
||||
|
||||
*ptr = work->dfw_next;
|
||||
delete work;
|
||||
pending_events = true;
|
||||
@ -651,7 +655,9 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
|
||||
}
|
||||
|
||||
if (pending_events)
|
||||
EVENT_deliver();
|
||||
{
|
||||
dbb->dbb_event_mgr->deliverEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
1142
src/jrd/event.cpp
1142
src/jrd/event.cpp
File diff suppressed because it is too large
Load Diff
@ -20,11 +20,7 @@
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* 23-Feb-2002 Dmitry Yemanov - Events wildcarding
|
||||
*
|
||||
*
|
||||
* 2002-02-23 Sean Leyne - Code Cleanup, removed old Win3.1 port (Windows_Only)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef JRD_EVENT_H
|
||||
@ -38,14 +34,9 @@
|
||||
|
||||
const int EVENT_VERSION = 4;
|
||||
|
||||
const int EVENT_HASH_SIZE = 7;
|
||||
|
||||
const int EVENT_DEFAULT_SIZE = 32768;
|
||||
const int EVENT_EXTEND_SIZE = 32768;
|
||||
|
||||
struct evh
|
||||
{
|
||||
SLONG evh_length; // Current length of global section
|
||||
ULONG evh_length; // Current length of global section
|
||||
UCHAR evh_version; // Version number of global section
|
||||
srq evh_events; // Known events
|
||||
srq evh_processes; // Known processes
|
||||
@ -53,11 +44,8 @@ struct evh
|
||||
SRQ_PTR evh_current_process; // Current process, if any
|
||||
struct mtx evh_mutex; // Mutex controlling access
|
||||
SLONG evh_request_id; // Next request id
|
||||
SRQ_PTR evh_hash_table[EVENT_HASH_SIZE];
|
||||
};
|
||||
|
||||
typedef evh *EVH;
|
||||
|
||||
// Common block header
|
||||
|
||||
const int type_hdr = 1; // Event header
|
||||
@ -71,7 +59,7 @@ const int type_max = 8;
|
||||
|
||||
struct event_hdr // CVC: previous clash with ods.h's hdr
|
||||
{
|
||||
SLONG hdr_length; // Length of block
|
||||
ULONG hdr_length; // Length of block
|
||||
UCHAR hdr_type; // Type of block
|
||||
};
|
||||
|
||||
@ -82,7 +70,6 @@ struct frb
|
||||
event_hdr frb_header;
|
||||
SLONG frb_next; // Next block
|
||||
};
|
||||
typedef frb *FRB;
|
||||
|
||||
// Process blocks
|
||||
|
||||
@ -95,13 +82,13 @@ struct prb
|
||||
event_t prb_event; // Event on which to wait
|
||||
USHORT prb_flags;
|
||||
};
|
||||
typedef prb *PRB;
|
||||
|
||||
const int PRB_wakeup = 1; // Schedule a wakeup for process
|
||||
const int PRB_pending = 2; // Wakeup has been requested, and is dangling
|
||||
#if (defined HAVE_MMAP || defined WIN_NT)
|
||||
const int PRB_remap = 4; // need to remap shared memory
|
||||
const int PRB_remap_over= 8; // remap is over
|
||||
const int PRB_exiting = 16; // Process is exiting
|
||||
#endif
|
||||
|
||||
// Session block
|
||||
|
||||
@ -113,7 +100,6 @@ struct ses
|
||||
SRQ_PTR ses_interests; // Historical interests
|
||||
USHORT ses_flags;
|
||||
};
|
||||
typedef ses *SES;
|
||||
|
||||
const int SES_delivering = 1; // Watcher thread is delivering an event
|
||||
const int SES_purge = 2; // delete session after delivering an event
|
||||
@ -130,7 +116,6 @@ struct evnt
|
||||
USHORT evnt_length; // Length of event name
|
||||
TEXT evnt_name[1]; // Event name
|
||||
};
|
||||
typedef evnt *EVNT;
|
||||
|
||||
// Request block
|
||||
|
||||
@ -145,7 +130,6 @@ struct evt_req
|
||||
void *req_ast_arg; // Argument for ast
|
||||
SLONG req_request_id; // Request id, dummy
|
||||
};
|
||||
typedef evt_req *EVT_REQ;
|
||||
|
||||
// Request interest block
|
||||
|
||||
@ -158,7 +142,6 @@ struct req_int
|
||||
SRQ_PTR rint_next; // Next interest of request
|
||||
SLONG rint_count; // Threshold count
|
||||
};
|
||||
typedef req_int *RINT;
|
||||
|
||||
const int EPB_version1 = 1;
|
||||
|
||||
|
@ -19,21 +19,102 @@
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* 23-Feb-2002 Dmitry Yemanov - Events wildcarding
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef JRD_EVENT_PROTO_H
|
||||
#define JRD_EVENT_PROTO_H
|
||||
|
||||
void EVENT_cancel(SLONG);
|
||||
SLONG EVENT_create_session();
|
||||
void EVENT_delete_session(SLONG);
|
||||
void EVENT_deliver();
|
||||
void EVENT_post(USHORT, const TEXT*, USHORT, const TEXT*, USHORT);
|
||||
SLONG EVENT_que(SLONG, USHORT, const TEXT*, USHORT, const UCHAR*,
|
||||
#include "../common/classes/init.h"
|
||||
#include "../common/classes/semaphore.h"
|
||||
#include "../common/classes/GenericMap.h"
|
||||
#include "../common/classes/RefCounted.h"
|
||||
#include "../jrd/ThreadData.h"
|
||||
#include "../jrd/event.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class Database;
|
||||
|
||||
class EventManager: public Firebird::RefCounted, public Firebird::GlobalStorage
|
||||
{
|
||||
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::string, EventManager*> > > DbEventMgrMap;
|
||||
|
||||
static Firebird::GlobalPtr<DbEventMgrMap> g_emMap;
|
||||
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
|
||||
|
||||
const int PID;
|
||||
|
||||
public:
|
||||
static void init(Database*);
|
||||
|
||||
explicit EventManager(const Firebird::string&);
|
||||
~EventManager();
|
||||
|
||||
SLONG createSession();
|
||||
void deleteSession(SLONG);
|
||||
|
||||
SLONG queEvents(SLONG, USHORT, const TEXT*, USHORT, const UCHAR*,
|
||||
FPTR_EVENT_CALLBACK, void*);
|
||||
void cancelEvents(SLONG);
|
||||
void postEvent(USHORT, const TEXT*, USHORT, const TEXT*, USHORT);
|
||||
void deliverEvents();
|
||||
|
||||
private:
|
||||
evh* acquire_shmem();
|
||||
frb* alloc_global(UCHAR type, ULONG length, bool recurse);
|
||||
void create_process();
|
||||
void delete_event(evnt*);
|
||||
void delete_process(SLONG);
|
||||
void delete_request(evt_req*);
|
||||
void delete_session(SLONG);
|
||||
void deliver();
|
||||
void deliver_request(evt_req*);
|
||||
void exit_handler(void *);
|
||||
evnt* find_event(USHORT, const TEXT*, evnt*);
|
||||
void free_global(frb*);
|
||||
req_int* historical_interest(ses*, SLONG);
|
||||
void init_shmem(SH_MEM, bool);
|
||||
void insert_tail(srq*, srq*);
|
||||
evnt* make_event(USHORT, const TEXT*, SLONG);
|
||||
void post_process(prb*);
|
||||
void probe_processes();
|
||||
void release_shmem();
|
||||
void remove_que(srq*);
|
||||
bool request_completed(evt_req*);
|
||||
void watcher_thread();
|
||||
|
||||
static THREAD_ENTRY_DECLARE watcher_thread(THREAD_ENTRY_PARAM arg)
|
||||
{
|
||||
EventManager* const eventMgr = static_cast<EventManager*>(arg);
|
||||
eventMgr->watcher_thread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_shmem(void* arg, SH_MEM shmem, bool init)
|
||||
{
|
||||
EventManager* const eventMgr = static_cast<EventManager*>(arg);
|
||||
eventMgr->init_shmem(shmem, init);
|
||||
}
|
||||
|
||||
static void mutex_bugcheck(const TEXT*, int);
|
||||
static void punt(const TEXT*);
|
||||
|
||||
evh* m_header;
|
||||
prb* m_process;
|
||||
SLONG m_processOffset;
|
||||
SH_MEM_T m_shmemData;
|
||||
|
||||
Firebird::string m_dbId;
|
||||
|
||||
Firebird::Semaphore m_startupSemaphore;
|
||||
Firebird::Semaphore m_cleanupSemaphore;
|
||||
|
||||
#ifdef WIN_NT
|
||||
struct mtx m_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // JRD_EVENT_PROTO_H
|
||||
|
||||
|
@ -32,27 +32,13 @@
|
||||
#ifndef JRD_FILE_PARAMS_H
|
||||
#define JRD_FILE_PARAMS_H
|
||||
|
||||
#ifdef NOHOSTNAME
|
||||
static const char* EVENT_FILE = "isc_event1";
|
||||
static const char* LOCK_FILE = "isc_lock1.gbl";
|
||||
static const char* INIT_FILE = "isc_init1";
|
||||
static const char* GUARD_FILE = "isc_guard1";
|
||||
static const char* MONITOR_FILE = "isc_monitor1";
|
||||
static const char* SEM_FILE = "isc_sem1";
|
||||
#elif defined(WIN_NT)
|
||||
static const char* EVENT_FILE = "%s.evn";
|
||||
static const char* LOCK_FILE = "%s.lck";
|
||||
static const char* INIT_FILE = "%s.int";
|
||||
static const char* GUARD_FILE = "%s.grd";
|
||||
static const char* MONITOR_FILE = "%s.mon";
|
||||
static const char* SEM_FILE = "%s.sem";
|
||||
#else
|
||||
static const char* EVENT_FILE = "isc_event1.%s";
|
||||
static const char* LOCK_FILE = "isc_lock1.%s";
|
||||
static const char* INIT_FILE = "isc_init1.%s";
|
||||
static const char* GUARD_FILE = "isc_guard1.%s";
|
||||
static const char* MONITOR_FILE = "isc_monitor1.%s";
|
||||
static const char* SEM_FILE = "isc_sem1.%s";
|
||||
static const char* EVENT_FILE = "fb_event_%s";
|
||||
static const char* LOCK_FILE = "fb_lock_%s";
|
||||
static const char* MONITOR_FILE = "fb_monitor_%s";
|
||||
|
||||
#ifdef UNIX
|
||||
static const char* INIT_FILE = "fb_init";
|
||||
static const char* SEM_FILE = "fb_sem";
|
||||
#endif
|
||||
|
||||
// CVC: Do we really need this information here after using autoconf?
|
||||
|
@ -3648,7 +3648,7 @@ public:
|
||||
Firebird::PathName lockPrefix;
|
||||
if (!fb_utils::readenv(FB_LOCK_ENV, lockPrefix))
|
||||
{
|
||||
lockPrefix = prefix;
|
||||
lockPrefix = tempDir;
|
||||
}
|
||||
lockPrefix.copyTo(fb_prefix_lock_val, sizeof(fb_prefix_lock_val));
|
||||
fb_prefix_lock = fb_prefix_lock_val;
|
||||
|
@ -880,20 +880,6 @@ bool INTL_defined_type(thread_db* tdbb, USHORT t_type)
|
||||
}
|
||||
|
||||
|
||||
void INTL_init(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* I N T L _ i n i t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
*
|
||||
**************************************/
|
||||
}
|
||||
|
||||
|
||||
USHORT INTL_key_length(thread_db* tdbb, USHORT idxType, USHORT iLength)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -43,7 +43,6 @@ int INTL_convert_string(dsc*, const dsc*, ErrorFunction);
|
||||
int INTL_data(const dsc*);
|
||||
int INTL_data_or_binary(const dsc*);
|
||||
bool INTL_defined_type(Jrd::thread_db*, USHORT);
|
||||
void INTL_init(Jrd::thread_db*);
|
||||
USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT);
|
||||
Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1);
|
||||
Jrd::Collation* INTL_texttype_lookup(Jrd::thread_db* tdbb, USHORT parm1);
|
||||
|
@ -153,7 +153,7 @@ struct sh_mem
|
||||
void* sh_mem_object;
|
||||
void* sh_mem_interest;
|
||||
void* sh_mem_hdr_object;
|
||||
SLONG* sh_mem_hdr_address;
|
||||
ULONG* sh_mem_hdr_address;
|
||||
TEXT sh_mem_name[MAXPATHLEN];
|
||||
};
|
||||
typedef sh_mem SH_MEM_T;
|
||||
|
@ -45,7 +45,7 @@ void* ISC_make_signal(bool, bool, int, int);
|
||||
|
||||
typedef void (*FPTR_INIT_GLOBAL_REGION)(void*, struct sh_mem*, bool);
|
||||
UCHAR* ISC_map_file(ISC_STATUS*, const TEXT*, FPTR_INIT_GLOBAL_REGION,
|
||||
void*, SLONG, struct sh_mem*);
|
||||
void*, ULONG, struct sh_mem*);
|
||||
#if defined(WIN_NT)
|
||||
int ISC_mutex_init(struct mtx*, const TEXT*);
|
||||
#else
|
||||
@ -58,8 +58,8 @@ int ISC_mutex_unlock(struct mtx *);
|
||||
void ISC_mutex_fini(struct mtx *);
|
||||
|
||||
#if defined HAVE_MMAP || defined WIN_NT
|
||||
UCHAR* ISC_map_object(ISC_STATUS *, SH_MEM, SLONG, SLONG);
|
||||
void ISC_unmap_object(ISC_STATUS *, SH_MEM, UCHAR **, SLONG);
|
||||
UCHAR* ISC_map_object(ISC_STATUS *, SH_MEM, ULONG, ULONG);
|
||||
void ISC_unmap_object(ISC_STATUS *, SH_MEM, UCHAR **, ULONG);
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
@ -72,7 +72,7 @@ void ISC_sync_signals_reset();
|
||||
ULONG ISC_exception_post(ULONG, const TEXT*);
|
||||
#endif
|
||||
|
||||
UCHAR* ISC_remap_file(ISC_STATUS *, struct sh_mem *, SLONG, bool);
|
||||
UCHAR* ISC_remap_file(ISC_STATUS *, struct sh_mem *, ULONG, bool);
|
||||
void ISC_reset_timer(FPTR_VOID_PTR, void *, SLONG *, void **);
|
||||
void ISC_set_timer(SLONG, FPTR_VOID_PTR, void *, SLONG *, void **);
|
||||
void ISC_unmap_file(ISC_STATUS *, struct sh_mem *);
|
||||
|
@ -131,7 +131,7 @@ union semun
|
||||
ushort *array;
|
||||
};
|
||||
#endif
|
||||
#endif /* UNIX */
|
||||
#endif // UNIX
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
@ -1889,7 +1889,9 @@ void *ISC_make_signal(bool create_flag, bool manual_reset, int process_idL, int
|
||||
UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
const TEXT* filename,
|
||||
FPTR_INIT_GLOBAL_REGION init_routine,
|
||||
void* init_arg, SLONG length, SH_MEM shmem_data)
|
||||
void* init_arg,
|
||||
ULONG length,
|
||||
SH_MEM shmem_data)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1903,25 +1905,20 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
* routine (if given) or punt (leaving the file unmapped).
|
||||
*
|
||||
**************************************/
|
||||
TEXT expanded_filename[MAXPATHLEN], hostname[64];
|
||||
sprintf(expanded_filename, filename, ISC_get_host(hostname, sizeof(hostname)));
|
||||
|
||||
TEXT expanded_filename[MAXPATHLEN];
|
||||
gds__prefix_lock(expanded_filename, filename);
|
||||
|
||||
/* make the complete filename for the init file this file is to be used as a
|
||||
master lock to eliminate possible race conditions with just a single file
|
||||
locking. The race condition is caused as the conversion of a EXCLUSIVE
|
||||
lock to a SHARED lock is not atomic*/
|
||||
|
||||
TEXT tmp[MAXPATHLEN];
|
||||
gds__prefix_lock(tmp, INIT_FILE);
|
||||
string init_filename; /* to hold the complete filename of the init file. */
|
||||
init_filename.printf(tmp, hostname); /* already have the hostname! */
|
||||
TEXT init_filename[MAXPATHLEN];
|
||||
gds__prefix_lock(init_filename, INIT_FILE);
|
||||
|
||||
const int oldmask = umask(0);
|
||||
bool trunc_flag = true;
|
||||
if (length < 0) {
|
||||
length = -length;
|
||||
trunc_flag = false;
|
||||
}
|
||||
const bool trunc_flag = (length != 0);
|
||||
|
||||
/* open the init lock file */
|
||||
MutexLockGuard guard(openFdInit);
|
||||
@ -1931,7 +1928,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
#else
|
||||
int
|
||||
#endif
|
||||
fd_init = open(init_filename.c_str(), O_RDWR | O_CREAT, 0666);
|
||||
fd_init = open(init_filename, O_RDWR | O_CREAT, 0666);
|
||||
if (fd_init == -1) {
|
||||
error(status_vector, "open", errno);
|
||||
return NULL;
|
||||
@ -1950,10 +1947,9 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
#ifdef USE_SYS5SEMAPHORE
|
||||
if (fdSem < 0)
|
||||
{
|
||||
string semFileName;
|
||||
gds__prefix_lock(tmp, SEM_FILE);
|
||||
semFileName.printf(tmp, hostname);
|
||||
int f = open(semFileName.c_str(), O_RDWR | O_CREAT, 0666);
|
||||
TEXT sem_filename[MAXPATHLEN];
|
||||
gds__prefix_lock(sem_filename, SEM_FILE);
|
||||
int f = open(sem_filename, O_RDWR | O_CREAT, 0666);
|
||||
if (f == -1) {
|
||||
error(status_vector, "open", errno);
|
||||
return NULL;
|
||||
@ -2098,7 +2094,9 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
const TEXT* filename,
|
||||
FPTR_INIT_GLOBAL_REGION init_routine,
|
||||
void* init_arg, SLONG length, SH_MEM shmem_data)
|
||||
void* init_arg,
|
||||
ULONG length,
|
||||
SH_MEM shmem_data)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2112,18 +2110,12 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
* routine (if given) or punt (leaving the file unmapped).
|
||||
*
|
||||
**************************************/
|
||||
//SSHORT count;
|
||||
TEXT expanded_filename[512];
|
||||
#ifdef NOHOSTNAME
|
||||
strcpy(expanded_filename, filename);
|
||||
#else
|
||||
TEXT hostname[64];
|
||||
sprintf(expanded_filename, filename, ISC_get_host(hostname, sizeof(hostname)));
|
||||
#endif
|
||||
|
||||
TEXT expanded_filename[MAXPATHLEN];
|
||||
gds__prefix_lock(expanded_filename, filename);
|
||||
|
||||
const int oldmask = umask(0);
|
||||
bool init_flag = false;
|
||||
if (length < 0)
|
||||
length = -length;
|
||||
|
||||
/* Produce shared memory key for file */
|
||||
|
||||
@ -2383,12 +2375,11 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
|
||||
|
||||
#ifdef WIN_NT
|
||||
UCHAR* ISC_map_file(
|
||||
ISC_STATUS* status_vector,
|
||||
UCHAR* ISC_map_file(ISC_STATUS* status_vector,
|
||||
const TEXT* filename,
|
||||
FPTR_INIT_GLOBAL_REGION init_routine,
|
||||
void* init_arg,
|
||||
SLONG length,
|
||||
ULONG length,
|
||||
SH_MEM shmem_data)
|
||||
{
|
||||
/**************************************
|
||||
@ -2403,17 +2394,14 @@ UCHAR* ISC_map_file(
|
||||
* routine (if given) or punt (leaving the file unmapped).
|
||||
*
|
||||
**************************************/
|
||||
TEXT expanded_filename[MAXPATHLEN], hostname[64];
|
||||
TEXT map_file[MAXPATHLEN];
|
||||
TEXT object_name[MAXPATHLEN];
|
||||
HANDLE file_handle, event_handle;
|
||||
int retry_count = 0;
|
||||
|
||||
bool trunc_flag = true;
|
||||
if (length < 0) {
|
||||
length = -length;
|
||||
fb_assert(length > 0); // Was someone so crazy as to pass a bigger value than MAX_SLONG?
|
||||
trunc_flag = false;
|
||||
}
|
||||
TEXT expanded_filename[MAXPATHLEN];
|
||||
gds__prefix_lock(expanded_filename, filename);
|
||||
|
||||
const bool trunc_flag = (length != 0);
|
||||
|
||||
/* retry to attach to mmapped file if the process initializing
|
||||
* dies during initialization.
|
||||
@ -2422,10 +2410,7 @@ UCHAR* ISC_map_file(
|
||||
retry:
|
||||
retry_count++;
|
||||
|
||||
ISC_get_host(hostname, sizeof(hostname));
|
||||
sprintf(map_file, filename, hostname);
|
||||
|
||||
file_handle = CreateFile(map_file,
|
||||
file_handle = CreateFile(expanded_filename,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
@ -2444,14 +2429,14 @@ UCHAR* ISC_map_file(
|
||||
// Create an event that can be used to determine if someone has already
|
||||
// initialized shared memory.
|
||||
|
||||
if (!make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_event"))
|
||||
if (!make_object_name(object_name, sizeof(object_name), filename, "_event"))
|
||||
{
|
||||
error(status_vector, "make_object_name", GetLastError());
|
||||
CloseHandle(file_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, expanded_filename);
|
||||
event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, object_name);
|
||||
if (!event_handle) {
|
||||
error(status_vector, "CreateEvent", GetLastError());
|
||||
CloseHandle(file_handle);
|
||||
@ -2512,7 +2497,7 @@ UCHAR* ISC_map_file(
|
||||
else
|
||||
fdw_create = OPEN_ALWAYS;
|
||||
|
||||
file_handle = CreateFile(map_file,
|
||||
file_handle = CreateFile(expanded_filename,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
@ -2528,7 +2513,7 @@ UCHAR* ISC_map_file(
|
||||
/* Create a file mapping object that will be used to make remapping possible.
|
||||
The current length of real mapped file and its name are saved in it. */
|
||||
|
||||
if (!make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_mapping"))
|
||||
if (!make_object_name(object_name, sizeof(object_name), filename, "_mapping"))
|
||||
{
|
||||
error(status_vector, "make_object_name", GetLastError());
|
||||
CloseHandle(event_handle);
|
||||
@ -2536,12 +2521,11 @@ UCHAR* ISC_map_file(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HANDLE header_obj = CreateFileMapping ((HANDLE) -1,
|
||||
HANDLE header_obj = CreateFileMapping(INVALID_HANDLE_VALUE,
|
||||
ISC_get_security_desc(),
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
2 * sizeof (SLONG),
|
||||
expanded_filename);
|
||||
0, 2 * sizeof(ULONG),
|
||||
object_name);
|
||||
if (header_obj == NULL)
|
||||
{
|
||||
error(status_vector, "CreateFileMapping", GetLastError());
|
||||
@ -2561,7 +2545,7 @@ UCHAR* ISC_map_file(
|
||||
goto retry;
|
||||
}
|
||||
|
||||
SLONG* const header_address = (SLONG*) MapViewOfFile(header_obj, FILE_MAP_WRITE, 0, 0, 0);
|
||||
ULONG* const header_address = (ULONG*) MapViewOfFile(header_obj, FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
if (header_address == NULL) {
|
||||
error(status_vector, "MapViewOfFile", GetLastError());
|
||||
@ -2583,16 +2567,14 @@ UCHAR* ISC_map_file(
|
||||
|
||||
/* Create the real file mapping object. */
|
||||
|
||||
TEXT mapping_filename[sizeof(expanded_filename) + 15]; // enough for int32 as text
|
||||
sprintf(mapping_filename, "%s%"SLONGFORMAT, expanded_filename, header_address[1]);
|
||||
TEXT mapping_name[MAXPATHLEN + 15]; // enough for int32 as text
|
||||
sprintf(mapping_name, "%s_mapping_%"ULONGFORMAT, filename, header_address[1]);
|
||||
|
||||
HANDLE file_obj =
|
||||
CreateFileMapping(file_handle,
|
||||
HANDLE file_obj = CreateFileMapping(file_handle,
|
||||
ISC_get_security_desc(),
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
length,
|
||||
mapping_filename);
|
||||
0, length,
|
||||
mapping_name);
|
||||
if (file_obj == NULL) {
|
||||
error(status_vector, "CreateFileMapping", GetLastError());
|
||||
UnmapViewOfFile(header_address);
|
||||
@ -2628,7 +2610,7 @@ UCHAR* ISC_map_file(
|
||||
shmem_data->sh_mem_interest = event_handle;
|
||||
shmem_data->sh_mem_hdr_object = header_obj;
|
||||
shmem_data->sh_mem_hdr_address = header_address;
|
||||
strcpy(shmem_data->sh_mem_name, expanded_filename);
|
||||
strcpy(shmem_data->sh_mem_name, filename);
|
||||
|
||||
if (init_routine)
|
||||
(*init_routine) (init_arg, shmem_data, init_flag);
|
||||
@ -2636,7 +2618,7 @@ UCHAR* ISC_map_file(
|
||||
if (init_flag) {
|
||||
FlushViewOfFile(address, 0);
|
||||
SetEvent(event_handle);
|
||||
if (SetFilePointer(shmem_data->sh_mem_handle, length, NULL, FILE_BEGIN) == 0xFFFFFFFF ||
|
||||
if (SetFilePointer(shmem_data->sh_mem_handle, length, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ||
|
||||
!SetEndOfFile(shmem_data->sh_mem_handle) ||
|
||||
!FlushViewOfFile(shmem_data->sh_mem_address, 0))
|
||||
{
|
||||
@ -2653,7 +2635,8 @@ UCHAR* ISC_map_file(
|
||||
#ifdef HAVE_MMAP
|
||||
UCHAR* ISC_map_object(ISC_STATUS* status_vector,
|
||||
SH_MEM shmem_data,
|
||||
SLONG object_offset, SLONG object_length)
|
||||
ULONG object_offset,
|
||||
ULONG object_length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2668,13 +2651,13 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector,
|
||||
/* Get system page size as this is the unit of mapping. */
|
||||
|
||||
#ifdef SOLARIS
|
||||
const SLONG page_size = sysconf(_SC_PAGESIZE);
|
||||
const ULONG page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size == -1) {
|
||||
error(status_vector, "sysconf", errno);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
const SLONG page_size = (int) getpagesize();
|
||||
const ULONG page_size = (int) getpagesize();
|
||||
if (page_size == -1) {
|
||||
error(status_vector, "getpagesize", errno);
|
||||
return NULL;
|
||||
@ -2684,9 +2667,9 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector,
|
||||
/* Compute the start and end page-aligned offsets which
|
||||
contain the object being mapped. */
|
||||
|
||||
const SLONG start = (object_offset / page_size) * page_size;
|
||||
const SLONG end = (((object_offset + object_length) / page_size) + 1) * page_size;
|
||||
const SLONG length = end - start;
|
||||
const ULONG start = (object_offset / page_size) * page_size;
|
||||
const ULONG end = FB_ALIGN(object_offset + object_length, page_size);
|
||||
const ULONG length = end - start;
|
||||
int fd = shmem_data->sh_mem_handle;
|
||||
|
||||
UCHAR* address = (UCHAR*) mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start);
|
||||
@ -2706,7 +2689,8 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector,
|
||||
|
||||
void ISC_unmap_object(ISC_STATUS* status_vector,
|
||||
SH_MEM shmem_data,
|
||||
UCHAR** object_pointer, SLONG object_length)
|
||||
UCHAR** object_pointer,
|
||||
ULONG object_length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2722,13 +2706,13 @@ void ISC_unmap_object(ISC_STATUS* status_vector,
|
||||
/* Get system page size as this is the unit of mapping. */
|
||||
|
||||
#ifdef SOLARIS
|
||||
const SLONG page_size = sysconf(_SC_PAGESIZE);
|
||||
const ULONG page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size == -1) {
|
||||
error(status_vector, "sysconf", errno);
|
||||
return; // false;
|
||||
}
|
||||
#else
|
||||
const SLONG page_size = (int) getpagesize();
|
||||
const ULONG page_size = (int) getpagesize();
|
||||
if (page_size == -1) {
|
||||
error(status_vector, "getpagesize", errno);
|
||||
return; // false;
|
||||
@ -2741,7 +2725,7 @@ void ISC_unmap_object(ISC_STATUS* status_vector,
|
||||
UCHAR* start = (UCHAR *) ((U_IPTR) * object_pointer & ~(page_size - 1));
|
||||
const UCHAR* end =
|
||||
(UCHAR*) ((U_IPTR) ((*object_pointer + object_length) + (page_size - 1)) & ~(page_size - 1));
|
||||
const SLONG length = end - start;
|
||||
const ULONG length = end - start;
|
||||
|
||||
if (munmap((char *) start, length) == -1) {
|
||||
error(status_vector, "munmap", errno);
|
||||
@ -2757,7 +2741,8 @@ void ISC_unmap_object(ISC_STATUS* status_vector,
|
||||
#ifdef WIN_NT
|
||||
UCHAR* ISC_map_object(ISC_STATUS* status_vector,
|
||||
SH_MEM shmem_data,
|
||||
SLONG object_offset, SLONG object_length)
|
||||
ULONG object_offset,
|
||||
ULONG object_length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2772,14 +2757,14 @@ UCHAR* ISC_map_object(ISC_STATUS* status_vector,
|
||||
|
||||
SYSTEM_INFO sys_info;
|
||||
GetSystemInfo(&sys_info);
|
||||
const SLONG page_size = sys_info.dwAllocationGranularity;
|
||||
const ULONG page_size = sys_info.dwAllocationGranularity;
|
||||
|
||||
// Compute the start and end page-aligned offsets which
|
||||
// contain the object being mapped.
|
||||
|
||||
const SLONG start = (object_offset / page_size) * page_size;
|
||||
const SLONG end = (((object_offset + object_length) / page_size) + 1) * page_size;
|
||||
const SLONG length = end - start;
|
||||
const ULONG start = (object_offset / page_size) * page_size;
|
||||
const ULONG end = FB_ALIGN(object_offset + object_length, page_size);
|
||||
const ULONG length = end - start;
|
||||
const HANDLE handle = shmem_data->sh_mem_object;
|
||||
|
||||
UCHAR* address = (UCHAR*) MapViewOfFile(handle, FILE_MAP_WRITE, 0, start, length);
|
||||
@ -2797,7 +2782,8 @@ UCHAR* ISC_map_object(ISC_STATUS* status_vector,
|
||||
|
||||
void ISC_unmap_object(ISC_STATUS* status_vector,
|
||||
SH_MEM shmem_data,
|
||||
UCHAR** object_pointer, SLONG object_length)
|
||||
UCHAR** object_pointer,
|
||||
ULONG object_length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2812,7 +2798,7 @@ void ISC_unmap_object(ISC_STATUS* status_vector,
|
||||
**************************************/
|
||||
SYSTEM_INFO sys_info;
|
||||
GetSystemInfo(&sys_info);
|
||||
const SLONG page_size = sys_info.dwAllocationGranularity;
|
||||
const ULONG page_size = sys_info.dwAllocationGranularity;
|
||||
|
||||
// Compute the start and end page-aligned offsets which
|
||||
// contain the object being mapped.
|
||||
@ -3624,7 +3610,9 @@ void ISC_mutex_set_spin_count (struct mtx *mutex, ULONG spins)
|
||||
#ifdef HAVE_MMAP
|
||||
#define ISC_REMAP_FILE_DEFINED
|
||||
UCHAR *ISC_remap_file(ISC_STATUS* status_vector,
|
||||
SH_MEM shmem_data, SLONG new_length, bool flag)
|
||||
SH_MEM shmem_data,
|
||||
ULONG new_length,
|
||||
bool flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -3670,7 +3658,7 @@ UCHAR *ISC_remap_file(ISC_STATUS * status_vector,
|
||||
#define ISC_REMAP_FILE_DEFINED
|
||||
UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
|
||||
SH_MEM shmem_data,
|
||||
SLONG new_length,
|
||||
ULONG new_length,
|
||||
bool flag)
|
||||
{
|
||||
/**************************************
|
||||
@ -3686,7 +3674,7 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
|
||||
|
||||
if (flag)
|
||||
{
|
||||
if (SetFilePointer(shmem_data->sh_mem_handle, new_length, NULL, FILE_BEGIN) == 0xFFFFFFFF ||
|
||||
if (SetFilePointer(shmem_data->sh_mem_handle, new_length, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ||
|
||||
!SetEndOfFile(shmem_data->sh_mem_handle) ||
|
||||
!FlushViewOfFile(shmem_data->sh_mem_address, 0))
|
||||
{
|
||||
@ -3709,16 +3697,15 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
|
||||
HANDLE file_obj;
|
||||
|
||||
while (true) {
|
||||
TEXT expanded_filename[MAXPATHLEN];
|
||||
sprintf(expanded_filename, "%s%"SLONGFORMAT, shmem_data->sh_mem_name,
|
||||
shmem_data->sh_mem_hdr_address[1] + 1);
|
||||
TEXT mapping_name[MAXPATHLEN + 15]; // enough for int32 as text
|
||||
sprintf(mapping_name, "%s_mapping_%"ULONGFORMAT,
|
||||
shmem_data->sh_mem_name, shmem_data->sh_mem_hdr_address[1] + 1);
|
||||
|
||||
file_obj = CreateFileMapping(shmem_data->sh_mem_handle,
|
||||
ISC_get_security_desc(),
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
new_length,
|
||||
expanded_filename);
|
||||
0, new_length,
|
||||
mapping_name);
|
||||
|
||||
if (!((GetLastError() == ERROR_ALREADY_EXISTS) && flag))
|
||||
break;
|
||||
@ -3766,7 +3753,7 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
|
||||
#ifndef ISC_REMAP_FILE_DEFINED
|
||||
UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
|
||||
SH_MEM shmem_data,
|
||||
SLONG new_length,
|
||||
ULONG new_length,
|
||||
bool flag)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -861,9 +861,6 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
bool first = false;
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_attachment); // For the attachment
|
||||
attachment->att_flags |= ATT_lck_init_done;
|
||||
|
||||
if (dbb->dbb_filename.empty())
|
||||
{
|
||||
#if defined(DEV_BUILD) && defined(SUPERSERVER)
|
||||
@ -891,19 +888,22 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
else
|
||||
dbb->dbb_database_name = expanded_name;
|
||||
|
||||
// Extra LCK_init() done to keep the lock table until the
|
||||
// database is shutdown() after the last detach.
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
pageSpace->file = PIO_open(dbb, expanded_name, file_name, false);
|
||||
|
||||
// Initialize the lock manager
|
||||
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId());
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
dbb->dbb_flags |= DBB_lck_init_done;
|
||||
|
||||
INI_init(tdbb);
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
pageSpace->file = PIO_open(dbb, expanded_name, file_name, false);
|
||||
LCK_init(tdbb, LCK_OWNER_attachment);
|
||||
attachment->att_flags |= ATT_lck_init_done;
|
||||
|
||||
// Initialize locks
|
||||
init_database_locks(tdbb);
|
||||
|
||||
INI_init(tdbb);
|
||||
SHUT_init(tdbb);
|
||||
PAG_header_init(tdbb);
|
||||
INI_init2(tdbb);
|
||||
@ -939,6 +939,11 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
// looks like someone tries to attach incompatibly
|
||||
status_exception::raise(Arg::Gds(isc_bad_dpb_content));
|
||||
}
|
||||
|
||||
fb_assert(dbb->dbb_lock_mgr);
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_attachment);
|
||||
attachment->att_flags |= ATT_lck_init_done;
|
||||
}
|
||||
|
||||
// Attachments to a ReadOnly database need NOT do garbage collection
|
||||
@ -1361,9 +1366,7 @@ ISC_STATUS GDS_CANCEL_BLOB(ISC_STATUS* user_status, blb** blob_handle)
|
||||
}
|
||||
|
||||
|
||||
ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status,
|
||||
Attachment** handle,
|
||||
SLONG* id)
|
||||
ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status, Attachment** handle, SLONG* id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1383,7 +1386,12 @@ ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status,
|
||||
DatabaseContextHolder dbbHolder(tdbb);
|
||||
check_database(tdbb);
|
||||
|
||||
EVENT_cancel(*id);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
if (dbb->dbb_event_mgr)
|
||||
{
|
||||
dbb->dbb_event_mgr->cancelEvents(*id);
|
||||
}
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
@ -1823,19 +1831,6 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
dbb->dbb_page_size = (page_size > MAX_PAGE_SIZE) ? MAX_PAGE_SIZE : page_size;
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_attachment); // For the attachment
|
||||
attachment->att_flags |= ATT_lck_init_done;
|
||||
// Extra LCK_init() done to keep the lock table until the
|
||||
// database is shutdown() after the last detach.
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
dbb->dbb_flags |= DBB_lck_init_done;
|
||||
|
||||
INI_init(tdbb);
|
||||
PAG_init(tdbb);
|
||||
initing_security = true;
|
||||
|
||||
SCL_init(tdbb, true, userId);
|
||||
|
||||
initing_security = false;
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
@ -1885,9 +1880,24 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
const jrd_file* const first_dbb_file = pageSpace->file;
|
||||
|
||||
// Initialize the lock manager
|
||||
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId());
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
dbb->dbb_flags |= DBB_lck_init_done;
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_attachment);
|
||||
attachment->att_flags |= ATT_lck_init_done;
|
||||
|
||||
// Initialize locks
|
||||
init_database_locks(tdbb);
|
||||
|
||||
INI_init(tdbb);
|
||||
PAG_init(tdbb);
|
||||
initing_security = true;
|
||||
|
||||
SCL_init(tdbb, true, userId);
|
||||
|
||||
if (options.dpb_set_page_buffers)
|
||||
dbb->dbb_page_buffers = options.dpb_page_buffers;
|
||||
|
||||
@ -2524,13 +2534,17 @@ ISC_STATUS GDS_QUE_EVENTS(ISC_STATUS* user_status,
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
Lock* const lock = dbb->dbb_lock;
|
||||
|
||||
EventManager::init(dbb);
|
||||
|
||||
if (!attachment->att_event_session)
|
||||
{
|
||||
attachment->att_event_session = EVENT_create_session();
|
||||
attachment->att_event_session = dbb->dbb_event_mgr->createSession();
|
||||
}
|
||||
|
||||
*id = EVENT_que(attachment->att_event_session, lock->lck_length,
|
||||
(const TEXT*) &lock->lck_key, length, items, ast, arg);
|
||||
*id = dbb->dbb_event_mgr->queEvents(attachment->att_event_session,
|
||||
lock->lck_length, (const TEXT*) &lock->lck_key,
|
||||
length, items,
|
||||
ast, arg);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
@ -4654,10 +4668,6 @@ static Database* init(thread_db* tdbb,
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the lock manager
|
||||
|
||||
dbb->dbb_lock_mgr = LockManager::create(expanded_filename);
|
||||
|
||||
// Initialize a number of subsystems
|
||||
|
||||
TRA_init(dbb);
|
||||
@ -4672,8 +4682,6 @@ static Database* init(thread_db* tdbb,
|
||||
dbb->dbb_decrypt = (Database::crypt_routine) crypt_lib.lookupSymbol(decrypt_entrypoint);
|
||||
}
|
||||
|
||||
INTL_init(tdbb);
|
||||
|
||||
return dbb;
|
||||
}
|
||||
|
||||
@ -4838,8 +4846,10 @@ static void release_attachment(thread_db* tdbb, Attachment* attachment, ISC_STAT
|
||||
}
|
||||
#endif
|
||||
|
||||
if (attachment->att_event_session)
|
||||
EVENT_delete_session(attachment->att_event_session);
|
||||
if (dbb->dbb_event_mgr && attachment->att_event_session)
|
||||
{
|
||||
dbb->dbb_event_mgr->deleteSession(attachment->att_event_session);
|
||||
}
|
||||
|
||||
if (attachment->att_id_lock)
|
||||
LCK_release(tdbb, attachment->att_id_lock);
|
||||
@ -4870,7 +4880,7 @@ static void release_attachment(thread_db* tdbb, Attachment* attachment, ISC_STAT
|
||||
detachLocksFromAttachment(attachment);
|
||||
|
||||
if (attachment->att_flags & ATT_lck_init_done) {
|
||||
LCK_fini(tdbb, LCK_OWNER_attachment); // For the attachment
|
||||
LCK_fini(tdbb, LCK_OWNER_attachment);
|
||||
attachment->att_flags &= ~ATT_lck_init_done;
|
||||
}
|
||||
|
||||
@ -5088,8 +5098,6 @@ static void shutdown_database(Database* dbb, const bool release_pools)
|
||||
CMP_fini(tdbb);
|
||||
CCH_fini(tdbb);
|
||||
|
||||
DatabaseSnapshot::cleanup(tdbb);
|
||||
|
||||
if (dbb->dbb_backup_manager)
|
||||
dbb->dbb_backup_manager->shutdown(tdbb);
|
||||
|
||||
@ -5150,7 +5158,7 @@ static void shutdown_database(Database* dbb, const bool release_pools)
|
||||
if (dbb->dbb_flags & DBB_lck_init_done) {
|
||||
dbb->dbb_page_manager.releaseLocks();
|
||||
|
||||
LCK_fini(tdbb, LCK_OWNER_database); // For the database
|
||||
LCK_fini(tdbb, LCK_OWNER_database);
|
||||
dbb->dbb_flags &= ~DBB_lck_init_done;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../common/classes/alloc.h"
|
||||
#include "../common/classes/init.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../jrd/ThreadStart.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#include "../include/fb_blk.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../jrd/ods.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
|
@ -96,7 +96,7 @@
|
||||
#include <process.h>
|
||||
#define MUTEX &m_shmemMutex
|
||||
#else
|
||||
#define MUTEX m_header->lhb_mutex
|
||||
#define MUTEX &m_header->lhb_mutex
|
||||
#endif
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
@ -159,17 +159,12 @@ static const bool compatibility[LCK_max][LCK_max] =
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
const char* LockManager::PATTERN = "firebird_db_%d_lock";
|
||||
|
||||
Firebird::GlobalPtr<LockManager::DbLockMgrMap> LockManager::g_lmMap;
|
||||
Firebird::GlobalPtr<Firebird::Mutex> LockManager::g_mapMutex;
|
||||
|
||||
|
||||
LockManager* LockManager::create(const Firebird::PathName& filename)
|
||||
LockManager* LockManager::create(const Firebird::string& id)
|
||||
{
|
||||
//const size_t HASH_SIZE = 997;
|
||||
const int id = 0;//filename.hash(HASH_SIZE);
|
||||
|
||||
Firebird::MutexLockGuard guard(g_mapMutex);
|
||||
|
||||
LockManager* lockMgr = NULL;
|
||||
@ -180,26 +175,24 @@ LockManager* LockManager::create(const Firebird::PathName& filename)
|
||||
|
||||
fb_assert(lockMgr);
|
||||
|
||||
lockMgr->addRef();
|
||||
return lockMgr;
|
||||
}
|
||||
|
||||
LockManager::LockManager(int dbId)
|
||||
|
||||
LockManager::LockManager(const Firebird::string& id)
|
||||
: PID(getpid()),
|
||||
m_bugcheck(false),
|
||||
m_header(NULL),
|
||||
m_process(NULL),
|
||||
m_processOffset(0),
|
||||
m_dbId(dbId),
|
||||
m_lockFile(getPool())
|
||||
m_dbId(getPool(), id)
|
||||
{
|
||||
// m_lockFile.printf(PATTERN, m_dbId);
|
||||
TEXT buffer[MAXPATHLEN];
|
||||
gds__prefix_lock(buffer, LOCK_FILE);
|
||||
m_lockFile = buffer;
|
||||
Firebird::string name;
|
||||
name.printf(LOCK_FILE, m_dbId.c_str());
|
||||
|
||||
ISC_STATUS_ARRAY local_status;
|
||||
if (!(m_header = (lhb*) ISC_map_file(local_status, m_lockFile.c_str(),
|
||||
if (!(m_header = (lhb*) ISC_map_file(local_status,
|
||||
name.c_str(),
|
||||
initialize, this,
|
||||
Config::getLockMemSize(),
|
||||
&m_shmem)))
|
||||
@ -207,6 +200,8 @@ LockManager::LockManager(int dbId)
|
||||
Firebird::status_exception::raise(local_status);
|
||||
}
|
||||
|
||||
fb_assert(m_header->lhb_version == LHB_VERSION);
|
||||
|
||||
Firebird::MutexLockGuard guard(g_mapMutex);
|
||||
|
||||
if (g_lmMap->put(m_dbId, this))
|
||||
@ -251,10 +246,9 @@ LockManager::~LockManager()
|
||||
release_mutex();
|
||||
}
|
||||
|
||||
ISC_mutex_fini(MUTEX);
|
||||
|
||||
if (m_header)
|
||||
{
|
||||
ISC_mutex_fini(MUTEX);
|
||||
ISC_unmap_file(local_status, &m_shmem);
|
||||
}
|
||||
|
||||
@ -1062,7 +1056,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const SLONG length = m_header->lhb_length;
|
||||
const ULONG new_length = m_header->lhb_length;
|
||||
|
||||
#if (defined HAVE_MMAP || defined WIN_NT)
|
||||
Firebird::WriteLockGuard guard(m_remapSync);
|
||||
@ -1070,7 +1064,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset)
|
||||
remap_local_owners();
|
||||
// Remap the shared memory region
|
||||
ISC_STATUS_ARRAY status_vector;
|
||||
lhb* const header = (lhb*) ISC_remap_file(status_vector, &m_shmem, length, false);
|
||||
lhb* const header = (lhb*) ISC_remap_file(status_vector, &m_shmem, new_length, false);
|
||||
if (header)
|
||||
m_header = header;
|
||||
else
|
||||
@ -1109,7 +1103,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset)
|
||||
}
|
||||
|
||||
|
||||
UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector)
|
||||
UCHAR* LockManager::alloc(USHORT size, ISC_STATUS* status_vector)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1124,32 +1118,22 @@ UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector)
|
||||
size = FB_ALIGN(size, FB_ALIGNMENT);
|
||||
ASSERT_ACQUIRED;
|
||||
const ULONG block = m_header->lhb_used;
|
||||
m_header->lhb_used += size;
|
||||
|
||||
// Make sure we haven't overflowed the lock table. If so, bump the size of the table.
|
||||
|
||||
if (m_header->lhb_used > m_header->lhb_length
|
||||
#ifdef LOCK_DEBUG_REMAP
|
||||
// If we're debugging remaps, force a remap every-so-often.
|
||||
|| ((debug_remap_count++ % DEBUG_REMAP_INTERVAL) == 0 && m_processOffset)
|
||||
#endif
|
||||
)
|
||||
if (m_header->lhb_used + size > m_header->lhb_length)
|
||||
{
|
||||
const bool extend = (m_header->lhb_used > m_header->lhb_length);
|
||||
m_header->lhb_used -= size;
|
||||
|
||||
#if (defined HAVE_MMAP || defined WIN_NT)
|
||||
Firebird::WriteLockGuard guard(m_remapSync);
|
||||
// Post remapping notifications
|
||||
remap_local_owners();
|
||||
// Remap the shared memory region
|
||||
const ULONG length = m_shmem.sh_mem_length_mapped + (extend ? Config::getLockMemSize() : 0);
|
||||
lhb* header = (lhb*) ISC_remap_file(status_vector, &m_shmem, length, true);
|
||||
const ULONG new_length = m_shmem.sh_mem_length_mapped + Config::getLockMemSize();
|
||||
lhb* header = (lhb*) ISC_remap_file(status_vector, &m_shmem, new_length, true);
|
||||
if (header) {
|
||||
m_header = header;
|
||||
ASSERT_ACQUIRED;
|
||||
m_header->lhb_length = m_shmem.sh_mem_length_mapped;
|
||||
m_header->lhb_used += size;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -1169,6 +1153,8 @@ UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector)
|
||||
}
|
||||
}
|
||||
|
||||
m_header->lhb_used += size;
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
// This version of alloc() doesn't initialize memory. To shake out
|
||||
// any bugs, in DEV_BUILD we initialize it to a "funny" pattern.
|
||||
@ -1299,14 +1285,6 @@ void LockManager::blocking_action(thread_db* tdbb,
|
||||
}
|
||||
|
||||
|
||||
THREAD_ENTRY_DECLARE LockManager::blocking_action_thread(THREAD_ENTRY_PARAM arg)
|
||||
{
|
||||
LockManager* const lockMgr = static_cast<LockManager*>(arg);
|
||||
lockMgr->blocking_action_thread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void LockManager::blocking_action_thread()
|
||||
{
|
||||
/**************************************
|
||||
@ -1334,14 +1312,12 @@ void LockManager::blocking_action_thread()
|
||||
|
||||
try
|
||||
{
|
||||
SRQ_PTR* process_offset_ptr = (SRQ_PTR*) &m_processOffset;
|
||||
|
||||
while (true)
|
||||
{
|
||||
m_localMutex.enter();
|
||||
|
||||
// See if the main thread has requested us to go away
|
||||
if (!*process_offset_ptr || m_process->prc_process_id != PID)
|
||||
if (!m_processOffset || m_process->prc_process_id != PID)
|
||||
{
|
||||
if (atStartup)
|
||||
{
|
||||
@ -1357,7 +1333,7 @@ void LockManager::blocking_action_thread()
|
||||
Firebird::HalfStaticArray<SRQ_PTR, 4> blocking_owners;
|
||||
|
||||
acquire_shmem(DUMMY_OWNER);
|
||||
const prc* const process = (prc*) SRQ_ABS_PTR(*process_offset_ptr);
|
||||
const prc* const process = (prc*) SRQ_ABS_PTR(m_processOffset);
|
||||
|
||||
srq* lock_srq;
|
||||
SRQ_LOOP(process->prc_owners, lock_srq)
|
||||
@ -1368,7 +1344,7 @@ void LockManager::blocking_action_thread()
|
||||
|
||||
release_mutex();
|
||||
|
||||
while (blocking_owners.getCount() && *process_offset_ptr)
|
||||
while (blocking_owners.getCount() && m_processOffset)
|
||||
{
|
||||
const SRQ_PTR owner_offset = blocking_owners.pop();
|
||||
acquire_shmem(owner_offset);
|
||||
@ -1466,6 +1442,18 @@ void LockManager::bug(ISC_STATUS* status_vector, const TEXT* string)
|
||||
{
|
||||
m_bugcheck = true;
|
||||
|
||||
// The lock table has some problem - copy it for later analysis
|
||||
|
||||
TEXT buffer[MAXPATHLEN];
|
||||
gds__prefix(buffer, "lock_table.dump");
|
||||
const TEXT* const lock_file = buffer;
|
||||
FILE* const fd = fopen(lock_file, "wb");
|
||||
if (fd)
|
||||
{
|
||||
fwrite(m_header, 1, m_header->lhb_used, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
// If the current mutex acquirer is in the same process, release the mutex
|
||||
|
||||
if (m_header && (m_header->lhb_active_owner > 0)) {
|
||||
@ -1519,8 +1507,7 @@ bool LockManager::create_owner(ISC_STATUS* status_vector,
|
||||
if (m_header->lhb_version != LHB_VERSION)
|
||||
{
|
||||
TEXT bug_buffer[BUFFER_TINY];
|
||||
sprintf(bug_buffer,
|
||||
"inconsistent lock table version number; found %d, expected %d",
|
||||
sprintf(bug_buffer, "inconsistent lock table version number; found %d, expected %d",
|
||||
m_header->lhb_version, LHB_VERSION);
|
||||
bug(status_vector, bug_buffer);
|
||||
return false;
|
||||
@ -2152,6 +2139,7 @@ void LockManager::init_owner_block(own* owner, UCHAR owner_type, LOCK_OWNER_T ow
|
||||
owner->own_count = 1;
|
||||
owner->own_owner_id = owner_id;
|
||||
owner->own_process = m_processOffset;
|
||||
owner->own_thread_id = 0;
|
||||
SRQ_INIT(owner->own_lhb_owners);
|
||||
SRQ_INIT(owner->own_prc_owners);
|
||||
SRQ_INIT(owner->own_requests);
|
||||
@ -2177,7 +2165,7 @@ void LockManager::initialize(SH_MEM shmem_data, bool initialize)
|
||||
*
|
||||
**************************************/
|
||||
#ifdef WIN_NT
|
||||
if (ISC_mutex_init(MUTEX, m_lockFile.c_str())) {
|
||||
if (ISC_mutex_init(MUTEX, shmem_data->sh_mem_name)) {
|
||||
bug(NULL, "mutex init failed");
|
||||
}
|
||||
#endif
|
||||
@ -2236,7 +2224,7 @@ void LockManager::initialize(SH_MEM shmem_data, bool initialize)
|
||||
if (Config::getLockGrantOrder())
|
||||
m_header->lhb_flags |= LHB_lock_ordering;
|
||||
|
||||
const SLONG length = sizeof(lhb) + (m_header->lhb_hash_slots * sizeof(m_header->lhb_hash[0]));
|
||||
const ULONG length = sizeof(lhb) + (m_header->lhb_hash_slots * sizeof(m_header->lhb_hash[0]));
|
||||
m_header->lhb_length = shmem_data->sh_mem_length_mapped;
|
||||
m_header->lhb_used = FB_ALIGN(length, FB_ALIGNMENT);
|
||||
|
||||
|
@ -90,14 +90,12 @@ const SSHORT LCK_NO_WAIT = 0;
|
||||
|
||||
const UCHAR type_null = 0;
|
||||
const UCHAR type_lhb = 1;
|
||||
const UCHAR type_prb = 2;
|
||||
const UCHAR type_lrq = 3;
|
||||
const UCHAR type_lbl = 4;
|
||||
const UCHAR type_his = 5;
|
||||
const UCHAR type_smbx = 6;
|
||||
const UCHAR type_shb = 7;
|
||||
const UCHAR type_own = 8;
|
||||
const UCHAR type_lpr = 9;
|
||||
const UCHAR type_lrq = 2;
|
||||
const UCHAR type_lbl = 3;
|
||||
const UCHAR type_his = 4;
|
||||
const UCHAR type_shb = 5;
|
||||
const UCHAR type_own = 6;
|
||||
const UCHAR type_lpr = 7;
|
||||
const UCHAR type_MAX = type_lpr;
|
||||
|
||||
// Version number of the lock table.
|
||||
@ -134,11 +132,11 @@ struct lhb
|
||||
srq lhb_free_owners; // Free owner blocks
|
||||
srq lhb_free_locks; // Free lock blocks
|
||||
srq lhb_free_requests; // Free lock requests
|
||||
SLONG lhb_length; // Size of lock table
|
||||
SLONG lhb_used; // Bytes of lock table in use
|
||||
ULONG lhb_length; // Size of lock table
|
||||
ULONG lhb_used; // Bytes of lock table in use
|
||||
USHORT lhb_hash_slots; // Number of hash slots allocated
|
||||
USHORT lhb_flags; // Miscellaneous info
|
||||
mtx lhb_mutex[1]; // Mutex controlling access
|
||||
struct mtx lhb_mutex; // Mutex controlling access
|
||||
SRQ_PTR lhb_history;
|
||||
ULONG lhb_scan_interval; // Deadlock scan interval (secs)
|
||||
ULONG lhb_acquire_spins;
|
||||
|
@ -43,16 +43,15 @@ class thread_db;
|
||||
|
||||
class LockManager : public Firebird::RefCounted, public Firebird::GlobalStorage
|
||||
{
|
||||
typedef Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<int, LockManager*> > > DbLockMgrMap;
|
||||
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::string, LockManager*> > > DbLockMgrMap;
|
||||
|
||||
static Firebird::GlobalPtr<DbLockMgrMap> g_lmMap;
|
||||
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
|
||||
static const char* PATTERN;
|
||||
|
||||
const int PID;
|
||||
|
||||
public:
|
||||
static LockManager* create(const Firebird::PathName&);
|
||||
static LockManager* create(const Firebird::string&);
|
||||
|
||||
bool initializeOwner(thread_db*, LOCK_OWNER_T, UCHAR, SRQ_PTR*);
|
||||
void shutdownOwner(thread_db*, SRQ_PTR*);
|
||||
@ -72,7 +71,7 @@ public:
|
||||
SLONG writeData(SRQ_PTR, SLONG);
|
||||
|
||||
private:
|
||||
explicit LockManager(int);
|
||||
explicit LockManager(const Firebird::string&);
|
||||
~LockManager();
|
||||
|
||||
bool lockOrdering() const
|
||||
@ -81,7 +80,7 @@ private:
|
||||
}
|
||||
|
||||
void acquire_shmem(SRQ_PTR);
|
||||
UCHAR* alloc(SSHORT, ISC_STATUS*);
|
||||
UCHAR* alloc(USHORT, ISC_STATUS*);
|
||||
lbl* alloc_lock(USHORT, ISC_STATUS*);
|
||||
void blocking_action(thread_db*, SRQ_PTR, SRQ_PTR);
|
||||
void blocking_action_thread();
|
||||
@ -133,7 +132,12 @@ private:
|
||||
#endif
|
||||
USHORT wait_for_request(thread_db*, lrq*, SSHORT);
|
||||
|
||||
static THREAD_ENTRY_DECLARE blocking_action_thread(THREAD_ENTRY_PARAM);
|
||||
static THREAD_ENTRY_DECLARE blocking_action_thread(THREAD_ENTRY_PARAM arg)
|
||||
{
|
||||
LockManager* const lockMgr = static_cast<LockManager*>(arg);
|
||||
lockMgr->blocking_action_thread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void initialize(void* arg, SH_MEM shmem, bool init)
|
||||
{
|
||||
@ -155,8 +159,7 @@ private:
|
||||
Firebird::Semaphore m_cleanupSemaphore;
|
||||
Firebird::Semaphore m_startupSemaphore;
|
||||
|
||||
const int m_dbId;
|
||||
Firebird::PathName m_lockFile;
|
||||
Firebird::string m_dbId;
|
||||
|
||||
#ifdef WIN_NT
|
||||
struct mtx m_shmemMutex;
|
||||
|
@ -67,6 +67,8 @@ const char* INTERBASE_USER = "interbase";
|
||||
const char* FIREBIRD_USER = "firebird";
|
||||
const char* INTERBASE_USER_SHORT= "interbas";
|
||||
|
||||
const char* GUARD_FILE = "fb_guard";
|
||||
|
||||
volatile sig_atomic_t shutting_down;
|
||||
|
||||
|
||||
|
@ -256,11 +256,10 @@ int UTIL_ex_lock(const TEXT* file)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
TEXT expanded_filename[MAXPATHLEN], tmp[MAXPATHLEN], hostname[64];
|
||||
TEXT expanded_filename[MAXPATHLEN];
|
||||
|
||||
/* get the file name and prepend the complete path etc */
|
||||
gds__prefix_lock(tmp, file);
|
||||
sprintf(expanded_filename, tmp, ISC_get_host(hostname, sizeof(hostname)));
|
||||
gds__prefix(expanded_filename, file);
|
||||
|
||||
/* file fd for the opened and locked file */
|
||||
int fd_file = open(expanded_filename, O_RDWR | O_CREAT, 0666);
|
||||
|
Loading…
Reference in New Issue
Block a user