2009-02-01 23:07:35 +01:00
|
|
|
/*
|
|
|
|
* PROGRAM: Firebird Trace Services
|
|
|
|
* MODULE: TraceConfigStorage.cpp
|
|
|
|
* DESCRIPTION: Trace API shared configurations storage
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Initial
|
|
|
|
* Developer's Public License Version 1.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed AS IS,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing rights
|
|
|
|
* and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Khorsun Vladyslav
|
|
|
|
* for the Firebird Open Source RDBMS project.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2008 Khorsun Vladyslav <hvlad@users.sourceforge.net>
|
|
|
|
* and all contributors signed below.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
|
|
|
#include "../../common/classes/TempFile.h"
|
|
|
|
#include "../../common/StatusArg.h"
|
2009-02-20 17:18:12 +01:00
|
|
|
#include "../../common/utils_proto.h"
|
2009-02-01 23:07:35 +01:00
|
|
|
#include "../../jrd/common.h"
|
|
|
|
#include "../../jrd/err_proto.h"
|
|
|
|
#include "../../jrd/isc_proto.h"
|
|
|
|
#include "../../jrd/isc_s_proto.h"
|
|
|
|
#include "../../jrd/jrd.h"
|
|
|
|
#include "../../jrd/os/path_utils.h"
|
|
|
|
#include "../../jrd/os/config_root.h"
|
|
|
|
#include "../../jrd/trace/TraceConfigStorage.h"
|
|
|
|
|
2009-02-02 14:31:20 +01:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_IO_H
|
2009-02-02 14:11:48 +01:00
|
|
|
#include <io.h>
|
2009-02-02 14:31:20 +01:00
|
|
|
#endif
|
2009-02-02 14:11:48 +01:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2009-02-02 14:31:20 +01:00
|
|
|
#ifndef O_BINARY
|
|
|
|
#define O_BINARY 0
|
|
|
|
#endif
|
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
using namespace Firebird;
|
|
|
|
|
|
|
|
namespace Jrd {
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
|
2009-02-11 02:32:09 +01:00
|
|
|
void checkFileError(const char* filename, const char* operation, ISC_STATUS iscError)
|
2009-02-10 12:32:11 +01:00
|
|
|
{
|
|
|
|
if (errno == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
// we can't use SYS_ERR(errno) on Windows as errno codes is not
|
|
|
|
// the same as GetLastError() codes
|
2009-02-11 02:32:09 +01:00
|
|
|
const char* strErr = strerror(errno);
|
2009-02-10 12:32:11 +01:00
|
|
|
|
|
|
|
ERR_post(Arg::Gds(isc_io_error) << Arg::Str(operation) << Arg::Str(filename) <<
|
|
|
|
Arg::Gds(iscError) << Arg::Str(strErr));
|
|
|
|
#else
|
|
|
|
ERR_post(Arg::Gds(isc_io_error) << Arg::Str(operation) << Arg::Str(filename) <<
|
|
|
|
Arg::Gds(iscError) << SYS_ERR(errno));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
ConfigStorage::ConfigStorage()
|
|
|
|
{
|
|
|
|
m_base = NULL;
|
|
|
|
m_cfg_file = -1;
|
|
|
|
m_dirty = false;
|
|
|
|
|
|
|
|
PathName filename;
|
|
|
|
filename.printf(TRACE_FILE); // TODO: it must be per engine instance
|
|
|
|
|
|
|
|
ISC_STATUS_ARRAY status;
|
|
|
|
ISC_map_file(status, filename.c_str(), initShMem, this, sizeof(ShMemHeader), &m_handle);
|
|
|
|
if (!m_base)
|
|
|
|
{
|
2009-02-11 16:19:20 +01:00
|
|
|
iscLogStatus("ConfigStorage: Cannot initialize the shared memory region", status);
|
2009-02-02 10:12:38 +01:00
|
|
|
status_exception::raise(status);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fb_assert(m_base->version == 1);
|
|
|
|
|
|
|
|
StorageGuard guard(this);
|
|
|
|
checkFile();
|
2009-02-02 23:27:03 +01:00
|
|
|
++m_base->cnt_uses;
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ConfigStorage::~ConfigStorage()
|
|
|
|
{
|
|
|
|
::close(m_cfg_file);
|
|
|
|
m_cfg_file = -1;
|
2009-02-02 23:27:03 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
StorageGuard guard(this);
|
|
|
|
--m_base->cnt_uses;
|
|
|
|
if (m_base->cnt_uses == 0)
|
|
|
|
{
|
2009-02-06 14:47:10 +01:00
|
|
|
unlink(m_base->cfg_file_name);
|
2009-02-02 23:27:03 +01:00
|
|
|
memset(m_base->cfg_file_name, 0, sizeof(m_base->cfg_file_name));
|
|
|
|
}
|
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
ISC_STATUS_ARRAY status;
|
|
|
|
ISC_unmap_file(status, &m_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConfigStorage::checkMutex(const TEXT* string, int state)
|
|
|
|
{
|
|
|
|
if (state)
|
|
|
|
{
|
|
|
|
TEXT msg[BUFFER_TINY];
|
|
|
|
|
2009-02-11 16:19:20 +01:00
|
|
|
sprintf(msg, "ConfigStorage: mutex %s error, status = %d", string, state);
|
2009-02-01 23:07:35 +01:00
|
|
|
gds__log(msg);
|
|
|
|
|
|
|
|
fprintf(stderr, "%s\n", msg);
|
|
|
|
exit(FINI_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-02 10:53:25 +02:00
|
|
|
void ConfigStorage::initShMem(void* arg, sh_mem* shmemData, bool initialize)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
|
|
|
ConfigStorage* const storage = (ConfigStorage*) arg;
|
|
|
|
fb_assert(storage);
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
checkMutex("init", ISC_mutex_init(&storage->m_mutex, shmemData->sh_mem_name));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ShMemHeader* const header = (ShMemHeader*) shmemData->sh_mem_address;
|
|
|
|
storage->m_base = header;
|
|
|
|
|
|
|
|
// Initialize the shared data header
|
|
|
|
if (initialize)
|
|
|
|
{
|
|
|
|
header->version = 1;
|
|
|
|
header->change_number = 0;
|
|
|
|
header->session_number = 1;
|
2009-02-02 23:27:03 +01:00
|
|
|
header->cnt_uses = 0;
|
2009-02-02 17:24:33 +01:00
|
|
|
memset(header->cfg_file_name, 0, sizeof(header->cfg_file_name));
|
2009-02-01 23:07:35 +01:00
|
|
|
#ifndef WIN_NT
|
|
|
|
checkMutex("init", ISC_mutex_init(&header->mutex));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConfigStorage::checkFile()
|
|
|
|
{
|
|
|
|
if (m_cfg_file >= 0)
|
|
|
|
return;
|
|
|
|
|
2009-02-06 14:47:10 +01:00
|
|
|
char* cfg_file_name = m_base->cfg_file_name;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
if (!(*cfg_file_name))
|
|
|
|
{
|
2009-02-02 23:27:03 +01:00
|
|
|
fb_assert(m_base->cnt_uses == 0);
|
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
PathName filename = TempFile::create("fb_trace_");
|
|
|
|
filename.copyTo(cfg_file_name, sizeof(m_base->cfg_file_name));
|
2009-02-20 17:18:12 +01:00
|
|
|
m_cfg_file = fb_utils::openCreateFile(cfg_file_name, O_BINARY);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
2009-02-02 14:11:48 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
m_cfg_file = ::open(cfg_file_name, O_RDWR | O_BINARY);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (m_cfg_file < 0) {
|
2009-02-10 12:32:11 +01:00
|
|
|
checkFileError(cfg_file_name, "open", isc_io_open_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// put default (audit) trace file contents into storage
|
|
|
|
if (m_base->change_number == 0)
|
|
|
|
{
|
2009-02-10 12:32:11 +01:00
|
|
|
FILE* cfgFile = NULL;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
PathName configFileName(Config::getAuditTraceConfigFile());
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
if (configFileName.empty())
|
|
|
|
return;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-11 12:36:49 +01:00
|
|
|
if (PathUtils::isRelative(configFileName))
|
|
|
|
{
|
|
|
|
PathName root(Config::getRootDirectory());
|
|
|
|
PathUtils::ensureSeparator(root);
|
|
|
|
configFileName.insert(0, root);
|
2009-02-10 12:32:11 +01:00
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
cfgFile = fopen(configFileName.c_str(), "rb");
|
|
|
|
if (!cfgFile) {
|
|
|
|
checkFileError(configFileName.c_str(), "fopen", isc_io_open_err);
|
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
TraceSession session(*getDefaultMemoryPool());
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
fseek(cfgFile, 0, SEEK_END);
|
|
|
|
const long len = ftell(cfgFile);
|
|
|
|
if (len)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
2009-02-10 12:32:11 +01:00
|
|
|
fseek(cfgFile, 0, SEEK_SET);
|
|
|
|
char* p = session.ses_config.getBuffer(len + 1);
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
if (fread(p, 1, len, cfgFile) != size_t(len)) {
|
|
|
|
checkFileError(configFileName.c_str(), "fread", isc_io_read_err);
|
|
|
|
}
|
|
|
|
p[len] = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
gds__log("Audit configuration file \"%s\" is empty", configFileName.c_str());
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
session.ses_user = SYSDBA_USER_NAME;
|
|
|
|
session.ses_name = "Firebird Audit";
|
|
|
|
session.ses_flags = trs_admin | trs_system;
|
|
|
|
|
|
|
|
addSession(session);
|
|
|
|
}
|
|
|
|
catch(const Exception& ex)
|
|
|
|
{
|
|
|
|
ISC_STATUS_ARRAY temp;
|
|
|
|
ex.stuff_exception(temp);
|
|
|
|
iscLogStatus("Cannot open audit configuration file", temp);
|
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
if (cfgFile) {
|
|
|
|
fclose(cfgFile);
|
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ConfigStorage::acquire()
|
|
|
|
{
|
|
|
|
#ifdef WIN_NT
|
|
|
|
checkMutex("lock", ISC_mutex_lock(&m_mutex));
|
|
|
|
#else
|
|
|
|
checkMutex("lock", ISC_mutex_lock(&m_base->mutex));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConfigStorage::release()
|
|
|
|
{
|
|
|
|
checkDirty();
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
checkMutex("unlock", ISC_mutex_unlock(&m_mutex));
|
|
|
|
#else
|
|
|
|
checkMutex("unlock", ISC_mutex_unlock(&m_base->mutex));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-02-02 15:46:24 +01:00
|
|
|
void ConfigStorage::addSession(TraceSession& session)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
|
|
|
setDirty();
|
|
|
|
session.ses_id = m_base->session_number++;
|
|
|
|
session.ses_flags |= trs_active;
|
|
|
|
time(&session.ses_start);
|
|
|
|
|
|
|
|
const long pos1 = lseek(m_cfg_file, 0, SEEK_END);
|
|
|
|
if (pos1 < 0)
|
|
|
|
{
|
2009-02-06 14:47:10 +01:00
|
|
|
const char* fn = m_base->cfg_file_name;
|
2009-02-01 23:07:35 +01:00
|
|
|
ERR_post(Arg::Gds(isc_io_error) << Arg::Str("lseek") << Arg::Str(fn) <<
|
|
|
|
Arg::Gds(isc_io_read_err) << SYS_ERR(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
putItem(tagID, sizeof(session.ses_id), &session.ses_id);
|
|
|
|
if (!session.ses_name.empty()) {
|
|
|
|
putItem(tagName, session.ses_name.length(), session.ses_name.c_str());
|
|
|
|
}
|
|
|
|
putItem(tagUserName, session.ses_user.length(), session.ses_user.c_str());
|
|
|
|
putItem(tagFlags, sizeof(session.ses_flags), &session.ses_flags);
|
|
|
|
putItem(tagConfig, session.ses_config.length(), session.ses_config.c_str());
|
|
|
|
putItem(tagStartTS, sizeof(session.ses_start), &session.ses_start);
|
|
|
|
if (!session.ses_logfile.empty()) {
|
|
|
|
putItem(tagLogFile, session.ses_logfile.length(), session.ses_logfile.c_str());
|
|
|
|
}
|
|
|
|
putItem(tagEnd, 0, NULL);
|
|
|
|
|
2009-02-02 14:11:48 +01:00
|
|
|
// const long pos2 = lseek(m_cfg_file, 0, SEEK_END);
|
2009-02-01 23:07:35 +01:00
|
|
|
// m_base->used_space += pos2 - pos1;
|
|
|
|
}
|
|
|
|
|
2009-02-02 15:46:24 +01:00
|
|
|
bool ConfigStorage::getNextSession(TraceSession& session)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
|
|
|
ITEM tag = tagID;
|
2009-02-10 12:32:11 +01:00
|
|
|
ULONG len;
|
2009-02-01 23:07:35 +01:00
|
|
|
session.clear();
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (!getItemLength(tag, len))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (tag == tagEnd)
|
|
|
|
{
|
|
|
|
if (session.ses_id != 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-02-02 15:46:24 +01:00
|
|
|
void* p = NULL;
|
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
switch (tag)
|
|
|
|
{
|
|
|
|
case tagID:
|
|
|
|
fb_assert(len == sizeof(session.ses_id));
|
|
|
|
p = &session.ses_id;
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagName:
|
|
|
|
if (session.ses_id)
|
|
|
|
p = session.ses_name.getBuffer(len);
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagUserName:
|
|
|
|
if (session.ses_id)
|
|
|
|
p = session.ses_user.getBuffer(len);
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagFlags:
|
|
|
|
fb_assert(len == sizeof(session.ses_flags));
|
|
|
|
if (session.ses_id)
|
|
|
|
p = &session.ses_flags;
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagConfig:
|
|
|
|
if (session.ses_id)
|
|
|
|
p = session.ses_config.getBuffer(len);
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagStartTS:
|
|
|
|
fb_assert(len == sizeof(session.ses_start));
|
|
|
|
if (session.ses_id)
|
|
|
|
p = &session.ses_start;
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagLogFile:
|
|
|
|
if (session.ses_id)
|
|
|
|
p = session.ses_logfile.getBuffer(len);
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
if (p)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
2009-02-10 12:32:11 +01:00
|
|
|
if (::read(m_cfg_file, p, len) != len)
|
|
|
|
checkFileError(m_base->cfg_file_name, "read", isc_io_read_err);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (lseek(m_cfg_file, len, SEEK_CUR) < 0)
|
|
|
|
checkFileError(m_base->cfg_file_name, "lseek", isc_io_read_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConfigStorage::removeSession(ULONG id)
|
|
|
|
{
|
|
|
|
ITEM tag = tagID;
|
2009-02-10 12:32:11 +01:00
|
|
|
ULONG len;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
restart();
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (!getItemLength(tag, len))
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool err;
|
|
|
|
if (tag == tagID)
|
|
|
|
{
|
|
|
|
ULONG currID;
|
|
|
|
fb_assert(len == sizeof(currID));
|
2009-02-10 12:32:11 +01:00
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
err = (::read(m_cfg_file, &currID, len) != len);
|
|
|
|
if (!err && currID == id)
|
|
|
|
{
|
|
|
|
setDirty();
|
|
|
|
|
|
|
|
currID = 0;
|
2009-02-08 12:23:46 +01:00
|
|
|
// Do not delete this temporary signed var, otherwise we get
|
|
|
|
// warning C4146: unary minus operator applied to unsigned type, result still unsigned
|
|
|
|
// but we need a negative offset here.
|
|
|
|
const long local_len = len;
|
2009-02-10 12:32:11 +01:00
|
|
|
if (lseek(m_cfg_file, -local_len, SEEK_CUR) < 0)
|
|
|
|
checkFileError(m_base->cfg_file_name, "lseek", isc_io_read_err);
|
|
|
|
|
|
|
|
if (write(m_cfg_file, &currID, len) != len)
|
|
|
|
checkFileError(m_base->cfg_file_name, "write", isc_io_write_err);
|
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-10 12:32:11 +01:00
|
|
|
if (lseek(m_cfg_file, len, SEEK_CUR) < 0)
|
|
|
|
checkFileError(m_base->cfg_file_name, "lseek", isc_io_read_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
2009-02-07 16:20:34 +01:00
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
|
2009-02-01 23:07:35 +01:00
|
|
|
void ConfigStorage::restart()
|
|
|
|
{
|
|
|
|
checkDirty();
|
2009-02-10 12:32:11 +01:00
|
|
|
|
|
|
|
if (lseek(m_cfg_file, 0, SEEK_SET) < 0)
|
|
|
|
checkFileError(m_base->cfg_file_name, "lseek", isc_io_read_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-11 16:19:20 +01:00
|
|
|
void ConfigStorage::updateSession(TraceSession& session)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
|
|
|
restart();
|
|
|
|
|
|
|
|
ITEM tag;
|
2009-02-10 12:32:11 +01:00
|
|
|
ULONG len;
|
2009-02-01 23:07:35 +01:00
|
|
|
ULONG currID = 0;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (!getItemLength(tag, len))
|
|
|
|
return;
|
|
|
|
|
2009-02-02 15:46:24 +01:00
|
|
|
void* p = NULL;
|
2009-02-01 23:07:35 +01:00
|
|
|
switch (tag)
|
|
|
|
{
|
|
|
|
case tagID:
|
|
|
|
fb_assert(len == sizeof(currID));
|
|
|
|
read(m_cfg_file, &currID, len);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case tagFlags:
|
|
|
|
fb_assert(len == sizeof(session.ses_flags));
|
|
|
|
if (currID == session.ses_id)
|
|
|
|
p = &session.ses_flags;
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
case tagEnd:
|
|
|
|
if (currID == session.ses_id)
|
|
|
|
return;
|
|
|
|
len = 0;
|
2009-02-02 15:46:24 +01:00
|
|
|
break;
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
setDirty();
|
2009-02-10 12:32:11 +01:00
|
|
|
if (write(m_cfg_file, p, len) != len)
|
|
|
|
checkFileError(m_base->cfg_file_name, "write", isc_io_write_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
else if (len)
|
|
|
|
{
|
2009-02-10 12:32:11 +01:00
|
|
|
if (lseek(m_cfg_file, len, SEEK_CUR) < 0)
|
|
|
|
checkFileError(m_base->cfg_file_name, "lseek", isc_io_read_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
void ConfigStorage::putItem(ITEM tag, ULONG len, const void* data)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
|
|
|
const char tag_data = (char) tag;
|
2009-02-10 12:32:11 +01:00
|
|
|
ULONG to_write = sizeof(tag_data);
|
|
|
|
if (write(m_cfg_file, &tag_data, to_write) != to_write)
|
|
|
|
checkFileError(m_base->cfg_file_name, "write", isc_io_write_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
if (tag == tagEnd)
|
|
|
|
return;
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
to_write = sizeof(len);
|
|
|
|
if (write(m_cfg_file, &len, to_write) != to_write)
|
|
|
|
checkFileError(m_base->cfg_file_name, "write", isc_io_write_err);
|
|
|
|
|
|
|
|
if (len)
|
|
|
|
{
|
|
|
|
if (write(m_cfg_file, data, len) != len)
|
|
|
|
checkFileError(m_base->cfg_file_name, "write", isc_io_write_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-10 12:32:11 +01:00
|
|
|
bool ConfigStorage::getItemLength(ITEM& tag, ULONG& len)
|
2009-02-01 23:07:35 +01:00
|
|
|
{
|
|
|
|
char data;
|
2009-02-02 14:11:48 +01:00
|
|
|
const int cnt_read = read(m_cfg_file, &data, sizeof(data));
|
|
|
|
|
|
|
|
if (cnt_read == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (cnt_read < 0)
|
2009-02-10 12:32:11 +01:00
|
|
|
checkFileError(m_base->cfg_file_name, "read", isc_io_read_err);
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
tag = (ITEM) data;
|
|
|
|
|
|
|
|
if (tag == tagEnd)
|
|
|
|
len = 0;
|
|
|
|
else
|
2009-02-10 12:32:11 +01:00
|
|
|
{
|
|
|
|
if (read(m_cfg_file, &len, sizeof(ULONG)) != sizeof(ULONG))
|
|
|
|
checkFileError(m_base->cfg_file_name, "read", isc_io_read_err);
|
|
|
|
}
|
2009-02-01 23:07:35 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Jrd
|