File Coverage

xs/si32.xs
Criterion Covered Total %
statement 85 377 22.5
branch 100 726 13.7
condition n/a
subroutine n/a
pod n/a
total 185 1103 16.7


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::SI32
2             PROTOTYPES: DISABLE
3              
4             SV*
5             new(char* class, SV* path_sv, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
6             CODE:
7 4 50         char errbuf[SHM_ERR_BUFLEN]; const char* path = SvOK(path_sv) ? SvPV_nolen(path_sv) : NULL; ShmHandle* map = shm_si32_create(path, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
8 4 50         if (!map) croak("HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
9 4           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
10             OUTPUT:
11             RETVAL
12              
13             SV*
14             new_sharded(char* class, char* path_prefix, UV num_shards, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
15             CODE:
16 0           char errbuf[SHM_ERR_BUFLEN]; ShmHandle* map = shm_si32_create_sharded(path_prefix, (uint32_t)num_shards, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
17 0 0         if (!map) croak("HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
18 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
19             OUTPUT:
20             RETVAL
21              
22              
23             SV*
24             new_memfd(char* class, SV* name_sv, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
25             CODE:
26             char errbuf[SHM_ERR_BUFLEN];
27 0 0         const char* name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
28 0           ShmHandle* map = shm_si32_create_memfd(name, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
29 0 0         if (!map) croak("Data::HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
30 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
31             OUTPUT:
32             RETVAL
33              
34             SV*
35             new_from_fd(char* class, int fd)
36             CODE:
37             char errbuf[SHM_ERR_BUFLEN];
38 0           ShmHandle* map = shm_si32_open_fd(fd, errbuf);
39 0 0         if (!map) croak("Data::HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
40 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
41             OUTPUT:
42             RETVAL
43              
44             IV
45             memfd(SV* self_sv)
46             CODE:
47 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
48 0 0         RETVAL = h->backing_fd;
49             OUTPUT:
50             RETVAL
51              
52              
53             void
54             sync(SV* self_sv)
55             CODE:
56 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
57 0 0         if (shm_msync(h) != 0) croak("Data::HashMap::Shared::SI32 sync: %s", strerror(errno));
58              
59             void
60             DESTROY(SV* self_sv)
61             CODE:
62 4 50         if (!SvROK(self_sv)) return;
63 4           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_sv)));
64 4 50         if (!h) return;
65 4           sv_setiv(SvRV(self_sv), 0);
66 4           shm_close_map(h);
67              
68             bool
69             put(SV* self_sv, SV* key_sv, int32_t value)
70             CODE:
71 14 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
72 14 50         EXTRACT_STR_KEY(key_sv);
73 14 50         RETVAL = shm_si32_put(h, _kstr, (uint32_t)_klen, _kutf8, value);
74             OUTPUT:
75             RETVAL
76              
77             UV
78             set_multi(SV* self_sv, ...)
79             CODE:
80 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
81 0 0         if ((items - 1) % 2 != 0) croak("set_multi requires even number of arguments (key, value pairs)");
82 0           uint32_t count = 0;
83 0 0         if (h->shard_handles) {
84 0 0         for (int i = 1; i < items; i += 2) {
85 0           STRLEN _klen; const char *_kstr = SvPV(ST(i), _klen);
86 0           bool _kutf8 = SvUTF8(ST(i)) ? 1 : 0;
87 0           count += shm_si32_put(h, _kstr, (uint32_t)_klen, _kutf8, (int32_t)SvIV(ST(i + 1)));
88             }
89             } else {
90 0           ShmHeader *hdr = h->hdr;
91 0           shm_rwlock_wrlock(hdr);
92 0           shm_seqlock_write_begin(&hdr->seq);
93 0 0         for (int i = 1; i < items; i += 2) {
94 0           STRLEN _klen; const char *_kstr = SvPV(ST(i), _klen);
95 0           bool _kutf8 = SvUTF8(ST(i)) ? 1 : 0;
96 0 0         if (_klen > SHM_MAX_STR_LEN) { shm_seqlock_write_end(&hdr->seq); shm_rwlock_wrunlock(hdr); croak("key too long"); }
97 0           count += shm_si32_put_inner(h, _kstr, (uint32_t)_klen, _kutf8, (int32_t)SvIV(ST(i + 1)), SHM_TTL_USE_DEFAULT);
98             }
99 0           shm_seqlock_write_end(&hdr->seq);
100 0           shm_rwlock_wrunlock(hdr);
101             }
102 0 0         RETVAL = count;
103             OUTPUT:
104             RETVAL
105              
106             UV
107             remove_multi(SV* self_sv, ...)
108             CODE:
109 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
110 0           uint32_t count = 0;
111 0 0         if (h->shard_handles) {
112 0 0         for (int i = 1; i < items; i++) {
113 0           STRLEN _kl; const char *_ks = SvPV(ST(i), _kl);
114 0           bool _ku = SvUTF8(ST(i)) ? 1 : 0;
115 0 0         if (_kl > SHM_MAX_STR_LEN) croak("key too long (max 2GB)");
116 0           count += shm_si32_remove(h, _ks, (uint32_t)_kl, _ku);
117             }
118             } else {
119 0           ShmHeader *hdr = h->hdr;
120 0           shm_rwlock_wrlock(hdr);
121 0           shm_seqlock_write_begin(&hdr->seq);
122 0 0         for (int i = 1; i < items; i++) {
123 0           STRLEN _kl; const char *_ks = SvPV(ST(i), _kl);
124 0           bool _ku = SvUTF8(ST(i)) ? 1 : 0;
125 0 0         if (_kl > SHM_MAX_STR_LEN) { shm_seqlock_write_end(&hdr->seq); shm_rwlock_wrunlock(hdr); croak("key too long (max 2GB)"); }
126 0           count += shm_si32_remove_inner(h, _ks, (uint32_t)_kl, _ku);
127             }
128 0 0         if (count) shm_si32_maybe_shrink(h);
129 0           shm_seqlock_write_end(&hdr->seq);
130 0           shm_rwlock_wrunlock(hdr);
131             }
132 0 0         RETVAL = count;
133             OUTPUT:
134             RETVAL
135              
136             void
137             get_multi(SV* self_sv, ...)
138             PPCODE:
139 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
140 0           int nkeys = items - 1;
141 0 0         if (nkeys == 0) XSRETURN_EMPTY;
142 0 0         EXTEND(SP, nkeys);
    0          
143 0 0         if (h->shard_handles) {
144 0 0         for (int i = 0; i < nkeys; i++) {
145 0           STRLEN _kl; const char *_ks = SvPV(ST(i + 1), _kl);
146 0           bool _ku = SvUTF8(ST(i + 1)) ? 1 : 0;
147             int32_t val;
148 0 0         if (shm_si32_get(h, _ks, (uint32_t)_kl, _ku, &val))
149 0           mPUSHi(val);
150             else
151 0           PUSHs(&PL_sv_undef);
152             }
153             } else {
154 0           ShmHeader *hdr = h->hdr;
155 0           ShmNodeSI32 *nodes = (ShmNodeSI32 *)h->nodes;
156 0           uint8_t *states = h->states;
157 0           char *arena = h->arena;
158 0 0         uint32_t now = h->expires_at ? shm_now() : 0;
159 0           RDLOCK_GUARD(hdr);
160 0           uint32_t mask = hdr->table_cap - 1;
161 0 0         for (int i = 0; i < nkeys; i++) {
162 0           STRLEN _kl; const char *_ks = SvPV(ST(i + 1), _kl);
163 0           bool _ku = SvUTF8(ST(i + 1)) ? 1 : 0;
164 0           uint32_t hash = shm_hash_string(_ks, (uint32_t)_kl);
165 0           uint32_t pos = hash & mask;
166 0           uint8_t tag = SHM_MAKE_TAG(hash);
167 0           int found = 0;
168 0           int32_t val = 0;
169 0 0         for (uint32_t j = 0; j <= mask; j++) {
170 0           uint32_t idx = (pos + j) & mask;
171 0           uint8_t st = states[idx];
172 0 0         if (st == SHM_EMPTY) break;
173 0 0         if (st != tag) continue;
174 0 0         if (shm_si32__key_eq_str(&nodes[idx], arena, _ks, (uint32_t)_kl, _ku)) {
175 0 0         if (h->expires_at && h->expires_at[idx] && now >= h->expires_at[idx]) break;
    0          
    0          
176 0           val = nodes[idx].value;
177 0           found = 1; break;
178             }
179             }
180 0 0         if (found) mPUSHi(val);
181 0           else PUSHs(&PL_sv_undef);
182             /* Prefetch next key's probe start */
183 0 0         if (i + 1 < nkeys) {
184 0           STRLEN nkl; const char *nks = SvPV(ST(i + 2), nkl);
185 0           uint32_t nh = shm_hash_string(nks, (uint32_t)nkl);
186 0           __builtin_prefetch(&states[nh & mask], 0, 0);
187             }
188             }
189             }
190              
191             void
192             get_with_ttl(SV* self_sv, SV* key_sv)
193             PPCODE:
194 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
195 0 0         EXTRACT_STR_KEY(key_sv);
196             int32_t out_value;
197             int64_t out_ttl;
198 0 0         if (!shm_si32_get_with_ttl(h, _kstr, (uint32_t)_klen, _kutf8, &out_value, &out_ttl)) XSRETURN_EMPTY;
199 0 0         EXTEND(SP, 2);
200 0           mPUSHi(out_value);
201 0 0         if (out_ttl < 0) PUSHs(&PL_sv_undef);
202 0           else mPUSHi(out_ttl);
203              
204             SV*
205             stats(SV* self_sv)
206             CODE:
207 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
208 0           HV *hv = newHV();
209 0           hv_store(hv, "size", 4, newSVuv(shm_si32_size(h)), 0);
210 0           hv_store(hv, "capacity", 8, newSVuv(shm_si32_capacity(h)), 0);
211 0           hv_store(hv, "max_entries", 11, newSVuv(shm_si32_max_entries(h)), 0);
212 0           hv_store(hv, "tombstones", 10, newSVuv(shm_si32_tombstones(h)), 0);
213 0           hv_store(hv, "mmap_size", 9, newSVuv(shm_si32_mmap_size(h)), 0);
214 0           hv_store(hv, "arena_used", 10, newSVuv(shm_si32_arena_used(h)), 0);
215 0           hv_store(hv, "arena_cap", 9, newSVuv(shm_si32_arena_cap(h)), 0);
216 0           hv_store(hv, "evictions", 9, newSVuv(shm_si32_stat_evictions(h)), 0);
217 0           hv_store(hv, "expired", 7, newSVuv(shm_si32_stat_expired(h)), 0);
218 0           hv_store(hv, "recoveries", 10, newSVuv(shm_si32_stat_recoveries(h)), 0);
219 0           hv_store(hv, "max_size", 8, newSVuv(shm_si32_max_size(h)), 0);
220 0           hv_store(hv, "ttl", 3, newSVuv(shm_si32_ttl(h)), 0);
221 0           RETVAL = newRV_noinc((SV*)hv);
222             OUTPUT:
223             RETVAL
224              
225             bool
226             cas(SV* self_sv, SV* key_sv, int32_t expected, int32_t desired)
227             CODE:
228 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
229 2 50         EXTRACT_STR_KEY(key_sv);
230 2 100         RETVAL = shm_si32_cas(h, _kstr, (uint32_t)_klen, _kutf8, expected, desired);
231             OUTPUT:
232             RETVAL
233              
234             SV*
235             cas_take(SV* self_sv, SV* key_sv, int32_t expected)
236             CODE:
237 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
238 0 0         EXTRACT_STR_KEY(key_sv);
239             int32_t out_value;
240 0 0         if (!shm_si32_cas_take(h, _kstr, (uint32_t)_klen, _kutf8, expected, &out_value)) XSRETURN_UNDEF;
241 0           RETVAL = newSViv(out_value);
242             OUTPUT:
243             RETVAL
244              
245             bool
246             persist(SV* self_sv, SV* key_sv)
247             CODE:
248 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
249 1 50         EXTRACT_STR_KEY(key_sv);
250 1 50         RETVAL = shm_si32_persist(h, _kstr, (uint32_t)_klen, _kutf8);
251             OUTPUT:
252             RETVAL
253              
254             bool
255             set_ttl(SV* self_sv, SV* key_sv, UV ttl_sec)
256             CODE:
257 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
258 1 50         EXTRACT_STR_KEY(key_sv);
259 1 50         RETVAL = shm_si32_set_ttl(h, _kstr, (uint32_t)_klen, _kutf8, (uint32_t)ttl_sec);
260             OUTPUT:
261             RETVAL
262              
263             bool
264             put_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl_sec)
265             CODE:
266 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
267 0 0         EXTRACT_STR_KEY(key_sv);
268 0 0         REQUIRE_TTL(h);
    0          
269 0 0         RETVAL = shm_si32_put_ttl(h, _kstr, (uint32_t)_klen, _kutf8, value, (uint32_t)ttl_sec);
270             OUTPUT:
271             RETVAL
272              
273             UV
274             max_size(SV* self_sv)
275             CODE:
276 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
277 0 0         RETVAL = (UV)shm_si32_max_size(h);
278             OUTPUT:
279             RETVAL
280              
281             UV
282             ttl(SV* self_sv)
283             CODE:
284 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
285 0 0         RETVAL = (UV)shm_si32_ttl(h);
286             OUTPUT:
287             RETVAL
288              
289             SV*
290             get(SV* self_sv, SV* key_sv)
291             CODE:
292 5 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
293 5 50         EXTRACT_STR_KEY(key_sv);
294             int32_t value;
295 5 50         if (!shm_si32_get(h, _kstr, (uint32_t)_klen, _kutf8, &value)) XSRETURN_UNDEF;
296 5           RETVAL = newSViv(value);
297             OUTPUT:
298             RETVAL
299              
300             bool
301             remove(SV* self_sv, SV* key_sv)
302             CODE:
303 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
304 0 0         EXTRACT_STR_KEY(key_sv);
305 0 0         RETVAL = shm_si32_remove(h, _kstr, (uint32_t)_klen, _kutf8);
306             OUTPUT:
307             RETVAL
308              
309             bool
310             exists(SV* self_sv, SV* key_sv)
311             CODE:
312 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
313 0 0         EXTRACT_STR_KEY(key_sv);
314 0 0         RETVAL = shm_si32_exists(h, _kstr, (uint32_t)_klen, _kutf8);
315             OUTPUT:
316             RETVAL
317              
318             SV*
319             incr(SV* self_sv, SV* key_sv)
320             CODE:
321 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
322 1 50         EXTRACT_STR_KEY(key_sv);
323             int ok;
324 1           int32_t val = shm_si32_incr_by(h, _kstr, (uint32_t)_klen, _kutf8, 1, &ok);
325 1 50         if (!ok) croak("HashMap::Shared::SI32: increment failed");
326 1           RETVAL = newSViv(val);
327             OUTPUT:
328             RETVAL
329              
330             SV*
331             decr(SV* self_sv, SV* key_sv)
332             CODE:
333 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
334 0 0         EXTRACT_STR_KEY(key_sv);
335             int ok;
336 0           int32_t val = shm_si32_incr_by(h, _kstr, (uint32_t)_klen, _kutf8, -1, &ok);
337 0 0         if (!ok) croak("HashMap::Shared::SI32: decrement failed");
338 0           RETVAL = newSViv(val);
339             OUTPUT:
340             RETVAL
341              
342             SV*
343             incr_by(SV* self_sv, SV* key_sv, int32_t delta)
344             CODE:
345 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
346 1 50         EXTRACT_STR_KEY(key_sv);
347             int ok;
348 1           int32_t val = shm_si32_incr_by(h, _kstr, (uint32_t)_klen, _kutf8, delta, &ok);
349 1 50         if (!ok) croak("HashMap::Shared::SI32: incr_by failed");
350 1           RETVAL = newSViv(val);
351             OUTPUT:
352             RETVAL
353              
354             UV
355             size(SV* self_sv)
356             CODE:
357 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
358 0 0         RETVAL = (UV)shm_si32_size(h);
359             OUTPUT:
360             RETVAL
361              
362             UV
363             max_entries(SV* self_sv)
364             CODE:
365 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
366 0 0         RETVAL = (UV)shm_si32_max_entries(h);
367             OUTPUT:
368             RETVAL
369              
370             void
371             keys(SV* self_sv)
372             PPCODE:
373 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
374 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
375 2 100         for (uint32_t si = 0; si < ns; si++) {
376 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
377 1           ShmHeader *hdr = sh->hdr;
378 1           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
379 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
380 1           RDLOCK_GUARD(hdr);
381 1 50         EXTEND(SP, hdr->size);
382 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
383 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
384             char _ib[SHM_INLINE_MAX]; uint32_t klen;
385 13           const char *kp = shm_str_ptr(nodes[i].key_off, nodes[i].key_len, sh->arena, _ib, &klen);
386 13           SV* sv = newSVpvn(kp, klen);
387 13 50         if (SHM_UNPACK_UTF8(nodes[i].key_len)) SvUTF8_on(sv);
388 13 50         mXPUSHs(sv);
389             }
390             }
391             }
392              
393             void
394             values(SV* self_sv)
395             PPCODE:
396 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
397 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
398 0 0         for (uint32_t si = 0; si < ns; si++) {
399 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
400 0           ShmHeader *hdr = sh->hdr;
401 0           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
402 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
403 0           RDLOCK_GUARD(hdr);
404 0 0         EXTEND(SP, hdr->size);
405 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
406 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    0          
    0          
    0          
407 0 0         mXPUSHi(nodes[i].value);
408             }
409             }
410              
411             void
412             items(SV* self_sv)
413             PPCODE:
414 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
415 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
416 0 0         for (uint32_t si = 0; si < ns; si++) {
417 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
418 0           ShmHeader *hdr = sh->hdr;
419 0           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
420 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
421 0           RDLOCK_GUARD(hdr);
422 0 0         EXTEND(SP, hdr->size * 2);
423 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
424 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
425             char _ib[SHM_INLINE_MAX]; uint32_t klen;
426 0           const char *kp = shm_str_ptr(nodes[i].key_off, nodes[i].key_len, sh->arena, _ib, &klen);
427 0           SV* sv = newSVpvn(kp, klen);
428 0 0         if (SHM_UNPACK_UTF8(nodes[i].key_len)) SvUTF8_on(sv);
429 0 0         mXPUSHs(sv);
430 0 0         mXPUSHi(nodes[i].value);
431             }
432             }
433             }
434            
435              
436             void
437             each(SV* self_sv)
438             PPCODE:
439 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
440             const char *out_key; uint32_t out_klen; bool out_kutf8;
441             int32_t out_value;
442 0 0         if (shm_si32_each(h, &out_key, &out_klen, &out_kutf8, &out_value)) {
443 0 0         EXTEND(SP, 2);
444 0           SV* ksv = newSVpvn(out_key, out_klen);
445 0 0         if (out_kutf8) SvUTF8_on(ksv);
446 0 0         mXPUSHs(ksv);
447 0 0         mXPUSHi(out_value);
448 0           XSRETURN(2);
449             }
450 0           shm_si32_flush_deferred(h);
451 0           XSRETURN_EMPTY;
452              
453             void
454             iter_reset(SV* self_sv)
455             CODE:
456 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
457 0           shm_si32_iter_reset(h);
458 0           shm_si32_flush_deferred(h);
459              
460             void
461             clear(SV* self_sv)
462             CODE:
463 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
464 0           shm_si32_clear(h);
465              
466             SV*
467             to_hash(SV* self_sv)
468             CODE:
469 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
470 1           HV* hv = newHV();
471 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
472 2 100         for (uint32_t si = 0; si < ns; si++) {
473 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
474 1           ShmHeader *hdr = sh->hdr;
475 1           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
476 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
477 1           RDLOCK_GUARD(hdr);
478 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
479 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
480             char _ib[SHM_INLINE_MAX]; uint32_t klen;
481 13           const char *kp = shm_str_ptr(nodes[i].key_off, nodes[i].key_len, sh->arena, _ib, &klen);
482 13           bool kutf8 = SHM_UNPACK_UTF8(nodes[i].key_len);
483 13           SV* val = newSViv(nodes[i].value);
484 13 50         if (!hv_store(hv, kp,
    50          
485 0           kutf8 ? -(I32)klen : (I32)klen, val, 0)) SvREFCNT_dec(val);
486             }
487             }
488             }
489            
490 1           RETVAL = newRV_noinc((SV*)hv);
491             OUTPUT:
492             RETVAL
493              
494             SV*
495             get_or_set(SV* self_sv, SV* key_sv, int32_t default_value)
496             CODE:
497 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
498 0 0         EXTRACT_STR_KEY(key_sv);
499             int32_t out;
500 0           int rc = shm_si32_get_or_set(h, _kstr, (uint32_t)_klen, _kutf8, default_value, &out);
501 0 0         if (!rc) XSRETURN_UNDEF;
502 0           RETVAL = newSViv(out);
503             OUTPUT:
504             RETVAL
505              
506             SV*
507             take(SV* self_sv, SV* key_sv)
508             CODE:
509 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
510 0 0         EXTRACT_STR_KEY(key_sv);
511             int32_t out_value;
512 0 0         if (!shm_si32_take(h, _kstr, (uint32_t)_klen, _kutf8, &out_value)) XSRETURN_UNDEF;
513 0           RETVAL = newSViv(out_value);
514             OUTPUT:
515             RETVAL
516              
517             void
518             pop(SV* self_sv)
519             PPCODE:
520 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
521             const char *out_key; uint32_t out_klen; bool out_kutf8;
522             int32_t out_val;
523 0 0         if (!shm_si32_pop(h, &out_key, &out_klen, &out_kutf8, &out_val)) XSRETURN_EMPTY;
524 0 0         EXTEND(SP, 2);
525 0           SV *ksv = newSVpvn(out_key, out_klen);
526 0 0         if (out_kutf8) SvUTF8_on(ksv);
527 0           mPUSHs(ksv);
528 0           mPUSHi(out_val);
529              
530             void
531             shift(SV* self_sv)
532             PPCODE:
533 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
534             const char *out_key; uint32_t out_klen; bool out_kutf8;
535             int32_t out_val;
536 0 0         if (!shm_si32_shift(h, &out_key, &out_klen, &out_kutf8, &out_val)) XSRETURN_EMPTY;
537 0 0         EXTEND(SP, 2);
538 0           SV *ksv = newSVpvn(out_key, out_klen);
539 0 0         if (out_kutf8) SvUTF8_on(ksv);
540 0           mPUSHs(ksv);
541 0           mPUSHi(out_val);
542              
543             void
544             drain(SV* self_sv, UV limit)
545             PPCODE:
546 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
547 0 0         if (limit == 0) XSRETURN_EMPTY;
548             shm_si32_drain_entry *entries;
549 0 0         Newxz(entries, limit, shm_si32_drain_entry);
550            
551 0           SAVEFREEPV(entries);
552 0           char *buf = NULL; uint32_t buf_cap = 0;
553 0           uint32_t n = shm_si32_drain(h, (uint32_t)limit, entries, &buf, &buf_cap);
554            
555 0 0         EXTEND(SP, n * 2);
556 0 0         for (uint32_t i = 0; i < n; i++) {
557 0           SV *ksv = newSVpvn(buf + entries[i].key_off, entries[i].key_len);
558 0 0         if (entries[i].key_utf8) SvUTF8_on(ksv);
559 0           mPUSHs(ksv);
560 0           mPUSHi(entries[i].value);
561             }
562 0 0         if (buf) free(buf);
563            
564              
565             UV
566             flush_expired(SV* self_sv)
567             CODE:
568 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
569 0 0         RETVAL = (UV)shm_si32_flush_expired(h);
570             OUTPUT:
571             RETVAL
572              
573             void
574             flush_expired_partial(SV* self_sv, UV limit)
575             PPCODE:
576 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
577 0           int done = 0;
578 0           uint32_t flushed = shm_si32_flush_expired_partial(h, (uint32_t)limit, &done);
579 0 0         EXTEND(SP, 2);
580 0           mPUSHu(flushed);
581 0           mPUSHi(done);
582              
583             UV
584             mmap_size(SV* self_sv)
585             CODE:
586 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
587 0           RETVAL = (UV)shm_si32_mmap_size(h);
588             OUTPUT:
589             RETVAL
590              
591             bool
592             touch(SV* self_sv, SV* key_sv)
593             CODE:
594 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
595 0 0         EXTRACT_STR_KEY(key_sv);
596 0 0         RETVAL = shm_si32_touch(h, _kstr, (uint32_t)_klen, _kutf8);
597             OUTPUT:
598             RETVAL
599              
600             bool
601             reserve(SV* self_sv, UV target)
602             CODE:
603 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
604 0 0         RETVAL = shm_si32_reserve(h, (uint32_t)target);
605             OUTPUT:
606             RETVAL
607              
608             UV
609             stat_evictions(SV* self_sv)
610             CODE:
611 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
612 0           RETVAL = (UV)shm_si32_stat_evictions(h);
613             OUTPUT:
614             RETVAL
615              
616             UV
617             stat_expired(SV* self_sv)
618             CODE:
619 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
620 0           RETVAL = (UV)shm_si32_stat_expired(h);
621             OUTPUT:
622             RETVAL
623              
624             UV
625             stat_recoveries(SV* self_sv)
626             CODE:
627 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
628 0 0         RETVAL = (UV)shm_si32_stat_recoveries(h);
629             OUTPUT:
630             RETVAL
631              
632             UV
633             arena_used(SV* self_sv)
634             CODE:
635 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
636 0           RETVAL = (UV)shm_si32_arena_used(h);
637             OUTPUT:
638             RETVAL
639              
640             UV
641             arena_cap(SV* self_sv)
642             CODE:
643 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
644 0           RETVAL = (UV)shm_si32_arena_cap(h);
645             OUTPUT:
646             RETVAL
647              
648             bool
649             add(SV* self_sv, SV* key_sv, int32_t value)
650             CODE:
651 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
652 2 50         EXTRACT_STR_KEY(key_sv);
653 2 100         RETVAL = shm_si32_add(h, _kstr, (uint32_t)_klen, _kutf8, value);
654             OUTPUT:
655             RETVAL
656              
657             bool
658             add_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl_sec)
659             CODE:
660 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
661 2 50         EXTRACT_STR_KEY(key_sv);
662 2 50         REQUIRE_TTL(h);
    50          
663 2 100         RETVAL = shm_si32_add_ttl(h, _kstr, (uint32_t)_klen, _kutf8, value, (uint32_t)ttl_sec);
664             OUTPUT:
665             RETVAL
666              
667             bool
668             update(SV* self_sv, SV* key_sv, int32_t value)
669             CODE:
670 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
671 1 50         EXTRACT_STR_KEY(key_sv);
672 1 50         RETVAL = shm_si32_update(h, _kstr, (uint32_t)_klen, _kutf8, value);
673             OUTPUT:
674             RETVAL
675              
676             bool
677             update_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl_sec)
678             CODE:
679 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
680 0 0         EXTRACT_STR_KEY(key_sv);
681 0 0         REQUIRE_TTL(h);
    0          
682 0 0         RETVAL = shm_si32_update_ttl(h, _kstr, (uint32_t)_klen, _kutf8, value, (uint32_t)ttl_sec);
683             OUTPUT:
684             RETVAL
685              
686             SV*
687             swap(SV* self_sv, SV* key_sv, int32_t value)
688             CODE:
689 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
690 1 50         EXTRACT_STR_KEY(key_sv);
691             int32_t out_value;
692 1           int rc = shm_si32_swap(h, _kstr, (uint32_t)_klen, _kutf8, value, &out_value);
693 1 50         if (rc != 1) XSRETURN_UNDEF;
694 1           RETVAL = newSViv(out_value);
695             OUTPUT:
696             RETVAL
697              
698             SV*
699             path(SV* self_sv)
700             CODE:
701 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
702 0 0         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
703             OUTPUT:
704             RETVAL
705              
706             bool
707             unlink(SV* self_or_class, ...)
708             CODE:
709             const char *p;
710 0 0         if (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) {
    0          
711 0           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)));
712 0 0         if (!h) croak("Attempted to use a destroyed Data::HashMap::Shared::SI32 object");
713 0           p = h->path;
714             } else {
715 0 0         if (items < 2) croak("Usage: Data::HashMap::Shared::SI32->unlink($path)");
716 0           p = SvPV_nolen(ST(1));
717             }
718 0 0         RETVAL = (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) ?
    0          
719 0 0         shm_unlink_sharded(INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)))) :
720 0           shm_unlink_path(p);
721             OUTPUT:
722             RETVAL
723              
724             SV*
725             ttl_remaining(SV* self_sv, SV* key_sv)
726             CODE:
727 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
728 2 50         EXTRACT_STR_KEY(key_sv);
729 2           int64_t remaining = shm_si32_ttl_remaining(h, _kstr, (uint32_t)_klen, _kutf8);
730 2 50         if (remaining < 0) XSRETURN_UNDEF;
731 2           RETVAL = newSViv(remaining);
732             OUTPUT:
733             RETVAL
734              
735             UV
736             capacity(SV* self_sv)
737             CODE:
738 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
739 0 0         RETVAL = (UV)shm_si32_capacity(h);
740             OUTPUT:
741             RETVAL
742              
743             UV
744             tombstones(SV* self_sv)
745             CODE:
746 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
747 0 0         RETVAL = (UV)shm_si32_tombstones(h);
748             OUTPUT:
749             RETVAL
750              
751             SV*
752             cursor(SV* self_sv)
753             CODE:
754 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
755 0           ShmCursor* c = shm_cursor_create(h);
756 0 0         if (!c) croak("Failed to allocate cursor");
757 0           RETVAL = sv_setref_pv(newSV(0), "Data::HashMap::Shared::SI32::Cursor", (void*)c);
758             OUTPUT:
759             RETVAL
760              
761             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::SI32::Cursor
762             PROTOTYPES: DISABLE
763              
764             void
765             DESTROY(SV* self_sv)
766             CODE:
767 0 0         if (!SvROK(self_sv)) return;
768 0           ShmCursor* c = INT2PTR(ShmCursor*, SvIV(SvRV(self_sv)));
769 0 0         if (!c) return;
770 0           ShmHandle* h = c->current;
771 0           shm_cursor_destroy(c);
772 0 0         if (h) shm_si32_flush_deferred(h);
773 0           sv_setiv(SvRV(self_sv), 0);
774              
775             void
776             next(SV* self_sv)
777             PPCODE:
778 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::SI32::Cursor", self_sv);
    0          
    0          
779             const char *out_key; uint32_t out_klen; bool out_kutf8;
780             int32_t out_value;
781 0 0         if (shm_si32_cursor_next(c, &out_key, &out_klen, &out_kutf8, &out_value)) {
782 0 0         EXTEND(SP, 2);
783 0           SV* ksv = newSVpvn(out_key, out_klen);
784 0 0         if (out_kutf8) SvUTF8_on(ksv);
785 0 0         mXPUSHs(ksv);
786 0 0         mXPUSHi(out_value);
787 0           XSRETURN(2);
788             }
789 0           XSRETURN_EMPTY;
790              
791             void
792             reset(SV* self_sv)
793             CODE:
794 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::SI32::Cursor", self_sv);
    0          
    0          
795 0           shm_si32_cursor_reset(c);
796              
797             bool
798             seek(SV* self_sv, SV* key_sv)
799             CODE:
800 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::SI32::Cursor", self_sv);
    0          
    0          
801 0 0         EXTRACT_STR_KEY(key_sv);
802 0 0         RETVAL = shm_si32_cursor_seek(c, _kstr, (uint32_t)_klen, _kutf8);
803             OUTPUT:
804             RETVAL
805