2009-12-16 19:57:51 +01:00
< ? php
2010-05-08 04:16:29 +02:00
/* Copyright ( C ) 2009 - 2010 Laurent Destailleur < eldy @ users . sourceforge . net >
2021-02-19 23:16:56 +01:00
* Copyright ( C ) 2021 Frédéric France < frederic . france @ netlogic . fr >
2009-12-16 19:57:51 +01:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2009-12-16 19:57:51 +01:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2009-12-16 19:57:51 +01:00
*/
/**
2011-10-24 10:45:06 +02:00
* \file htdocs / core / lib / memory . lib . php
2010-05-25 00:38:02 +02:00
* \brief Set of function for memory / cache management
2009-12-16 19:57:51 +01:00
*/
2020-04-10 10:59:32 +02:00
global $shmkeys , $shmoffset ;
2009-12-16 22:42:42 +01:00
2021-02-19 23:16:56 +01:00
$shmkeys = array (
'main' => 1 ,
'admin' => 2 ,
'dict' => 3 ,
'companies' => 4 ,
'suppliers' => 5 ,
'products' => 6 ,
'commercial' => 7 ,
'compta' => 8 ,
'projects' => 9 ,
'cashdesk' => 10 ,
'agenda' => 11 ,
'bills' => 12 ,
'propal' => 13 ,
'boxes' => 14 ,
'banks' => 15 ,
'other' => 16 ,
'errors' => 17 ,
'members' => 18 ,
'ecm' => 19 ,
'orders' => 20 ,
'users' => 21 ,
'help' => 22 ,
'stocks' => 23 ,
'interventions' => 24 ,
'donations' => 25 ,
'contracts' => 26 ,
);
2020-04-10 10:59:32 +02:00
$shmoffset = 1000 ; // Max number of entries found into a language file. If too low, some entries will be overwritten.
2009-12-16 22:42:42 +01:00
2009-12-16 19:57:51 +01:00
2010-01-04 21:30:30 +01:00
2010-05-08 16:18:27 +02:00
/**
2023-03-06 18:03:30 +01:00
* Save data into a memory area shared by all users , all sessions on server . Note : MAIN_CACHE_COUNT must be set .
2011-08-17 23:39:08 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param string $memoryid Memory id of shared area
2021-02-20 17:23:03 +01:00
* @ param mixed $data Data to save . It must not be a null value .
2021-02-20 20:47:01 +01:00
* @ param int $expire ttl in seconds , 0 never expire
2021-02-20 18:32:16 +01:00
* @ return int < 0 if KO , 0 if nothing is done , Nb of bytes written if OK
2021-02-19 14:05:46 +01:00
* @ see dol_getcache ()
2010-05-08 04:16:29 +02:00
*/
2021-02-20 20:47:01 +01:00
function dol_setcache ( $memoryid , $data , $expire = 0 )
2010-05-08 04:16:29 +02:00
{
global $conf ;
2023-02-20 01:12:15 +01:00
2020-04-25 13:52:07 +02:00
$result = 0 ;
2010-05-08 04:16:29 +02:00
2021-02-20 18:32:16 +01:00
if ( strpos ( $memoryid , 'count_' ) === 0 ) { // The memoryid key start with 'count_...'
2021-02-23 22:03:23 +01:00
if ( empty ( $conf -> global -> MAIN_CACHE_COUNT )) {
return 0 ;
}
2021-02-20 18:32:16 +01:00
}
2021-10-25 22:07:31 +02:00
if ( ! empty ( $conf -> memcached -> enabled ) && class_exists ( 'Memcached' )) {
2021-02-19 23:16:56 +01:00
// Using a memcached server
2020-10-31 14:32:18 +01:00
global $dolmemcache ;
2021-02-19 23:16:56 +01:00
if ( empty ( $dolmemcache ) || ! is_object ( $dolmemcache )) {
$dolmemcache = new Memcached ();
$tmparray = explode ( ':' , $conf -> global -> MEMCACHED_SERVER );
$result = $dolmemcache -> addServer ( $tmparray [ 0 ], $tmparray [ 1 ] ? $tmparray [ 1 ] : 11211 );
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
return - 1 ;
}
2021-02-19 23:16:56 +01:00
}
2019-10-20 17:17:22 +02:00
2021-10-25 22:07:31 +02:00
$memoryid = session_name () . '_' . $memoryid ;
2015-09-07 20:22:44 +02:00
//$dolmemcache->setOption(Memcached::OPT_COMPRESSION, false);
2021-02-20 20:47:01 +01:00
$dolmemcache -> add ( $memoryid , $data , $expire ); // This fails if key already exists
2020-04-25 13:52:07 +02:00
$rescode = $dolmemcache -> getResultCode ();
2021-02-19 23:16:56 +01:00
if ( $rescode == 0 ) {
2021-11-28 15:41:19 +01:00
return is_array ( $data ) ? count ( $data ) : ( is_scalar ( $data ) ? strlen ( $data ) : 0 );
2020-05-21 15:05:19 +02:00
} else {
2010-05-08 16:18:27 +02:00
return - $rescode ;
}
2021-02-20 18:21:10 +01:00
} elseif ( ! empty ( $conf -> memcached -> enabled ) && class_exists ( 'Memcache' )) { // This is a really not reliable cache ! Use Memcached instead.
2021-02-19 23:16:56 +01:00
// Using a memcache server
2015-09-07 20:22:44 +02:00
global $dolmemcache ;
2021-02-19 23:16:56 +01:00
if ( empty ( $dolmemcache ) || ! is_object ( $dolmemcache )) {
$dolmemcache = new Memcache ();
$tmparray = explode ( ':' , $conf -> global -> MEMCACHED_SERVER );
$result = $dolmemcache -> addServer ( $tmparray [ 0 ], $tmparray [ 1 ] ? $tmparray [ 1 ] : 11211 );
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
return - 1 ;
}
2021-02-19 23:16:56 +01:00
}
2019-10-20 17:17:22 +02:00
2021-10-25 22:07:31 +02:00
$memoryid = session_name () . '_' . $memoryid ;
2015-09-07 20:22:44 +02:00
//$dolmemcache->setOption(Memcached::OPT_COMPRESSION, false);
2021-02-20 20:47:01 +01:00
$result = $dolmemcache -> add ( $memoryid , $data , false , $expire ); // This fails if key already exists
2021-02-19 23:16:56 +01:00
if ( $result ) {
2021-11-28 15:41:19 +01:00
return is_array ( $data ) ? count ( $data ) : ( is_scalar ( $data ) ? strlen ( $data ) : 0 );
2020-05-21 15:05:19 +02:00
} else {
2010-05-25 00:38:02 +02:00
return - 1 ;
}
2021-02-20 18:21:10 +01:00
} elseif ( isset ( $conf -> global -> MAIN_OPTIMIZE_SPEED ) && ( $conf -> global -> MAIN_OPTIMIZE_SPEED & 0x02 )) { // This is a really not reliable cache ! Use Memcached instead.
2021-02-19 23:16:56 +01:00
// Using shmop
2021-02-20 20:47:01 +01:00
$result = dol_setshmop ( $memoryid , $data , $expire );
2023-02-20 01:12:15 +01:00
} else {
// No intersession cache system available, we use at least the perpage cache
$conf -> cache [ 'cachememory_' . $memoryid ] = $data ;
$result = is_array ( $data ) ? count ( $data ) : ( is_scalar ( $data ) ? strlen ( $data ) : 0 );
2010-05-08 04:16:29 +02:00
}
2010-05-08 16:18:27 +02:00
return $result ;
2010-05-08 04:16:29 +02:00
}
2010-05-08 16:18:27 +02:00
/**
2011-08-17 23:39:08 +02:00
* Read a memory area shared by all users , all sessions on server
*
2012-02-04 14:39:47 +01:00
* @ param string $memoryid Memory id of shared area
2021-02-20 18:32:16 +01:00
* @ return int | mixed < 0 if KO , data if OK , null if not found into cache or no caching feature enabled
2021-02-19 14:05:46 +01:00
* @ see dol_setcache ()
2010-05-08 04:16:29 +02:00
*/
function dol_getcache ( $memoryid )
{
global $conf ;
2021-02-20 18:32:16 +01:00
if ( strpos ( $memoryid , 'count_' ) === 0 ) { // The memoryid key start with 'count_...'
2021-02-23 22:03:23 +01:00
if ( empty ( $conf -> global -> MAIN_CACHE_COUNT )) {
return null ;
}
2021-02-20 18:32:16 +01:00
}
2010-05-08 04:16:29 +02:00
// Using a memcached server
2023-05-04 21:41:59 +02:00
if ( isModEnabled ( 'memcached' ) && class_exists ( 'Memcached' )) {
2015-09-07 20:17:05 +02:00
global $m ;
2021-02-19 23:16:56 +01:00
if ( empty ( $m ) || ! is_object ( $m )) {
2020-10-31 14:32:18 +01:00
$m = new Memcached ();
2021-02-19 23:16:56 +01:00
$tmparray = explode ( ':' , $conf -> global -> MEMCACHED_SERVER );
$result = $m -> addServer ( $tmparray [ 0 ], $tmparray [ 1 ] ? $tmparray [ 1 ] : 11211 );
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
return - 1 ;
}
2021-02-19 23:16:56 +01:00
}
2019-10-20 17:17:22 +02:00
2021-10-25 22:07:31 +02:00
$memoryid = session_name () . '_' . $memoryid ;
2010-05-08 16:18:27 +02:00
//$m->setOption(Memcached::OPT_COMPRESSION, false);
2011-08-17 23:39:08 +02:00
//print "Get memoryid=".$memoryid;
2020-04-25 13:52:07 +02:00
$data = $m -> get ( $memoryid );
$rescode = $m -> getResultCode ();
2021-02-20 18:21:10 +01:00
//print "memoryid=".$memoryid." - rescode=".$rescode." - count(response)=".count($data)."\n<br>";
2010-05-08 16:18:27 +02:00
//var_dump($data);
2021-02-19 23:16:56 +01:00
if ( $rescode == 0 ) {
2010-05-08 16:18:27 +02:00
return $data ;
2021-02-20 18:21:10 +01:00
} elseif ( $rescode == 16 ) { // = Memcached::MEMCACHED_NOTFOUND but this constant doe snot exists.
return null ;
2020-05-21 15:05:19 +02:00
} else {
2010-05-08 16:18:27 +02:00
return - $rescode ;
}
2023-05-04 21:41:59 +02:00
} elseif ( isModEnabled ( 'memcached' ) && class_exists ( 'Memcache' )) { // This is a really not reliable cache ! Use Memcached instead.
2015-09-07 20:17:05 +02:00
global $m ;
2021-02-19 23:16:56 +01:00
if ( empty ( $m ) || ! is_object ( $m )) {
$m = new Memcache ();
$tmparray = explode ( ':' , $conf -> global -> MEMCACHED_SERVER );
$result = $m -> addServer ( $tmparray [ 0 ], $tmparray [ 1 ] ? $tmparray [ 1 ] : 11211 );
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
return - 1 ;
}
2021-02-19 23:16:56 +01:00
}
2019-10-20 17:17:22 +02:00
2021-10-25 22:07:31 +02:00
$memoryid = session_name () . '_' . $memoryid ;
2010-05-25 00:38:02 +02:00
//$m->setOption(Memcached::OPT_COMPRESSION, false);
2020-04-25 13:52:07 +02:00
$data = $m -> get ( $memoryid );
2011-09-17 21:49:50 +02:00
//print "memoryid=".$memoryid." - rescode=".$rescode." - data=".count($data)."\n<br>";
2010-05-25 00:38:02 +02:00
//var_dump($data);
2021-02-19 23:16:56 +01:00
if ( $data ) {
2010-05-25 00:38:02 +02:00
return $data ;
2020-05-21 15:05:19 +02:00
} else {
2021-10-25 22:07:31 +02:00
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.
2010-05-25 00:38:02 +02:00
}
2021-02-20 18:21:10 +01:00
} elseif ( isset ( $conf -> global -> MAIN_OPTIMIZE_SPEED ) && ( $conf -> global -> MAIN_OPTIMIZE_SPEED & 0x02 )) { // This is a really not reliable cache ! Use Memcached instead.
2021-02-19 23:16:56 +01:00
// Using shmop
2020-04-10 10:59:32 +02:00
$data = dol_getshmop ( $memoryid );
2010-05-08 16:18:27 +02:00
return $data ;
2023-02-20 01:12:15 +01:00
} else {
// No intersession cache system available, we use at least the perpage cache
if ( isset ( $conf -> cache [ 'cachememory_' . $memoryid ])) {
return $conf -> cache [ 'cachememory_' . $memoryid ];
}
2010-05-08 04:16:29 +02:00
}
2021-02-20 17:23:03 +01:00
return null ;
2010-05-08 04:16:29 +02:00
}
2010-01-12 13:21:29 +01:00
2010-05-08 16:18:27 +02:00
/**
2012-02-04 14:39:47 +01:00
* Return shared memory address used to store dataset with key memoryid
*
2014-09-04 15:48:49 +02:00
* @ param string $memoryid Memory id of shared area ( 'main' , 'agenda' , ... )
2012-02-04 14:39:47 +01:00
* @ return int < 0 if KO , Memoy address of shared memory for key
2010-01-12 13:21:29 +01:00
*/
function dol_getshmopaddress ( $memoryid )
{
2020-04-10 10:59:32 +02:00
global $shmkeys , $shmoffset ;
2021-02-20 18:21:10 +01:00
if ( empty ( $shmkeys [ $memoryid ])) { // No room reserved for thid memoryid, no way to use cache
2021-02-19 23:16:56 +01:00
return 0 ;
}
2020-04-10 10:59:32 +02:00
return $shmkeys [ $memoryid ] + $shmoffset ;
2010-01-12 13:21:29 +01:00
}
2010-05-08 16:18:27 +02:00
/**
2012-02-04 14:39:47 +01:00
* Return list of contents of all memory area shared
*
2015-02-10 10:52:48 +01:00
* @ return array
2010-01-04 21:30:30 +01:00
*/
function dol_listshmop ()
{
2020-04-10 10:59:32 +02:00
global $shmkeys , $shmoffset ;
2010-01-04 21:30:30 +01:00
2020-04-10 10:59:32 +02:00
$resarray = array ();
2021-02-19 23:16:56 +01:00
foreach ( $shmkeys as $key => $val ) {
2020-04-10 10:59:32 +02:00
$result = dol_getshmop ( $key );
2021-02-19 23:16:56 +01:00
if ( ! is_numeric ( $result ) || $result > 0 ) {
$resarray [ $key ] = $result ;
}
2010-01-04 21:30:30 +01:00
}
return $resarray ;
}
2010-05-08 16:18:27 +02:00
/**
2012-02-04 14:39:47 +01:00
* Save data into a memory area shared by all users , all sessions on server
*
2014-09-04 15:48:49 +02:00
* @ param int $memoryid Memory id of shared area ( 'main' , 'agenda' , ... )
2021-02-20 18:21:10 +01:00
* @ param string $data Data to save . Must be a not null value .
2021-02-20 20:47:01 +01:00
* @ param int $expire ttl in seconds , 0 never expire
2021-02-20 18:21:10 +01:00
* @ return int < 0 if KO , 0 = Caching not available , Nb of bytes written if OK
2009-12-16 19:57:51 +01:00
*/
2021-02-20 20:47:01 +01:00
function dol_setshmop ( $memoryid , $data , $expire )
2009-12-16 19:57:51 +01:00
{
2020-04-10 10:59:32 +02:00
global $shmkeys , $shmoffset ;
2010-01-04 21:30:30 +01:00
2009-12-16 22:42:42 +01:00
//print 'dol_setshmop memoryid='.$memoryid."<br>\n";
2021-02-23 22:03:23 +01:00
if ( empty ( $shmkeys [ $memoryid ]) || ! function_exists ( " shmop_write " )) {
return 0 ;
}
2020-04-10 10:59:32 +02:00
$shmkey = dol_getshmopaddress ( $memoryid );
2021-02-23 22:03:23 +01:00
if ( empty ( $shmkey )) {
2021-10-25 22:07:31 +02:00
return 0 ; // No key reserved for this memoryid, we can't cache this memoryid
2021-02-23 22:03:23 +01:00
}
2021-02-20 18:21:10 +01:00
2020-04-10 10:59:32 +02:00
$newdata = serialize ( $data );
$size = strlen ( $newdata );
2009-12-16 22:42:42 +01:00
//print 'dol_setshmop memoryid='.$memoryid." shmkey=".$shmkey." newdata=".$size."bytes<br>\n";
2020-04-10 10:59:32 +02:00
$handle = shmop_open ( $shmkey , 'c' , 0644 , 6 + $size );
2021-02-19 23:16:56 +01:00
if ( $handle ) {
2020-04-10 10:59:32 +02:00
$shm_bytes_written1 = shmop_write ( $handle , str_pad ( $size , 6 ), 0 );
$shm_bytes_written2 = shmop_write ( $handle , $newdata , 6 );
2021-02-19 23:16:56 +01:00
if (( $shm_bytes_written1 + $shm_bytes_written2 ) != ( 6 + dol_strlen ( $newdata ))) {
print " Couldn't write the entire length of data \n " ;
2009-12-16 19:57:51 +01:00
}
shmop_close ( $handle );
2020-04-10 10:59:32 +02:00
return ( $shm_bytes_written1 + $shm_bytes_written2 );
2020-05-21 15:05:19 +02:00
} else {
2021-10-25 22:07:31 +02:00
print 'Error in shmop_open for memoryid=' . $memoryid . ' shmkey=' . $shmkey . ' 6+size=6+' . $size ;
2009-12-16 19:57:51 +01:00
return - 1 ;
}
}
2010-05-08 16:18:27 +02:00
/**
2012-02-04 14:39:47 +01:00
* Read a memory area shared by all users , all sessions on server
*
2014-09-04 15:48:49 +02:00
* @ param string $memoryid Memory id of shared area ( 'main' , 'agenda' , ... )
2021-02-20 18:21:10 +01:00
* @ return int < 0 if KO , data if OK , Null if no cache enabled or not found
2010-05-08 04:16:29 +02:00
*/
function dol_getshmop ( $memoryid )
{
2020-04-10 10:59:32 +02:00
global $shmkeys , $shmoffset ;
2010-05-08 04:16:29 +02:00
2021-02-20 18:21:10 +01:00
$data = null ;
if ( empty ( $shmkeys [ $memoryid ]) || ! function_exists ( " shmop_open " )) {
return null ;
}
2020-04-10 10:59:32 +02:00
$shmkey = dol_getshmopaddress ( $memoryid );
2021-02-23 22:03:23 +01:00
if ( empty ( $shmkey )) {
2021-10-25 22:07:31 +02:00
return null ; // No key reserved for this memoryid, we can't cache this memoryid
2021-02-23 22:03:23 +01:00
}
2021-02-20 18:21:10 +01:00
2010-05-08 04:16:29 +02:00
//print 'dol_getshmop memoryid='.$memoryid." shmkey=".$shmkey."<br>\n";
2020-04-10 10:59:32 +02:00
$handle = @ shmop_open ( $shmkey , 'a' , 0 , 0 );
2021-02-19 23:16:56 +01:00
if ( $handle ) {
2020-04-10 10:59:32 +02:00
$size = trim ( shmop_read ( $handle , 0 , 6 ));
2021-02-23 22:03:23 +01:00
if ( $size ) {
$data = unserialize ( shmop_read ( $handle , 6 , $size ));
} else {
return - 1 ;
}
2010-05-08 04:16:29 +02:00
shmop_close ( $handle );
2020-05-21 15:05:19 +02:00
} else {
2021-10-25 22:07:31 +02:00
return null ; // Can't open existing block, so we suppose it was not created, so nothing were cached yet for the memoryid
2010-05-08 04:16:29 +02:00
}
return $data ;
}