/* * 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 Dmitry Yemanov * for the Firebird Open Source RDBMS project. * * Copyright (c) 2002 Dmitry Yemanov * and all contributors signed below. * * All Rights Reserved. * Contributor(s): ______________________________________. */ #include "firebird.h" #include "../../common/config/config.h" #include "../../common/config/config_impl.h" #include "../../common/config/config_file.h" #ifdef HAVE_STDLIB_H #include #endif // config_file works with OS case-sensitivity typedef Firebird::PathName string; /****************************************************************************** * * Configuration entries */ const char* GCPolicyCooperative = "cooperative"; const char* GCPolicyBackground = "background"; const char* GCPolicyCombined = "combined"; #ifdef SUPERSERVER const char* GCPolicyDefault = GCPolicyCombined; #else const char* GCPolicyDefault = GCPolicyCooperative; #endif const char* AmNative = "native"; const char* AmTrusted = "trusted"; const char* AmMixed = "mixed"; char defIpcName[MAXPATHLEN]; const ConfigImpl::ConfigEntry ConfigImpl::entries[] = { {TYPE_STRING, "RootDirectory", (ConfigValue) 0}, {TYPE_INTEGER, "TempBlockSize", (ConfigValue) 1048576}, // bytes #ifdef SUPERSERVER {TYPE_INTEGER, "TempCacheLimit", (ConfigValue) 67108864}, // bytes #elif defined(WIN_NT) // win32 CS {TYPE_INTEGER, "TempCacheLimit", (ConfigValue) 8388608}, // bytes #else // non-win32 CS {TYPE_INTEGER, "TempCacheLimit", (ConfigValue) 0}, // bytes #endif {TYPE_BOOLEAN, "RemoteFileOpenAbility", (ConfigValue) false}, {TYPE_INTEGER, "GuardianOption", (ConfigValue) 1}, {TYPE_INTEGER, "CpuAffinityMask", (ConfigValue) 1}, {TYPE_BOOLEAN, "OldParameterOrdering", (ConfigValue) false}, {TYPE_INTEGER, "TcpRemoteBufferSize", (ConfigValue) 8192}, // bytes {TYPE_BOOLEAN, "TcpNoNagle", (ConfigValue) true}, #ifdef SUPERSERVER {TYPE_INTEGER, "DefaultDbCachePages", (ConfigValue) 2048}, // pages #else {TYPE_INTEGER, "DefaultDbCachePages", (ConfigValue) 75}, // pages #endif {TYPE_INTEGER, "ConnectionTimeout", (ConfigValue) 180}, // seconds {TYPE_INTEGER, "DummyPacketInterval", (ConfigValue) 0}, // seconds {TYPE_INTEGER, "LockMemSize", (ConfigValue) 1048576}, // bytes #if defined(SINIXZ) || defined(FREEBSD) || defined(NETBSD) {TYPE_INTEGER, "LockSemCount", (ConfigValue) 25}, // semaphores #else {TYPE_INTEGER, "LockSemCount", (ConfigValue) 32}, // semaphores #endif {TYPE_INTEGER, "LockSignal", (ConfigValue) 16}, // signal # {TYPE_BOOLEAN, "LockGrantOrder", (ConfigValue) true}, {TYPE_INTEGER, "LockHashSlots", (ConfigValue) 1009}, // slots {TYPE_INTEGER, "LockAcquireSpins", (ConfigValue) 0}, {TYPE_INTEGER, "EventMemSize", (ConfigValue) 65536}, // bytes {TYPE_INTEGER, "DeadlockTimeout", (ConfigValue) 10}, // seconds {TYPE_INTEGER, "SolarisStallValue", (ConfigValue) 60}, // seconds {TYPE_BOOLEAN, "TraceMemoryPools", (ConfigValue) false}, // for internal use only {TYPE_INTEGER, "PrioritySwitchDelay", (ConfigValue) 100}, // milliseconds {TYPE_BOOLEAN, "UsePriorityScheduler", (ConfigValue) true}, {TYPE_INTEGER, "PriorityBoost", (ConfigValue) 5}, // ratio oh high- to low-priority thread ticks in jrd.cpp {TYPE_STRING, "RemoteServiceName", (ConfigValue) FB_SERVICE_NAME}, {TYPE_INTEGER, "RemoteServicePort", (ConfigValue) 0}, {TYPE_STRING, "RemotePipeName", (ConfigValue) FB_PIPE_NAME}, {TYPE_STRING, "IpcName", (ConfigValue) defIpcName}, #ifdef WIN_NT {TYPE_INTEGER, "MaxUnflushedWrites", (ConfigValue) 100}, {TYPE_INTEGER, "MaxUnflushedWriteTime", (ConfigValue) 5}, #else {TYPE_INTEGER, "MaxUnflushedWrites", (ConfigValue) -1}, {TYPE_INTEGER, "MaxUnflushedWriteTime", (ConfigValue) -1}, #endif {TYPE_INTEGER, "ProcessPriorityLevel", (ConfigValue) 0}, {TYPE_BOOLEAN, "CreateInternalWindow", (ConfigValue) true}, {TYPE_BOOLEAN, "CompleteBooleanEvaluation", (ConfigValue) false}, {TYPE_INTEGER, "RemoteAuxPort", (ConfigValue) 0}, {TYPE_STRING, "RemoteBindAddress", (ConfigValue) 0}, {TYPE_STRING, "ExternalFileAccess", (ConfigValue) "None"}, // location(s) of external files for tables {TYPE_STRING, "DatabaseAccess", (ConfigValue) "Full"}, // location(s) of databases {TYPE_STRING, "UdfAccess", (ConfigValue) "Restrict UDF"}, // location(s) of UDFs {TYPE_STRING, "TempDirectories", (ConfigValue) 0}, #ifdef DEV_BUILD {TYPE_BOOLEAN, "BugcheckAbort", (ConfigValue) true}, // whether to abort() engine when internal error is found #else {TYPE_BOOLEAN, "BugcheckAbort", (ConfigValue) false}, // whether to abort() engine when internal error is found #endif {TYPE_INTEGER, "TraceDSQL", (ConfigValue) 0}, // bitmask {TYPE_BOOLEAN, "LegacyHash", (ConfigValue) true}, // let use old passwd hash verification {TYPE_STRING, "GCPolicy", (ConfigValue) GCPolicyDefault}, // garbage collection policy {TYPE_BOOLEAN, "Redirection", (ConfigValue) false}, {TYPE_BOOLEAN, "OldColumnNaming", (ConfigValue) false}, // if true use old style concatenation {TYPE_STRING, "Authentication", (ConfigValue) AmMixed}, // use native, trusted or mixed {TYPE_INTEGER, "DatabaseGrowthIncrement", (ConfigValue) 128 * 1048576} // bytes }; /****************************************************************************** * * Static instance of the system configuration file */ // was: const static ConfigImpl sysConfig; static ConfigImpl *sys_config = NULL; #ifdef MULTI_THREAD static Firebird::Mutex config_init_lock; #endif const ConfigImpl& ConfigImpl::instance() { if (!sys_config) { #ifdef MULTI_THREAD try { config_init_lock.enter(); if (!sys_config) { sys_config = FB_NEW(*getDefaultMemoryPool()) ConfigImpl(*getDefaultMemoryPool()); } } catch (const Firebird::Exception&) { config_init_lock.leave(); throw; } config_init_lock.leave(); #else sys_config = FB_NEW(*getDefaultMemoryPool()) ConfigImpl(*getDefaultMemoryPool()); #endif } return *sys_config; } #define sysConfig ConfigImpl::instance() /****************************************************************************** * * Implementation interface */ ConfigImpl::ConfigImpl(MemoryPool& p) : ConfigRoot(p) { /* Prepare some stuff */ ConfigFile file(true); root_dir = getRootDirectory(); const int size = FB_NELEM(entries); values = FB_NEW(p) ConfigValue[size]; string val_sep = ","; file.setConfigFilePath(getConfigFilePath()); strncpy(defIpcName, FB_IPC_NAME, sizeof(defIpcName)); #ifdef WIN_NT fb_utils::prefix_kernel_object_name(defIpcName, sizeof(defIpcName)); #endif /* Iterate through the known configuration entries */ for (int i = 0; i < size; i++) { ConfigEntry entry = entries[i]; string value = getValue(file, entries[i].key); if (!value.length()) { /* Assign the default value */ values[i] = entries[i].default_value; continue; } /* Assign the actual value */ switch (entry.data_type) { case TYPE_BOOLEAN: values[i] = (ConfigValue) asBoolean(value); break; case TYPE_INTEGER: values[i] = (ConfigValue) asInteger(value); break; case TYPE_STRING: { const char *src = asString(value); char *dst = FB_NEW(p) char[strlen(src) + 1]; strcpy(dst, src); values[i] = (ConfigValue) dst; } break; case TYPE_STRING_VECTOR: break; } } } ConfigImpl::~ConfigImpl() { const int size = FB_NELEM(entries); /* Free allocated memory */ for (int i = 0; i < size; i++) { if (values[i] == entries[i].default_value) continue; switch (entries[i].data_type) { case TYPE_STRING: delete[] (char*)values[i]; break; case TYPE_STRING_VECTOR: break; } } delete[] values; } string ConfigImpl::getValue(ConfigFile& file, const ConfigKey key) { return file.doesKeyExist(key) ? file.getString(key) : ""; } int ConfigImpl::asInteger(const string &value) { return atoi(value.data()); } bool ConfigImpl::asBoolean(const string &value) { return (atoi(value.data()) != 0); } const char* ConfigImpl::asString(const string &value) { return value.c_str(); } /****************************************************************************** * * Public interface */ const char* Config::getInstallDirectory() { return sysConfig.getInstallDirectory(); } static Firebird::PathName* rootFromCommandLine = 0; void Config::setRootDirectoryFromCommandLine(const Firebird::PathName& newRoot) { delete rootFromCommandLine; rootFromCommandLine = FB_NEW(*getDefaultMemoryPool()) Firebird::PathName(*getDefaultMemoryPool(), newRoot); } const Firebird::PathName* Config::getCommandLineRootDirectory() { return rootFromCommandLine; } const char* Config::getRootDirectory() { // must check it here - command line must override any other root settings, including firebird.conf if (rootFromCommandLine) { return rootFromCommandLine->c_str(); } const char* result = (char*) sysConfig.values[KEY_ROOT_DIRECTORY]; return result ? result : sysConfig.root_dir; } int Config::getTempBlockSize() { return (int) sysConfig.values[KEY_TEMP_BLOCK_SIZE]; } int Config::getTempCacheLimit() { int v = (int) sysConfig.values[KEY_TEMP_CACHE_LIMIT]; return v < 0 ? 0 : v; } bool Config::getRemoteFileOpenAbility() { return (bool) sysConfig.values[KEY_REMOTE_FILE_OPEN_ABILITY]; } int Config::getGuardianOption() { return (int) sysConfig.values[KEY_GUARDIAN_OPTION]; } int Config::getCpuAffinityMask() { return (int) sysConfig.values[KEY_CPU_AFFINITY_MASK]; } bool Config::getOldParameterOrdering() { return (bool) sysConfig.values[KEY_OLD_PARAMETER_ORDERING]; } int Config::getTcpRemoteBufferSize() { int rc = (int) sysConfig.values[KEY_TCP_REMOTE_BUFFER_SIZE]; if (rc < 1448) rc = 1448; if (rc > MAX_SSHORT) rc = MAX_SSHORT; return rc; } bool Config::getTcpNoNagle() { return (bool) sysConfig.values[KEY_TCP_NO_NAGLE]; } int Config::getDefaultDbCachePages() { return (int) sysConfig.values[KEY_DEFAULT_DB_CACHE_PAGES]; } int Config::getConnectionTimeout() { return (int) sysConfig.values[KEY_CONNECTION_TIMEOUT]; } int Config::getDummyPacketInterval() { return (int) sysConfig.values[KEY_DUMMY_PACKET_INTERVAL]; } int Config::getLockMemSize() { return (int) sysConfig.values[KEY_LOCK_MEM_SIZE]; } int Config::getLockSemCount() { return (int) sysConfig.values[KEY_LOCK_SEM_COUNT]; } int Config::getLockSignal() { return (int) sysConfig.values[KEY_LOCK_SIGNAL]; } bool Config::getLockGrantOrder() { return (bool) sysConfig.values[KEY_LOCK_GRANT_ORDER]; } int Config::getLockHashSlots() { return (int) sysConfig.values[KEY_LOCK_HASH_SLOTS]; } int Config::getLockAcquireSpins() { return (int) sysConfig.values[KEY_LOCK_ACQUIRE_SPINS]; } int Config::getEventMemSize() { return (int) sysConfig.values[KEY_EVENT_MEM_SIZE]; } int Config::getDeadlockTimeout() { return (int) sysConfig.values[KEY_DEADLOCK_TIMEOUT]; } int Config::getSolarisStallValue() { return (int) sysConfig.values[KEY_SOLARIS_STALL_VALUE]; } bool Config::getTraceMemoryPools() { return (bool) sysConfig.values[KEY_TRACE_MEMORY_POOLS]; } int Config::getPrioritySwitchDelay() { int rc = (int) sysConfig.values[KEY_PRIORITY_SWITCH_DELAY]; if (rc < 1) rc = 1; return rc; } int Config::getPriorityBoost() { int rc = (int) sysConfig.values[KEY_PRIORITY_BOOST]; if (rc < 1) rc = 1; if (rc > 1000) rc = 1000; return rc; } bool Config::getUsePriorityScheduler() { return (bool) sysConfig.values[KEY_USE_PRIORITY_SCHEDULER]; } const char *Config::getRemoteServiceName() { return (const char*) sysConfig.values[KEY_REMOTE_SERVICE_NAME]; } unsigned short Config::getRemoteServicePort() { return (unsigned short) sysConfig.values[KEY_REMOTE_SERVICE_PORT]; } const char *Config::getRemotePipeName() { return (const char*) sysConfig.values[KEY_REMOTE_PIPE_NAME]; } const char *Config::getIpcName() { return (const char*) sysConfig.values[KEY_IPC_NAME]; } int Config::getMaxUnflushedWrites() { return (int) sysConfig.values[KEY_MAX_UNFLUSHED_WRITES]; } int Config::getMaxUnflushedWriteTime() { return (int) sysConfig.values[KEY_MAX_UNFLUSHED_WRITE_TIME]; } int Config::getProcessPriorityLevel() { return (int) sysConfig.values[KEY_PROCESS_PRIORITY_LEVEL]; } bool Config::getCreateInternalWindow() { return (bool) sysConfig.values[KEY_CREATE_INTERNAL_WINDOW]; } bool Config::getCompleteBooleanEvaluation() { return (bool) sysConfig.values[KEY_COMPLETE_BOOLEAN_EVALUATION]; } int Config::getRemoteAuxPort() { #ifdef SUPERSERVER return (int) sysConfig.values[KEY_REMOTE_AUX_PORT]; #else return 0; #endif } const char *Config::getRemoteBindAddress() { return (const char*) sysConfig.values[KEY_REMOTE_BIND_ADDRESS]; } const char *Config::getExternalFileAccess() { return (const char*) sysConfig.values[KEY_EXTERNAL_FILE_ACCESS]; } const char *Config::getDatabaseAccess() { return (const char*) sysConfig.values[KEY_DATABASE_ACCESS]; } const char *Config::getUdfAccess() { return (const char*) sysConfig.values[KEY_UDF_ACCESS]; } const char *Config::getTempDirectories() { return (const char*) sysConfig.values[KEY_TEMP_DIRECTORIES]; } bool Config::getBugcheckAbort() { return (bool) sysConfig.values[KEY_BUGCHECK_ABORT]; } int Config::getTraceDSQL() { return (int) sysConfig.values[KEY_TRACE_DSQL]; } bool Config::getLegacyHash() { return (bool) sysConfig.values[KEY_LEGACY_HASH]; } const char *Config::getGCPolicy() { return (const char *) sysConfig.values[KEY_GC_POLICY]; } bool Config::getRedirection() { return (bool) sysConfig.values[KEY_REDIRECTION]; } bool Config::getOldColumnNaming() { return (bool) sysConfig.values[KEY_OLD_COLUMN_NAMING]; } const char *Config::getAuthMethod() { return (const char *) sysConfig.values[KEY_AUTH_METHOD]; } int Config::getDatabaseGrowthIncrement() { return (int) sysConfig.values[KEY_DATABASE_GROWTH_INCREMENT]; }