|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* Class SnCache |
|
5
|
|
|
* |
|
6
|
|
|
* Permanent cache for classSupernova |
|
7
|
|
|
*/ |
|
8
|
|
|
class SnCache { |
|
9
|
|
|
/** |
|
10
|
|
|
* Кэш данных - юзера, планеты, юниты, очередь, альянсы итд |
|
11
|
|
|
* |
|
12
|
|
|
* @var array $data |
|
13
|
|
|
*/ |
|
14
|
|
|
protected static $data = array(); |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Кэширует соответствия между расположением объектов - в частности юнитов и очередей |
|
18
|
|
|
* |
|
19
|
|
|
* Массив $locator - хранит отношения между записями для быстрого доступа по тип_записи:тип_локации:ид_локации:внутренний_ид_записи=>информация |
|
20
|
|
|
* Для LOC_UNIT внутренний ИД - это SNID, а информация - это ссылка на запись `unit` |
|
21
|
|
|
* Для LOC_QUE внутренний ИД - это тип очереди, а информация - массив ссылок на `que` |
|
22
|
|
|
* |
|
23
|
|
|
* @var array $locator |
|
24
|
|
|
*/ |
|
25
|
|
|
protected static $locator = array(); |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* Кэш запросов |
|
29
|
|
|
* |
|
30
|
|
|
* @var array $queries |
|
31
|
|
|
*/ |
|
32
|
|
|
protected static $queries = array(); |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Информация о блокировках |
|
36
|
|
|
* |
|
37
|
|
|
* @var array $locks |
|
38
|
|
|
*/ |
|
39
|
|
|
protected static $locks = array(); |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* Repacking data for $location_type |
|
43
|
|
|
* |
|
44
|
|
|
* @param int $location_type |
|
45
|
|
|
* @param int $record_id |
|
46
|
|
|
*/ |
|
47
|
|
|
public static function cache_repack($location_type, $record_id = 0) { |
|
48
|
|
|
// Если есть $user_id - проверяем, а надо ли перепаковывать? |
|
49
|
|
|
if ($record_id && isset(static::$data[$location_type][$record_id]) && static::$data[$location_type][$record_id] !== null) { |
|
50
|
|
|
return; |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
HelperArray::array_repack(static::$data[$location_type]); |
|
54
|
|
|
HelperArray::array_repack(static::$locator[$location_type], 3); // TODO У каждого типа локации - своя глубина!!!! Но можно и глубже ??? |
|
55
|
|
|
HelperArray::array_repack(static::$queries[$location_type], 1); |
|
56
|
|
|
} |
|
57
|
|
|
|
|
58
|
|
|
public static function cache_clear($location_type, $hard = true) { |
|
59
|
|
|
if ($hard && !empty(static::$data[$location_type])) { |
|
60
|
|
|
// Здесь нельзя делать unset - надо записывать NULL, что бы это отразилось на зависимых записях |
|
61
|
|
|
// TODO - replace with setNull |
|
62
|
|
|
array_walk(static::$data[$location_type], function (&$item) { $item = null; }); |
|
63
|
|
|
} |
|
64
|
|
|
static::$locator[$location_type] = array(); |
|
65
|
|
|
static::$queries[$location_type] = array(); |
|
66
|
|
|
static::cache_repack($location_type); // Перепаковываем внутренние структуры, если нужно |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
public static function setNull(&$item) { |
|
70
|
|
|
$item = null; |
|
71
|
|
|
} |
|
72
|
|
|
|
|
73
|
|
|
public static function cache_clear_all($hard = true) { |
|
74
|
|
|
if ($hard) { |
|
75
|
|
|
static::$data = array(); |
|
76
|
|
|
static::cache_lock_unset_all(); |
|
77
|
|
|
} |
|
78
|
|
|
static::$locator = array(); |
|
79
|
|
|
static::$queries = array(); |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
public static function cache_isset($location_type, $record_id) { |
|
83
|
|
|
return isset(static::$data[$location_type][$record_id]) && static::$data[$location_type][$record_id] !== null; |
|
84
|
|
|
} |
|
85
|
|
|
|
|
86
|
|
|
// TODO - UNUSED ???????????? |
|
|
|
|
|
|
87
|
|
|
public static function cache_get($location_type, $record_id) { |
|
88
|
|
|
return isset(static::$data[$location_type][$record_id]) ? static::$data[$location_type][$record_id] : null; |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/* Кэшируем запись в соответствующий кэш |
|
92
|
|
|
|
|
93
|
|
|
Писать в кэш: |
|
94
|
|
|
1. Если записи не существует в кэше |
|
95
|
|
|
2. Если стоит $force_overwrite |
|
96
|
|
|
3. Если во время транзакции существующая запись не заблокирована |
|
97
|
|
|
|
|
98
|
|
|
Блокировать запись: |
|
99
|
|
|
1. Если идет транзакция и запись не заблокирована |
|
100
|
|
|
2. Если не стоит скип-лок |
|
101
|
|
|
*/ |
|
102
|
|
|
public static function cache_set($location_type, $record, $force_overwrite = false, $skip_lock = false) { |
|
103
|
|
|
// нет идентификатора - выход |
|
104
|
|
|
if (!($record_id = $record[classSupernova::$location_info[$location_type][P_ID]])) { |
|
105
|
|
|
return; |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
$in_transaction = classSupernova::db_transaction_check(false); |
|
109
|
|
|
if ( |
|
110
|
|
|
$force_overwrite |
|
111
|
|
|
|| |
|
112
|
|
|
// Не заменяются заблокированные записи во время транзакции |
|
113
|
|
|
($in_transaction && !static::cache_lock_get($location_type, $record_id)) |
|
114
|
|
|
|| |
|
115
|
|
|
!static::cache_isset($location_type, $record_id) |
|
116
|
|
|
) { |
|
117
|
|
|
static::$data[$location_type][$record_id] = $record; |
|
118
|
|
|
if ($in_transaction && !$skip_lock) { |
|
119
|
|
|
static::cache_lock_set($location_type, $record_id); |
|
120
|
|
|
} |
|
121
|
|
|
} |
|
122
|
|
|
} |
|
123
|
|
|
|
|
124
|
|
|
public static function queryCacheSetByFilter($location_type, $filter, $record_id) { |
|
125
|
|
|
SnCache::$queries[$location_type][$filter][$record_id] = &SnCache::getDataRefByLocationAndId($location_type, $record_id); |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
public static function cache_unset($cache_id, $safe_record_id) { |
|
129
|
|
|
// $record_id должен быть проверен заранее ! |
|
130
|
|
|
if (isset(static::$data[$cache_id][$safe_record_id]) && static::$data[$cache_id][$safe_record_id] !== null) { |
|
131
|
|
|
// Выставляем запись в null |
|
132
|
|
|
static::$data[$cache_id][$safe_record_id] = null; |
|
133
|
|
|
// Очищаем кэш мягко - что бы удалить очистить связанные данные - кэш локаций и кэш запоросов и всё, что потребуется впредь |
|
134
|
|
|
static::cache_clear($cache_id, false); |
|
135
|
|
|
} |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
public static function cache_lock_get($location_type, $record_id) { |
|
139
|
|
|
return isset(static::$locks[$location_type][$record_id]); |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
public static function cache_lock_set($location_type, $record_id) { |
|
143
|
|
|
return static::$locks[$location_type][$record_id] = true; // Не всегда - от результата |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
// TODO - UNUSED ???????????? |
|
|
|
|
|
|
147
|
|
|
public static function cache_lock_unset($location_type, $record_id) { |
|
148
|
|
|
if (isset(static::$locks[$location_type][$record_id])) { |
|
149
|
|
|
unset(static::$locks[$location_type][$record_id]); |
|
150
|
|
|
} |
|
151
|
|
|
|
|
152
|
|
|
return true; // Не всегда - от результата |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
public static function cache_lock_unset_all() { |
|
156
|
|
|
// Когда будем работать с xcache - это понадобиться, что бы снимать в xcache блокировки с записей |
|
157
|
|
|
// Пройти по массиву - снять блокировки для кэшера в памяти |
|
158
|
|
|
static::$locks = array(); |
|
159
|
|
|
|
|
160
|
|
|
return true; // Не всегда - от результата |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
public static function getData($locationType = LOC_NONE) { |
|
164
|
|
|
return $locationType == LOC_NONE ? static::$data : static::$data[$locationType]; |
|
165
|
|
|
} |
|
166
|
|
|
|
|
167
|
|
|
public static function cacheUnsetElement($locationType, $recordId) { |
|
168
|
|
|
static::$data[$locationType][$recordId] = null; |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
public static function isArrayLocation($locationType) { |
|
172
|
|
|
return is_array(static::$data[$locationType]); |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
/** |
|
176
|
|
|
* Return reference to record in $data by locationType and recordId |
|
177
|
|
|
* |
|
178
|
|
|
* @param int $locationType |
|
179
|
|
|
* @param int $recordId |
|
180
|
|
|
* |
|
181
|
|
|
* @return &mixed |
|
|
|
|
|
|
182
|
|
|
*/ |
|
183
|
|
|
public static function &getDataRefByLocationAndId($locationType, $recordId) { |
|
184
|
|
|
return static::$data[$locationType][$recordId]; |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
public static function setUnitLocator($unit, $unit_id) { |
|
188
|
|
|
if (is_array($unit)) { |
|
189
|
|
|
static::$locator[LOC_UNIT][$unit['unit_location_type']][$unit['unit_location_id']][$unit['unit_snid']] = &static::getDataRefByLocationAndId(LOC_UNIT, $unit_id); |
|
190
|
|
|
} |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
public static function getUnitLocator($location_type, $location_id, $unit_snid) { |
|
194
|
|
|
return $unit_snid ? static::$locator[LOC_UNIT][$location_type][$location_id][$unit_snid] : static::$locator[LOC_UNIT][$location_type][$location_id]; |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
|
|
public static function getUnitLocatorByFullLocation($location_type, $location_id) { |
|
198
|
|
|
return is_array(static::$locator[LOC_UNIT][$location_type][$location_id]) ? static::$locator[LOC_UNIT][$location_type][$location_id] : array(); |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
|
|
public static function setUnitLocatorByLocationAndIDs($location_type, $location_id, $unit_data) { |
|
202
|
|
|
SnCache::$locator[LOC_UNIT][$location_type][$location_id][$unit_data['unit_snid']] = &static::$data[LOC_UNIT][$unit_data['unit_id']]; |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
public static function isUnitLocatorNotSet($location_type, $location_id) { |
|
206
|
|
|
return !isset(static::$locator[LOC_UNIT][$location_type][$location_id]); |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
public static function locatorReset() { |
|
210
|
|
|
static::$locator = array(); |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
public static function queriesReset() { |
|
214
|
|
|
static::$queries = array(); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
public static function getQueries() { |
|
218
|
|
|
return static::$queries; |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
|
|
public static function getLocks() { |
|
222
|
|
|
return static::$locks; |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
public static function getQueriesByLocationAndFilter($locationType, $filter) { |
|
226
|
|
|
return !empty(static::$queries[$locationType][$filter]) && is_array(static::$queries[$locationType][$filter]) ? static::$queries[$locationType][$filter] : array(); |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
public static function isQueryCacheByLocationAndFilterEmpty($locationType, $filter) { |
|
230
|
|
|
return !isset(SnCache::$queries[$locationType][$filter]) || SnCache::$queries[$locationType][$filter] === null; |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
|
|
public static function queryCacheResetByLocationAndFilter($locationType, $filter) { |
|
234
|
|
|
SnCache::$queries[$locationType][$filter] = array(); |
|
235
|
|
|
} |
|
236
|
|
|
} |
|
237
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.