mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-27 06:03:02 +01:00
383 lines
13 KiB
C++
383 lines
13 KiB
C++
/*
|
|
* PROGRAM: JRD access method
|
|
* MODULE: svc.h
|
|
* DESCRIPTION: Service manager declarations
|
|
*
|
|
* The contents of this file are subject to the Interbase Public
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
*
|
|
* Software distributed under the License is distributed on an
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
* or implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code was created by Inprise Corporation
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
* Copyright (C) Inprise Corporation.
|
|
*
|
|
* All Rights Reserved.
|
|
* Contributor(s): ______________________________________.
|
|
*/
|
|
|
|
#ifndef JRD_SVC_H
|
|
#define JRD_SVC_H
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "fb_blk.h"
|
|
#include "consts_pub.h"
|
|
|
|
#include "../jrd/svc_undoc.h"
|
|
#include "../common/ThreadStart.h"
|
|
|
|
#include "../common/classes/semaphore.h"
|
|
#include "../common/classes/array.h"
|
|
#include "../common/classes/SafeArg.h"
|
|
#include "../common/UtilSvc.h"
|
|
#include "../jrd/EngineInterface.h"
|
|
#include "../common/classes/Switches.h"
|
|
#include "../common/classes/ClumpletReader.h"
|
|
#include "../common/classes/RefMutex.h"
|
|
#include "../burp/split/spit.h"
|
|
#include "../jrd/status.h"
|
|
|
|
// forward decl.
|
|
|
|
namespace Jrd {
|
|
struct serv_entry;
|
|
}
|
|
|
|
namespace Firebird {
|
|
namespace Arg {
|
|
class StatusVector;
|
|
}
|
|
}
|
|
|
|
namespace Jrd {
|
|
|
|
const ULONG SERVICE_VERSION = 2;
|
|
|
|
const int SVC_STDOUT_BUFFER_SIZE = 1024;
|
|
|
|
// Flag of capabilities supported by the server
|
|
//const ULONG WAL_SUPPORT = 0x1L; // Write Ahead Log
|
|
const ULONG MULTI_CLIENT_SUPPORT = 0x2L; // SuperServer model (vs. multi-inet)
|
|
const ULONG REMOTE_HOP_SUPPORT = 0x4L; // Server can connect to other server
|
|
//const ULONG NO_SVR_STATS_SUPPORT = 0x8L; // Does not support statistics
|
|
|
|
//const ULONG NO_DB_STATS_SUPPORT = 0x10L; // Does not support statistics
|
|
// Really the 16 bit LIBS here?
|
|
//const ULONG LOCAL_ENGINE_SUPPORT = 0x20L; // The local 16 bit engine
|
|
//const ULONG NO_FORCED_WRITE_SUPPORT = 0x40L; // Can not configure sync writes
|
|
//const ULONG NO_SHUTDOWN_SUPPORT = 0x80L; // Can not shutdown/restart databases
|
|
const ULONG NO_SERVER_SHUTDOWN_SUPPORT = 0x100L; // Can not shutdown server
|
|
//const ULONG SERVER_CONFIG_SUPPORT = 0x200L; // Can configure server
|
|
const ULONG QUOTED_FILENAME_SUPPORT = 0x400L; // Can pass quoted filenames in
|
|
|
|
// Range definitions for service actions. Any action outside of
|
|
// this range is not supported
|
|
const USHORT isc_action_min = 1;
|
|
const USHORT isc_action_max = isc_action_svc_last;
|
|
|
|
// Range definitions for service actions. Any action outside of
|
|
// this range is not supported
|
|
//define isc_info_min 50
|
|
//define isc_info_max 67
|
|
|
|
// Bitmask values for the svc_flags variable
|
|
//const int SVC_shutdown = 0x1;
|
|
//const int SVC_timeout = 0x2;
|
|
//const int SVC_forked = 0x4;
|
|
const int SVC_detached = 0x8;
|
|
const int SVC_finished = 0x10;
|
|
//const int SVC_thd_running = 0x20;
|
|
const int SVC_evnt_fired = 0x40;
|
|
const int SVC_cmd_line = 0x80;
|
|
|
|
// forward decl.
|
|
class thread_db;
|
|
class TraceManager;
|
|
|
|
// Service manager
|
|
class Service : public Firebird::UtilSvc, public TypedHandle<type_svc>
|
|
{
|
|
public: // utilities interface with service
|
|
// output to svc_stdout verbose info
|
|
virtual void outputVerbose(const char* text);
|
|
// outpur error text
|
|
virtual void outputError(const char* text);
|
|
// output some data to service
|
|
virtual void outputData(const void* data, FB_SIZE_T len);
|
|
// printf() to svc_stdout
|
|
virtual void printf(bool err, const SCHAR* format, ...);
|
|
// returns true - it's service :)
|
|
virtual bool isService();
|
|
// client thread started
|
|
virtual void started();
|
|
// put various info items in info buffer
|
|
virtual void putLine(char tag, const char* val);
|
|
virtual void putSLong(char tag, SLONG val);
|
|
virtual void putChar(char tag, char val);
|
|
// put raw bytes to svc_stdout
|
|
virtual void putBytes(const UCHAR*, FB_SIZE_T);
|
|
// get raw bytes from svc_stdin
|
|
virtual ULONG getBytes(UCHAR*, ULONG);
|
|
// append status_vector to service's status
|
|
virtual void setServiceStatus(const ISC_STATUS* status_vector);
|
|
// append error message to service's status
|
|
virtual void setServiceStatus(const USHORT facility, const USHORT errcode, const MsgFormat::SafeArg& args);
|
|
// no-op for services
|
|
virtual void hidePasswd(ArgvType&, int);
|
|
// return service status
|
|
virtual const FbStatusVector* getStatus();
|
|
// reset service status
|
|
virtual void initStatus();
|
|
// no-op for services
|
|
virtual void checkService();
|
|
// add address path and utf8 flag (taken from spb) to dpb if present
|
|
virtual void fillDpb(Firebird::ClumpletWriter& dpb);
|
|
// encoding for string parameters passed to utility
|
|
virtual bool utf8FileNames();
|
|
|
|
virtual TraceManager* getTraceManager()
|
|
{
|
|
return svc_trace_manager;
|
|
}
|
|
|
|
virtual bool finished()
|
|
{
|
|
return ((svc_flags & (SVC_finished | SVC_detached)) != 0)
|
|
|| checkForShutdown();
|
|
}
|
|
|
|
// Get authentication block if present
|
|
virtual unsigned int getAuthBlock(const unsigned char** bytes);
|
|
|
|
public: // external interface with service
|
|
// Attach - service ctor
|
|
Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_data,
|
|
Firebird::ICryptKeyCallback* crypt_callback);
|
|
// Start service thread
|
|
void start(USHORT spb_length, const UCHAR* spb_data);
|
|
// Query service state (v. 1 & 2)
|
|
void query(USHORT send_item_length, const UCHAR* send_items, USHORT recv_item_length,
|
|
const UCHAR* recv_items, USHORT buffer_length, UCHAR* info);
|
|
ISC_STATUS query2(thread_db* tdbb, USHORT send_item_length, const UCHAR* send_items,
|
|
USHORT recv_item_length, const UCHAR* recv_items, USHORT buffer_length, UCHAR* info);
|
|
// Detach from service
|
|
void detach();
|
|
// get service version
|
|
USHORT getVersion() const
|
|
{
|
|
return svc_spb_version;
|
|
}
|
|
|
|
// Firebird log reader
|
|
static int readFbLog(Firebird::UtilSvc* uSvc);
|
|
// Shuts all service threads (should be called after databases shutdown)
|
|
static void shutdownServices();
|
|
|
|
// Total number of service attachments
|
|
static ULONG totalCount();
|
|
|
|
const char* getServiceMgr() const;
|
|
const char* getServiceName() const;
|
|
|
|
const Firebird::string& getUserName() const
|
|
{
|
|
return svc_username;
|
|
}
|
|
|
|
const Firebird::string& getNetworkProtocol() const { return svc_network_protocol; }
|
|
const Firebird::string& getRemoteAddress() const { return svc_remote_address; }
|
|
const Firebird::string& getRemoteProcess() const { return svc_remote_process; }
|
|
int getRemotePID() const { return svc_remote_pid; }
|
|
|
|
private:
|
|
// Service must have private destructor, called from finish
|
|
// when both (server and client) threads are finished
|
|
~Service();
|
|
// Find current service in global services list
|
|
bool locateInAllServices(FB_SIZE_T* posPtr = NULL);
|
|
// Detach self from global services list
|
|
void removeFromAllServices();
|
|
// The only service, implemented internally
|
|
void readFbLog();
|
|
// Create argv, argc and svc_parsed_sw
|
|
void parseSwitches();
|
|
// Check does this action need arg or not
|
|
static bool actionNeedsArg(UCHAR action);
|
|
// Put data into stdout buffer
|
|
void enqueue(const UCHAR* s, ULONG len);
|
|
// true if there is no data in stdout buffer
|
|
bool empty() const;
|
|
// true if no more space in stdout buffer
|
|
bool full() const;
|
|
// start service thread
|
|
void start(const serv_entry* service_run);
|
|
// Set the flag (either SVC_finished for the main service thread or SVC_detached for the client thread).
|
|
// If both main thread and client thread are completed that is main thread is finished and
|
|
// client is detached then free memory used by service.
|
|
void finish(USHORT flag);
|
|
// Throws shutdown exception if global flag is set for it
|
|
bool checkForShutdown();
|
|
// Transfer data from svc_stdout into buffer
|
|
void get(UCHAR* buffer, USHORT length, USHORT flags, USHORT timeout, USHORT* return_length);
|
|
// Sends stdin for a service
|
|
// Returns number of bytes service wants more
|
|
ULONG put(const UCHAR* buffer, ULONG length);
|
|
|
|
// Increment circular buffer pointer
|
|
static ULONG add_one(ULONG i);
|
|
static ULONG add_val(ULONG i, ULONG val);
|
|
// Convert spb flags to utility switches
|
|
static void conv_switches(Firebird::ClumpletReader& spb, Firebird::string& switches);
|
|
// Find spb switch in switch table
|
|
static const TEXT* find_switch(int in_spb_sw, const Switches::in_sw_tab_t* table);
|
|
// Loop through the appropriate switch table looking for the text for the given command switch
|
|
static bool process_switches(Firebird::ClumpletReader& spb, Firebird::string& switches);
|
|
// Get bitmask from within spb buffer, find corresponding switches within specified table,
|
|
// add them to the command line
|
|
static bool get_action_svc_bitmask(const Firebird::ClumpletReader& spb,
|
|
const Switches::in_sw_tab_t* table,
|
|
Firebird::string& sw);
|
|
// Get string from within spb buffer, add it to the command line
|
|
static void get_action_svc_string(const Firebird::ClumpletReader& spb, Firebird::string& sw);
|
|
// Get integer from within spb buffer, add it to the command line
|
|
static void get_action_svc_data(const Firebird::ClumpletReader& spb, Firebird::string& sw);
|
|
// Get parameter from within spb buffer, find corresponding switch within specified table,
|
|
// add it to the command line
|
|
static bool get_action_svc_parameter(UCHAR tag, const Switches::in_sw_tab_t* table,
|
|
Firebird::string&);
|
|
// Create 'SYSDBA needed' error in status vector
|
|
static void need_admin_privs(Firebird::Arg::StatusVector& status, const char* message);
|
|
// Does info buffer have enough space for SLONG?
|
|
static bool ck_space_for_numeric(UCHAR*& info, const UCHAR* const end);
|
|
// Make status vector permamnent, if one present in worker thread's space
|
|
void makePermanentStatusVector() throw();
|
|
// Read SPB on attach
|
|
void getOptions(Firebird::ClumpletReader&);
|
|
// Invoke appropriate service thread entry and finalize it correctly
|
|
static THREAD_ENTRY_DECLARE run(THREAD_ENTRY_PARAM arg);
|
|
|
|
private:
|
|
FbLocalStatus svc_status; // status vector for running service
|
|
Firebird::string svc_parsed_sw; // Here point elements of argv
|
|
ULONG svc_stdout_head;
|
|
ULONG svc_stdout_tail;
|
|
UCHAR svc_stdout[SVC_STDOUT_BUFFER_SIZE]; // output from service
|
|
Firebird::Semaphore svcStart;
|
|
const serv_entry* svc_service; // attached service's entry
|
|
const serv_entry* svc_service_run; // running service's entry
|
|
Firebird::Array<UCHAR> svc_resp_alloc;
|
|
UCHAR* svc_resp_buf;
|
|
const UCHAR* svc_resp_ptr;
|
|
USHORT svc_resp_buf_len;
|
|
USHORT svc_resp_len;
|
|
USHORT svc_flags;
|
|
USHORT svc_user_flag;
|
|
USHORT svc_spb_version;
|
|
bool svc_do_shutdown;
|
|
bool svc_shutdown_in_progress;
|
|
bool svc_timeout;
|
|
|
|
Firebird::string svc_username;
|
|
Firebird::string svc_sql_role;
|
|
Firebird::AuthReader::AuthBlock svc_auth_block;
|
|
Firebird::PathName svc_expected_db;
|
|
bool svc_trusted_role;
|
|
bool svc_utf8;
|
|
Firebird::string svc_switches; // Full set of switches
|
|
Firebird::string svc_perm_sw; // Switches, taken from services table and/or passed using spb_command_line
|
|
Firebird::string svc_address_path;
|
|
Firebird::string svc_command_line;
|
|
|
|
Firebird::string svc_network_protocol;
|
|
Firebird::string svc_remote_address;
|
|
Firebird::string svc_remote_process;
|
|
SLONG svc_remote_pid;
|
|
|
|
TraceManager* svc_trace_manager;
|
|
Firebird::ICryptKeyCallback* svc_crypt_callback;
|
|
|
|
public:
|
|
Firebird::Semaphore svc_detach_sem;
|
|
|
|
class SvcMutex : public Firebird::RefMutex
|
|
{
|
|
public:
|
|
explicit SvcMutex(Service* svc)
|
|
: link(svc)
|
|
{ }
|
|
|
|
Service* link;
|
|
};
|
|
|
|
Firebird::RefPtr<SvcMutex> svc_existence;
|
|
|
|
private:
|
|
Firebird::Semaphore svc_sem_empty, svc_sem_full;
|
|
|
|
class Validate
|
|
{
|
|
public:
|
|
explicit Validate(Service* svc);
|
|
Firebird::MutexEnsureUnlock sharedGuard;
|
|
};
|
|
|
|
class SafeMutexLock : private Validate
|
|
{
|
|
public:
|
|
SafeMutexLock(Service* svc, const char* f);
|
|
bool lock();
|
|
|
|
protected:
|
|
Firebird::RefPtr<SvcMutex> existenceMutex;
|
|
const char* from;
|
|
};
|
|
|
|
friend class SafeMutexLock;
|
|
|
|
//Service existence guard
|
|
class ExistenceGuard : private SafeMutexLock
|
|
{
|
|
public:
|
|
explicit ExistenceGuard(Service* svc, const char* from);
|
|
~ExistenceGuard();
|
|
};
|
|
|
|
//Service unlock guard
|
|
class UnlockGuard : private SafeMutexLock
|
|
{
|
|
public:
|
|
explicit UnlockGuard(Service* svc, const char* from);
|
|
bool enter();
|
|
~UnlockGuard();
|
|
private:
|
|
bool locked, doLock;
|
|
};
|
|
|
|
// Data pipe from client to service
|
|
Firebird::Semaphore svc_stdin_semaphore;
|
|
Firebird::Mutex svc_stdin_mutex;
|
|
// Size of data, requested by service (set in getBytes, reset in put)
|
|
ULONG svc_stdin_size_requested;
|
|
// Buffer passed by service
|
|
UCHAR* svc_stdin_buffer;
|
|
// Size of data, preloaded by user (set in put, reset in getBytes)
|
|
ULONG svc_stdin_size_preload;
|
|
// Buffer for datam preloaded by user
|
|
Firebird::AutoPtr<UCHAR> svc_stdin_preload;
|
|
// Size of data, requested from user to preload (set in getBytes)
|
|
ULONG svc_stdin_preload_requested;
|
|
// Size of data, placed into svc_stdin_buffer (set in put)
|
|
ULONG svc_stdin_user_size;
|
|
static const ULONG PRELOAD_BUFFER_SIZE = SVC_IO_BUFFER_SIZE;
|
|
};
|
|
|
|
} //namespace Jrd
|
|
|
|
#endif // JRD_SVC_H
|