Перенос классов в файлы

Классы работы с базой данных, кеша, датастора переносим в отдельные файлы. Обычный require, но надо добавить require только при выбранности данного вида кеширования.
This commit is contained in:
Exile 2014-11-23 00:22:21 +03:00
commit 80c99e7c8e
20 changed files with 1734 additions and 1652 deletions

1682
common.php

File diff suppressed because it is too large Load diff

View file

@ -262,6 +262,7 @@ define('ATTACH_DIR', BB_PATH .'/library/attach_mod/' );
define('CFG_DIR', BB_PATH .'/library/config/' );
define('INC_DIR', BB_PATH .'/library/includes/' );
define('CLASS_DIR', BB_PATH .'/library/includes/classes/');
define('CORE_DIR', BB_PATH .'/library/includes/core/' );
define('UCP_DIR', BB_PATH .'/library/includes/ucp/' );
define('LANG_ROOT_DIR', BB_PATH .'/library/language/' );
define('IMAGES_DIR', BB_PATH .'/styles/images/' );

65
library/includes/cache/apc.php vendored Normal file
View file

@ -0,0 +1,65 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_apc extends cache_common
{
var $used = true;
var $engine = 'APC';
var $prefix = null;
function cache_apc ($prefix = null)
{
if (!$this->is_installed())
{
die('Error: APC extension not installed');
}
$this->dbg_enabled = sql_dbg_enabled();
$this->prefix = $prefix;
}
function get ($name, $get_miss_key_callback = '', $ttl = 0)
{
$this->cur_query = "cache->get('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return apc_fetch($this->prefix . $name);
}
function set ($name, $value, $ttl = 0)
{
$this->cur_query = "cache->set('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return apc_store($this->prefix . $name, $value, $ttl);
}
function rm ($name = '')
{
if ($name)
{
$this->cur_query = "cache->rm('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return apc_delete($this->prefix . $name);
}
else
{
return apc_clear_cache();
}
}
function is_installed ()
{
return function_exists('apc_fetch');
}
}

84
library/includes/cache/common.php vendored Normal file
View file

@ -0,0 +1,84 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_common
{
var $used = false;
/**
* Returns value of variable
*/
function get ($name, $get_miss_key_callback = '', $ttl = 604800)
{
if ($get_miss_key_callback) return $get_miss_key_callback($name);
return is_array($name) ? array() : false;
}
/**
* Store value of variable
*/
function set ($name, $value, $ttl = 604800)
{
return false;
}
/**
* Remove variable
*/
function rm ($name = '')
{
return false;
}
var $num_queries = 0;
var $sql_starttime = 0;
var $sql_inittime = 0;
var $sql_timetotal = 0;
var $cur_query_time = 0;
var $dbg = array();
var $dbg_id = 0;
var $dbg_enabled = false;
var $cur_query = null;
function debug ($mode, $cur_query = null)
{
if (!$this->dbg_enabled) return;
$id =& $this->dbg_id;
$dbg =& $this->dbg[$id];
if ($mode == 'start')
{
$this->sql_starttime = utime();
$dbg['sql'] = isset($cur_query) ? short_query($cur_query) : short_query($this->cur_query);
$dbg['src'] = $this->debug_find_source();
$dbg['file'] = $this->debug_find_source('file');
$dbg['line'] = $this->debug_find_source('line');
$dbg['time'] = '';
}
else if ($mode == 'stop')
{
$this->cur_query_time = utime() - $this->sql_starttime;
$this->sql_timetotal += $this->cur_query_time;
$dbg['time'] = $this->cur_query_time;
$id++;
}
}
function debug_find_source ($mode = '')
{
foreach (debug_backtrace() as $trace)
{
if ($trace['file'] !== __FILE__)
{
switch ($mode)
{
case 'file': return $trace['file'];
case 'line': return $trace['line'];
default: return hide_bb_path($trace['file']) .'('. $trace['line'] .')';
}
}
}
return 'src not found';
}
}

136
library/includes/cache/file.php vendored Normal file
View file

@ -0,0 +1,136 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_file extends cache_common
{
var $used = true;
var $engine = 'Filecache';
var $dir = null;
var $prefix = null;
function cache_file ($dir, $prefix = null)
{
$this->dir = $dir;
$this->prefix = $prefix;
$this->dbg_enabled = sql_dbg_enabled();
}
function get ($name, $get_miss_key_callback = '', $ttl = 0)
{
$filename = $this->dir . clean_filename($this->prefix . $name) . '.php';
$this->cur_query = "cache->set('$name')";
$this->debug('start');
if (file_exists($filename))
{
require($filename);
}
$this->debug('stop');
$this->cur_query = null;
return (!empty($filecache['value'])) ? $filecache['value'] : false;
}
function set ($name, $value, $ttl = 86400)
{
if (!function_exists('var_export'))
{
return false;
}
$this->cur_query = "cache->set('$name')";
$this->debug('start');
$filename = $this->dir . clean_filename($this->prefix . $name) . '.php';
$expire = TIMENOW + $ttl;
$cache_data = array(
'expire' => $expire,
'value' => $value,
);
$filecache = "<?php\n";
$filecache .= "if (!defined('BB_ROOT')) die(basename(__FILE__));\n";
$filecache .= '$filecache = ' . var_export($cache_data, true) . ";\n";
$filecache .= '?>';
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return (bool) file_write($filecache, $filename, false, true, true);
}
function rm ($name = '')
{
$clear = false;
if ($name)
{
$this->cur_query = "cache->rm('$name')";
$this->debug('start');
$filename = $this->dir . clean_filename($this->prefix . $name) . '.php';
if (file_exists($filename))
{
$clear = (bool) unlink($filename);
}
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
}
else
{
if (is_dir($this->dir))
{
if ($dh = opendir($this->dir))
{
while (($file = readdir($dh)) !== false)
{
if ($file != "." && $file != "..")
{
$filename = $this->dir . $file;
unlink($filename);
$clear = true;
}
}
closedir($dh);
}
}
}
return $clear;
}
function gc ($expire_time = TIMENOW)
{
$clear = false;
if (is_dir($this->dir))
{
if ($dh = opendir($this->dir))
{
while (($file = readdir($dh)) !== false)
{
if ($file != "." && $file != "..")
{
$filename = $this->dir . $file;
require($filename);
if(!empty($filecache['expire']) && ($filecache['expire'] < $expire_time))
{
unlink($filename);
$clear = true;
}
}
}
closedir($dh);
}
}
return $clear;
}
}

100
library/includes/cache/memcache.php vendored Normal file
View file

@ -0,0 +1,100 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_memcache extends cache_common
{
var $used = true;
var $engine = 'Memcache';
var $cfg = null;
var $prefix = null;
var $memcache = null;
var $connected = false;
function cache_memcache ($cfg, $prefix = null)
{
if (!$this->is_installed())
{
die('Error: Memcached extension not installed');
}
$this->cfg = $cfg;
$this->prefix = $prefix;
$this->memcache = new Memcache;
$this->dbg_enabled = sql_dbg_enabled();
}
function connect ()
{
$connect_type = ($this->cfg['pconnect']) ? 'pconnect' : 'connect';
$this->cur_query = $connect_type .' '. $this->cfg['host'] .':'. $this->cfg['port'];
$this->debug('start');
if (@$this->memcache->$connect_type($this->cfg['host'], $this->cfg['port']))
{
$this->connected = true;
}
if (DBG_LOG) dbg_log(' ', 'CACHE-connect'. ($this->connected ? '' : '-FAIL'));
if (!$this->connected && $this->cfg['con_required'])
{
die('Could not connect to memcached server');
}
$this->debug('stop');
$this->cur_query = null;
}
function get ($name, $get_miss_key_callback = '', $ttl = 0)
{
if (!$this->connected) $this->connect();
$this->cur_query = "cache->get('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return ($this->connected) ? $this->memcache->get($this->prefix . $name) : false;
}
function set ($name, $value, $ttl = 0)
{
if (!$this->connected) $this->connect();
$this->cur_query = "cache->set('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return ($this->connected) ? $this->memcache->set($this->prefix . $name, $value, false, $ttl) : false;
}
function rm ($name = '')
{
if (!$this->connected) $this->connect();
if ($name)
{
$this->cur_query = "cache->rm('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return ($this->connected) ? $this->memcache->delete($this->prefix . $name, 0) : false;
}
else
{
return ($this->connected) ? $this->memcache->flush() : false;
}
}
function is_installed ()
{
return class_exists('Memcache');
}
}

109
library/includes/cache/redis.php vendored Normal file
View file

@ -0,0 +1,109 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_redis extends cache_common
{
var $used = true;
var $engine = 'Redis';
var $cfg = null;
var $redis = null;
var $prefix = null;
var $connected = false;
function cache_redis ($cfg, $prefix = null)
{
if (!$this->is_installed())
{
die('Error: Redis extension not installed');
}
$this->cfg = $cfg;
$this->prefix = $prefix;
$this->redis = new Redis();
$this->dbg_enabled = sql_dbg_enabled();
}
function connect ()
{
$this->cur_query = 'connect '. $this->cfg['host'] .':'. $this->cfg['port'];
$this->debug('start');
if (@$this->redis->connect($this->cfg['host'], $this->cfg['port']))
{
$this->connected = true;
}
if (!$this->connected && $this->cfg['con_required'])
{
die('Could not connect to redis server');
}
$this->debug('stop');
$this->cur_query = null;
}
function get ($name, $get_miss_key_callback = '', $ttl = 0)
{
if (!$this->connected) $this->connect();
$this->cur_query = "cache->get('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return ($this->connected) ? unserialize($this->redis->get($this->prefix . $name)) : false;
}
function set ($name, $value, $ttl = 0)
{
if (!$this->connected) $this->connect();
$this->cur_query = "cache->set('$name')";
$this->debug('start');
if ($this->redis->set($this->prefix . $name, serialize($value)))
{
if ($ttl > 0)
{
$this->redis->expire($this->prefix . $name, $ttl);
}
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return true;
}
else
{
return false;
}
}
function rm ($name = '')
{
if (!$this->connected) $this->connect();
if ($name)
{
$this->cur_query = "cache->rm('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return ($this->connected) ? $this->redis->del($this->prefix . $name) : false;
}
else
{
return ($this->connected) ? $this->redis->flushdb() : false;
}
}
function is_installed ()
{
return class_exists('Redis');
}
}

110
library/includes/cache/sqlite.php vendored Normal file
View file

@ -0,0 +1,110 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_sqlite extends cache_common
{
var $used = true;
var $db = null;
var $prefix = null;
var $cfg = array(
'db_file_path' => '/path/to/cache.db.sqlite',
'table_name' => 'cache',
'table_schema' => 'CREATE TABLE cache (
cache_name VARCHAR(255),
cache_expire_time INT,
cache_value TEXT,
PRIMARY KEY (cache_name)
)',
'pconnect' => true,
'con_required' => true,
'log_name' => 'CACHE',
);
function cache_sqlite ($cfg, $prefix = null)
{
$this->cfg = array_merge($this->cfg, $cfg);
$this->db = new sqlite_common($this->cfg);
$this->prefix = $prefix;
}
function get ($name, $get_miss_key_callback = '', $ttl = 604800)
{
if (empty($name))
{
return is_array($name) ? array() : false;
}
$this->db->shard($name);
$cached_items = array();
$this->prefix_len = strlen($this->prefix);
$this->prefix_sql = sqlite_escape_string($this->prefix);
$name_ary = $name_sql = (array) $name;
array_deep($name_sql, 'sqlite_escape_string');
// get available items
$rowset = $this->db->fetch_rowset("
SELECT cache_name, cache_value
FROM ". $this->cfg['table_name'] ."
WHERE cache_name IN('$this->prefix_sql". join("','$this->prefix_sql", $name_sql) ."') AND cache_expire_time > ". TIMENOW ."
LIMIT ". count($name) ."
");
$this->db->debug('start', 'unserialize()');
foreach ($rowset as $row)
{
$cached_items[substr($row['cache_name'], $this->prefix_len)] = unserialize($row['cache_value']);
}
$this->db->debug('stop');
// get miss items
if ($get_miss_key_callback AND $miss_key = array_diff($name_ary, array_keys($cached_items)))
{
foreach ($get_miss_key_callback($miss_key) as $k => $v)
{
$this->set($this->prefix . $k, $v, $ttl);
$cached_items[$k] = $v;
}
}
// return
if (is_array($this->prefix . $name))
{
return $cached_items;
}
else
{
return isset($cached_items[$name]) ? $cached_items[$name] : false;
}
}
function set ($name, $value, $ttl = 604800)
{
$this->db->shard($this->prefix . $name);
$name_sql = sqlite_escape_string($this->prefix . $name);
$expire = TIMENOW + $ttl;
$value_sql = sqlite_escape_string(serialize($value));
$result = $this->db->query("REPLACE INTO ". $this->cfg['table_name'] ." (cache_name, cache_expire_time, cache_value) VALUES ('$name_sql', $expire, '$value_sql')");
return (bool) $result;
}
function rm ($name = '')
{
if ($name)
{
$this->db->shard($this->prefix . $name);
$result = $this->db->query("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_name = '". sqlite_escape_string($this->prefix . $name) ."'");
}
else
{
$result = $this->db->query("DELETE FROM ". $this->cfg['table_name']);
}
return (bool) $result;
}
function gc ($expire_time = TIMENOW)
{
$result = $this->db->query("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_expire_time < $expire_time");
return ($result) ? $this->db->changes() : 0;
}
}

181
library/includes/cache/sqlite_common.php vendored Normal file
View file

@ -0,0 +1,181 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class sqlite_common extends cache_common
{
var $cfg = array(
'db_file_path' => 'sqlite.db',
'table_name' => 'table_name',
'table_schema' => 'CREATE TABLE table_name (...)',
'pconnect' => true,
'con_required' => true,
'log_name' => 'SQLite',
'shard_type' => 'none', # none, string, int (тип перевичного ключа для шардинга)
'shard_val' => 0, # для string - кол. начальных символов, для int - делитель (будет использован остаток от деления)
);
var $engine = 'SQLite';
var $dbh = null;
var $connected = false;
var $shard_val = false;
var $table_create_attempts = 0;
function sqlite_common ($cfg)
{
$this->cfg = array_merge($this->cfg, $cfg);
$this->dbg_enabled = sql_dbg_enabled();
}
function connect ()
{
$this->cur_query = ($this->dbg_enabled) ? 'connect to: '. $this->cfg['db_file_path'] : 'connect';
$this->debug('start');
if (@$this->dbh = new SQLite3($this->cfg['db_file_path']))
{
$this->connected = true;
}
if (DBG_LOG) dbg_log(' ', $this->cfg['log_name'] .'-connect'. ($this->connected ? '' : '-FAIL'));
if (!$this->connected && $this->cfg['con_required'])
{
trigger_error('SQLite not connected', E_USER_ERROR);
}
$this->debug('stop');
$this->cur_query = null;
}
function create_table ()
{
$this->table_create_attempts++;
return $this->dbh->query($this->cfg['table_schema']);
}
function shard ($name)
{
$type = $this->cfg['shard_type'];
if ($type == 'none') return;
if (is_array($name)) trigger_error('cannot shard: $name is array', E_USER_ERROR);
// define shard_val
if ($type == 'string')
{
$shard_val = substr($name, 0, $this->cfg['shard_val']);
}
else
{
$shard_val = $name % $this->cfg['shard_val'];
}
// все запросы должны быть к одному и тому же шарду
if ($this->shard_val !== false)
{
if ($shard_val != $this->shard_val)
{
trigger_error("shard cannot be reassigned. [{$this->shard_val}, $shard_val, $name]", E_USER_ERROR);
}
else
{
return;
}
}
$this->shard_val = $shard_val;
$this->cfg['db_file_path'] = str_replace('*', $shard_val, $this->cfg['db_file_path']);
}
function query ($query)
{
if (!$this->connected) $this->connect();
$this->cur_query = $query;
$this->debug('start');
if (!$result = @$this->dbh->query($query))
{
$rowsresult = $this->dbh->query("PRAGMA table_info({$this->cfg['table_name']})");
$rowscount = 0;
while ($row = $rowsresult->fetchArray(SQLITE3_ASSOC))
{
$rowscount++;
}
if (!$this->table_create_attempts && !$rowscount)
{
if ($this->create_table())
{
$result = $this->dbh->query($query);
}
}
if (!$result)
{
$this->trigger_error($this->get_error_msg());
}
}
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return $result;
}
function fetch_row ($query)
{
$result = $this->query($query);
return is_resource($result) ? $result->fetchArray(SQLITE3_ASSOC) : false;
}
function fetch_rowset ($query)
{
$result = $this->query($query);
$rowset = array();
while ($row = $result->fetchArray(SQLITE3_ASSOC))
{
$rowset[] = $row;
}
return $rowset;
}
function changes ()
{
return is_resource($this->dbh) ? $this->dbh->changes() : 0;
}
function escape ($str)
{
return sqlite_escape_string($str);
}
function get_error_msg ()
{
return 'SQLite error #'. ($err_code = $this->dbh->lastErrorCode()) .': '. $this->dbh->lastErrorMsg();
}
function rm ($name = '')
{
if ($name)
{
$this->db->shard($this->prefix . $name);
$result = $this->db->query("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_name = '". sqlite_escape_string($this->prefix . $name) ."'");
}
else
{
$result = $this->db->query("DELETE FROM ". $this->cfg['table_name']);
}
return (bool) $result;
}
function gc ($expire_time = TIMENOW)
{
$result = $this->db->query("DELETE FROM ". $this->cfg['table_name'] ." WHERE cache_expire_time < $expire_time");
return ($result) ? sqlite_changes($this->db->dbh) : 0;
}
function trigger_error ($msg = 'DB Error')
{
if (error_reporting()) trigger_error($msg, E_USER_ERROR);
}
}

67
library/includes/cache/xcache.php vendored Normal file
View file

@ -0,0 +1,67 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class cache_xcache extends cache_common
{
var $used = true;
var $engine = 'XCache';
var $prefix = null;
function cache_xcache ($prefix = null)
{
if (!$this->is_installed())
{
die('Error: XCache extension not installed');
}
$this->dbg_enabled = sql_dbg_enabled();
$this->prefix = $prefix;
}
function get ($name, $get_miss_key_callback = '', $ttl = 0)
{
$this->cur_query = "cache->get('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return xcache_get($this->prefix . $name);
}
function set ($name, $value, $ttl = 0)
{
$this->cur_query = "cache->set('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return xcache_set($this->prefix . $name, $value, $ttl);
}
function rm ($name = '')
{
if ($name)
{
$this->cur_query = "cache->rm('$name')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return xcache_unset($this->prefix . $name);
}
else
{
xcache_clear_cache(XC_TYPE_PHP, 0);
xcache_clear_cache(XC_TYPE_VAR, 0);
return;
}
}
function is_installed ()
{
return function_exists('xcache_get');
}
}

View file

@ -0,0 +1,118 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class CACHES
{
var $cfg = array(); // конфиг
var $obj = array(); // кеш-объекты
var $ref = array(); // ссылки на $obj (имя_кеша => кеш_объект)
function CACHES ($cfg)
{
$this->cfg = $cfg['cache'];
$this->obj['__stub'] = new cache_common();
}
function get_cache_obj ($cache_name)
{
if (!isset($this->ref[$cache_name]))
{
if (!$engine_cfg =& $this->cfg['engines'][$cache_name])
{
$this->ref[$cache_name] =& $this->obj['__stub'];
}
else
{
$cache_type =& $engine_cfg[0];
$cache_cfg =& $engine_cfg[1];
switch ($cache_type)
{
case 'memcache':
if (!isset($this->obj[$cache_name]))
{
$this->obj[$cache_name] = new cache_memcache($this->cfg['memcache'], $this->cfg['prefix']);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
case 'sqlite':
if (!isset($this->obj[$cache_name]))
{
$cache_cfg['pconnect'] = $this->cfg['pconnect'];
$cache_cfg['db_file_path'] = $this->get_db_path($cache_name, $cache_cfg, '.sqlite.db');
$this->obj[$cache_name] = new cache_sqlite($cache_cfg, $this->cfg['prefix']);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
case 'db_sqlite':
if (!isset($this->obj[$cache_name]))
{
$cache_cfg['pconnect'] = $this->cfg['pconnect'];
$cache_cfg['db_file_path'] = $this->get_db_path($cache_name, $cache_cfg, '.sqlite.db');
$cache_cfg['table_name'] = $cache_name;
$cache_cfg['table_schema'] = $this->get_table_schema($cache_cfg);
$this->obj[$cache_name] = new sqlite_common($cache_cfg);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
case 'redis':
if (!isset($this->obj[$cache_name]))
{
$this->obj[$cache_name] = new cache_redis($this->cfg['redis'], $this->cfg['prefix']);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
case 'apc':
if (!isset($this->obj[$cache_name]))
{
$this->obj[$cache_name] = new cache_apc($this->cfg['prefix']);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
case 'xcache':
if (!isset($this->obj[$cache_name]))
{
$this->obj[$cache_name] = new cache_xcache($this->cfg['prefix']);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
default: //filecache
if (!isset($this->obj[$cache_name]))
{
$this->obj[$cache_name] = new cache_file($this->cfg['db_dir'] . $cache_name .'/', $this->cfg['prefix']);
}
$this->ref[$cache_name] =& $this->obj[$cache_name];
break;
}
}
}
return $this->ref[$cache_name];
}
function get_db_path ($name, $cfg, $ext)
{
if (!empty($cfg['shard_type']) && $cfg['shard_type'] != 'none')
{
return $this->cfg['db_dir'] . $name .'_*'. $ext;
}
else
{
return $this->cfg['db_dir'] . $name . $ext;
}
}
function get_table_schema ($cfg)
{
return "CREATE TABLE {$cfg['table_name']} ( {$cfg['columns']} )";
}
}

View file

@ -0,0 +1,58 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class DBS
{
var $cfg = array(); // $srv_name => $srv_cfg
var $srv = array(); // $srv_name => $db_obj
var $alias = array(); // $srv_alias => $srv_name
var $log_file = 'sql_queries';
var $log_counter = 0;
var $num_queries = 0;
var $sql_inittime = 0;
var $sql_timetotal = 0;
function DBS ($cfg)
{
$this->cfg = $cfg['db'];
$this->alias = $cfg['db_alias'];
foreach ($this->cfg as $srv_name => $srv_cfg)
{
$this->srv[$srv_name] = null;
}
}
// получение/инициализация класса для сервера $srv_name
function get_db_obj ($srv_name_or_alias = 'db1')
{
$srv_name = $this->get_srv_name($srv_name_or_alias);
if (!is_object($this->srv[$srv_name]))
{
$this->srv[$srv_name] = new sql_db($this->cfg[$srv_name]);
$this->srv[$srv_name]->db_server = $srv_name;
}
return $this->srv[$srv_name];
}
// определение имени сервера
function get_srv_name ($name)
{
if (isset($this->alias[$name]))
{
$srv_name = $this->alias[$name];
}
else if (isset($this->cfg[$name]))
{
$srv_name = $name;
}
else
{
$srv_name = 'db1';
}
return $srv_name;
}
}

View file

@ -0,0 +1,71 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_apc extends datastore_common
{
var $engine = 'APC';
var $prefix = null;
function datastore_apc ($prefix = null)
{
if (!$this->is_installed())
{
die('Error: APC extension not installed');
}
$this->dbg_enabled = sql_dbg_enabled();
$this->prefix = $prefix;
}
function store ($title, $var)
{
$this->data[$title] = $var;
$this->cur_query = "cache->set('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return (bool) apc_store($this->prefix . $title, $var);
}
function clean ()
{
foreach ($this->known_items as $title => $script_name)
{
$this->cur_query = "cache->rm('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
apc_delete($this->prefix . $title);
}
}
function _fetch_from_store ()
{
if (!$items = $this->queued_items)
{
$src = $this->_debug_find_caller('enqueue');
trigger_error("Datastore: item '$item' already enqueued [$src]", E_USER_ERROR);
}
foreach ($items as $item)
{
$this->cur_query = "cache->get('$item')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
$this->data[$item] = apc_fetch($this->prefix . $item);
}
}
function is_installed ()
{
return function_exists('apc_fetch');
}
}

View file

@ -0,0 +1,175 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_common
{
/**
* Директория с builder-скриптами (внутри INC_DIR)
*/
var $ds_dir = 'datastore/';
/**
* Готовая к употреблению data
* array('title' => data)
*/
var $data = array();
/**
* Список элементов, которые будут извлечены из хранилища при первом же запросе get()
* до этого момента они ставятся в очередь $queued_items для дальнейшего извлечения _fetch()'ем
* всех элементов одним запросом
* array('title1', 'title2'...)
*/
var $queued_items = array();
/**
* 'title' => 'builder script name' inside "includes/datastore" dir
*/
var $known_items = array(
'cat_forums' => 'build_cat_forums.php',
'jumpbox' => 'build_cat_forums.php',
'viewtopic_forum_select' => 'build_cat_forums.php',
'latest_news' => 'build_cat_forums.php',
'network_news' => 'build_cat_forums.php',
'ads' => 'build_cat_forums.php',
'moderators' => 'build_moderators.php',
'stats' => 'build_stats.php',
'ranks' => 'build_ranks.php',
'attach_extensions' => 'build_attach_extensions.php',
'smile_replacements' => 'build_smilies.php',
);
/**
* Constructor
*/
function datastore_common () {}
/**
* @param array(item1_title, item2_title...) or single item's title
*/
function enqueue ($items)
{
foreach ((array) $items as $item)
{
// игнор уже поставленного в очередь либо уже извлеченного
if (!in_array($item, $this->queued_items) && !isset($this->data[$item]))
{
$this->queued_items[] = $item;
}
}
}
function &get ($title)
{
if (!isset($this->data[$title]))
{
$this->enqueue($title);
$this->_fetch();
}
return $this->data[$title];
}
function store ($item_name, $item_data) {}
function rm ($items)
{
foreach ((array) $items as $item)
{
unset($this->data[$item]);
}
}
function update ($items)
{
if ($items == 'all')
{
$items = array_keys(array_unique($this->known_items));
}
foreach ((array) $items as $item)
{
$this->_build_item($item);
}
}
function _fetch ()
{
$this->_fetch_from_store();
foreach ($this->queued_items as $title)
{
if (!isset($this->data[$title]) || $this->data[$title] === false)
{
$this->_build_item($title);
}
}
$this->queued_items = array();
}
function _fetch_from_store () {}
function _build_item ($title)
{
if (!empty($this->known_items[$title]))
{
require(INC_DIR . $this->ds_dir . $this->known_items[$title]);
}
else
{
trigger_error("Unknown datastore item: $title", E_USER_ERROR);
}
}
var $num_queries = 0;
var $sql_starttime = 0;
var $sql_inittime = 0;
var $sql_timetotal = 0;
var $cur_query_time = 0;
var $dbg = array();
var $dbg_id = 0;
var $dbg_enabled = false;
var $cur_query = null;
function debug ($mode, $cur_query = null)
{
if (!$this->dbg_enabled) return;
$id =& $this->dbg_id;
$dbg =& $this->dbg[$id];
if ($mode == 'start')
{
$this->sql_starttime = utime();
$dbg['sql'] = isset($cur_query) ? short_query($cur_query) : short_query($this->cur_query);
$dbg['src'] = $this->debug_find_source();
$dbg['file'] = $this->debug_find_source('file');
$dbg['line'] = $this->debug_find_source('line');
$dbg['time'] = '';
}
else if ($mode == 'stop')
{
$this->cur_query_time = utime() - $this->sql_starttime;
$this->sql_timetotal += $this->cur_query_time;
$dbg['time'] = $this->cur_query_time;
$id++;
}
}
function debug_find_source ($mode = '')
{
foreach (debug_backtrace() as $trace)
{
if ($trace['file'] !== __FILE__)
{
switch ($mode)
{
case 'file': return $trace['file'];
case 'line': return $trace['line'];
default: return hide_bb_path($trace['file']) .'('. $trace['line'] .')';
}
}
}
return 'src not found';
}
}

View file

@ -0,0 +1,87 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_file extends datastore_common
{
var $dir = null;
var $prefix = null;
var $engine = 'Filecache';
function datastore_file ($dir, $prefix = null)
{
$this->prefix = $prefix;
$this->dir = $dir;
$this->dbg_enabled = sql_dbg_enabled();
}
function store ($title, $var)
{
$this->cur_query = "cache->set('$title')";
$this->debug('start');
$this->data[$title] = $var;
$filename = $this->dir . clean_filename($this->prefix . $title) . '.php';
$filecache = "<?php\n";
$filecache .= "if (!defined('BB_ROOT')) die(basename(__FILE__));\n";
$filecache .= '$filecache = ' . var_export($var, true) . ";\n";
$filecache .= '?>';
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return (bool) file_write($filecache, $filename, false, true, true);
}
function clean ()
{
$dir = $this->dir;
if (is_dir($dir))
{
if ($dh = opendir($dir))
{
while (($file = readdir($dh)) !== false)
{
if ($file != "." && $file != "..")
{
$filename = $dir . $file;
unlink($filename);
}
}
closedir($dh);
}
}
}
function _fetch_from_store ()
{
if (!$items = $this->queued_items)
{
$src = $this->_debug_find_caller('enqueue');
trigger_error("Datastore: item '$item' already enqueued [$src]", E_USER_ERROR);
}
foreach($items as $item)
{
$filename = $this->dir . $this->prefix . $item . '.php';
$this->cur_query = "cache->get('$item')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
if(file_exists($filename))
{
require($filename);
$this->data[$item] = $filecache;
}
}
}
}

View file

@ -0,0 +1,103 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_memcache extends datastore_common
{
var $cfg = null;
var $memcache = null;
var $connected = false;
var $engine = 'Memcache';
var $prefix = null;
function datastore_memcache ($cfg, $prefix = null)
{
if (!$this->is_installed())
{
die('Error: Memcached extension not installed');
}
$this->cfg = $cfg;
$this->prefix = $prefix;
$this->memcache = new Memcache;
$this->dbg_enabled = sql_dbg_enabled();
}
function connect ()
{
$connect_type = ($this->cfg['pconnect']) ? 'pconnect' : 'connect';
$this->cur_query = $connect_type .' '. $this->cfg['host'] .':'. $this->cfg['port'];
$this->debug('start');
if (@$this->memcache->$connect_type($this->cfg['host'], $this->cfg['port']))
{
$this->connected = true;
}
if (DBG_LOG) dbg_log(' ', 'CACHE-connect'. ($this->connected ? '' : '-FAIL'));
if (!$this->connected && $this->cfg['con_required'])
{
die('Could not connect to memcached server');
}
$this->debug('stop');
$this->cur_query = null;
}
function store ($title, $var)
{
if (!$this->connected) $this->connect();
$this->data[$title] = $var;
$this->cur_query = "cache->set('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return (bool) $this->memcache->set($this->prefix . $title, $var);
}
function clean ()
{
if (!$this->connected) $this->connect();
foreach ($this->known_items as $title => $script_name)
{
$this->cur_query = "cache->rm('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
$this->memcache->delete($this->prefix . $title, 0);
}
}
function _fetch_from_store ()
{
if (!$items = $this->queued_items)
{
$src = $this->_debug_find_caller('enqueue');
trigger_error("Datastore: item '$item' already enqueued [$src]", E_USER_ERROR);
}
if (!$this->connected) $this->connect();
foreach ($items as $item)
{
$this->cur_query = "cache->get('$item')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
$this->data[$item] = $this->memcache->get($this->prefix . $item);
}
}
function is_installed ()
{
return class_exists('Memcache');
}
}

View file

@ -0,0 +1,99 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_redis extends datastore_common
{
var $cfg = null;
var $redis = null;
var $prefix = null;
var $connected = false;
var $engine = 'Redis';
function datastore_redis ($cfg, $prefix = null)
{
if (!$this->is_installed())
{
die('Error: Redis extension not installed');
}
$this->cfg = $cfg;
$this->redis = new Redis();
$this->dbg_enabled = sql_dbg_enabled();
$this->prefix = $prefix;
}
function connect ()
{
$this->cur_query = 'connect '. $this->cfg['host'] .':'. $this->cfg['port'];
$this->debug('start');
if (@$this->redis->connect($this->cfg['host'],$this->cfg['port']))
{
$this->connected = true;
}
if (!$this->connected && $this->cfg['con_required'])
{
die('Could not connect to redis server');
}
$this->debug('stop');
$this->cur_query = null;
}
function store ($title, $var)
{
if (!$this->connected) $this->connect();
$this->data[$title] = $var;
$this->cur_query = "cache->set('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return (bool) $this->redis->set($this->prefix . $title, serialize($var));
}
function clean ()
{
if (!$this->connected) $this->connect();
foreach ($this->known_items as $title => $script_name)
{
$this->cur_query = "cache->rm('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
$this->redis->del($this->prefix . $title);
}
}
function _fetch_from_store ()
{
if (!$items = $this->queued_items)
{
$src = $this->_debug_find_caller('enqueue');
trigger_error("Datastore: item '$item' already enqueued [$src]", E_USER_ERROR);
}
if (!$this->connected) $this->connect();
foreach ($items as $item)
{
$this->cur_query = "cache->get('$item')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
$this->data[$item] = unserialize($this->redis->get($this->prefix . $item));
}
}
function is_installed ()
{
return class_exists('Redis');
}
}

View file

@ -0,0 +1,66 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_sqlite extends datastore_common
{
var $engine = 'SQLite';
var $db = null;
var $prefix = null;
var $cfg = array(
'db_file_path' => '/path/to/datastore.db.sqlite',
'table_name' => 'datastore',
'table_schema' => 'CREATE TABLE datastore (
ds_title VARCHAR(255),
ds_data TEXT,
PRIMARY KEY (ds_title)
)',
'pconnect' => true,
'con_required' => true,
'log_name' => 'DATASTORE',
);
function datastore_sqlite ($cfg, $prefix = null)
{
$this->cfg = array_merge($this->cfg, $cfg);
$this->db = new sqlite_common($this->cfg);
$this->prefix = $prefix;
}
function store ($item_name, $item_data)
{
$this->data[$item_name] = $item_data;
$ds_title = sqlite_escape_string($this->prefix . $item_name);
$ds_data = sqlite_escape_string(serialize($item_data));
$result = $this->db->query("REPLACE INTO ". $this->cfg['table_name'] ." (ds_title, ds_data) VALUES ('$ds_title', '$ds_data')");
return (bool) $result;
}
function clean ()
{
$this->db->query("DELETE FROM ". $this->cfg['table_name']);
}
function _fetch_from_store ()
{
if (!$items = $this->queued_items) return;
$prefix_len = strlen($this->prefix);
$prefix_sql = sqlite_escape_string($this->prefix);
array_deep($items, 'sqlite_escape_string');
$items_list = $prefix_sql . join("','$prefix_sql", $items);
$rowset = $this->db->fetch_rowset("SELECT ds_title, ds_data FROM ". $this->cfg['table_name'] ." WHERE ds_title IN ('$items_list')");
$this->db->debug('start', "unserialize()");
foreach ($rowset as $row)
{
$this->data[substr($row['ds_title'], $prefix_len)] = unserialize($row['ds_data']);
}
$this->db->debug('stop');
}
}

View file

@ -0,0 +1,72 @@
<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
class datastore_xcache extends datastore_common
{
var $prefix = null;
var $engine = 'XCache';
function datastore_xcache ($prefix = null)
{
if (!$this->is_installed())
{
die('Error: XCache extension not installed');
}
$this->dbg_enabled = sql_dbg_enabled();
$this->prefix = $prefix;
}
function store ($title, $var)
{
$this->data[$title] = $var;
$this->cur_query = "cache->set('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
return (bool) xcache_set($this->prefix . $title, $var);
}
function clean ()
{
foreach ($this->known_items as $title => $script_name)
{
$this->cur_query = "cache->rm('$title')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
xcache_unset($this->prefix . $title);
}
}
function _fetch_from_store ()
{
if (!$items = $this->queued_items)
{
$src = $this->_debug_find_caller('enqueue');
trigger_error("Datastore: item '$item' already enqueued [$src]", E_USER_ERROR);
}
foreach ($items as $item)
{
$this->cur_query = "cache->set('$item')";
$this->debug('start');
$this->debug('stop');
$this->cur_query = null;
$this->num_queries++;
$this->data[$item] = xcache_get($this->prefix . $item);
}
}
function is_installed ()
{
return function_exists('xcache_get');
}
}

View file

@ -429,7 +429,7 @@ function make_url ($path = '')
require(INC_DIR .'functions.php');
require(INC_DIR .'sessions.php');
require(INC_DIR .'template.php');
require(INC_DIR .'core/mysql.php');
require(CORE_DIR .'mysql.php');
define('SQL_LAYER', 'mysql');