Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/cache/PhabricatorKeyValueDatabaseCache.php
12242 views
1
<?php
2
3
final class PhabricatorKeyValueDatabaseCache
4
extends PhutilKeyValueCache {
5
6
const CACHE_FORMAT_RAW = 'raw';
7
const CACHE_FORMAT_DEFLATE = 'deflate';
8
9
public function setKeys(array $keys, $ttl = null) {
10
if (PhabricatorEnv::isReadOnly()) {
11
return;
12
}
13
14
if ($keys) {
15
$map = $this->digestKeys(array_keys($keys));
16
$conn_w = $this->establishConnection('w');
17
18
$sql = array();
19
foreach ($map as $key => $hash) {
20
$value = $keys[$key];
21
22
list($format, $storage_value) = $this->willWriteValue($key, $value);
23
24
$sql[] = qsprintf(
25
$conn_w,
26
'(%s, %s, %s, %B, %d, %nd)',
27
$hash,
28
$key,
29
$format,
30
$storage_value,
31
time(),
32
$ttl ? (time() + $ttl) : null);
33
}
34
35
$guard = AphrontWriteGuard::beginScopedUnguardedWrites();
36
foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
37
queryfx(
38
$conn_w,
39
'INSERT INTO %T
40
(cacheKeyHash, cacheKey, cacheFormat, cacheData,
41
cacheCreated, cacheExpires) VALUES %LQ
42
ON DUPLICATE KEY UPDATE
43
cacheKey = VALUES(cacheKey),
44
cacheFormat = VALUES(cacheFormat),
45
cacheData = VALUES(cacheData),
46
cacheCreated = VALUES(cacheCreated),
47
cacheExpires = VALUES(cacheExpires)',
48
$this->getTableName(),
49
$chunk);
50
}
51
unset($guard);
52
}
53
54
return $this;
55
}
56
57
public function getKeys(array $keys) {
58
$results = array();
59
if ($keys) {
60
$map = $this->digestKeys($keys);
61
62
$rows = queryfx_all(
63
$this->establishConnection('r'),
64
'SELECT * FROM %T WHERE cacheKeyHash IN (%Ls)',
65
$this->getTableName(),
66
$map);
67
$rows = ipull($rows, null, 'cacheKey');
68
69
foreach ($keys as $key) {
70
if (empty($rows[$key])) {
71
continue;
72
}
73
74
$row = $rows[$key];
75
76
if ($row['cacheExpires'] && ($row['cacheExpires'] < time())) {
77
continue;
78
}
79
80
try {
81
$results[$key] = $this->didReadValue(
82
$row['cacheFormat'],
83
$row['cacheData']);
84
} catch (Exception $ex) {
85
// Treat this as a cache miss.
86
phlog($ex);
87
}
88
}
89
}
90
91
return $results;
92
}
93
94
public function deleteKeys(array $keys) {
95
if ($keys) {
96
$map = $this->digestKeys($keys);
97
queryfx(
98
$this->establishConnection('w'),
99
'DELETE FROM %T WHERE cacheKeyHash IN (%Ls)',
100
$this->getTableName(),
101
$map);
102
}
103
104
return $this;
105
}
106
107
public function destroyCache() {
108
queryfx(
109
$this->establishConnection('w'),
110
'DELETE FROM %T',
111
$this->getTableName());
112
return $this;
113
}
114
115
116
/* -( Raw Cache Access )--------------------------------------------------- */
117
118
119
public function establishConnection($mode) {
120
// TODO: This is the only concrete table we have on the database right
121
// now.
122
return id(new PhabricatorMarkupCache())->establishConnection($mode);
123
}
124
125
public function getTableName() {
126
return 'cache_general';
127
}
128
129
130
/* -( Implementation )----------------------------------------------------- */
131
132
133
private function digestKeys(array $keys) {
134
$map = array();
135
foreach ($keys as $key) {
136
$map[$key] = PhabricatorHash::digestForIndex($key);
137
}
138
return $map;
139
}
140
141
private function willWriteValue($key, $value) {
142
if (!is_string($value)) {
143
throw new Exception(pht('Only strings may be written to the DB cache!'));
144
}
145
146
static $can_deflate;
147
if ($can_deflate === null) {
148
$can_deflate = function_exists('gzdeflate');
149
}
150
151
if ($can_deflate) {
152
$deflated = PhabricatorCaches::maybeDeflateData($value);
153
if ($deflated !== null) {
154
return array(self::CACHE_FORMAT_DEFLATE, $deflated);
155
}
156
}
157
158
return array(self::CACHE_FORMAT_RAW, $value);
159
}
160
161
private function didReadValue($format, $value) {
162
switch ($format) {
163
case self::CACHE_FORMAT_RAW:
164
return $value;
165
case self::CACHE_FORMAT_DEFLATE:
166
return PhabricatorCaches::inflateData($value);
167
default:
168
throw new Exception(pht('Unknown cache format.'));
169
}
170
}
171
172
173
}
174
175