Вход Регистрация
Файл: boot/db_cache.class.php
Строк: 151
<?php

/**
* @name        JMY CMS
* @link        http://jmy.su/
* @copyright   Copyright (C) 2012-2014 JMY LTD
* @license     LICENSE.txt (see attached file)
* @version     VERSION.txt (see attached file)
* @author      Komarov Ivan
* @outside     Youshi
*/
 
if (!defined('ACCESS')) {
    
header('Location: /');
    exit;
}
define('NOW_TIME', time());
 
class 
dateBase extends controlDB 
{
    var 
$prefix = '';    
    private 
$dir = 'tmp/mysql';
    private 
$index_file = 'index';
    private 
$index = array('drop' => array());
    private 
$cached = array();
    private 
$pointer = array();
    private 
$hashDrop = array();
    private 
$flush_by = array('INSERT', 'UPDATE', 'DELETE', 'REPLACE', 'ALTER');
    private 
$real_time_tables = array('online', 'comments', 'plugins', 'logs', 'reffers');
    private 
$real_time_func = array('NOW', 'UNIX_TIMESTAMP');
    private 
$no_cache_timeout = 300;

    function 
__construct() 
    {
        require_once 
ROOT . 'etc/db.config.php';
        
parent::connect($dbhost, $dbuser, $dbpass, $dbname);        
        
define("DB_PREFIX", $prefix); 
        
define("USER_PREFIX", $user_prefix);
        
define("USER_DB", $user_db);        
        if (!
is_dir(ROOT.'tmp/mysql/')) {mkdir(ROOT.'tmp/mysql/', 0777); @chmod_R(ROOT.'tmp/mysql/', 0777);}        
        
$this->dir = ROOT.'tmp/mysql/';        
        if (
file_exists($this->dir.$this->index_file)) include_once($this->dir.$this->index_file);
        unset(
$dbhost, $dbuser, $dbpass, $prefix, $user_prefix, $user_db);
    }
    
    function 
__destruct()
    {
        if (
sizeof($this->index['drop']) > 0)
        {
            
$this->index['drop'] = array_unique($this->index['drop']);
            foreach (
$this->index['drop'] AS $hash)
            {
                unset(
$this->index['lifetime'][$hash]);
                @
unlink($this->dir.$hash);
            }
            
$this->index['drop'] = array();
        }
        
        
$index = '<?php $this->index='.$this->arr2str($this->index).'; ?>';
        
$this->write_file($this->index_file, $index);
    }
    

    function 
query($query) 
    {
        
$hash = md5 (preg_replace('~([0-9]{10})~', '', $query));
        
$is_realtime = preg_match('~([0-9]{10})~', $query);
        
$is_cached = false;
        
$do = trim(strtoupper(mb_substr($query, 0, strpos($query, ' '))));
        if (!isset(
$this->cached[$hash]))
        {
            if (
$do == 'SELECT' or $do == 'DO')
            {
                
preg_match_all('~' . $this->prefix . '_([^s`]+)~i', $query, $match);
                
$tables =& $match[1]; unset ($match);
                
                if (
sizeof($tables) > 0 && sizeof(array_intersect($tables, $this->real_time_tables)) == 0)
                {
                    if (
in_array($hash, $this->index['drop']) or !file_exists($this->dir.$hash))
                    {
                        foreach (
$tables AS $table)
                        {
                            
$this->index['links'][$table][$hash] = array_diff($tables, array($table));
                        }
                        
$this->index['times'][$hash] = NOW_TIME;
                    }
                    else
                    {
                        
$modified =& $this->index['times'][$hash];
                        if (
$is_realtime or preg_match('~('.implode('|', $this->real_time_func).')~i', $query))
                        {        
                            if (
$this->no_cache_timeout && (NOW_TIME - $modified) < $this->no_cache_timeout) $is_cached = true;
                            else
                            {
                                
$this->index['times'][$hash] = NOW_TIME;
                            }
                        }
                        else 
$is_cached = true;
                    }
                    if (
$is_cached) $this->readcache($hash);
                    else
                    {
                        
$mysql = parent::doQuery($query, false, $this->prefix);                        
                        if (
$mysql)
                        {
                            while (
$row = parent::getRow($mysql)) $this->cached[$hash]['data'][] = $row;
                            
$this->cached[$hash]['sizeof'] = parent::numRows($mysql);
                            if (!
$this->cached[$hash]['sizeof']) $this->cached[$hash]['sizeof'] = 0;
                            
$this->pointer[$hash] = 0;
                            
$this->iQuery_id = $hash;
                            
$this->write_cache($hash);
                        }
                    }
                    return 
$hash;
                }
            }
            
        
            if (
in_array($do, $this->flush_by))
            {                    
                if (
preg_match('~' . $this->prefix . '_([^s`]+)~i', $query, $match))
                {        
                    
$table =& $match[1]; unset ($match);                
                    if (isset(
$this->index['links'][$table]))
                    {
                        foreach (
$this->index['links'][$table] AS $h => $link)
                        {
                            if(!isset(
$this->hashDrop[$h]))
                            {
                                foreach (
$link AS $tbl)
                                {
                                    unset(
$this->index['links'][$tbl][$h]);
                                }
                                
$this->index['drop'][] = $h;
                                
$this->hashDrop[$h] = true;
                            }
                        }
                    }
                }
            }
            return 
parent::doQuery($query, false, $this->prefix);
        }
        return 
$hash;

    }

    function 
arr2str (&$arr, $depth = 0)
    {
            
$ret = array();
            if (
is_array($arr) && sizeof($arr) > 0)
            {
                    foreach (
$arr AS $key => $value)
                    {
                            
$key = str_replace("'", "'", $key);
                            if (
is_array($value)) $ret[] = "'{$key}'=>".$this->arr2str($value, $depth+1);
                            elseif (
is_int($value)) $ret[] = "'{$key}'=>$value";
                            else
                            {
                                    if (
is_string($value)) $value = str_replace("'", '"', $value);
                                    
$ret[] = "'{$key}'=>'".strval($value)."'";
                            }
                    }
            }
            return 
'array('.implode(',', $ret).')';
    }

    function 
freeResult($resource) 
    {
        return 
parent::freeResult($resource);
    }
    
    function &
getRow($query_id)
    {
        
$ret = false;
        if (isset(
$this->cached[$query_id]))
        {
            if (
$this->pointer[$query_id] < $this->cached[$query_id]['sizeof'])
            {
                
$ret = $this->cached[$query_id]['data'][$this->pointer[$query_id]];
                
$this->pointer[$query_id]++;
            }
        }
        else 
$ret = parent::getRow($query_id);
        
        return 
$ret;
    }
    
    function 
fetchRow($query_id) 
    {
        
$ret =& $this->fetch_assoc($query_id);
        return 
$ret ? array_values($ret) : $ret;
    }
    
    function &
fetch_assoc ($query_id = -1)
    {
        
$ret = false;
        if (isset(
$this->cached[$query_id]))
        {
            if (
$this->pointer[$query_id] < $this->cached[$query_id]['sizeof'])
            {
                
$ret = $this->cached[$query_id]['data'][$this->pointer[$query_id]];
                
$this->pointer[$query_id]++;
            }
        }
        elseif (
$query_id != -1) $ret = parent::getRow($query_id);
        return 
$ret;
    }
    
    function 
numRows($query_id)
    {
        if (isset(
$this->cached[$query_id])) return $this->cached[$query_id]['sizeof'];
        else return 
parent::numRows($query_id);
    }
    

    private function 
readcache ($hash)
    {
        include_once(
$this->dir.$hash);
        
$this->pointer[$hash] = 0;
        
$this->iQuery_id = $hash;
    }
    
    private function 
write_cache ($hash)
    {
        
$data = "<?php $this->cached['$hash']=".$this->arr2str($this->cached[$hash]).'; ?>';
        
$this->write_file($hash, $data);
    }
    
    private function 
write_file($filename, &$content)
    {
        
ignore_user_abort(1);
        
$lockfile = $this->dir.$filename . '.lock';
        if (
file_exists($lockfile) && (time() - filemtime($lockfile)) > 5) @unlink($lockfile);
        
$lock_ex = @fopen($lockfile, 'x');
        for (
$i=0; ($lock_ex === false) && ($i < 20); $i++)
        {
            
clearstatcache();
            
usleep(rand(5, 15));
            
$lock_ex = @fopen($lockfile, 'x');
        }
        
        
$success = false;
        if (
$lock_ex !== false)
        {
            
$fp = @fopen($this->dir.$filename, 'wb');
            if (@
fwrite($fp, $content)) $success = true;
            @
fclose($fp);
            
fclose($lock_ex);
            @
unlink($lockfile);
        }
        
ignore_user_abort(0);
        return 
$success;
    }
}
$db = new dateBase();
Онлайн: 2
Реклама