root/dev/common/includes/class.db_memcache.php @ 424

Revision 424, 6.4 KB (checked in by kovell, 11 years ago)

Fixes: killlists with both involved corps and alliances work. Memory use reduced.

Line 
1<?php
2
3class DBMemcachedQuery
4{
5    function DBMemcachedQuery()
6    {
7        static $totalexectime = 0;
8                $this->totalexectime_ = &$totalexectime;
9        $this->executed_ = false;
10        $this->_cache = array();
11        $this->_cached = false;
12
13        // this is the minimum runtime a query has to run to be
14        // eligible for caching in seconds
15        $this->_minruntime = 0.1;
16
17        // maximum size of a cached result set (512kB)
18        $this->_maxcachesize = 524288;
19        $this->d = true;
20    }
21
22    function checkCache()
23    {
24        global $mc;
25
26        // only cache selects
27        // we don't use select ... into so there is no problem
28        $this->_sql = str_replace(array("\r\n", "\n"), ' ', $this->_sql);
29        if (strtolower(substr($this->_sql, 0, 6)) != 'select' && strtolower(substr($this->_sql, 0, 4)) != 'show')
30            return false;
31
32        $cached = $mc->get(KB_SITE . '_sql_' . $this->_hash);
33        if($cached) {
34            return true;
35        }
36
37        return false;
38    }
39
40    function parseSQL()
41    {
42        // gets all involved tables for a select statement
43        $text = strtolower($this->_sql).' ';
44
45        // we try to get the text from 'from' to 'where' because all involved
46        // tables are declared in that part
47        $from = strpos($text, 'from')+5;
48        if (!$to = strpos($text, 'where'))
49        {
50            $to = strlen($text);
51        }
52        $parse = trim(substr($text, $from, $to-$from));
53
54        $tables = array();
55        if (strpos($parse, ',') !== false)
56        {
57            // , is a synonym for join so we'll replace them
58            $parse = str_replace(',', ' join ', $parse);
59        }
60
61        $parse = 'join '.$parse;
62        if (strpos($parse, 'join'))
63        {
64            // if this query is a join we parse it with regexp to get all tables
65            preg_match_all('/join (.*?) /', $parse, $match);
66            $tables = $match[1];
67        }
68        else
69        {
70            // no join so it is hopefully a simple table select
71            $tables[] = $parse;
72        }
73
74        $this->_usedtables = $tables;
75    }
76
77    function genCache()
78    {
79        global $mc;
80
81        // this function fetches all rows and writes the data into a textfile
82
83        // don't attemp to cache updates!
84        if (strtolower(substr($this->_sql, 0, 6)) != 'select' && strtolower(substr($this->_sql, 0, 4)) != 'show')
85        {
86            return false;
87        }
88
89        $bsize = 0;
90        while ($row = $this->getRow())
91        {
92            $this->_cache[] = $row;
93
94            $bsize += strlen(join('', $row));
95            if ($bsize > $this->_maxcachesize)
96            {
97                $this->_cache[] = array();
98                $this->_cached = false;
99                $this->rewind();
100                return false;
101            }
102
103        }
104
105        // write data into textfile
106        $mc->set(KB_SITE . '_sql_' . $this->_hash, $this->_cache, 0, 600);
107
108        $this->_cached = true;
109        $this->_currrow = 0;
110        $this->executed_ = true;
111    }
112
113    function execute($sql)
114    {
115        global $mc; 
116
117        $this->_sql = trim($sql);
118        $this->_hash = md5($this->_sql);
119        $this->_cache = array();
120        $this->_cached = false;
121
122        $cached = $mc->get(KB_SITE . '_sql_' . $this->_hash);
123        if($cached) {
124            $this->_cache = $cached;
125            $this->_cached = true;
126            $this->_currrow = 0;
127            $this->executed_ = true;
128            $this->queryCachedCount(true);
129            return true;
130        }
131
132        // we got no or no valid cache so open the connection and run the query
133        $this->dbconn_ = new DBConnection;
134
135        $t1 = strtok(microtime(), ' ') + strtok('');
136
137        $this->resid_ = mysql_query($sql, $this->dbconn_->id());
138
139        if ($this->resid_ === false)
140        {
141            if(defined('KB_PROFILE'))
142                        {
143                                DBDebug::recordError("Database error: ".mysql_error($this->dbconn_->id()));
144                                DBDebug::recordError("SQL: ".$this->_sql);
145                        }
146            if (DB_HALTONERROR === true)
147            {
148                echo "Database error: ".mysql_error($this->dbconn_->id())."<br/>";
149                echo "SQL: ".$this->_sql."<br/>";
150                exit;
151            }
152            else
153            {
154                return false;
155            }
156        }
157
158        $this->exectime_ = strtok(microtime(), ' ') + strtok('') - $t1;
159        $this->totalexectime_ += $this->exectime_;
160        $this->executed_ = true;
161
162        if (KB_PROFILE == 2)
163        {
164            file_put_contents('/tmp/profile.lst', $sql."\nExecution time: ".$this->exectime_."\n", FILE_APPEND);
165        }
166
167        // if the query was too slow we'll fetch all rows and run it cached
168        $this->genCache();
169
170        $this->queryCount(true);
171        return true;
172    }
173
174    function queryCount($increase = false)
175    {
176        static $count;
177
178        if ($increase)
179        {
180            $count++;
181        }
182
183        return $count;
184    }
185
186    function queryCachedCount($increase = false)
187    {
188        static $count;
189
190        if ($increase)
191        {
192            $count++;
193        }
194
195        return $count;
196    }
197
198    function recordCount()
199    {
200        if ($this->_cached)
201        {
202            return count($this->_cache);
203        }
204        return mysql_num_rows($this->resid_);
205    }
206
207    function getRow()
208    {
209        if ($this->_cached)
210        {
211            if (!isset($this->_cache[$this->_currrow]))
212            {
213                return false;
214            }
215            // return the current row and increase the pointer by one
216            return $this->_cache[$this->_currrow++];
217        }
218        if (is_resource($this->resid_))
219        {
220            return mysql_fetch_assoc($this->resid_);
221        }
222        return false;
223    }
224
225    function rewind()
226    {
227        if ($this->_cached)
228        {
229            $this->_currrow = 0;
230        }
231        @mysql_data_seek($this->resid_, 0);
232    }
233
234    function getInsertID()
235    {
236        return mysql_insert_id();
237    }
238
239    function execTime()
240    {
241        return $this->exectime_;
242    }
243
244    function executed()
245    {
246        return $this->executed_;
247    }
248
249    function getErrorMsg()
250    {
251        $msg = $this->sql_."<br>";
252        $msg .= "Query failed. ".mysql_error($this->dbconn_->id());
253
254        return $msg;
255    }
256    //Not implemented with mysql library
257    function autocommit($commit = true)
258    {
259        return false;
260    }
261   
262    //Not implemented with mysql library
263    function rollback()
264    {
265        return false;
266    }
267}
268?>
Note: See TracBrowser for help on using the browser.