8
0
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:
dimitr 2009-01-28 12:27:18 +00:00
parent bb59a30d0f
commit 1b3927b026
23 changed files with 1040 additions and 1011 deletions

View File

@ -54,6 +54,28 @@ namespace Jrd
#endif #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() Database::~Database()
{ {
delete dbb_sys_trans; delete dbb_sys_trans;
@ -66,9 +88,14 @@ namespace Jrd
MemoryPool::deletePool(dbb_pools[i]); MemoryPool::deletePool(dbb_pools[i]);
} }
delete dbb_monitoring_data;
dbb_flags |= DBB_destroying; dbb_flags |= DBB_destroying;
Checkout dcoHolder(this); 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) void Database::deletePool(MemoryPool* pool)

View File

@ -57,19 +57,20 @@
#include "../common/classes/PublicHandle.h" #include "../common/classes/PublicHandle.h"
#include "../common/classes/semaphore.h" #include "../common/classes/semaphore.h"
#include "../common/utils_proto.h" #include "../common/utils_proto.h"
#include "../jrd/DatabaseSnapshot.h"
#include "../jrd/RandomGenerator.h" #include "../jrd/RandomGenerator.h"
#include "../jrd/os/guid.h" #include "../jrd/os/guid.h"
#include "../jrd/sbm.h" #include "../jrd/sbm.h"
#include "../jrd/flu.h" #include "../jrd/flu.h"
#include "../jrd/RuntimeStatistics.h" #include "../jrd/RuntimeStatistics.h"
#include "../lock/lock_proto.h"
#include "../jrd/os/thd_priority.h" #include "../jrd/os/thd_priority.h"
#include "../jrd/event_proto.h"
#include "../lock/lock_proto.h"
class CharSetContainer; class CharSetContainer;
namespace Jrd namespace Jrd
{ {
class Trigger; class Trigger;
template <typename T> class vec; template <typename T> class vec;
class jrd_prc; class jrd_prc;
@ -326,10 +327,10 @@ public:
return TypedHandle<type_dbb>::checkHandle(); return TypedHandle<type_dbb>::checkHandle();
} }
mutable Sync* dbb_sync; // Database sync primitive mutable Firebird::RefPtr<Sync> dbb_sync; // Database sync primitive
Firebird::Reference dbb_sync_ref; // Database reference to dbb_sync
LockManager* dbb_lock_mgr; Firebird::RefPtr<LockManager> dbb_lock_mgr;
Firebird::RefPtr<EventManager> dbb_event_mgr;
Database* dbb_next; // Next database block in system Database* dbb_next; // Next database block in system
Attachment* dbb_attachments; // Active attachments 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_curr; // current value of shared counter lock
SLONG dbb_sh_counter_max; // maximum cached 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_tra* dbb_sys_trans; // system transaction
// jrd_file* dbb_file; // files for I/O operations
Shadow* dbb_shadow; // shadow control block Shadow* dbb_shadow; // shadow control block
Lock* dbb_shadow_lock; // lock for synchronizing addition of shadows 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_retaining_lock; // lock for preserving commit retaining snapshot
Lock* dbb_monitor_lock; // lock for monitoring purposes Lock* dbb_monitor_lock; // lock for monitoring purposes
PageManager dbb_page_manager; PageManager dbb_page_manager;
@ -354,6 +353,8 @@ public:
BlobFilter* dbb_blob_filters; // known blob filters BlobFilter* dbb_blob_filters; // known blob filters
trig_vec* dbb_triggers[DB_TRIGGER_MAX]; trig_vec* dbb_triggers[DB_TRIGGER_MAX];
DatabaseSnapshot::SharedData* dbb_monitoring_data; // monitoring data
DatabaseModules dbb_modules; // external function/filter modules DatabaseModules dbb_modules; // external function/filter modules
Firebird::Mutex dbb_meta_mutex; // Mutex to protect metadata changes while dbb_sync is unlocked 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 // returns true if primary file is located on raw device
bool onRawDevice() const; bool onRawDevice() const;
// returns an unique ID string for a database file
const Firebird::string& getUniqueFileId() const;
MemoryPool* createPool() MemoryPool* createPool()
{ {
MemoryPool* const pool = MemoryPool::createPool(dbb_permanent, dbb_memory_stats); MemoryPool* const pool = MemoryPool::createPool(dbb_permanent, dbb_memory_stats);
@ -459,7 +463,6 @@ public:
private: private:
explicit Database(MemoryPool* p) explicit Database(MemoryPool* p)
: dbb_sync(FB_NEW(*getDefaultMemoryPool()) Sync), : dbb_sync(FB_NEW(*getDefaultMemoryPool()) Sync),
dbb_sync_ref(*dbb_sync),
dbb_page_manager(*p), dbb_page_manager(*p),
dbb_modules(*p), dbb_modules(*p),
dbb_filename(*p), dbb_filename(*p),

View File

@ -72,35 +72,40 @@ const UCHAR TAG_RECORD = MAX_UCHAR;
// SharedMemory class // SharedMemory class
const ULONG DatabaseSnapshot::SharedMemory::VERSION = 2; DatabaseSnapshot::SharedData::SharedData(const Database* dbb)
const ULONG DatabaseSnapshot::SharedMemory::DEFAULT_SIZE = 1048576; : process_id(getpid()), local_id(dbb->dbb_monitoring_id)
DatabaseSnapshot::SharedMemory::SharedMemory()
{ {
TEXT filename[MAXPATHLEN]; Firebird::string name;
gds__prefix_lock(filename, MONITOR_FILE); name.printf(MONITOR_FILE, dbb->getUniqueFileId().c_str());
ISC_STATUS_ARRAY statusVector; 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) if (!base)
{ {
iscLogStatus("Cannot initialize the shared memory region", statusVector); iscLogStatus("Cannot initialize the shared memory region", statusVector);
status_exception::raise(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_STATUS_ARRAY statusVector;
ISC_unmap_file(statusVector, &handle); ISC_unmap_file(statusVector, &handle);
} }
void DatabaseSnapshot::SharedMemory::acquire() void DatabaseSnapshot::SharedData::acquire()
{ {
#ifdef WIN_NT #ifdef WIN_NT
checkMutex("lock", ISC_mutex_lock(&mutex)); 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 #ifdef WIN_NT
checkMutex("unlock", ISC_mutex_unlock(&mutex)); 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); DumpGuard guard(this);
ULONG self_dbb_offset = 0; 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 Element* const element = (Element*) ptr;
const ULONG length = sizeof(Element) + element->length; 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; 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); DumpGuard guard(this);
// Remove old copies of our element, if any // Remove old copies of our element, if any
doCleanup(dbb); cleanup();
// Do we need to extend the allocated memory? // Do we need to extend the allocated memory?
while (base->used + sizeof(Element) + length > base->allocated) 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 // Put an up-to-date element at the tail
UCHAR* const ptr = (UCHAR*) base + base->used; UCHAR* const ptr = (UCHAR*) base + base->used;
Element* const element = (Element*) ptr; Element* const element = (Element*) ptr;
element->processId = getpid(); element->processId = process_id;
element->localId = dbb->dbb_monitoring_id; element->localId = local_id;
element->length = length; element->length = length;
memcpy(ptr + sizeof(Element), buffer, length); memcpy(ptr + sizeof(Element), buffer, length);
base->used += sizeof(Element) + 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 // Remove information about our dbb
doCleanup(dbb);
}
void DatabaseSnapshot::SharedMemory::doCleanup(const Database* const dbb)
{
for (ULONG offset = sizeof(Header); offset < base->used;) for (ULONG offset = sizeof(Header); offset < base->used;)
{ {
UCHAR* const ptr = (UCHAR*) base + offset; UCHAR* const ptr = (UCHAR*) base + offset;
const Element* const element = (Element*) ptr; const Element* const element = (Element*) ptr;
const ULONG length = sizeof(Element) + element->length; 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); fb_assert(base->used >= offset + length);
memmove(ptr, ptr + length, 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; 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) 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); fb_assert(shmem);
#ifdef WIN_NT #ifdef WIN_NT
char buffer[MAXPATHLEN]; checkMutex("init", ISC_mutex_init(&shmem->mutex, shmemData->sh_mem_name));
gds__prefix_lock(buffer, MONITOR_FILE);
checkMutex("init", ISC_mutex_init(&shmem->mutex, buffer));
#endif #endif
if (!initialize) if (!initialize)
@ -320,7 +300,7 @@ void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool i
// Initialize the shared data header // Initialize the shared data header
Header* const header = (Header*) shmemData->sh_mem_address; Header* const header = (Header*) shmemData->sh_mem_address;
header->version = VERSION; header->version = MONITOR_VERSION;
header->used = sizeof(Header); header->used = sizeof(Header);
header->allocated = shmemData->sh_mem_length_mapped; 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 class
DatabaseSnapshot::SharedMemory* DatabaseSnapshot::dump = NULL;
InitMutex<DatabaseSnapshot> DatabaseSnapshot::startup;
DatabaseSnapshot* DatabaseSnapshot::create(thread_db* tdbb) 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) int DatabaseSnapshot::blockingAst(void* ast_object)
{ {
Database* dbb = static_cast<Database*>(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; dbb->dbb_ast_flags |= DBB_monitor_off;
// Read the shared memory // Read the shared memory
fb_assert(dump); fb_assert(dbb->dbb_monitoring_data);
ULONG dataSize = 0; 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); fb_assert(dataSize);
ClumpletReader reader(ClumpletReader::WideUnTagged, data, 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); dbb->dbb_monitoring_data->write(writer.getBufferLength(), writer.getBuffer());
dump->writeData(tdbb, writer.getBufferLength(), writer.getBuffer());
} }

View File

@ -30,6 +30,11 @@
namespace Jrd { namespace Jrd {
// forward declarations
class jrd_rel;
class RecordBuffer;
class RuntimeStatistics;
class DatabaseSnapshot class DatabaseSnapshot
{ {
struct RelationData struct RelationData
@ -38,10 +43,18 @@ class DatabaseSnapshot
RecordBuffer* data; RecordBuffer* data;
}; };
class SharedMemory struct Element
{ {
static const ULONG VERSION; SLONG processId;
static const ULONG DEFAULT_SIZE; SLONG localId;
ULONG length;
};
public:
class SharedData
{
static const ULONG MONITOR_VERSION = 2;
static const ULONG DEFAULT_SIZE = 1048576;
struct Header struct Header
{ {
@ -56,42 +69,40 @@ class DatabaseSnapshot
class DumpGuard class DumpGuard
{ {
public: public:
explicit DumpGuard(SharedMemory* ptr) explicit DumpGuard(SharedData* ptr)
: dump(ptr) : data(ptr)
{ {
dump->acquire(); data->acquire();
} }
~DumpGuard() ~DumpGuard()
{ {
dump->release(); data->release();
} }
private: private:
DumpGuard(const DumpGuard&); DumpGuard(const DumpGuard&);
DumpGuard& operator=(const DumpGuard&); DumpGuard& operator=(const DumpGuard&);
SharedMemory* dump; SharedData* const data;
}; };
public: public:
SharedMemory(); explicit SharedData(const Database*);
~SharedMemory(); ~SharedData();
void acquire(); void acquire();
void release(); void release();
UCHAR* readData(thread_db*, MemoryPool&, ULONG&); UCHAR* read(MemoryPool&, ULONG&);
void writeData(thread_db*, ULONG, const UCHAR*); void write(ULONG, const UCHAR*);
void cleanup(thread_db*);
private: private:
// copying is prohibited // copying is prohibited
SharedMemory(const SharedMemory&); SharedData(const SharedData&);
SharedMemory& operator =(const SharedMemory&); SharedData& operator =(const SharedData&);
void doCleanup(const Database* const dbb); void cleanup();
void extend(); void extend();
static void checkMutex(const TEXT*, int); static void checkMutex(const TEXT*, int);
@ -102,29 +113,18 @@ class DatabaseSnapshot
struct mtx mutex; struct mtx mutex;
#endif #endif
Header* base; Header* base;
const SLONG process_id;
const SLONG local_id;
}; };
struct Element
{
SLONG processId;
SLONG localId;
ULONG length;
};
public:
~DatabaseSnapshot(); ~DatabaseSnapshot();
RecordBuffer* getData(const jrd_rel*) const; RecordBuffer* getData(const jrd_rel*) const;
static DatabaseSnapshot* create(thread_db*); static DatabaseSnapshot* create(thread_db*);
static void cleanup(thread_db*);
static int blockingAst(void*); static int blockingAst(void*);
static void init()
{
dump = FB_NEW(*getDefaultMemoryPool()) SharedMemory;
}
protected: protected:
DatabaseSnapshot(thread_db*, MemoryPool&); DatabaseSnapshot(thread_db*, MemoryPool&);
@ -147,9 +147,6 @@ private:
static void putContextVars(Firebird::StringMap&, Firebird::ClumpletWriter&, int, bool); static void putContextVars(Firebird::StringMap&, Firebird::ClumpletWriter&, int, bool);
static void putMemoryUsage(const Firebird::MemoryStats&, Firebird::ClumpletWriter&, int, int); static void putMemoryUsage(const Firebird::MemoryStats&, Firebird::ClumpletWriter&, int, int);
static SharedMemory* dump;
static Firebird::InitMutex<DatabaseSnapshot> startup;
Firebird::Array<RelationData> snapshot; Firebird::Array<RelationData> snapshot;
Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<SINT64, SLONG> > > idMap; Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<SINT64, SLONG> > > idMap;
int idCounter; int idCounter;

View File

@ -634,8 +634,12 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
switch (work->dfw_type) switch (work->dfw_type)
{ {
case dfw_post_event: case dfw_post_event:
EVENT_post(lock->lck_length, (const TEXT*) &lock->lck_key, EventManager::init(dbb);
work->dfw_name.length(), work->dfw_name.c_str(), work->dfw_count);
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; *ptr = work->dfw_next;
delete work; delete work;
pending_events = true; pending_events = true;
@ -651,7 +655,9 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
} }
if (pending_events) if (pending_events)
EVENT_deliver(); {
dbb->dbb_event_mgr->deliverEvents();
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -20,11 +20,7 @@
* All Rights Reserved. * All Rights Reserved.
* Contributor(s): ______________________________________. * Contributor(s): ______________________________________.
* *
* 23-Feb-2002 Dmitry Yemanov - Events wildcarding
*
*
* 2002-02-23 Sean Leyne - Code Cleanup, removed old Win3.1 port (Windows_Only) * 2002-02-23 Sean Leyne - Code Cleanup, removed old Win3.1 port (Windows_Only)
*
*/ */
#ifndef JRD_EVENT_H #ifndef JRD_EVENT_H
@ -36,16 +32,11 @@
// Global section header // Global section header
const int EVENT_VERSION = 4; 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 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 UCHAR evh_version; // Version number of global section
srq evh_events; // Known events srq evh_events; // Known events
srq evh_processes; // Known processes srq evh_processes; // Known processes
@ -53,11 +44,8 @@ struct evh
SRQ_PTR evh_current_process; // Current process, if any SRQ_PTR evh_current_process; // Current process, if any
struct mtx evh_mutex; // Mutex controlling access struct mtx evh_mutex; // Mutex controlling access
SLONG evh_request_id; // Next request id SLONG evh_request_id; // Next request id
SRQ_PTR evh_hash_table[EVENT_HASH_SIZE];
}; };
typedef evh *EVH;
// Common block header // Common block header
const int type_hdr = 1; // Event 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 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 UCHAR hdr_type; // Type of block
}; };
@ -82,7 +70,6 @@ struct frb
event_hdr frb_header; event_hdr frb_header;
SLONG frb_next; // Next block SLONG frb_next; // Next block
}; };
typedef frb *FRB;
// Process blocks // Process blocks
@ -95,13 +82,13 @@ struct prb
event_t prb_event; // Event on which to wait event_t prb_event; // Event on which to wait
USHORT prb_flags; USHORT prb_flags;
}; };
typedef prb *PRB;
const int PRB_wakeup = 1; // Schedule a wakeup for process const int PRB_wakeup = 1; // Schedule a wakeup for process
const int PRB_pending = 2; // Wakeup has been requested, and is dangling 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 = 4; // need to remap shared memory
const int PRB_remap_over= 8; // remap is over const int PRB_remap_over= 8; // remap is over
const int PRB_exiting = 16; // Process is exiting #endif
// Session block // Session block
@ -113,7 +100,6 @@ struct ses
SRQ_PTR ses_interests; // Historical interests SRQ_PTR ses_interests; // Historical interests
USHORT ses_flags; USHORT ses_flags;
}; };
typedef ses *SES;
const int SES_delivering = 1; // Watcher thread is delivering an event const int SES_delivering = 1; // Watcher thread is delivering an event
const int SES_purge = 2; // delete session after 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 USHORT evnt_length; // Length of event name
TEXT evnt_name[1]; // Event name TEXT evnt_name[1]; // Event name
}; };
typedef evnt *EVNT;
// Request block // Request block
@ -145,7 +130,6 @@ struct evt_req
void *req_ast_arg; // Argument for ast void *req_ast_arg; // Argument for ast
SLONG req_request_id; // Request id, dummy SLONG req_request_id; // Request id, dummy
}; };
typedef evt_req *EVT_REQ;
// Request interest block // Request interest block
@ -158,7 +142,6 @@ struct req_int
SRQ_PTR rint_next; // Next interest of request SRQ_PTR rint_next; // Next interest of request
SLONG rint_count; // Threshold count SLONG rint_count; // Threshold count
}; };
typedef req_int *RINT;
const int EPB_version1 = 1; const int EPB_version1 = 1;

View File

@ -19,21 +19,102 @@
* *
* All Rights Reserved. * All Rights Reserved.
* Contributor(s): ______________________________________. * Contributor(s): ______________________________________.
*
* 23-Feb-2002 Dmitry Yemanov - Events wildcarding
*
*/ */
#ifndef JRD_EVENT_PROTO_H #ifndef JRD_EVENT_PROTO_H
#define JRD_EVENT_PROTO_H #define JRD_EVENT_PROTO_H
void EVENT_cancel(SLONG); #include "../common/classes/init.h"
SLONG EVENT_create_session(); #include "../common/classes/semaphore.h"
void EVENT_delete_session(SLONG); #include "../common/classes/GenericMap.h"
void EVENT_deliver(); #include "../common/classes/RefCounted.h"
void EVENT_post(USHORT, const TEXT*, USHORT, const TEXT*, USHORT); #include "../jrd/ThreadData.h"
SLONG EVENT_que(SLONG, USHORT, const TEXT*, USHORT, const UCHAR*, #include "../jrd/event.h"
FPTR_EVENT_CALLBACK, void*);
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 #endif // JRD_EVENT_PROTO_H

View File

@ -32,27 +32,13 @@
#ifndef JRD_FILE_PARAMS_H #ifndef JRD_FILE_PARAMS_H
#define JRD_FILE_PARAMS_H #define JRD_FILE_PARAMS_H
#ifdef NOHOSTNAME static const char* EVENT_FILE = "fb_event_%s";
static const char* EVENT_FILE = "isc_event1"; static const char* LOCK_FILE = "fb_lock_%s";
static const char* LOCK_FILE = "isc_lock1.gbl"; static const char* MONITOR_FILE = "fb_monitor_%s";
static const char* INIT_FILE = "isc_init1";
static const char* GUARD_FILE = "isc_guard1"; #ifdef UNIX
static const char* MONITOR_FILE = "isc_monitor1"; static const char* INIT_FILE = "fb_init";
static const char* SEM_FILE = "isc_sem1"; static const char* SEM_FILE = "fb_sem";
#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";
#endif #endif
// CVC: Do we really need this information here after using autoconf? // CVC: Do we really need this information here after using autoconf?

View File

@ -3648,7 +3648,7 @@ public:
Firebird::PathName lockPrefix; Firebird::PathName lockPrefix;
if (!fb_utils::readenv(FB_LOCK_ENV, lockPrefix)) if (!fb_utils::readenv(FB_LOCK_ENV, lockPrefix))
{ {
lockPrefix = prefix; lockPrefix = tempDir;
} }
lockPrefix.copyTo(fb_prefix_lock_val, sizeof(fb_prefix_lock_val)); lockPrefix.copyTo(fb_prefix_lock_val, sizeof(fb_prefix_lock_val));
fb_prefix_lock = fb_prefix_lock_val; fb_prefix_lock = fb_prefix_lock_val;

View File

@ -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) USHORT INTL_key_length(thread_db* tdbb, USHORT idxType, USHORT iLength)
{ {
/************************************** /**************************************

View File

@ -43,7 +43,6 @@ int INTL_convert_string(dsc*, const dsc*, ErrorFunction);
int INTL_data(const dsc*); int INTL_data(const dsc*);
int INTL_data_or_binary(const dsc*); int INTL_data_or_binary(const dsc*);
bool INTL_defined_type(Jrd::thread_db*, USHORT); bool INTL_defined_type(Jrd::thread_db*, USHORT);
void INTL_init(Jrd::thread_db*);
USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT); USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT);
Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1); Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1);
Jrd::Collation* INTL_texttype_lookup(Jrd::thread_db* tdbb, USHORT parm1); Jrd::Collation* INTL_texttype_lookup(Jrd::thread_db* tdbb, USHORT parm1);

View File

@ -153,7 +153,7 @@ struct sh_mem
void* sh_mem_object; void* sh_mem_object;
void* sh_mem_interest; void* sh_mem_interest;
void* sh_mem_hdr_object; void* sh_mem_hdr_object;
SLONG* sh_mem_hdr_address; ULONG* sh_mem_hdr_address;
TEXT sh_mem_name[MAXPATHLEN]; TEXT sh_mem_name[MAXPATHLEN];
}; };
typedef sh_mem SH_MEM_T; typedef sh_mem SH_MEM_T;

View File

@ -45,7 +45,7 @@ void* ISC_make_signal(bool, bool, int, int);
typedef void (*FPTR_INIT_GLOBAL_REGION)(void*, struct sh_mem*, bool); typedef void (*FPTR_INIT_GLOBAL_REGION)(void*, struct sh_mem*, bool);
UCHAR* ISC_map_file(ISC_STATUS*, const TEXT*, FPTR_INIT_GLOBAL_REGION, 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) #if defined(WIN_NT)
int ISC_mutex_init(struct mtx*, const TEXT*); int ISC_mutex_init(struct mtx*, const TEXT*);
#else #else
@ -58,8 +58,8 @@ int ISC_mutex_unlock(struct mtx *);
void ISC_mutex_fini(struct mtx *); void ISC_mutex_fini(struct mtx *);
#if defined HAVE_MMAP || defined WIN_NT #if defined HAVE_MMAP || defined WIN_NT
UCHAR* ISC_map_object(ISC_STATUS *, SH_MEM, SLONG, SLONG); UCHAR* ISC_map_object(ISC_STATUS *, SH_MEM, ULONG, ULONG);
void ISC_unmap_object(ISC_STATUS *, SH_MEM, UCHAR **, SLONG); void ISC_unmap_object(ISC_STATUS *, SH_MEM, UCHAR **, ULONG);
#endif #endif
#ifdef UNIX #ifdef UNIX
@ -72,7 +72,7 @@ void ISC_sync_signals_reset();
ULONG ISC_exception_post(ULONG, const TEXT*); ULONG ISC_exception_post(ULONG, const TEXT*);
#endif #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_reset_timer(FPTR_VOID_PTR, void *, SLONG *, void **);
void ISC_set_timer(SLONG, 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 *); void ISC_unmap_file(ISC_STATUS *, struct sh_mem *);

View File

@ -131,7 +131,7 @@ union semun
ushort *array; ushort *array;
}; };
#endif #endif
#endif /* UNIX */ #endif // UNIX
#ifdef HAVE_SYS_PARAM_H #ifdef HAVE_SYS_PARAM_H
#include <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, UCHAR* ISC_map_file(ISC_STATUS* status_vector,
const TEXT* filename, const TEXT* filename,
FPTR_INIT_GLOBAL_REGION init_routine, 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). * 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 /* 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 master lock to eliminate possible race conditions with just a single file
locking. The race condition is caused as the conversion of a EXCLUSIVE locking. The race condition is caused as the conversion of a EXCLUSIVE
lock to a SHARED lock is not atomic*/ lock to a SHARED lock is not atomic*/
TEXT tmp[MAXPATHLEN]; TEXT init_filename[MAXPATHLEN];
gds__prefix_lock(tmp, INIT_FILE); gds__prefix_lock(init_filename, INIT_FILE);
string init_filename; /* to hold the complete filename of the init file. */
init_filename.printf(tmp, hostname); /* already have the hostname! */
const int oldmask = umask(0); const int oldmask = umask(0);
bool trunc_flag = true; const bool trunc_flag = (length != 0);
if (length < 0) {
length = -length;
trunc_flag = false;
}
/* open the init lock file */ /* open the init lock file */
MutexLockGuard guard(openFdInit); MutexLockGuard guard(openFdInit);
@ -1931,7 +1928,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
#else #else
int int
#endif #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) { if (fd_init == -1) {
error(status_vector, "open", errno); error(status_vector, "open", errno);
return NULL; return NULL;
@ -1950,10 +1947,9 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
#ifdef USE_SYS5SEMAPHORE #ifdef USE_SYS5SEMAPHORE
if (fdSem < 0) if (fdSem < 0)
{ {
string semFileName; TEXT sem_filename[MAXPATHLEN];
gds__prefix_lock(tmp, SEM_FILE); gds__prefix_lock(sem_filename, SEM_FILE);
semFileName.printf(tmp, hostname); int f = open(sem_filename, O_RDWR | O_CREAT, 0666);
int f = open(semFileName.c_str(), O_RDWR | O_CREAT, 0666);
if (f == -1) { if (f == -1) {
error(status_vector, "open", errno); error(status_vector, "open", errno);
return NULL; return NULL;
@ -2098,7 +2094,9 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
UCHAR* ISC_map_file(ISC_STATUS* status_vector, UCHAR* ISC_map_file(ISC_STATUS* status_vector,
const TEXT* filename, const TEXT* filename,
FPTR_INIT_GLOBAL_REGION init_routine, 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). * routine (if given) or punt (leaving the file unmapped).
* *
**************************************/ **************************************/
//SSHORT count;
TEXT expanded_filename[512]; TEXT expanded_filename[MAXPATHLEN];
#ifdef NOHOSTNAME gds__prefix_lock(expanded_filename, filename);
strcpy(expanded_filename, filename);
#else
TEXT hostname[64];
sprintf(expanded_filename, filename, ISC_get_host(hostname, sizeof(hostname)));
#endif
const int oldmask = umask(0); const int oldmask = umask(0);
bool init_flag = false; bool init_flag = false;
if (length < 0)
length = -length;
/* Produce shared memory key for file */ /* Produce shared memory key for file */
@ -2383,13 +2375,12 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector,
#ifdef WIN_NT #ifdef WIN_NT
UCHAR* ISC_map_file( UCHAR* ISC_map_file(ISC_STATUS* status_vector,
ISC_STATUS* status_vector, const TEXT* filename,
const TEXT* filename, FPTR_INIT_GLOBAL_REGION init_routine,
FPTR_INIT_GLOBAL_REGION init_routine, void* init_arg,
void* init_arg, ULONG length,
SLONG length, SH_MEM shmem_data)
SH_MEM shmem_data)
{ {
/************************************** /**************************************
* *
@ -2403,17 +2394,14 @@ UCHAR* ISC_map_file(
* routine (if given) or punt (leaving the file unmapped). * routine (if given) or punt (leaving the file unmapped).
* *
**************************************/ **************************************/
TEXT expanded_filename[MAXPATHLEN], hostname[64]; TEXT object_name[MAXPATHLEN];
TEXT map_file[MAXPATHLEN];
HANDLE file_handle, event_handle; HANDLE file_handle, event_handle;
int retry_count = 0; int retry_count = 0;
bool trunc_flag = true; TEXT expanded_filename[MAXPATHLEN];
if (length < 0) { gds__prefix_lock(expanded_filename, filename);
length = -length;
fb_assert(length > 0); // Was someone so crazy as to pass a bigger value than MAX_SLONG? const bool trunc_flag = (length != 0);
trunc_flag = false;
}
/* retry to attach to mmapped file if the process initializing /* retry to attach to mmapped file if the process initializing
* dies during initialization. * dies during initialization.
@ -2422,16 +2410,13 @@ UCHAR* ISC_map_file(
retry: retry:
retry_count++; retry_count++;
ISC_get_host(hostname, sizeof(hostname)); file_handle = CreateFile(expanded_filename,
sprintf(map_file, filename, hostname); GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
file_handle = CreateFile(map_file, NULL,
GENERIC_READ | GENERIC_WRITE, OPEN_ALWAYS,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_ATTRIBUTE_NORMAL,
NULL, NULL);
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (file_handle == INVALID_HANDLE_VALUE) { if (file_handle == INVALID_HANDLE_VALUE) {
error(status_vector, "CreateFile", GetLastError()); error(status_vector, "CreateFile", GetLastError());
return NULL; return NULL;
@ -2444,14 +2429,14 @@ UCHAR* ISC_map_file(
// Create an event that can be used to determine if someone has already // Create an event that can be used to determine if someone has already
// initialized shared memory. // 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()); error(status_vector, "make_object_name", GetLastError());
CloseHandle(file_handle); CloseHandle(file_handle);
return NULL; 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) { if (!event_handle) {
error(status_vector, "CreateEvent", GetLastError()); error(status_vector, "CreateEvent", GetLastError());
CloseHandle(file_handle); CloseHandle(file_handle);
@ -2512,13 +2497,13 @@ UCHAR* ISC_map_file(
else else
fdw_create = OPEN_ALWAYS; fdw_create = OPEN_ALWAYS;
file_handle = CreateFile(map_file, file_handle = CreateFile(expanded_filename,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, NULL,
fdw_create, fdw_create,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL); NULL);
if (file_handle == INVALID_HANDLE_VALUE) { if (file_handle == INVALID_HANDLE_VALUE) {
CloseHandle(event_handle); CloseHandle(event_handle);
error(status_vector, "CreateFile", GetLastError()); error(status_vector, "CreateFile", GetLastError());
@ -2528,7 +2513,7 @@ UCHAR* ISC_map_file(
/* Create a file mapping object that will be used to make remapping possible. /* 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. */ 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()); error(status_vector, "make_object_name", GetLastError());
CloseHandle(event_handle); CloseHandle(event_handle);
@ -2536,12 +2521,11 @@ UCHAR* ISC_map_file(
return NULL; return NULL;
} }
HANDLE header_obj = CreateFileMapping ((HANDLE) -1, HANDLE header_obj = CreateFileMapping(INVALID_HANDLE_VALUE,
ISC_get_security_desc(), ISC_get_security_desc(),
PAGE_READWRITE, PAGE_READWRITE,
0, 0, 2 * sizeof(ULONG),
2 * sizeof (SLONG), object_name);
expanded_filename);
if (header_obj == NULL) if (header_obj == NULL)
{ {
error(status_vector, "CreateFileMapping", GetLastError()); error(status_vector, "CreateFileMapping", GetLastError());
@ -2561,7 +2545,7 @@ UCHAR* ISC_map_file(
goto retry; 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) { if (header_address == NULL) {
error(status_vector, "MapViewOfFile", GetLastError()); error(status_vector, "MapViewOfFile", GetLastError());
@ -2583,16 +2567,14 @@ UCHAR* ISC_map_file(
/* Create the real file mapping object. */ /* Create the real file mapping object. */
TEXT mapping_filename[sizeof(expanded_filename) + 15]; // enough for int32 as text TEXT mapping_name[MAXPATHLEN + 15]; // enough for int32 as text
sprintf(mapping_filename, "%s%"SLONGFORMAT, expanded_filename, header_address[1]); sprintf(mapping_name, "%s_mapping_%"ULONGFORMAT, filename, header_address[1]);
HANDLE file_obj = HANDLE file_obj = CreateFileMapping(file_handle,
CreateFileMapping(file_handle, ISC_get_security_desc(),
ISC_get_security_desc(), PAGE_READWRITE,
PAGE_READWRITE, 0, length,
0, mapping_name);
length,
mapping_filename);
if (file_obj == NULL) { if (file_obj == NULL) {
error(status_vector, "CreateFileMapping", GetLastError()); error(status_vector, "CreateFileMapping", GetLastError());
UnmapViewOfFile(header_address); UnmapViewOfFile(header_address);
@ -2628,7 +2610,7 @@ UCHAR* ISC_map_file(
shmem_data->sh_mem_interest = event_handle; shmem_data->sh_mem_interest = event_handle;
shmem_data->sh_mem_hdr_object = header_obj; shmem_data->sh_mem_hdr_object = header_obj;
shmem_data->sh_mem_hdr_address = header_address; 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) if (init_routine)
(*init_routine) (init_arg, shmem_data, init_flag); (*init_routine) (init_arg, shmem_data, init_flag);
@ -2636,7 +2618,7 @@ UCHAR* ISC_map_file(
if (init_flag) { if (init_flag) {
FlushViewOfFile(address, 0); FlushViewOfFile(address, 0);
SetEvent(event_handle); 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) || !SetEndOfFile(shmem_data->sh_mem_handle) ||
!FlushViewOfFile(shmem_data->sh_mem_address, 0)) !FlushViewOfFile(shmem_data->sh_mem_address, 0))
{ {
@ -2651,9 +2633,10 @@ UCHAR* ISC_map_file(
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
UCHAR *ISC_map_object(ISC_STATUS * status_vector, UCHAR* ISC_map_object(ISC_STATUS* status_vector,
SH_MEM shmem_data, 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. */ /* Get system page size as this is the unit of mapping. */
#ifdef SOLARIS #ifdef SOLARIS
const SLONG page_size = sysconf(_SC_PAGESIZE); const ULONG page_size = sysconf(_SC_PAGESIZE);
if (page_size == -1) { if (page_size == -1) {
error(status_vector, "sysconf", errno); error(status_vector, "sysconf", errno);
return NULL; return NULL;
} }
#else #else
const SLONG page_size = (int) getpagesize(); const ULONG page_size = (int) getpagesize();
if (page_size == -1) { if (page_size == -1) {
error(status_vector, "getpagesize", errno); error(status_vector, "getpagesize", errno);
return NULL; return NULL;
@ -2684,9 +2667,9 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector,
/* Compute the start and end page-aligned offsets which /* Compute the start and end page-aligned offsets which
contain the object being mapped. */ contain the object being mapped. */
const SLONG start = (object_offset / page_size) * page_size; const ULONG start = (object_offset / page_size) * page_size;
const SLONG end = (((object_offset + object_length) / page_size) + 1) * page_size; const ULONG end = FB_ALIGN(object_offset + object_length, page_size);
const SLONG length = end - start; const ULONG length = end - start;
int fd = shmem_data->sh_mem_handle; int fd = shmem_data->sh_mem_handle;
UCHAR* address = (UCHAR*) mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); 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, void ISC_unmap_object(ISC_STATUS* status_vector,
SH_MEM shmem_data, 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. */ /* Get system page size as this is the unit of mapping. */
#ifdef SOLARIS #ifdef SOLARIS
const SLONG page_size = sysconf(_SC_PAGESIZE); const ULONG page_size = sysconf(_SC_PAGESIZE);
if (page_size == -1) { if (page_size == -1) {
error(status_vector, "sysconf", errno); error(status_vector, "sysconf", errno);
return; // false; return; // false;
} }
#else #else
const SLONG page_size = (int) getpagesize(); const ULONG page_size = (int) getpagesize();
if (page_size == -1) { if (page_size == -1) {
error(status_vector, "getpagesize", errno); error(status_vector, "getpagesize", errno);
return; // false; return; // false;
@ -2741,7 +2725,7 @@ void ISC_unmap_object(ISC_STATUS* status_vector,
UCHAR* start = (UCHAR *) ((U_IPTR) * object_pointer & ~(page_size - 1)); UCHAR* start = (UCHAR *) ((U_IPTR) * object_pointer & ~(page_size - 1));
const UCHAR* end = const UCHAR* end =
(UCHAR*) ((U_IPTR) ((*object_pointer + object_length) + (page_size - 1)) & ~(page_size - 1)); (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) { if (munmap((char *) start, length) == -1) {
error(status_vector, "munmap", errno); error(status_vector, "munmap", errno);
@ -2757,7 +2741,8 @@ void ISC_unmap_object(ISC_STATUS* status_vector,
#ifdef WIN_NT #ifdef WIN_NT
UCHAR* ISC_map_object(ISC_STATUS* status_vector, UCHAR* ISC_map_object(ISC_STATUS* status_vector,
SH_MEM shmem_data, 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; SYSTEM_INFO sys_info;
GetSystemInfo(&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 // Compute the start and end page-aligned offsets which
// contain the object being mapped. // contain the object being mapped.
const SLONG start = (object_offset / page_size) * page_size; const ULONG start = (object_offset / page_size) * page_size;
const SLONG end = (((object_offset + object_length) / page_size) + 1) * page_size; const ULONG end = FB_ALIGN(object_offset + object_length, page_size);
const SLONG length = end - start; const ULONG length = end - start;
const HANDLE handle = shmem_data->sh_mem_object; const HANDLE handle = shmem_data->sh_mem_object;
UCHAR* address = (UCHAR*) MapViewOfFile(handle, FILE_MAP_WRITE, 0, start, length); 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, void ISC_unmap_object(ISC_STATUS* status_vector,
SH_MEM shmem_data, 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; SYSTEM_INFO sys_info;
GetSystemInfo(&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 // Compute the start and end page-aligned offsets which
// contain the object being mapped. // contain the object being mapped.
@ -3623,8 +3609,10 @@ void ISC_mutex_set_spin_count (struct mtx *mutex, ULONG spins)
#ifdef UNIX #ifdef UNIX
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
#define ISC_REMAP_FILE_DEFINED #define ISC_REMAP_FILE_DEFINED
UCHAR *ISC_remap_file(ISC_STATUS * status_vector, 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)
{ {
/************************************** /**************************************
* *
@ -3669,9 +3657,9 @@ UCHAR *ISC_remap_file(ISC_STATUS * status_vector,
#ifdef WIN_NT #ifdef WIN_NT
#define ISC_REMAP_FILE_DEFINED #define ISC_REMAP_FILE_DEFINED
UCHAR* ISC_remap_file(ISC_STATUS * status_vector, UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
SH_MEM shmem_data, SH_MEM shmem_data,
SLONG new_length, ULONG new_length,
bool flag) bool flag)
{ {
/************************************** /**************************************
* *
@ -3686,7 +3674,7 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
if (flag) 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) || !SetEndOfFile(shmem_data->sh_mem_handle) ||
!FlushViewOfFile(shmem_data->sh_mem_address, 0)) !FlushViewOfFile(shmem_data->sh_mem_address, 0))
{ {
@ -3709,16 +3697,15 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
HANDLE file_obj; HANDLE file_obj;
while (true) { while (true) {
TEXT expanded_filename[MAXPATHLEN]; TEXT mapping_name[MAXPATHLEN + 15]; // enough for int32 as text
sprintf(expanded_filename, "%s%"SLONGFORMAT, shmem_data->sh_mem_name, sprintf(mapping_name, "%s_mapping_%"ULONGFORMAT,
shmem_data->sh_mem_hdr_address[1] + 1); shmem_data->sh_mem_name, shmem_data->sh_mem_hdr_address[1] + 1);
file_obj = CreateFileMapping(shmem_data->sh_mem_handle, file_obj = CreateFileMapping(shmem_data->sh_mem_handle,
ISC_get_security_desc(), ISC_get_security_desc(),
PAGE_READWRITE, PAGE_READWRITE,
0, 0, new_length,
new_length, mapping_name);
expanded_filename);
if (!((GetLastError() == ERROR_ALREADY_EXISTS) && flag)) if (!((GetLastError() == ERROR_ALREADY_EXISTS) && flag))
break; break;
@ -3766,7 +3753,7 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
#ifndef ISC_REMAP_FILE_DEFINED #ifndef ISC_REMAP_FILE_DEFINED
UCHAR* ISC_remap_file(ISC_STATUS * status_vector, UCHAR* ISC_remap_file(ISC_STATUS * status_vector,
SH_MEM shmem_data, SH_MEM shmem_data,
SLONG new_length, ULONG new_length,
bool flag) bool flag)
{ {
/************************************** /**************************************

View File

@ -861,9 +861,6 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
bool first = false; 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 (dbb->dbb_filename.empty())
{ {
#if defined(DEV_BUILD) && defined(SUPERSERVER) #if defined(DEV_BUILD) && defined(SUPERSERVER)
@ -891,19 +888,22 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
else else
dbb->dbb_database_name = expanded_name; dbb->dbb_database_name = expanded_name;
// Extra LCK_init() done to keep the lock table until the PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
// database is shutdown() after the last detach. 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); LCK_init(tdbb, LCK_OWNER_database);
dbb->dbb_flags |= DBB_lck_init_done; dbb->dbb_flags |= DBB_lck_init_done;
INI_init(tdbb); LCK_init(tdbb, LCK_OWNER_attachment);
attachment->att_flags |= ATT_lck_init_done;
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
pageSpace->file = PIO_open(dbb, expanded_name, file_name, false);
// Initialize locks // Initialize locks
init_database_locks(tdbb); init_database_locks(tdbb);
INI_init(tdbb);
SHUT_init(tdbb); SHUT_init(tdbb);
PAG_header_init(tdbb); PAG_header_init(tdbb);
INI_init2(tdbb); INI_init2(tdbb);
@ -939,6 +939,11 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
// looks like someone tries to attach incompatibly // looks like someone tries to attach incompatibly
status_exception::raise(Arg::Gds(isc_bad_dpb_content)); 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 // 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, ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status, Attachment** handle, SLONG* id)
Attachment** handle,
SLONG* id)
{ {
/************************************** /**************************************
* *
@ -1383,7 +1386,12 @@ ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status,
DatabaseContextHolder dbbHolder(tdbb); DatabaseContextHolder dbbHolder(tdbb);
check_database(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) 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; 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; initing_security = false;
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); 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; 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 // Initialize locks
init_database_locks(tdbb); init_database_locks(tdbb);
INI_init(tdbb);
PAG_init(tdbb);
initing_security = true;
SCL_init(tdbb, true, userId);
if (options.dpb_set_page_buffers) if (options.dpb_set_page_buffers)
dbb->dbb_page_buffers = options.dpb_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(); Database* const dbb = tdbb->getDatabase();
Lock* const lock = dbb->dbb_lock; Lock* const lock = dbb->dbb_lock;
EventManager::init(dbb);
if (!attachment->att_event_session) 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, *id = dbb->dbb_event_mgr->queEvents(attachment->att_event_session,
(const TEXT*) &lock->lck_key, length, items, ast, arg); lock->lck_length, (const TEXT*) &lock->lck_key,
length, items,
ast, arg);
} }
catch (const Exception& ex) 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 // Initialize a number of subsystems
TRA_init(dbb); TRA_init(dbb);
@ -4672,8 +4682,6 @@ static Database* init(thread_db* tdbb,
dbb->dbb_decrypt = (Database::crypt_routine) crypt_lib.lookupSymbol(decrypt_entrypoint); dbb->dbb_decrypt = (Database::crypt_routine) crypt_lib.lookupSymbol(decrypt_entrypoint);
} }
INTL_init(tdbb);
return dbb; return dbb;
} }
@ -4838,8 +4846,10 @@ static void release_attachment(thread_db* tdbb, Attachment* attachment, ISC_STAT
} }
#endif #endif
if (attachment->att_event_session) if (dbb->dbb_event_mgr && attachment->att_event_session)
EVENT_delete_session(attachment->att_event_session); {
dbb->dbb_event_mgr->deleteSession(attachment->att_event_session);
}
if (attachment->att_id_lock) if (attachment->att_id_lock)
LCK_release(tdbb, 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); detachLocksFromAttachment(attachment);
if (attachment->att_flags & ATT_lck_init_done) { 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; attachment->att_flags &= ~ATT_lck_init_done;
} }
@ -5088,8 +5098,6 @@ static void shutdown_database(Database* dbb, const bool release_pools)
CMP_fini(tdbb); CMP_fini(tdbb);
CCH_fini(tdbb); CCH_fini(tdbb);
DatabaseSnapshot::cleanup(tdbb);
if (dbb->dbb_backup_manager) if (dbb->dbb_backup_manager)
dbb->dbb_backup_manager->shutdown(tdbb); 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) { if (dbb->dbb_flags & DBB_lck_init_done) {
dbb->dbb_page_manager.releaseLocks(); 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; dbb->dbb_flags &= ~DBB_lck_init_done;
} }

View File

@ -39,6 +39,7 @@
#include "../common/classes/alloc.h" #include "../common/classes/alloc.h"
#include "../common/classes/init.h" #include "../common/classes/init.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../jrd/ThreadStart.h"
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>

View File

@ -36,6 +36,7 @@
#include "../include/fb_blk.h" #include "../include/fb_blk.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../jrd/ods.h"
namespace Jrd { namespace Jrd {

View File

@ -96,7 +96,7 @@
#include <process.h> #include <process.h>
#define MUTEX &m_shmemMutex #define MUTEX &m_shmemMutex
#else #else
#define MUTEX m_header->lhb_mutex #define MUTEX &m_header->lhb_mutex
#endif #endif
#ifdef DEV_BUILD #ifdef DEV_BUILD
@ -159,17 +159,12 @@ static const bool compatibility[LCK_max][LCK_max] =
namespace Jrd { namespace Jrd {
const char* LockManager::PATTERN = "firebird_db_%d_lock";
Firebird::GlobalPtr<LockManager::DbLockMgrMap> LockManager::g_lmMap; Firebird::GlobalPtr<LockManager::DbLockMgrMap> LockManager::g_lmMap;
Firebird::GlobalPtr<Firebird::Mutex> LockManager::g_mapMutex; 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); Firebird::MutexLockGuard guard(g_mapMutex);
LockManager* lockMgr = NULL; LockManager* lockMgr = NULL;
@ -180,26 +175,24 @@ LockManager* LockManager::create(const Firebird::PathName& filename)
fb_assert(lockMgr); fb_assert(lockMgr);
lockMgr->addRef();
return lockMgr; return lockMgr;
} }
LockManager::LockManager(int dbId)
LockManager::LockManager(const Firebird::string& id)
: PID(getpid()), : PID(getpid()),
m_bugcheck(false), m_bugcheck(false),
m_header(NULL), m_header(NULL),
m_process(NULL), m_process(NULL),
m_processOffset(0), m_processOffset(0),
m_dbId(dbId), m_dbId(getPool(), id)
m_lockFile(getPool())
{ {
// m_lockFile.printf(PATTERN, m_dbId); Firebird::string name;
TEXT buffer[MAXPATHLEN]; name.printf(LOCK_FILE, m_dbId.c_str());
gds__prefix_lock(buffer, LOCK_FILE);
m_lockFile = buffer;
ISC_STATUS_ARRAY local_status; 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, initialize, this,
Config::getLockMemSize(), Config::getLockMemSize(),
&m_shmem))) &m_shmem)))
@ -207,6 +200,8 @@ LockManager::LockManager(int dbId)
Firebird::status_exception::raise(local_status); Firebird::status_exception::raise(local_status);
} }
fb_assert(m_header->lhb_version == LHB_VERSION);
Firebird::MutexLockGuard guard(g_mapMutex); Firebird::MutexLockGuard guard(g_mapMutex);
if (g_lmMap->put(m_dbId, this)) if (g_lmMap->put(m_dbId, this))
@ -251,10 +246,9 @@ LockManager::~LockManager()
release_mutex(); release_mutex();
} }
ISC_mutex_fini(MUTEX);
if (m_header) if (m_header)
{ {
ISC_mutex_fini(MUTEX);
ISC_unmap_file(local_status, &m_shmem); ISC_unmap_file(local_status, &m_shmem);
} }
@ -507,7 +501,7 @@ SRQ_PTR LockManager::enqueue(thread_db* tdbb,
else { else {
++m_header->lhb_operations[0]; ++m_header->lhb_operations[0];
} }
insert_tail(&lock->lbl_requests, &request->lrq_lbl_requests); insert_tail(&lock->lbl_requests, &request->lrq_lbl_requests);
request->lrq_data = data; request->lrq_data = data;
const SRQ_PTR lock_id = grant_or_que(tdbb, request, lock, lck_wait); const SRQ_PTR lock_id = grant_or_que(tdbb, request, lock, lck_wait);
@ -1062,7 +1056,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset)
#endif #endif
) )
{ {
const SLONG length = m_header->lhb_length; const ULONG new_length = m_header->lhb_length;
#if (defined HAVE_MMAP || defined WIN_NT) #if (defined HAVE_MMAP || defined WIN_NT)
Firebird::WriteLockGuard guard(m_remapSync); Firebird::WriteLockGuard guard(m_remapSync);
@ -1070,7 +1064,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset)
remap_local_owners(); remap_local_owners();
// Remap the shared memory region // Remap the shared memory region
ISC_STATUS_ARRAY status_vector; 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) if (header)
m_header = header; m_header = header;
else 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); size = FB_ALIGN(size, FB_ALIGNMENT);
ASSERT_ACQUIRED; ASSERT_ACQUIRED;
const ULONG block = m_header->lhb_used; 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. // 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 if (m_header->lhb_used + size > 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
)
{ {
const bool extend = (m_header->lhb_used > m_header->lhb_length);
m_header->lhb_used -= size;
#if (defined HAVE_MMAP || defined WIN_NT) #if (defined HAVE_MMAP || defined WIN_NT)
Firebird::WriteLockGuard guard(m_remapSync); Firebird::WriteLockGuard guard(m_remapSync);
// Post remapping notifications // Post remapping notifications
remap_local_owners(); remap_local_owners();
// Remap the shared memory region // Remap the shared memory region
const ULONG length = m_shmem.sh_mem_length_mapped + (extend ? Config::getLockMemSize() : 0); const ULONG new_length = m_shmem.sh_mem_length_mapped + Config::getLockMemSize();
lhb* header = (lhb*) ISC_remap_file(status_vector, &m_shmem, length, true); lhb* header = (lhb*) ISC_remap_file(status_vector, &m_shmem, new_length, true);
if (header) { if (header) {
m_header = header; m_header = header;
ASSERT_ACQUIRED; ASSERT_ACQUIRED;
m_header->lhb_length = m_shmem.sh_mem_length_mapped; m_header->lhb_length = m_shmem.sh_mem_length_mapped;
m_header->lhb_used += size;
} }
else else
#endif #endif
@ -1169,6 +1153,8 @@ UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector)
} }
} }
m_header->lhb_used += size;
#ifdef DEV_BUILD #ifdef DEV_BUILD
// This version of alloc() doesn't initialize memory. To shake out // This version of alloc() doesn't initialize memory. To shake out
// any bugs, in DEV_BUILD we initialize it to a "funny" pattern. // 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() void LockManager::blocking_action_thread()
{ {
/************************************** /**************************************
@ -1334,14 +1312,12 @@ void LockManager::blocking_action_thread()
try try
{ {
SRQ_PTR* process_offset_ptr = (SRQ_PTR*) &m_processOffset;
while (true) while (true)
{ {
m_localMutex.enter(); m_localMutex.enter();
// See if the main thread has requested us to go away // 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) if (atStartup)
{ {
@ -1357,7 +1333,7 @@ void LockManager::blocking_action_thread()
Firebird::HalfStaticArray<SRQ_PTR, 4> blocking_owners; Firebird::HalfStaticArray<SRQ_PTR, 4> blocking_owners;
acquire_shmem(DUMMY_OWNER); 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* lock_srq;
SRQ_LOOP(process->prc_owners, lock_srq) SRQ_LOOP(process->prc_owners, lock_srq)
@ -1368,7 +1344,7 @@ void LockManager::blocking_action_thread()
release_mutex(); release_mutex();
while (blocking_owners.getCount() && *process_offset_ptr) while (blocking_owners.getCount() && m_processOffset)
{ {
const SRQ_PTR owner_offset = blocking_owners.pop(); const SRQ_PTR owner_offset = blocking_owners.pop();
acquire_shmem(owner_offset); acquire_shmem(owner_offset);
@ -1466,6 +1442,18 @@ void LockManager::bug(ISC_STATUS* status_vector, const TEXT* string)
{ {
m_bugcheck = true; 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 the current mutex acquirer is in the same process, release the mutex
if (m_header && (m_header->lhb_active_owner > 0)) { 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) if (m_header->lhb_version != LHB_VERSION)
{ {
TEXT bug_buffer[BUFFER_TINY]; TEXT bug_buffer[BUFFER_TINY];
sprintf(bug_buffer, sprintf(bug_buffer, "inconsistent lock table version number; found %d, expected %d",
"inconsistent lock table version number; found %d, expected %d",
m_header->lhb_version, LHB_VERSION); m_header->lhb_version, LHB_VERSION);
bug(status_vector, bug_buffer); bug(status_vector, bug_buffer);
return false; 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_count = 1;
owner->own_owner_id = owner_id; owner->own_owner_id = owner_id;
owner->own_process = m_processOffset; owner->own_process = m_processOffset;
owner->own_thread_id = 0;
SRQ_INIT(owner->own_lhb_owners); SRQ_INIT(owner->own_lhb_owners);
SRQ_INIT(owner->own_prc_owners); SRQ_INIT(owner->own_prc_owners);
SRQ_INIT(owner->own_requests); SRQ_INIT(owner->own_requests);
@ -2177,7 +2165,7 @@ void LockManager::initialize(SH_MEM shmem_data, bool initialize)
* *
**************************************/ **************************************/
#ifdef WIN_NT #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"); bug(NULL, "mutex init failed");
} }
#endif #endif
@ -2236,7 +2224,7 @@ void LockManager::initialize(SH_MEM shmem_data, bool initialize)
if (Config::getLockGrantOrder()) if (Config::getLockGrantOrder())
m_header->lhb_flags |= LHB_lock_ordering; 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_length = shmem_data->sh_mem_length_mapped;
m_header->lhb_used = FB_ALIGN(length, FB_ALIGNMENT); m_header->lhb_used = FB_ALIGN(length, FB_ALIGNMENT);

View File

@ -90,14 +90,12 @@ const SSHORT LCK_NO_WAIT = 0;
const UCHAR type_null = 0; const UCHAR type_null = 0;
const UCHAR type_lhb = 1; const UCHAR type_lhb = 1;
const UCHAR type_prb = 2; const UCHAR type_lrq = 2;
const UCHAR type_lrq = 3; const UCHAR type_lbl = 3;
const UCHAR type_lbl = 4; const UCHAR type_his = 4;
const UCHAR type_his = 5; const UCHAR type_shb = 5;
const UCHAR type_smbx = 6; const UCHAR type_own = 6;
const UCHAR type_shb = 7; const UCHAR type_lpr = 7;
const UCHAR type_own = 8;
const UCHAR type_lpr = 9;
const UCHAR type_MAX = type_lpr; const UCHAR type_MAX = type_lpr;
// Version number of the lock table. // Version number of the lock table.
@ -134,11 +132,11 @@ struct lhb
srq lhb_free_owners; // Free owner blocks srq lhb_free_owners; // Free owner blocks
srq lhb_free_locks; // Free lock blocks srq lhb_free_locks; // Free lock blocks
srq lhb_free_requests; // Free lock requests srq lhb_free_requests; // Free lock requests
SLONG lhb_length; // Size of lock table ULONG lhb_length; // Size of lock table
SLONG lhb_used; // Bytes of lock table in use ULONG lhb_used; // Bytes of lock table in use
USHORT lhb_hash_slots; // Number of hash slots allocated USHORT lhb_hash_slots; // Number of hash slots allocated
USHORT lhb_flags; // Miscellaneous info USHORT lhb_flags; // Miscellaneous info
mtx lhb_mutex[1]; // Mutex controlling access struct mtx lhb_mutex; // Mutex controlling access
SRQ_PTR lhb_history; SRQ_PTR lhb_history;
ULONG lhb_scan_interval; // Deadlock scan interval (secs) ULONG lhb_scan_interval; // Deadlock scan interval (secs)
ULONG lhb_acquire_spins; ULONG lhb_acquire_spins;

View File

@ -43,16 +43,15 @@ class thread_db;
class LockManager : public Firebird::RefCounted, public Firebird::GlobalStorage 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<DbLockMgrMap> g_lmMap;
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex; static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
static const char* PATTERN;
const int PID; const int PID;
public: public:
static LockManager* create(const Firebird::PathName&); static LockManager* create(const Firebird::string&);
bool initializeOwner(thread_db*, LOCK_OWNER_T, UCHAR, SRQ_PTR*); bool initializeOwner(thread_db*, LOCK_OWNER_T, UCHAR, SRQ_PTR*);
void shutdownOwner(thread_db*, SRQ_PTR*); void shutdownOwner(thread_db*, SRQ_PTR*);
@ -72,7 +71,7 @@ public:
SLONG writeData(SRQ_PTR, SLONG); SLONG writeData(SRQ_PTR, SLONG);
private: private:
explicit LockManager(int); explicit LockManager(const Firebird::string&);
~LockManager(); ~LockManager();
bool lockOrdering() const bool lockOrdering() const
@ -81,7 +80,7 @@ private:
} }
void acquire_shmem(SRQ_PTR); void acquire_shmem(SRQ_PTR);
UCHAR* alloc(SSHORT, ISC_STATUS*); UCHAR* alloc(USHORT, ISC_STATUS*);
lbl* alloc_lock(USHORT, ISC_STATUS*); lbl* alloc_lock(USHORT, ISC_STATUS*);
void blocking_action(thread_db*, SRQ_PTR, SRQ_PTR); void blocking_action(thread_db*, SRQ_PTR, SRQ_PTR);
void blocking_action_thread(); void blocking_action_thread();
@ -133,7 +132,12 @@ private:
#endif #endif
USHORT wait_for_request(thread_db*, lrq*, SSHORT); 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) static void initialize(void* arg, SH_MEM shmem, bool init)
{ {
@ -155,8 +159,7 @@ private:
Firebird::Semaphore m_cleanupSemaphore; Firebird::Semaphore m_cleanupSemaphore;
Firebird::Semaphore m_startupSemaphore; Firebird::Semaphore m_startupSemaphore;
const int m_dbId; Firebird::string m_dbId;
Firebird::PathName m_lockFile;
#ifdef WIN_NT #ifdef WIN_NT
struct mtx m_shmemMutex; struct mtx m_shmemMutex;

View File

@ -67,6 +67,8 @@ const char* INTERBASE_USER = "interbase";
const char* FIREBIRD_USER = "firebird"; const char* FIREBIRD_USER = "firebird";
const char* INTERBASE_USER_SHORT= "interbas"; const char* INTERBASE_USER_SHORT= "interbas";
const char* GUARD_FILE = "fb_guard";
volatile sig_atomic_t shutting_down; volatile sig_atomic_t shutting_down;

View File

@ -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 */ /* get the file name and prepend the complete path etc */
gds__prefix_lock(tmp, file); gds__prefix(expanded_filename, file);
sprintf(expanded_filename, tmp, ISC_get_host(hostname, sizeof(hostname)));
/* file fd for the opened and locked file */ /* file fd for the opened and locked file */
int fd_file = open(expanded_filename, O_RDWR | O_CREAT, 0666); int fd_file = open(expanded_filename, O_RDWR | O_CREAT, 0666);