File Coverage

xs/ii.xs
Criterion Covered Total %
statement 291 291 100.0
branch 343 570 60.1
condition n/a
subroutine n/a
pod n/a
total 634 861 73.6


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::II
2             PROTOTYPES: DISABLE
3              
4             SV*
5             new(char* class, char* path, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
6             CODE:
7 137           char errbuf[SHM_ERR_BUFLEN]; ShmHandle* map = shm_ii_create(path, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
8 137 100         if (!map) croak("HashMap::Shared::II: %s", errbuf[0] ? errbuf : "unknown error");
    50          
9 135           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 17           char errbuf[SHM_ERR_BUFLEN]; ShmHandle* map = shm_ii_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 17 50         if (!map) croak("HashMap::Shared::II: %s", errbuf[0] ? errbuf : "unknown error");
    0          
18 17           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
19             OUTPUT:
20             RETVAL
21              
22             void
23             DESTROY(SV* self_sv)
24             CODE:
25 152 50         if (!SvROK(self_sv)) return;
26 152           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_sv)));
27 152 50         if (!h) return;
28 152           shm_close_map(h);
29 152           sv_setiv(SvRV(self_sv), 0);
30              
31             bool
32             put(SV* self_sv, int64_t key, int64_t value)
33             CODE:
34 7205 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
35 7205 100         RETVAL = shm_ii_put(h, key, value);
36             OUTPUT:
37             RETVAL
38              
39             UV
40             set_multi(SV* self_sv, ...)
41             CODE:
42 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
43 6 100         if ((items - 1) % 2 != 0) croak("set_multi requires even number of arguments (key, value pairs)");
44 5           uint32_t count = 0;
45 5 100         if (h->shard_handles) {
46 6 100         for (int i = 1; i < items; i += 2)
47 5           count += shm_ii_put(h, (int64_t)SvIV(ST(i)), (int64_t)SvIV(ST(i + 1)));
48             } else {
49 4           ShmHeader *hdr = h->hdr;
50 4           shm_rwlock_wrlock(hdr);
51 4           shm_seqlock_write_begin(&hdr->seq);
52 1012 100         for (int i = 1; i < items; i += 2)
53 1008           count += shm_ii_put_inner(h, (int64_t)SvIV(ST(i)), (int64_t)SvIV(ST(i + 1)), SHM_TTL_USE_DEFAULT);
54 4           shm_seqlock_write_end(&hdr->seq);
55 4           shm_rwlock_wrunlock(hdr);
56             }
57 5 50         RETVAL = count;
58             OUTPUT:
59             RETVAL
60              
61             void
62             get_multi(SV* self_sv, ...)
63             PPCODE:
64 4 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
65 4           int nkeys = items - 1;
66 4 100         if (nkeys == 0) XSRETURN_EMPTY;
67 3 50         EXTEND(SP, nkeys);
    50          
68 3 100         if (h->shard_handles) {
69 5 100         for (int i = 0; i < nkeys; i++) {
70 4           int64_t key = (int64_t)SvIV(ST(i + 1));
71             int64_t val;
72 4 100         if (shm_ii_get(h, key, &val))
73 3           mPUSHi(val);
74             else
75 1           PUSHs(&PL_sv_undef);
76             }
77             } else {
78 2           ShmHeader *hdr = h->hdr;
79 2           ShmNodeII *nodes = (ShmNodeII *)h->nodes;
80 2           uint8_t *states = h->states;
81 2 100         uint32_t now = h->expires_at ? shm_now() : 0;
82             /* Phase 1: compute hashes and prefetch first probe positions */
83 2           uint32_t *hashes = NULL;
84 2           Newx(hashes, nkeys, uint32_t);
85 2           SAVEFREEPV(hashes);
86 2           RDLOCK_GUARD(hdr);
87 2           uint32_t mask = hdr->table_cap - 1;
88 9 100         for (int i = 0; i < nkeys; i++) {
89 7           hashes[i] = shm_hash_int64((int64_t)SvIV(ST(i + 1)));
90 7           __builtin_prefetch(&states[hashes[i] & mask], 0, 0);
91 7           __builtin_prefetch(&nodes[hashes[i] & mask], 0, 0);
92             }
93             /* Phase 2: probe each key */
94 9 100         for (int i = 0; i < nkeys; i++) {
95 7           int64_t key = (int64_t)SvIV(ST(i + 1));
96 7           uint32_t hash = hashes[i];
97 7           uint32_t pos = hash & mask;
98 7           uint8_t tag = SHM_MAKE_TAG(hash);
99 7           int found = 0;
100 7           int64_t val = 0;
101 9 50         for (uint32_t j = 0; j <= mask; j++) {
102 9           uint32_t idx = (pos + j) & mask;
103 9           uint8_t st = states[idx];
104 9 100         if (st == SHM_EMPTY) break;
105 8 100         if (st != tag) continue;
106 6 50         if (nodes[idx].key == key) {
107 6 100         if (h->expires_at && h->expires_at[idx] && now >= h->expires_at[idx]) break;
    50          
    100          
108 5           val = nodes[idx].value;
109 5           found = 1;
110 5           break;
111             }
112             }
113 7 100         if (found) mPUSHi(val);
114 2           else PUSHs(&PL_sv_undef);
115             /* Prefetch next key's probe position */
116 7 100         if (i + 1 < nkeys) {
117 5           uint32_t npos = hashes[i + 1] & mask;
118 5           __builtin_prefetch(&states[npos], 0, 0);
119 5           __builtin_prefetch(&nodes[npos], 0, 0);
120             }
121             }
122             }
123              
124             SV*
125             stats(SV* self_sv)
126             CODE:
127 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
128 2           HV *hv = newHV();
129 2           hv_store(hv, "size", 4, newSVuv(shm_ii_size(h)), 0);
130 2           hv_store(hv, "capacity", 8, newSVuv(shm_ii_capacity(h)), 0);
131 2           hv_store(hv, "max_entries", 11, newSVuv(shm_ii_max_entries(h)), 0);
132 2           hv_store(hv, "tombstones", 10, newSVuv(shm_ii_tombstones(h)), 0);
133 2           hv_store(hv, "mmap_size", 9, newSVuv(shm_ii_mmap_size(h)), 0);
134 2           hv_store(hv, "arena_used", 10, newSVuv(shm_ii_arena_used(h)), 0);
135 2           hv_store(hv, "arena_cap", 9, newSVuv(shm_ii_arena_cap(h)), 0);
136 2           hv_store(hv, "evictions", 9, newSVuv(shm_ii_stat_evictions(h)), 0);
137 2           hv_store(hv, "expired", 7, newSVuv(shm_ii_stat_expired(h)), 0);
138 2           hv_store(hv, "recoveries", 10, newSVuv(shm_ii_stat_recoveries(h)), 0);
139 2           hv_store(hv, "max_size", 8, newSVuv(shm_ii_max_size(h)), 0);
140 2           hv_store(hv, "ttl", 3, newSVuv(shm_ii_ttl(h)), 0);
141 2           RETVAL = newRV_noinc((SV*)hv);
142             OUTPUT:
143             RETVAL
144              
145             bool
146             cas(SV* self_sv, int64_t key, int64_t expected, int64_t desired)
147             CODE:
148 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
149 6 100         RETVAL = shm_ii_cas(h, key, expected, desired);
150             OUTPUT:
151             RETVAL
152              
153             bool
154             persist(SV* self_sv, int64_t key)
155             CODE:
156 4 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
157 4 100         RETVAL = shm_ii_persist(h, key);
158             OUTPUT:
159             RETVAL
160              
161             bool
162             set_ttl(SV* self_sv, int64_t key, UV ttl_sec)
163             CODE:
164 5 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
165 5 100         RETVAL = shm_ii_set_ttl(h, key, (uint32_t)ttl_sec);
166             OUTPUT:
167             RETVAL
168              
169             SV*
170             get(SV* self_sv, int64_t key)
171             CODE:
172 891 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
173             int64_t value;
174 891 100         if (!shm_ii_get(h, key, &value)) XSRETURN_UNDEF;
175 805           RETVAL = newSViv(value);
176             OUTPUT:
177             RETVAL
178              
179             bool
180             remove(SV* self_sv, int64_t key)
181             CODE:
182 2785 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
183 2785 50         RETVAL = shm_ii_remove(h, key);
184             OUTPUT:
185             RETVAL
186              
187             bool
188             exists(SV* self_sv, int64_t key)
189             CODE:
190 56 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
191 56 100         RETVAL = shm_ii_exists(h, key);
192             OUTPUT:
193             RETVAL
194              
195             SV*
196             incr(SV* self_sv, int64_t key)
197             CODE:
198 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
199             int ok;
200 8           int64_t val = shm_ii_incr_by(h, key, 1, &ok);
201 8 50         if (!ok) croak("HashMap::Shared::II: increment failed");
202 8           RETVAL = newSViv(val);
203             OUTPUT:
204             RETVAL
205              
206             SV*
207             decr(SV* self_sv, int64_t key)
208             CODE:
209 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
210             int ok;
211 3           int64_t val = shm_ii_incr_by(h, key, -1, &ok);
212 3 50         if (!ok) croak("HashMap::Shared::II: decrement failed");
213 3           RETVAL = newSViv(val);
214             OUTPUT:
215             RETVAL
216              
217             SV*
218             incr_by(SV* self_sv, int64_t key, int64_t delta)
219             CODE:
220 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
221             int ok;
222 6           int64_t val = shm_ii_incr_by(h, key, delta, &ok);
223 6 50         if (!ok) croak("HashMap::Shared::II: incr_by failed");
224 6           RETVAL = newSViv(val);
225             OUTPUT:
226             RETVAL
227              
228             UV
229             size(SV* self_sv)
230             CODE:
231 68 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
232 68 50         RETVAL = (UV)shm_ii_size(h);
233             OUTPUT:
234             RETVAL
235              
236             UV
237             max_entries(SV* self_sv)
238             CODE:
239 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
240 3 50         RETVAL = (UV)shm_ii_max_entries(h);
241             OUTPUT:
242             RETVAL
243              
244             void
245             keys(SV* self_sv)
246             PPCODE:
247 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
248 3 100         uint32_t ns = h->shard_handles ? h->num_shards : 1;
249 9 100         for (uint32_t si = 0; si < ns; si++) {
250 6 100         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
251 6           ShmHeader *hdr = sh->hdr;
252 6           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
253 6 100         uint32_t now = sh->expires_at ? shm_now() : 0;
254 6           RDLOCK_GUARD(hdr);
255 6 50         EXTEND(SP, hdr->size);
256 134 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
257 128 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    100          
    50          
    100          
258 54 50         mXPUSHi(nodes[i].key);
259             }
260             }
261              
262             void
263             values(SV* self_sv)
264             PPCODE:
265 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
266 2 100         uint32_t ns = h->shard_handles ? h->num_shards : 1;
267 7 100         for (uint32_t si = 0; si < ns; si++) {
268 5 100         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
269 5           ShmHeader *hdr = sh->hdr;
270 5           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
271 5 50         uint32_t now = sh->expires_at ? shm_now() : 0;
272 5           RDLOCK_GUARD(hdr);
273 5 50         EXTEND(SP, hdr->size);
274 117 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
275 112 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    50          
    0          
    0          
276 53 50         mXPUSHi(nodes[i].value);
277             }
278             }
279              
280             void
281             items(SV* self_sv)
282             PPCODE:
283 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
284 2 100         uint32_t ns = h->shard_handles ? h->num_shards : 1;
285 7 100         for (uint32_t si = 0; si < ns; si++) {
286 5 100         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
287 5           ShmHeader *hdr = sh->hdr;
288 5           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
289 5 50         uint32_t now = sh->expires_at ? shm_now() : 0;
290 5           RDLOCK_GUARD(hdr);
291 5 50         EXTEND(SP, hdr->size * 2);
292 117 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
293 112 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
294 53 50         mXPUSHi(nodes[i].key);
295 53 50         mXPUSHi(nodes[i].value);
296             }
297             }
298             }
299            
300              
301             void
302             each(SV* self_sv)
303             PPCODE:
304 662 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
305             int64_t out_key, out_value;
306 662 100         if (shm_ii_each(h, &out_key, &out_value)) {
307 649 50         EXTEND(SP, 2);
308 649 50         mXPUSHi(out_key);
309 649 50         mXPUSHi(out_value);
310 649           XSRETURN(2);
311             }
312 13           shm_ii_flush_deferred(h);
313 13           XSRETURN_EMPTY;
314              
315             void
316             iter_reset(SV* self_sv)
317             CODE:
318 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
319 2           shm_ii_iter_reset(h);
320 2           shm_ii_flush_deferred(h);
321              
322             void
323             clear(SV* self_sv)
324             CODE:
325 7 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
326 7           shm_ii_clear(h);
327              
328             SV*
329             to_hash(SV* self_sv)
330             CODE:
331 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
332 2           HV* hv = newHV();
333 2 100         uint32_t ns = h->shard_handles ? h->num_shards : 1;
334 7 100         for (uint32_t si = 0; si < ns; si++) {
335 5 100         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
336 5           ShmHeader *hdr = sh->hdr;
337 5           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
338 5 50         uint32_t now = sh->expires_at ? shm_now() : 0;
339 5           RDLOCK_GUARD(hdr);
340 117 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
341 112 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
342 52           SV* val = newSViv(nodes[i].value);
343             char kbuf[24];
344 52           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)nodes[i].key);
345 52 50         if (!hv_store(hv, kbuf, klen, val, 0)) SvREFCNT_dec(val);
346             }
347             }
348             }
349            
350 2           RETVAL = newRV_noinc((SV*)hv);
351             OUTPUT:
352             RETVAL
353              
354             SV*
355             get_or_set(SV* self_sv, int64_t key, int64_t default_value)
356             CODE:
357 7 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
358             int64_t out;
359 7           int rc = shm_ii_get_or_set(h, key, default_value, &out);
360 7 50         if (!rc) XSRETURN_UNDEF;
361 7           RETVAL = newSViv(out);
362             OUTPUT:
363             RETVAL
364              
365             bool
366             put_ttl(SV* self_sv, int64_t key, int64_t value, UV ttl_sec)
367             CODE:
368 21 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
369 21 100         REQUIRE_TTL(h);
    100          
370 20 50         RETVAL = shm_ii_put_ttl(h, key, value, (uint32_t)ttl_sec);
371             OUTPUT:
372             RETVAL
373              
374             UV
375             max_size(SV* self_sv)
376             CODE:
377 5 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
378 5 50         RETVAL = (UV)shm_ii_max_size(h);
379             OUTPUT:
380             RETVAL
381              
382             UV
383             ttl(SV* self_sv)
384             CODE:
385 5 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
386 5 50         RETVAL = (UV)shm_ii_ttl(h);
387             OUTPUT:
388             RETVAL
389              
390             SV*
391             take(SV* self_sv, int64_t key)
392             CODE:
393 5 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
394             int64_t out_value;
395 5 100         if (!shm_ii_take(h, key, &out_value)) XSRETURN_UNDEF;
396 3           RETVAL = newSViv(out_value);
397             OUTPUT:
398             RETVAL
399              
400             void
401             pop(SV* self_sv)
402             PPCODE:
403 12 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
404             int64_t out_key;
405             int64_t out_val;
406 12 100         if (!shm_ii_pop(h, &out_key, &out_val)) XSRETURN_EMPTY;
407 10 50         EXTEND(SP, 2);
408 10           mPUSHi(out_key);
409 10           mPUSHi(out_val);
410              
411             void
412             shift(SV* self_sv)
413             PPCODE:
414 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
415             int64_t out_key;
416             int64_t out_val;
417 8 100         if (!shm_ii_shift(h, &out_key, &out_val)) XSRETURN_EMPTY;
418 7 50         EXTEND(SP, 2);
419 7           mPUSHi(out_key);
420 7           mPUSHi(out_val);
421              
422             void
423             drain(SV* self_sv, UV limit)
424             PPCODE:
425 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
426 6 50         if (limit == 0) XSRETURN_EMPTY;
427 6           shm_ii_drain_entry *entries = (shm_ii_drain_entry *)calloc(limit, sizeof(shm_ii_drain_entry));
428 6 50         if (!entries) croak("drain: out of memory");
429 6           SAVEFREEPV(entries);
430 6           char *buf = NULL; uint32_t buf_cap = 0;
431 6           uint32_t n = shm_ii_drain(h, (uint32_t)limit, entries, &buf, &buf_cap);
432 6 50         if (buf) SAVEFREEPV(buf);
433 6 50         EXTEND(SP, n * 2);
434 21 100         for (uint32_t i = 0; i < n; i++) {
435 15           mPUSHi(entries[i].key);
436 15           mPUSHi(entries[i].value);
437             }
438            
439              
440             UV
441             flush_expired(SV* self_sv)
442             CODE:
443 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
444 8 50         RETVAL = (UV)shm_ii_flush_expired(h);
445             OUTPUT:
446             RETVAL
447              
448             void
449             flush_expired_partial(SV* self_sv, UV limit)
450             PPCODE:
451 27 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
452 27           int done = 0;
453 27           uint32_t flushed = shm_ii_flush_expired_partial(h, (uint32_t)limit, &done);
454 27 50         EXTEND(SP, 2);
455 27           mPUSHu(flushed);
456 27           mPUSHi(done);
457              
458             UV
459             mmap_size(SV* self_sv)
460             CODE:
461 4 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
462 4           RETVAL = (UV)shm_ii_mmap_size(h);
463             OUTPUT:
464             RETVAL
465              
466             bool
467             touch(SV* self_sv, int64_t key)
468             CODE:
469 9 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
470 9 100         RETVAL = shm_ii_touch(h, key);
471             OUTPUT:
472             RETVAL
473              
474             bool
475             reserve(SV* self_sv, UV target)
476             CODE:
477 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
478 8 100         RETVAL = shm_ii_reserve(h, (uint32_t)target);
479             OUTPUT:
480             RETVAL
481              
482             UV
483             stat_evictions(SV* self_sv)
484             CODE:
485 11 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
486 11           RETVAL = (UV)shm_ii_stat_evictions(h);
487             OUTPUT:
488             RETVAL
489              
490             UV
491             stat_expired(SV* self_sv)
492             CODE:
493 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
494 6           RETVAL = (UV)shm_ii_stat_expired(h);
495             OUTPUT:
496             RETVAL
497              
498             UV
499             stat_recoveries(SV* self_sv)
500             CODE:
501 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
502 2 50         RETVAL = (UV)shm_ii_stat_recoveries(h);
503             OUTPUT:
504             RETVAL
505              
506             UV
507             arena_used(SV* self_sv)
508             CODE:
509 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
510 2           RETVAL = (UV)shm_ii_arena_used(h);
511             OUTPUT:
512             RETVAL
513              
514             UV
515             arena_cap(SV* self_sv)
516             CODE:
517 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
518 2           RETVAL = (UV)shm_ii_arena_cap(h);
519             OUTPUT:
520             RETVAL
521              
522             bool
523             add(SV* self_sv, int64_t key, int64_t value)
524             CODE:
525 11 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
526 11 100         RETVAL = shm_ii_add(h, key, value);
527             OUTPUT:
528             RETVAL
529              
530             bool
531             update(SV* self_sv, int64_t key, int64_t value)
532             CODE:
533 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
534 6 100         RETVAL = shm_ii_update(h, key, value);
535             OUTPUT:
536             RETVAL
537              
538             SV*
539             swap(SV* self_sv, int64_t key, int64_t value)
540             CODE:
541 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
542             int64_t out_value;
543 8           int rc = shm_ii_swap(h, key, value, &out_value);
544 8 100         if (rc != 1) XSRETURN_UNDEF;
545 5           RETVAL = newSViv(out_value);
546             OUTPUT:
547             RETVAL
548              
549             SV*
550             path(SV* self_sv)
551             CODE:
552 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
553 2           RETVAL = newSVpv(h->path, 0);
554             OUTPUT:
555             RETVAL
556              
557             bool
558             unlink(SV* self_or_class, ...)
559             CODE:
560             const char *p;
561 4 100         if (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) {
    50          
562 2           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)));
563 2 50         if (!h) croak("Attempted to use a destroyed Data::HashMap::Shared::II object");
564 2           p = h->path;
565             } else {
566 2 50         if (items < 2) croak("Usage: Data::HashMap::Shared::II->unlink($path)");
567 2           p = SvPV_nolen(ST(1));
568             }
569 6 50         RETVAL = (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) ?
    100          
570 8 100         shm_unlink_sharded(INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)))) :
571 2           shm_unlink_path(p);
572             OUTPUT:
573             RETVAL
574              
575             SV*
576             ttl_remaining(SV* self_sv, int64_t key)
577             CODE:
578 33 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
579 33           int64_t remaining = shm_ii_ttl_remaining(h, key);
580 33 100         if (remaining < 0) XSRETURN_UNDEF;
581 31           RETVAL = newSViv(remaining);
582             OUTPUT:
583             RETVAL
584              
585             UV
586             capacity(SV* self_sv)
587             CODE:
588 15 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
589 15 50         RETVAL = (UV)shm_ii_capacity(h);
590             OUTPUT:
591             RETVAL
592              
593             UV
594             tombstones(SV* self_sv)
595             CODE:
596 7 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
597 7 50         RETVAL = (UV)shm_ii_tombstones(h);
598             OUTPUT:
599             RETVAL
600              
601             SV*
602             cursor(SV* self_sv)
603             CODE:
604 18 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
605 18           ShmCursor* c = shm_cursor_create(h);
606 18 50         if (!c) croak("Failed to allocate cursor");
607 18           RETVAL = sv_setref_pv(newSV(0), "Data::HashMap::Shared::II::Cursor", (void*)c);
608             OUTPUT:
609             RETVAL
610              
611             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::II::Cursor
612             PROTOTYPES: DISABLE
613              
614             void
615             DESTROY(SV* self_sv)
616             CODE:
617 18 50         if (!SvROK(self_sv)) return;
618 18           ShmCursor* c = INT2PTR(ShmCursor*, SvIV(SvRV(self_sv)));
619 18 50         if (!c) return;
620 18           ShmHandle* h = c->current;
621 18           shm_cursor_destroy(c);
622 18 50         if (h) shm_ii_flush_deferred(h);
623 18           sv_setiv(SvRV(self_sv), 0);
624              
625             void
626             next(SV* self_sv)
627             PPCODE:
628 745 50         EXTRACT_CURSOR("Data::HashMap::Shared::II::Cursor", self_sv);
    50          
    50          
629             int64_t out_key; int64_t out_value;
630 745 100         if (shm_ii_cursor_next(c, &out_key, &out_value)) {
631 731 50         EXTEND(SP, 2);
632 731 50         mXPUSHi(out_key);
633 731 50         mXPUSHi(out_value);
634 731           XSRETURN(2);
635             }
636 14           XSRETURN_EMPTY;
637              
638             void
639             reset(SV* self_sv)
640             CODE:
641 2 50         EXTRACT_CURSOR("Data::HashMap::Shared::II::Cursor", self_sv);
    50          
    50          
642 2           shm_ii_cursor_reset(c);
643              
644             bool
645             seek(SV* self_sv, int64_t key)
646             CODE:
647 5 50         EXTRACT_CURSOR("Data::HashMap::Shared::II::Cursor", self_sv);
    50          
    50          
648 5 100         RETVAL = shm_ii_cursor_seek(c, key);
649             OUTPUT:
650             RETVAL
651