dolibarr 21.0.0-beta
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
70function dol_setcache($memoryid, $data, $expire = 0, $filecache = 0)
71{
72 global $conf;
73
74 $result = 0;
75
76 if (strpos($memoryid, 'count_') === 0) { // The memoryid key start with 'count_...'
77 if (!getDolGlobalString('MAIN_CACHE_COUNT')) {
78 return 0;
79 }
80 }
81
82 if (isModEnabled('memcached') && class_exists('Memcached')) {
83 // Using a memcached server
84 global $dolmemcache;
85 if (empty($dolmemcache) || !is_object($dolmemcache)) {
86 $dolmemcache = new Memcached();
87 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
88 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
89 $result = $dolmemcache->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
90 if (!$result) {
91 return -1;
92 }
93 }
94
95 $memoryid = session_name().'_'.$memoryid;
96 //$dolmemcache->setOption(Memcached::OPT_COMPRESSION, false);
97 $dolmemcache->add($memoryid, $data, $expire); // This fails if key already exists
98 $rescode = $dolmemcache->getResultCode();
99 if ($rescode == 0) {
100 return is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
101 } else {
102 return -$rescode;
103 }
104 } elseif (isModEnabled('memcached') && class_exists('Memcache')) { // This is a really not reliable cache ! Use Memcached instead.
105 // Using a memcache server
106 global $dolmemcache;
107 if (empty($dolmemcache) || !is_object($dolmemcache)) {
108 $dolmemcache = new Memcache();
109 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
110 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
111 $result = $dolmemcache->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
112 if (!$result) {
113 return -1;
114 }
115 }
116
117 $memoryid = session_name().'_'.$memoryid;
118 //$dolmemcache->setOption(Memcached::OPT_COMPRESSION, false);
119 $result = $dolmemcache->add($memoryid, $data, 0, $expire); // This fails if key already exists
120 if ($result) {
121 return is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
122 } else {
123 return -1;
124 }
125 } elseif (getDolGlobalInt('MAIN_OPTIMIZE_SPEED') & 0x02) { // This is a really not reliable cache ! Use Memcached instead.
126 // Using shmop
127 $result = dol_setshmop($memoryid, $data, $expire);
128 } elseif ($filecache > 0) {
129 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
130 require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
131 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
132 $now = dol_now();
133 $memoryid = session_name().'_'.$memoryid;
134 $dircache = 'dolcache';
135 $pathcache = DOL_DATA_ROOT.'/'.$dircache;
136 if (!dol_is_dir($pathcache)) {
137 $result = dol_mkdir($pathcache);
138 if ($result < 0) {
139 return $result;
140 }
141 }
142 if ($expire != 0) {
143 $expire = dol_time_plus_duree($now, $expire, 's');
144 }
145
146 $cachedata = array("expire" => $expire, "data" => $data);
147 $cachejson = dolEncrypt(json_encode($cachedata));
148 if (!dol_is_file($pathcache.'/'.$memoryid.'.cache')) {
149 $result = file_put_contents($pathcache.'/'.$memoryid.'.cache', $cachejson);
150 } else {
151 return 0;
152 }
153 } else {
154 // No intersession cache system available, we use at least the perpage cache
155 $conf->cache['cachememory_'.$memoryid] = $data;
156 $result = is_array($data) ? count($data) : (is_scalar($data) ? strlen($data) : 0);
157 }
158
159 return $result;
160}
161
170function dol_getcache($memoryid, $filecache = 0)
171{
172 global $conf;
173
174 if (strpos($memoryid, 'count_') === 0) { // The memoryid key start with 'count_...'
175 if (!getDolGlobalString('MAIN_CACHE_COUNT')) {
176 return null;
177 }
178 }
179
180 // Using a memcached server
181 if (isModEnabled('memcached') && class_exists('Memcached')) {
182 global $m;
183 if (empty($m) || !is_object($m)) {
184 $m = new Memcached();
185 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
186 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
187 $result = $m->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
188 if (!$result) {
189 return -1;
190 }
191 }
192
193 $memoryid = session_name().'_'.$memoryid;
194 //$m->setOption(Memcached::OPT_COMPRESSION, false);
195 //print "Get memoryid=".$memoryid;
196 $data = $m->get($memoryid);
197 $rescode = $m->getResultCode();
198 //print "memoryid=".$memoryid." - rescode=".$rescode." - count(response)=".count($data)."\n<br>";
199 //var_dump($data);
200 if ($rescode == 0) {
201 return $data;
202 } elseif ($rescode == 16) { // = Memcached::MEMCACHED_NOTFOUND but this constant doe snot exists.
203 return null;
204 } else {
205 return -$rescode;
206 }
207 } elseif (isModEnabled('memcached') && class_exists('Memcache')) { // This is a really not reliable cache ! Use Memcached instead.
208 global $m;
209 if (empty($m) || !is_object($m)) {
210 $m = new Memcache();
211 $tmparray = explode(':', getDolGlobalString('MEMCACHED_SERVER'));
212 $port = (empty($tmparray[1]) ? 0 : $tmparray[1]);
213 $result = $m->addServer($tmparray[0], ($port || strpos($tmparray[0], '/') !== false) ? $port : 11211);
214 if (!$result) {
215 return -1;
216 }
217 }
218
219 $memoryid = session_name().'_'.$memoryid;
220 //$m->setOption(Memcached::OPT_COMPRESSION, false);
221 $data = $m->get($memoryid);
222 //print "memoryid=".$memoryid." - rescode=".$rescode." - data=".count($data)."\n<br>";
223 //var_dump($data);
224 if ($data) {
225 return $data;
226 } else {
227 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.
228 }
229 } elseif (getDolGlobalInt('MAIN_OPTIMIZE_SPEED') & 0x02) { // This is a really not reliable cache ! Use Memcached instead.
230 // Using shmop
231 $data = dol_getshmop($memoryid);
232 return $data;
233 } elseif ($filecache > 0) {
234 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
235 require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
236 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
237 $now = dol_now();
238 $memoryid = session_name().'_'.$memoryid;
239 $dircache = 'dolcache';
240 $pathcache = DOL_DATA_ROOT.'/'.$dircache;
241 if (!dol_is_file($pathcache.'/'.$memoryid.'.cache')) {
242 return null;
243 }
244 $data = file_get_contents($pathcache.'/'.$memoryid.'.cache');
245 if (!$data) {
246 return -1;
247 }
248 $json = json_decode(dolDecrypt($data));
249 if ($json->expire > $now) {
250 return $json->data;
251 } else {
252 $result = dol_delete_file($pathcache.'/'.$memoryid.'.cache');
253 if (!$result) {
254 return -2;
255 }
256 }
257 return null;
258 } else {
259 // No intersession cache system available, we use at least the perpage cache
260 if (isset($conf->cache['cachememory_'.$memoryid])) {
261 return $conf->cache['cachememory_'.$memoryid];
262 }
263 }
264
265 return null;
266}
267
268
269
276function dol_getshmopaddress($memoryid)
277{
278 global $shmkeys, $shmoffset;
279 if (empty($shmkeys[$memoryid])) { // No room reserved for this memoryid, no way to use cache
280 return 0;
281 }
282 return $shmkeys[$memoryid] + $shmoffset;
283}
284
291{
292 global $shmkeys;
293
294 $resarray = array();
295 foreach ($shmkeys as $key => $val) {
296 $result = dol_getshmop($key);
297 if (!is_numeric($result) || $result > 0) {
298 $resarray[$key] = $result;
299 }
300 }
301 return $resarray;
302}
303
312function dol_setshmop($memoryid, $data, $expire)
313{
314 global $shmkeys;
315
316 //print 'dol_setshmop memoryid='.$memoryid."<br>\n";
317 if (empty($shmkeys[$memoryid]) || !function_exists("shmop_write")) {
318 return 0;
319 }
320 $shmkey = dol_getshmopaddress($memoryid);
321 if (empty($shmkey)) {
322 return 0; // No key reserved for this memoryid, we can't cache this memoryid
323 }
324
325 $newdata = serialize($data);
326 $size = strlen($newdata);
327 //print 'dol_setshmop memoryid='.$memoryid." shmkey=".$shmkey." newdata=".$size."bytes<br>\n";
328 $handle = shmop_open($shmkey, 'c', 0644, 6 + $size);
329 if ($handle) {
330 $shm_bytes_written1 = shmop_write($handle, str_pad((string) $size, 6), 0);
331 $shm_bytes_written2 = shmop_write($handle, $newdata, 6);
332 if ($shm_bytes_written1 + $shm_bytes_written2 != 6 + dol_strlen($newdata)) {
333 print "Couldn't write the entire length of data\n";
334 }
335 // @phan-suppress-next-line PhanDeprecatedFunctionInternal
336 shmop_close($handle);
337 return ($shm_bytes_written1 + $shm_bytes_written2);
338 } else {
339 print 'Error in shmop_open for memoryid='.$memoryid.' shmkey='.$shmkey.' 6+size=6+'.$size;
340 return -1;
341 }
342}
343
350function dol_getshmop($memoryid)
351{
352 global $shmkeys;
353
354 $data = null;
355
356 if (empty($shmkeys[$memoryid]) || !function_exists("shmop_open")) {
357 return null;
358 }
359 $shmkey = dol_getshmopaddress($memoryid);
360 if (empty($shmkey)) {
361 return null; // No key reserved for this memoryid, we can't cache this memoryid
362 }
363
364 //print 'dol_getshmop memoryid='.$memoryid." shmkey=".$shmkey."<br>\n";
365 $handle = @shmop_open($shmkey, 'a', 0, 0);
366 if ($handle) {
367 $size = (int) trim(shmop_read($handle, 0, 6));
368 if ($size) {
369 $data = unserialize(shmop_read($handle, 6, $size));
370 } else {
371 return -1;
372 }
373 // @phan-suppress-next-line PhanDeprecatedFunctionInternal
374 shmop_close($handle);
375 } else {
376 return null; // Can't open existing block, so we suppose it was not created, so nothing were cached yet for the memoryid
377 }
378 return $data;
379}
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)
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.