|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* EGroupware API: Base class for all caching providers |
|
4
|
|
|
* |
|
5
|
|
|
* @link http://www.egroupware.org |
|
6
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
|
7
|
|
|
* @package api |
|
8
|
|
|
* @subpackage cache |
|
9
|
|
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> |
|
10
|
|
|
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de> |
|
11
|
|
|
* @version $Id$ |
|
12
|
|
|
*/ |
|
13
|
|
|
|
|
14
|
|
|
namespace EGroupware\Api\Cache; |
|
15
|
|
|
|
|
16
|
|
|
/*if (isset($_SERVER['SCRIPT_FILENAME']) && realpath($_SERVER['SCRIPT_FILENAME']) == __FILE__) |
|
17
|
|
|
{ |
|
18
|
|
|
require_once dirname(__DIR__).'/loader/common.php'; |
|
19
|
|
|
}*/ |
|
20
|
|
|
use EGroupware\Api; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Base class for all caching providers |
|
24
|
|
|
* |
|
25
|
|
|
* Implements some checks used for testing providers. |
|
26
|
|
|
*/ |
|
27
|
|
|
abstract class Base implements Provider |
|
28
|
|
|
{ |
|
29
|
|
|
/** |
|
30
|
|
|
* Run several checks on a caching provider |
|
31
|
|
|
* |
|
32
|
|
|
* @param boolean $verbose =false true: echo failed checks |
|
33
|
|
|
* @return int number of failed checks |
|
34
|
|
|
*/ |
|
35
|
|
|
function check($verbose=false) |
|
36
|
|
|
{ |
|
37
|
|
|
// set us up as provider for Api\Cache class |
|
38
|
|
|
$GLOBALS['egw_info']['server']['install_id'] = md5(microtime(true)); |
|
39
|
|
|
unset($GLOBALS['egw_info']['server']['cache_provider_instance']); |
|
40
|
|
|
unset($GLOBALS['egw_info']['server']['cache_provider_tree']); |
|
41
|
|
|
Api\Cache::$default_provider = get_class($this); |
|
|
|
|
|
|
42
|
|
|
|
|
43
|
|
|
$failed = 0; |
|
44
|
|
|
foreach(array( |
|
45
|
|
|
Api\Cache::TREE => 'tree', |
|
46
|
|
|
Api\Cache::INSTANCE => 'instance', |
|
47
|
|
|
) as $level => $label) |
|
48
|
|
|
{ |
|
49
|
|
|
$locations = array(); |
|
50
|
|
|
foreach(array('string',123,true,false,null,array(),array(1,2,3)) as $data) |
|
51
|
|
|
{ |
|
52
|
|
|
$location = md5(microtime(true).$label.serialize($data)); |
|
53
|
|
|
$get_before_set = $this->get(array($level,__CLASS__,$location)); |
|
54
|
|
|
if (!is_null($get_before_set)) |
|
55
|
|
|
{ |
|
56
|
|
|
if ($verbose) echo "$label: get_before_set=".array2string($get_before_set)." != NULL\n"; |
|
57
|
|
|
++$failed; |
|
58
|
|
|
} |
|
59
|
|
|
if (($set = $this->set(array($level,__CLASS__,$location), $data, 10)) !== true) |
|
60
|
|
|
{ |
|
61
|
|
|
if ($verbose) echo "$label: set returned ".array2string($set)." !== TRUE\n"; |
|
62
|
|
|
++$failed; |
|
63
|
|
|
} |
|
64
|
|
|
$get_after_set = $this->get(array($level,__CLASS__,$location)); |
|
65
|
|
|
if ($get_after_set !== $data) |
|
66
|
|
|
{ |
|
67
|
|
|
if ($verbose) echo "$label: get_after_set=".array2string($get_after_set)." !== ".array2string($data)."\n"; |
|
68
|
|
|
++$failed; |
|
69
|
|
|
} |
|
70
|
|
|
if (is_a($this, 'EGroupware\Api\Cache\ProviderMultiple')) |
|
71
|
|
|
{ |
|
72
|
|
|
$mget_after_set = $this->mget(array($level,__CLASS__,array($location))); |
|
73
|
|
|
if ($mget_after_set[$location] !== $data) |
|
74
|
|
|
{ |
|
75
|
|
|
if ($verbose) echo "$label: mget_after_set['$location']=".array2string($mget_after_set[$location])." !== ".array2string($data)."\n"; |
|
76
|
|
|
++$failed; |
|
77
|
|
|
} |
|
78
|
|
|
} |
|
79
|
|
|
$add_after_set = $this->add(array($level,__CLASS__,$location), 'other-data'); |
|
80
|
|
|
if ($add_after_set !== false) |
|
81
|
|
|
{ |
|
82
|
|
|
if ($verbose) echo "$label: add_after_set=".array2string($add_after_set)."\n"; |
|
83
|
|
|
++$failed; |
|
84
|
|
|
} |
|
85
|
|
|
if (($delete = $this->delete(array($level,__CLASS__,$location))) !== true) |
|
86
|
|
|
{ |
|
87
|
|
|
if ($verbose) echo "$label: delete returned ".array2string($delete)." !== TRUE\n"; |
|
88
|
|
|
++$failed; |
|
89
|
|
|
} |
|
90
|
|
|
$get_after_delete = $this->get(array($level,__CLASS__,$location)); |
|
91
|
|
|
if (!is_null($get_after_delete)) |
|
92
|
|
|
{ |
|
93
|
|
|
if ($verbose) echo "$label: get_after_delete=".array2string($get_after_delete)." != NULL\n"; |
|
94
|
|
|
++$failed; |
|
95
|
|
|
} |
|
96
|
|
|
// prepare for mget of everything |
|
97
|
|
|
if (is_a($this, 'EGroupware\Api\Cache\ProviderMultiple')) |
|
98
|
|
|
{ |
|
99
|
|
|
$locations[$location] = $data; |
|
100
|
|
|
$mget_after_delete = $this->mget(array($level,__CLASS__,array($location))); |
|
101
|
|
|
if (isset($mget_after_delete[$location])) |
|
102
|
|
|
{ |
|
103
|
|
|
if ($verbose) echo "$label: mget_after_delete['$location']=".array2string($mget_after_delete[$location])." != NULL\n"; |
|
104
|
|
|
++$failed; |
|
105
|
|
|
} |
|
106
|
|
|
} |
|
107
|
|
|
elseif (!is_null($data)) // emulation can NOT distinquish between null and not set |
|
108
|
|
|
{ |
|
109
|
|
|
$locations[$location] = $data; |
|
110
|
|
|
} |
|
111
|
|
|
$add_after_delete = $this->add(array($level,__CLASS__,$location), $data, 10); |
|
112
|
|
|
if ($add_after_delete !== true) |
|
113
|
|
|
{ |
|
114
|
|
|
if ($verbose) echo "$label: add_after_delete=".array2string($add_after_delete)."\n"; |
|
115
|
|
|
++$failed; |
|
116
|
|
|
} |
|
117
|
|
|
else |
|
118
|
|
|
{ |
|
119
|
|
|
$get_after_add = $this->get(array($level,__CLASS__,$location)); |
|
120
|
|
|
if ($get_after_add !== $data) |
|
121
|
|
|
{ |
|
122
|
|
|
if ($verbose) echo "$label: get_after_add=".array2string($get_after_add)." !== ".array2string($data)."\n"; |
|
123
|
|
|
++$failed; |
|
124
|
|
|
} |
|
125
|
|
|
} |
|
126
|
|
|
} |
|
127
|
|
|
// get all above in one request |
|
128
|
|
|
$keys = array_keys($locations); |
|
129
|
|
|
$keys_bogus = array_merge(array('not-set'),array_keys($locations),array('not-set-too')); |
|
130
|
|
|
if (is_a($this, 'EGroupware\Api\Cache\ProviderMultiple')) |
|
131
|
|
|
{ |
|
132
|
|
|
$mget = $this->mget(array($level,__CLASS__,$keys)); |
|
133
|
|
|
$mget_bogus = $this->mget(array($level,__CLASS__,$keys_bogus)); |
|
134
|
|
|
/* Api\Cache::getCache() gives a different result, as it does NOT use $level direkt |
|
135
|
|
|
} |
|
136
|
|
|
else |
|
137
|
|
|
{ |
|
138
|
|
|
$mget = Api\Cache::getCache($level, __CLASS__, $keys); |
|
139
|
|
|
$mget_bogus = Api\Cache::getCache($level, __CLASS__, $keys_bogus); |
|
140
|
|
|
}*/ |
|
141
|
|
|
if ($mget !== $locations) |
|
142
|
|
|
{ |
|
143
|
|
|
if ($verbose) echo "$label: mget=\n".array2string($mget)." !==\n".array2string($locations)."\n"; |
|
144
|
|
|
++$failed; |
|
145
|
|
|
} |
|
146
|
|
|
if ($mget_bogus !== $locations) |
|
147
|
|
|
{ |
|
148
|
|
|
if ($verbose) echo "$label: mget(".array2string($keys_bogus).")=\n".array2string($mget_bogus)." !==\n".array2string($locations)."\n"; |
|
149
|
|
|
++$failed; |
|
150
|
|
|
} |
|
151
|
|
|
} |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
return $failed; |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
|
/** |
|
158
|
|
|
* Delete all data under given keys |
|
159
|
|
|
* |
|
160
|
|
|
* Providers can return false, if they do not support flushing part of the cache (eg. memcache) |
|
161
|
|
|
* |
|
162
|
|
|
* @param array $keys eg. array($level,$app,$location) |
|
163
|
|
|
* @return boolean true on success, false on error (eg. $key not set) |
|
164
|
|
|
*/ |
|
165
|
|
|
function flush(array $keys) |
|
166
|
|
|
{ |
|
167
|
|
|
unset($keys); // required by function signature |
|
168
|
|
|
return false; |
|
169
|
|
|
} |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
// some testcode, if this file is called via it's URL |
|
173
|
|
|
// can be run on command-line: sudo php -d apc.enable_cli=1 -f api/src/Cache/Base.php |
|
174
|
|
|
/*if (isset($_SERVER['SCRIPT_FILENAME']) && realpath($_SERVER['SCRIPT_FILENAME']) == __FILE__) |
|
175
|
|
|
{ |
|
176
|
|
|
if (!isset($_SERVER['HTTP_HOST'])) |
|
177
|
|
|
{ |
|
178
|
|
|
chdir(dirname(__FILE__)); // to enable our relative pathes to work |
|
179
|
|
|
} |
|
180
|
|
|
$GLOBALS['egw_info'] = array( |
|
181
|
|
|
'flags' => array( |
|
182
|
|
|
'noapi' => true, |
|
183
|
|
|
), |
|
184
|
|
|
); |
|
185
|
|
|
include_once '../../../header.inc.php'; |
|
186
|
|
|
|
|
187
|
|
|
if (isset($_SERVER['HTTP_HOST'])) echo "<pre style='whitespace: nowrap'>\n"; |
|
188
|
|
|
|
|
189
|
|
|
foreach(array( |
|
190
|
|
|
'EGroupware\Api\Cache\Apcu' => array(), |
|
191
|
|
|
'EGroupware\Api\Cache\Apc' => array(), |
|
192
|
|
|
'EGroupware\Api\Cache\Memcached' => array('localhost'), |
|
193
|
|
|
'EGroupware\Api\Cache\Memcache' => array('localhost'), |
|
194
|
|
|
'EGroupware\Api\Cache\Files' => array('/tmp'), |
|
195
|
|
|
) as $class => $param) |
|
196
|
|
|
{ |
|
197
|
|
|
echo "Checking $class:\n"; |
|
198
|
|
|
try { |
|
199
|
|
|
$start = microtime(true); |
|
200
|
|
|
$provider = new $class($param); |
|
201
|
|
|
$n = 100; |
|
202
|
|
|
for($i=1; $i <= $n; ++$i) |
|
203
|
|
|
{ |
|
204
|
|
|
$failed = $provider->check($i == 1); |
|
205
|
|
|
} |
|
206
|
|
|
printf("$failed checks failed, $n iterations took %5.3f sec\n\n", microtime(true)-$start); |
|
207
|
|
|
} |
|
208
|
|
|
catch (\Exception $e) { |
|
209
|
|
|
printf($e->getMessage()."\n\n"); |
|
210
|
|
|
} |
|
211
|
|
|
} |
|
212
|
|
|
}*/ |
|
213
|
|
|
|
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..