File Coverage

xs/ii.xs
Criterion Covered Total %
statement 301 301 100.0
branch 360 600 60.0
condition n/a
subroutine n/a
pod n/a
total 661 901 73.3


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