|
34 | 34 | #include "apc_lock.h"
|
35 | 35 | #include "TSRM.h"
|
36 | 36 |
|
37 |
| -#ifndef APC_CACHE_API_H |
38 |
| -# include "apc_cache_api.h" |
| 37 | +typedef struct apc_cache_slam_key_t apc_cache_slam_key_t; |
| 38 | +struct apc_cache_slam_key_t { |
| 39 | + zend_ulong hash; /* hash of the key */ |
| 40 | + size_t len; /* length of the key */ |
| 41 | + time_t mtime; /* creation time of this key */ |
| 42 | + pid_t owner_pid; /* the pid that created this key */ |
| 43 | +#ifdef ZTS |
| 44 | + void ***owner_thread; /* TSRMLS cache of thread that created this key */ |
39 | 45 | #endif
|
| 46 | +}; |
| 47 | + |
| 48 | +/* {{{ struct definition: apc_cache_entry_t */ |
| 49 | +typedef struct apc_cache_entry_t apc_cache_entry_t; |
| 50 | +struct apc_cache_entry_t { |
| 51 | + zend_string *key; /* entry key */ |
| 52 | + zval val; /* the zval copied at store time */ |
| 53 | + apc_cache_entry_t *next; /* next entry in linked list */ |
| 54 | + zend_long ttl; /* the ttl on this specific entry */ |
| 55 | + zend_long ref_count; /* the reference count of this entry */ |
| 56 | + zend_long nhits; /* number of hits to this entry */ |
| 57 | + time_t ctime; /* time entry was initialized */ |
| 58 | + time_t mtime; /* the mtime of this cached entry */ |
| 59 | + time_t dtime; /* time entry was removed from cache */ |
| 60 | + time_t atime; /* time entry was last accessed */ |
| 61 | + zend_long mem_size; /* memory used */ |
| 62 | +}; |
| 63 | +/* }}} */ |
| 64 | + |
| 65 | +/* {{{ struct definition: apc_cache_header_t |
| 66 | + Any values that must be shared among processes should go in here. */ |
| 67 | +typedef struct _apc_cache_header_t { |
| 68 | + apc_lock_t lock; /* header lock */ |
| 69 | + zend_long nhits; /* hit count */ |
| 70 | + zend_long nmisses; /* miss count */ |
| 71 | + zend_long ninserts; /* insert count */ |
| 72 | + zend_long nexpunges; /* expunge count */ |
| 73 | + zend_long nentries; /* entry count */ |
| 74 | + zend_long mem_size; /* used */ |
| 75 | + time_t stime; /* start time */ |
| 76 | + unsigned short state; /* cache state */ |
| 77 | + apc_cache_slam_key_t lastkey; /* last key inserted (not necessarily without error) */ |
| 78 | + apc_cache_entry_t *gc; /* gc list */ |
| 79 | +} apc_cache_header_t; /* }}} */ |
| 80 | + |
| 81 | +/* {{{ struct definition: apc_cache_t */ |
| 82 | +typedef struct _apc_cache_t { |
| 83 | + void* shmaddr; /* process (local) address of shared cache */ |
| 84 | + apc_cache_header_t* header; /* cache header (stored in SHM) */ |
| 85 | + apc_cache_entry_t** slots; /* array of cache slots (stored in SHM) */ |
| 86 | + apc_sma_t* sma; /* shared memory allocator */ |
| 87 | + apc_serializer_t* serializer; /* serializer */ |
| 88 | + zend_long nslots; /* number of slots in cache */ |
| 89 | + zend_long gc_ttl; /* maximum time on GC list for a entry */ |
| 90 | + zend_long ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */ |
| 91 | + zend_long smart; /* smart parameter for gc */ |
| 92 | + zend_bool defend; /* defense parameter for runtime */ |
| 93 | +} apc_cache_t; /* }}} */ |
| 94 | + |
| 95 | +/* {{{ typedef: apc_cache_updater_t */ |
| 96 | +typedef zend_bool (*apc_cache_updater_t)(apc_cache_t*, apc_cache_entry_t*, void* data); /* }}} */ |
| 97 | + |
| 98 | +/* {{{ typedef: apc_cache_atomic_updater_t */ |
| 99 | +typedef zend_bool (*apc_cache_atomic_updater_t)(apc_cache_t*, zend_long*, void* data); /* }}} */ |
| 100 | + |
| 101 | +/* |
| 102 | + * apc_cache_create creates the shared memory cache. |
| 103 | + * |
| 104 | + * This function should be called once per process per cache |
| 105 | + * |
| 106 | + * serializer for APCu is set by globals on MINIT and ensured with apc_cache_serializer |
| 107 | + * during execution. Using apc_cache_serializer avoids race conditions between MINIT/RINIT of |
| 108 | + * APCU and the third party serializer. API users can choose to leave this null to use default |
| 109 | + * PHP serializers, or search the list of serializers for the preferred serializer |
| 110 | + * |
| 111 | + * size_hint is a "hint" at the total number entries that will be expected. |
| 112 | + * It determines the physical size of the hash table. Passing 0 for |
| 113 | + * this argument will use a reasonable default value |
| 114 | + * |
| 115 | + * gc_ttl is the maximum time a cache entry may speed on the garbage |
| 116 | + * collection list. This is basically a work around for the inherent |
| 117 | + * unreliability of our reference counting mechanism (see apc_cache_release). |
| 118 | + * |
| 119 | + * ttl is the maximum time a cache entry can idle in a slot in case the slot |
| 120 | + * is needed. This helps in cleaning up the cache and ensuring that entries |
| 121 | + * hit frequently stay cached and ones not hit very often eventually disappear. |
| 122 | + * |
| 123 | + * for an explanation of smart, see apc_cache_default_expunge |
| 124 | + * |
| 125 | + * defend enables/disables slam defense for this particular cache |
| 126 | + */ |
| 127 | +PHP_APCU_API apc_cache_t* apc_cache_create( |
| 128 | + apc_sma_t* sma, apc_serializer_t* serializer, zend_long size_hint, |
| 129 | + zend_long gc_ttl, zend_long ttl, zend_long smart, zend_bool defend); |
| 130 | +/* |
| 131 | +* apc_cache_preload preloads the data at path into the specified cache |
| 132 | +*/ |
| 133 | +PHP_APCU_API zend_bool apc_cache_preload(apc_cache_t* cache, const char* path); |
| 134 | + |
| 135 | +/* |
| 136 | + * apc_cache_detach detaches from the shared memory cache and cleans up |
| 137 | + * local allocations. Under apache, this function can be safely called by |
| 138 | + * the child processes when they exit. |
| 139 | + */ |
| 140 | +PHP_APCU_API void apc_cache_detach(apc_cache_t* cache); |
| 141 | + |
| 142 | +/* |
| 143 | + * apc_cache_clear empties a cache. This can safely be called at any time. |
| 144 | + */ |
| 145 | +PHP_APCU_API void apc_cache_clear(apc_cache_t* cache); |
| 146 | + |
| 147 | +/* |
| 148 | + * apc_cache_store creates key, entry and context in which to make an insertion of val into the specified cache |
| 149 | + */ |
| 150 | +PHP_APCU_API zend_bool apc_cache_store( |
| 151 | + apc_cache_t* cache, zend_string *key, const zval *val, |
| 152 | + const int32_t ttl, const zend_bool exclusive); |
| 153 | +/* |
| 154 | + * apc_cache_update updates an entry in place. The updater function must not bailout. |
| 155 | + * The update is performed under write-lock and doesn't have to be atomic. |
| 156 | + */ |
| 157 | +PHP_APCU_API zend_bool apc_cache_update( |
| 158 | + apc_cache_t *cache, zend_string *key, apc_cache_updater_t updater, void *data, |
| 159 | + zend_bool insert_if_not_found, zend_long ttl); |
| 160 | + |
| 161 | +/* |
| 162 | + * apc_cache_atomic_update_long updates an integer entry in place. The updater function must |
| 163 | + * perform the update atomically, as the update is performed under read-lock. |
| 164 | + */ |
| 165 | +PHP_APCU_API zend_bool apc_cache_atomic_update_long( |
| 166 | + apc_cache_t *cache, zend_string *key, apc_cache_atomic_updater_t updater, void *data, |
| 167 | + zend_bool insert_if_not_found, zend_long ttl); |
| 168 | + |
| 169 | +/* |
| 170 | + * apc_cache_find searches for a cache entry by its hashed identifier, |
| 171 | + * and returns a pointer to the entry if found, NULL otherwise. |
| 172 | + * |
| 173 | + */ |
| 174 | +PHP_APCU_API apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, zend_string *key, time_t t); |
| 175 | + |
| 176 | +/* |
| 177 | + * apc_cache_fetch fetches an entry from the cache directly into dst |
| 178 | + * |
| 179 | + */ |
| 180 | +PHP_APCU_API zend_bool apc_cache_fetch(apc_cache_t* cache, zend_string *key, time_t t, zval *dst); |
| 181 | + |
| 182 | +/* |
| 183 | + * apc_cache_exists searches for a cache entry by its hashed identifier, |
| 184 | + * and returns whether the entry exists. |
| 185 | + */ |
| 186 | +PHP_APCU_API zend_bool apc_cache_exists(apc_cache_t* cache, zend_string *key, time_t t); |
| 187 | + |
| 188 | +/* |
| 189 | + * apc_cache_delete and apc_cache_delete finds an entry in the cache and deletes it. |
| 190 | + */ |
| 191 | +PHP_APCU_API zend_bool apc_cache_delete(apc_cache_t* cache, zend_string *key); |
| 192 | + |
| 193 | +/* apc_cache_fetch_zval copies a cache entry value to be usable at runtime. |
| 194 | + */ |
| 195 | +PHP_APCU_API zend_bool apc_cache_entry_fetch_zval( |
| 196 | + apc_cache_t *cache, apc_cache_entry_t *entry, zval *dst); |
| 197 | + |
| 198 | +/* |
| 199 | + * apc_cache_entry_release decrements the reference count associated with a cache |
| 200 | + * entry. Calling apc_cache_find automatically increments the reference count, |
| 201 | + * and this function must be called post-execution to return the count to its |
| 202 | + * original value. Failing to do so will prevent the entry from being |
| 203 | + * garbage-collected. |
| 204 | + * |
| 205 | + * entry is the cache entry whose ref count you want to decrement. |
| 206 | + */ |
| 207 | +PHP_APCU_API void apc_cache_entry_release(apc_cache_t *cache, apc_cache_entry_t *entry); |
| 208 | + |
| 209 | +/* |
| 210 | + fetches information about the cache provided for userland status functions |
| 211 | +*/ |
| 212 | +PHP_APCU_API zend_bool apc_cache_info(zval *info, apc_cache_t *cache, zend_bool limited); |
| 213 | + |
| 214 | +/* |
| 215 | + fetches information about the key provided |
| 216 | +*/ |
| 217 | +PHP_APCU_API void apc_cache_stat(apc_cache_t *cache, zend_string *key, zval *stat); |
| 218 | + |
| 219 | +/* |
| 220 | +* apc_cache_defense: guard against slamming a key |
| 221 | +* will return true if the following conditions are met: |
| 222 | +* the key provided has a matching hash and length to the last key inserted into cache |
| 223 | +* the last key has a different owner |
| 224 | +* in ZTS mode, TSRM determines owner |
| 225 | +* in non-ZTS mode, PID determines owner |
| 226 | +* Note: this function sets the owner of key during execution |
| 227 | +*/ |
| 228 | +PHP_APCU_API zend_bool apc_cache_defense(apc_cache_t *cache, zend_string *key, time_t t); |
| 229 | + |
| 230 | +/* |
| 231 | +* apc_cache_serializer |
| 232 | +* sets the serializer for a cache, and by proxy contexts created for the cache |
| 233 | +* Note: this avoids race conditions between third party serializers and APCu |
| 234 | +*/ |
| 235 | +PHP_APCU_API void apc_cache_serializer(apc_cache_t* cache, const char* name); |
| 236 | + |
| 237 | +/* |
| 238 | +* The remaining functions allow a third party to reimplement expunge |
| 239 | +* |
| 240 | +* Look at the source of apc_cache_default_expunge for what is expected of this function |
| 241 | +* |
| 242 | +* The default behaviour of expunge is explained below, should no combination of those options |
| 243 | +* be suitable, you will need to reimplement apc_cache_default_expunge and pass it to your |
| 244 | +* call to apc_sma_api_impl, this will replace the default functionality. |
| 245 | +* The functions below you can use during your own implementation of expunge to gain more |
| 246 | +* control over how the expunge process works ... |
| 247 | +* |
| 248 | +* Note: beware of locking (copy it exactly), setting states is also important |
| 249 | +*/ |
| 250 | + |
| 251 | +/* {{{ apc_cache_default_expunge |
| 252 | +* Where smart is not set: |
| 253 | +* Where no ttl is set on cache: |
| 254 | +* 1) Perform cleanup of stale entries |
| 255 | +* 2) Expunge if available memory is less than sma->size/2 |
| 256 | +* Where ttl is set on cache: |
| 257 | +* 1) Perform cleanup of stale entries |
| 258 | +* 2) If available memory if less than the size requested, run full expunge |
| 259 | +* |
| 260 | +* Where smart is set: |
| 261 | +* Where no ttl is set on cache: |
| 262 | +* 1) Perform cleanup of stale entries |
| 263 | +* 2) Expunge is available memory is less than size * smart |
| 264 | +* Where ttl is set on cache: |
| 265 | +* 1) Perform cleanup of stale entries |
| 266 | +* 2) If available memory if less than the size requested, run full expunge |
| 267 | +* |
| 268 | +* The TTL of an entry takes precedence over the TTL of a cache |
| 269 | +*/ |
| 270 | +PHP_APCU_API void apc_cache_default_expunge(apc_cache_t* cache, size_t size); |
| 271 | + |
| 272 | +/* |
| 273 | +* apc_cache_entry: generate and create or fetch an entry |
| 274 | +* |
| 275 | +* @see https://github.com/krakjoe/apcu/issues/142 |
| 276 | +*/ |
| 277 | +PHP_APCU_API void apc_cache_entry(apc_cache_t *cache, zend_string *key, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_long ttl, zend_long now, zval *return_value); |
40 | 278 |
|
41 | 279 | #endif
|
42 | 280 |
|
|
0 commit comments