dolibarr 22.0.5
memory.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2009-2010 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2021-2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 * or see https://www.gnu.org/
19 */
20
26global $shmkeys, $shmoffset;
27
28$shmkeys = array(
29 'main' => 1,
30 'admin' => 2,
31 'dict' => 3,
32 'companies' => 4,
33 'suppliers' => 5,
34 'products' => 6,
35 'commercial' => 7,
36 'compta' => 8,
37 'projects' => 9,
38 'cashdesk' => 10,
39 'agenda' => 11,
40 'bills' => 12,
41 'propal' => 13,
42 'boxes' => 14,
43 'banks' => 15,
44 'other' => 16,
45 'errors' => 17,
46 'members' => 18,
47 'ecm' => 19,
48 'orders' => 20,
49 'users' => 21,
50 'help' => 22,
51 'stocks' => 23,
52 'interventions' => 24,
53 'donations' => 25,
54 'contracts' => 26,
55);
56$shmoffset = 1000; // Max number of entries found into a language file. If too low, some entries will be overwritten.
57
58
59
71function dol_setcache($memoryid, $data, $expire = 0, $filecache = 0, $replace = 0)
72{
73 global $conf;
74
75 $result = 0;
76
77 if (strpos($memoryid, 'count_') === 0) { // The memoryid key start with 'count_...'
78 if (!getDolGlobalString('MAIN_CACHE_COUNT')) {
79 return 0;
80 }
81 }
82
83 if (isModEnabled('memcached') && class_exists('Memcached')) {
84 // Using a memcached server
85 global $dolmemcache;
86 if (empty($dolmemcache) || !is_object($dolmemcache)) {
87 $dolmemcache = new Memcached();
88 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
89 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
90 $result = $dolmemcache->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
91 if (!$result) {
92 return -1;
93 }
94 }
95
96 $memoryid = session_name().'_'.$memoryid;
97 //$dolmemcache->setOption(Memcached::OPT_COMPRESSION, false);
98 $dolmemcache->add($memoryid, $data, $expire); // This fails if key already exists
99 $rescode = $dolmemcache->getResultCode();
100 if ($rescode == 0) {
101 return is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
102 } elseif (!empty($replace) && $rescode == Memcached::RES_NOTSTORED) {
103 $dolmemcache->replace($memoryid, $data, $expire); // This fails if key does not exists
104 $rescode = $dolmemcache->getResultCode();
105 if ($rescode == 0) {
106 return is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
107 } else {
108 return -$rescode;
109 }
110 } else {
111 return -$rescode;
112 }
113 } elseif (isModEnabled('memcached') && class_exists('Memcache')) { // This is a really not reliable cache ! Use Memcached instead.
114 // Using a memcache server
115 global $dolmemcache;
116 if (empty($dolmemcache) || !is_object($dolmemcache)) {
117 $dolmemcache = new Memcache();
118 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
119 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
120 $result = $dolmemcache->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
121 if (!$result) {
122 return -1;
123 }
124 }
125
126 $memoryid = session_name().'_'.$memoryid;
127 //$dolmemcache->setOption(Memcached::OPT_COMPRESSION, false);
128 $result = $dolmemcache->add($memoryid, $data, 0, $expire); // This fails if key already exists
129 if ($result) {
130 return is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
131 } else {
132 return -1;
133 }
134 } elseif (getDolGlobalInt('MAIN_OPTIMIZE_SPEED') & 0x02) { // This is a really not reliable cache ! Use Memcached instead.
135 // Using shmop
136 $result = dol_setshmop($memoryid, $data, $expire);
137 } elseif ($filecache > 0) {
138 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
139 require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
140 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
141 $now = dol_now();
142 $memoryid = session_name().'_'.$memoryid;
143 $dircache = 'dolcache';
144 $pathcache = DOL_DATA_ROOT.'/'.$dircache;
145 if (!dol_is_dir($pathcache)) {
146 $result = dol_mkdir($pathcache);
147 if ($result < 0) {
148 return $result;
149 }
150 }
151 if ($expire != 0) {
152 $expire = dol_time_plus_duree($now, $expire, 's');
153 }
154
155 $cachedata = array("expire" => $expire, "data" => $data);
156 $cachejson = dolEncrypt(json_encode($cachedata));
157 if (!dol_is_file($pathcache.'/'.$memoryid.'.cache') || $replace > 0) {
158 $result = file_put_contents($pathcache.'/'.$memoryid.'.cache', $cachejson);
159 } else {
160 return 0;
161 }
162 } else {
163 // No intersession cache system available, we use at least the perpage cache
164 $conf->cache['cachememory_'.$memoryid] = $data;
165 $result = is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
166 }
167
168 return $result;
169}
170
179function dol_getcache($memoryid, $filecache = 0)
180{
181 global $conf;
182
183 if (strpos($memoryid, 'count_') === 0) { // The memoryid key start with 'count_...'
184 if (!getDolGlobalString('MAIN_CACHE_COUNT')) {
185 return null;
186 }
187 }
188
189 // Using a memcached server
190 if (isModEnabled('memcached') && class_exists('Memcached')) {
191 global $m;
192 if (empty($m) || !is_object($m)) {
193 $m = new Memcached();
194 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
195 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
196 $result = $m->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
197 if (!$result) {
198 return -1;
199 }
200 }
201
202 $memoryid = session_name().'_'.$memoryid;
203 //$m->setOption(Memcached::OPT_COMPRESSION, false);
204 //print "Get memoryid=".$memoryid;
205 $data = $m->get($memoryid);
206 $rescode = $m->getResultCode();
207 //print "memoryid=".$memoryid." - rescode=".$rescode." - count(response)=".count($data)."\n<br>";
208 //var_dump($data);
209 if ($rescode == 0) {
210 return $data;
211 } elseif ($rescode == 16) { // = Memcached::MEMCACHED_NOTFOUND but this constant doe snot exists.
212 return null;
213 } else {
214 return -$rescode;
215 }
216 } elseif (isModEnabled('memcached') && class_exists('Memcache')) { // This is a really not reliable cache ! Use Memcached instead.
217 global $m;
218 if (empty($m) || !is_object($m)) {
219 $m = new Memcache();
220 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
221 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
222 $result = $m->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
223 if (!$result) {
224 return -1;
225 }
226 }
227
228 $memoryid = session_name().'_'.$memoryid;
229 //$m->setOption(Memcached::OPT_COMPRESSION, false);
230 $data = $m->get($memoryid);
231 //print "memoryid=".$memoryid." - rescode=".$rescode." - data=".count($data)."\n<br>";
232 //var_dump($data);
233 if ($data) {
234 return $data;
235 } else {
236 return null; // There is no way to make a difference between NOTFOUND and error when using Memcache. So do not use it, use Memcached instead.
237 }
238 } elseif (getDolGlobalInt('MAIN_OPTIMIZE_SPEED') & 0x02) { // This is a really not reliable cache ! Use Memcached instead.
239 // Using shmop
240 $data = dol_getshmop($memoryid);
241 return $data;
242 } elseif ($filecache > 0) {
243 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
244 require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
245 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
246 $now = dol_now();
247 $memoryid = session_name().'_'.$memoryid;
248 $dircache = 'dolcache';
249 $pathcache = DOL_DATA_ROOT.'/'.$dircache;
250 if (!dol_is_file($pathcache.'/'.$memoryid.'.cache')) {
251 return null;
252 }
253 $data = file_get_contents($pathcache.'/'.$memoryid.'.cache');
254 if (!$data) {
255 return -1;
256 }
257 $json = json_decode(dolDecrypt($data));
258 if ($json->expire > $now) {
259 return $json->data;
260 } else {
261 $result = dol_delete_file($pathcache.'/'.$memoryid.'.cache');
262 if (!$result) {
263 return -2;
264 }
265 }
266 return null;
267 } else {
268 // No intersession cache system available, we use at least the perpage cache
269 if (isset($conf->cache['cachememory_'.$memoryid])) {
270 return $conf->cache['cachememory_'.$memoryid];
271 }
272 }
273
274 return null;
275}
276
277
278
285function dol_getshmopaddress($memoryid)
286{
287 global $shmkeys, $shmoffset;
288 if (empty($shmkeys[$memoryid])) { // No room reserved for this memoryid, no way to use cache
289 return 0;
290 }
291 return $shmkeys[$memoryid] + $shmoffset;
292}
293
300{
301 global $shmkeys;
302
303 $resarray = array();
304 foreach ($shmkeys as $key => $val) {
305 $result = dol_getshmop($key);
306 if (!is_numeric($result) || $result > 0) {
307 $resarray[$key] = $result;
308 }
309 }
310 return $resarray;
311}
312
321function dol_setshmop($memoryid, $data, $expire)
322{
323 global $shmkeys;
324
325 //print 'dol_setshmop memoryid='.$memoryid."<br>\n";
326 if (empty($shmkeys[$memoryid]) || !function_exists("shmop_write")) {
327 return 0;
328 }
329 $shmkey = dol_getshmopaddress($memoryid);
330 if (empty($shmkey)) {
331 return 0; // No key reserved for this memoryid, we can't cache this memoryid
332 }
333
334 $newdata = serialize($data);
335 $size = strlen($newdata);
336 //print 'dol_setshmop memoryid='.$memoryid." shmkey=".$shmkey." newdata=".$size."bytes<br>\n";
337 $handle = shmop_open($shmkey, 'c', 0644, 6 + $size);
338 if ($handle) {
339 $shm_bytes_written1 = shmop_write($handle, str_pad((string) $size, 6), 0);
340 $shm_bytes_written2 = shmop_write($handle, $newdata, 6);
341 if ($shm_bytes_written1 + $shm_bytes_written2 != 6 + dol_strlen($newdata)) {
342 print "Couldn't write the entire length of data\n";
343 }
344 // @phan-suppress-next-line PhanDeprecatedFunctionInternal
345 shmop_close($handle);
346 return ($shm_bytes_written1 + $shm_bytes_written2);
347 } else {
348 print 'Error in shmop_open for memoryid='.$memoryid.' shmkey='.$shmkey.' 6+size=6+'.$size;
349 return -1;
350 }
351}
352
359function dol_getshmop($memoryid)
360{
361 global $shmkeys;
362
363 $data = null;
364
365 if (empty($shmkeys[$memoryid]) || !function_exists("shmop_open")) {
366 return null;
367 }
368 $shmkey = dol_getshmopaddress($memoryid);
369 if (empty($shmkey)) {
370 return null; // No key reserved for this memoryid, we can't cache this memoryid
371 }
372
373 //print 'dol_getshmop memoryid='.$memoryid." shmkey=".$shmkey."<br>\n";
374 $handle = @shmop_open($shmkey, 'a', 0, 0);
375 if ($handle) {
376 $size = (int) trim(shmop_read($handle, 0, 6));
377 if ($size) {
378 $data = unserialize(shmop_read($handle, 6, $size));
379 } else {
380 return -1;
381 }
382 // @phan-suppress-next-line PhanDeprecatedFunctionInternal
383 shmop_close($handle);
384 } else {
385 return null; // Can't open existing block, so we suppose it was not created, so nothing were cached yet for the memoryid
386 }
387 return $data;
388}
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_is_file($pathoffile)
Return if path is a file.
dol_is_dir($folder)
Test if filename is a directory.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
dol_setcache($memoryid, $data, $expire=0, $filecache=0, $replace=0)
Save data into a memory area shared by all users, all sessions on server.
dol_getcache($memoryid, $filecache=0)
Read a memory area shared by all users, all sessions on server.
dol_listshmop()
Return list of contents of all memory area shared.
dol_setshmop($memoryid, $data, $expire)
Save data into a memory area shared by all users, all sessions on server.
dol_getshmopaddress($memoryid)
Return shared memory address used to store dataset with key memoryid.
dol_getshmop($memoryid)
Read a memory area shared by all users, all sessions on server.
dolEncrypt($chain, $key='', $ciphering='', $forceseed='')
Encode a string with a symmetric encryption.
dolDecrypt($chain, $key='')
Decode a string with a symmetric encryption.