File Coverage

xs/is.xs
Criterion Covered Total %
statement 60 363 16.5
branch 84 692 12.1
condition n/a
subroutine n/a
pod n/a
total 144 1055 13.6


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::IS
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 7 100         char errbuf[SHM_ERR_BUFLEN]; const char* path = SvOK(path_sv) ? SvPV_nolen(path_sv) : NULL; ShmHandle* map = shm_is_create(path, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
8 7 50         if (!map) croak("HashMap::Shared::IS: %s", errbuf[0] ? errbuf : "unknown error");
    0          
9 7           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_is_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::IS: %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_is_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::IS: %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_is_open_fd(fd, errbuf);
39 0 0         if (!map) croak("Data::HashMap::Shared::IS: %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::IS", 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::IS", self_sv);
    0          
    0          
57 0 0         if (shm_msync(h) != 0) croak("Data::HashMap::Shared::IS sync: %s", strerror(errno));
58              
59             void
60             DESTROY(SV* self_sv)
61             CODE:
62 7 50         if (!SvROK(self_sv)) return;
63 7           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_sv)));
64 7 50         if (!h) return;
65 7           sv_setiv(SvRV(self_sv), 0);
66 7           shm_close_map(h);
67              
68             bool
69             put(SV* self_sv, int64_t key, SV* value)
70             CODE:
71 12 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
72 12 50         EXTRACT_STR_VAL(value);
73 12 50         RETVAL = shm_is_put(h, key, _vstr, (uint32_t)_vlen, _vutf8);
74             OUTPUT:
75             RETVAL
76              
77             UV
78             set_multi(SV* self_sv, ...)
79             CODE:
80 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", 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 _vl; const char *_vs = SvPV(ST(i+1), _vl);
86 0           bool _vu = SvUTF8(ST(i+1)) ? 1 : 0;
87 0           count += shm_is_put(h, (int64_t)SvIV(ST(i)), _vs, (uint32_t)_vl, _vu);
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 _vl; const char *_vs = SvPV(ST(i+1), _vl);
95 0           bool _vu = SvUTF8(ST(i+1)) ? 1 : 0;
96 0 0         if (_vl > SHM_MAX_STR_LEN) { shm_seqlock_write_end(&hdr->seq); shm_rwlock_wrunlock(hdr); croak("value too long"); }
97 0           count += shm_is_put_inner(h, (int64_t)SvIV(ST(i)), _vs, (uint32_t)_vl, _vu, 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::IS", 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           count += shm_is_remove(h, (int64_t)SvIV(ST(i)));
114             } else {
115 0           ShmHeader *hdr = h->hdr;
116 0           shm_rwlock_wrlock(hdr);
117 0           shm_seqlock_write_begin(&hdr->seq);
118 0 0         for (int i = 1; i < items; i++)
119 0           count += shm_is_remove_inner(h, (int64_t)SvIV(ST(i)));
120 0 0         if (count) shm_is_maybe_shrink(h);
121 0           shm_seqlock_write_end(&hdr->seq);
122 0           shm_rwlock_wrunlock(hdr);
123             }
124 0 0         RETVAL = count;
125             OUTPUT:
126             RETVAL
127              
128             void
129             get_multi(SV* self_sv, ...)
130             PPCODE:
131 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
132 0           int nkeys = items - 1;
133 0 0         if (nkeys == 0) XSRETURN_EMPTY;
134 0 0         EXTEND(SP, nkeys);
    0          
135 0 0         if (h->shard_handles) {
136 0 0         for (int i = 0; i < nkeys; i++) {
137 0           int64_t key = (int64_t)SvIV(ST(i + 1));
138             const char *out_s; uint32_t out_l; bool out_u;
139 0 0         if (shm_is_get(h, key, &out_s, &out_l, &out_u)) {
140 0           SV *sv = newSVpvn(out_s, out_l);
141 0 0         if (out_u) SvUTF8_on(sv);
142 0           mPUSHs(sv);
143 0           } else PUSHs(&PL_sv_undef);
144             }
145             } else {
146 0           ShmHeader *hdr = h->hdr;
147 0           ShmNodeIS *nodes = (ShmNodeIS *)h->nodes;
148 0           uint8_t *states = h->states;
149 0           char *arena = h->arena;
150 0 0         uint32_t now = h->expires_at ? shm_now() : 0;
151             /* Phase 1: compute hashes and prefetch first probe positions */
152 0           uint32_t *hashes = NULL;
153 0           Newx(hashes, nkeys, uint32_t);
154 0           SAVEFREEPV(hashes);
155 0           RDLOCK_GUARD(hdr);
156 0           uint32_t mask = hdr->table_cap - 1;
157 0 0         for (int i = 0; i < nkeys; i++) {
158 0           hashes[i] = shm_hash_int64((int64_t)SvIV(ST(i + 1)));
159 0           __builtin_prefetch(&states[hashes[i] & mask], 0, 0);
160 0           __builtin_prefetch(&nodes[hashes[i] & mask], 0, 0);
161             }
162             /* Phase 2: probe each key */
163 0 0         for (int i = 0; i < nkeys; i++) {
164 0           int64_t key = (int64_t)SvIV(ST(i + 1));
165 0           uint32_t hash = hashes[i];
166 0           uint32_t pos = hash & mask;
167 0           uint8_t tag = SHM_MAKE_TAG(hash);
168 0           int found = 0;
169 0           uint32_t vidx = 0;
170 0 0         for (uint32_t j = 0; j <= mask; j++) {
171 0           uint32_t idx = (pos + j) & mask;
172 0           uint8_t st = states[idx];
173 0 0         if (st == SHM_EMPTY) break;
174 0 0         if (st != tag) continue;
175 0 0         if (nodes[idx].key == key) {
176 0 0         if (h->expires_at && h->expires_at[idx] && now >= h->expires_at[idx]) break;
    0          
    0          
177 0           vidx = idx; found = 1; break;
178             }
179             }
180 0 0         if (found) {
181             char _vib[SHM_INLINE_MAX]; uint32_t vl;
182 0           const char *vp = shm_str_ptr(nodes[vidx].val_off, nodes[vidx].val_len, arena, _vib, &vl);
183 0           SV *sv = newSVpvn(vp, vl);
184 0 0         if (SHM_UNPACK_UTF8(nodes[vidx].val_len)) SvUTF8_on(sv);
185 0           mPUSHs(sv);
186 0           } else PUSHs(&PL_sv_undef);
187             /* Prefetch next key's probe position */
188 0 0         if (i + 1 < nkeys) {
189 0           uint32_t npos = hashes[i + 1] & mask;
190 0           __builtin_prefetch(&states[npos], 0, 0);
191 0           __builtin_prefetch(&nodes[npos], 0, 0);
192             }
193             }
194             }
195              
196             void
197             get_with_ttl(SV* self_sv, int64_t key)
198             PPCODE:
199 3 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
200             const char *out_s; uint32_t out_l; bool out_u;
201             int64_t out_ttl;
202 3 50         if (!shm_is_get_with_ttl(h, key, &out_s, &out_l, &out_u, &out_ttl)) XSRETURN_EMPTY;
203 3 50         EXTEND(SP, 2);
204 3           SV *vsv = newSVpvn(out_s, out_l);
205 3 50         if (out_u) SvUTF8_on(vsv);
206 3           mPUSHs(vsv);
207 3 50         if (out_ttl < 0) PUSHs(&PL_sv_undef);
208 3           else mPUSHi(out_ttl);
209              
210             SV*
211             stats(SV* self_sv)
212             CODE:
213 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
214 0           HV *hv = newHV();
215 0           hv_store(hv, "size", 4, newSVuv(shm_is_size(h)), 0);
216 0           hv_store(hv, "capacity", 8, newSVuv(shm_is_capacity(h)), 0);
217 0           hv_store(hv, "max_entries", 11, newSVuv(shm_is_max_entries(h)), 0);
218 0           hv_store(hv, "tombstones", 10, newSVuv(shm_is_tombstones(h)), 0);
219 0           hv_store(hv, "mmap_size", 9, newSVuv(shm_is_mmap_size(h)), 0);
220 0           hv_store(hv, "arena_used", 10, newSVuv(shm_is_arena_used(h)), 0);
221 0           hv_store(hv, "arena_cap", 9, newSVuv(shm_is_arena_cap(h)), 0);
222 0           hv_store(hv, "evictions", 9, newSVuv(shm_is_stat_evictions(h)), 0);
223 0           hv_store(hv, "expired", 7, newSVuv(shm_is_stat_expired(h)), 0);
224 0           hv_store(hv, "recoveries", 10, newSVuv(shm_is_stat_recoveries(h)), 0);
225 0           hv_store(hv, "max_size", 8, newSVuv(shm_is_max_size(h)), 0);
226 0           hv_store(hv, "ttl", 3, newSVuv(shm_is_ttl(h)), 0);
227 0           RETVAL = newRV_noinc((SV*)hv);
228             OUTPUT:
229             RETVAL
230              
231             bool
232             persist(SV* self_sv, int64_t key)
233             CODE:
234 2 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
235 2 50         RETVAL = shm_is_persist(h, key);
236             OUTPUT:
237             RETVAL
238              
239             bool
240             set_ttl(SV* self_sv, int64_t key, UV ttl_sec)
241             CODE:
242 1 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
243 1 50         RETVAL = shm_is_set_ttl(h, key, (uint32_t)ttl_sec);
244             OUTPUT:
245             RETVAL
246              
247             bool
248             put_ttl(SV* self_sv, int64_t key, SV* value, UV ttl_sec)
249             CODE:
250 1 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
251 1 50         EXTRACT_STR_VAL(value);
252 1 50         REQUIRE_TTL(h);
    50          
253 1 50         RETVAL = shm_is_put_ttl(h, key, _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl_sec);
254             OUTPUT:
255             RETVAL
256              
257             UV
258             max_size(SV* self_sv)
259             CODE:
260 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
261 0 0         RETVAL = (UV)shm_is_max_size(h);
262             OUTPUT:
263             RETVAL
264              
265             UV
266             ttl(SV* self_sv)
267             CODE:
268 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
269 0 0         RETVAL = (UV)shm_is_ttl(h);
270             OUTPUT:
271             RETVAL
272              
273             SV*
274             get(SV* self_sv, int64_t key)
275             CODE:
276 13 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
277             const char* val; uint32_t val_len; bool val_utf8;
278 13 50         if (!shm_is_get(h, key, &val, &val_len, &val_utf8)) XSRETURN_UNDEF;
279 13           RETVAL = newSVpvn(val, val_len);
280 13 100         if (val_utf8) SvUTF8_on(RETVAL);
281             OUTPUT:
282             RETVAL
283              
284             bool
285             remove(SV* self_sv, int64_t key)
286             CODE:
287 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
288 0 0         RETVAL = shm_is_remove(h, key);
289             OUTPUT:
290             RETVAL
291              
292             bool
293             exists(SV* self_sv, int64_t key)
294             CODE:
295 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
296 0 0         RETVAL = shm_is_exists(h, key);
297             OUTPUT:
298             RETVAL
299              
300             UV
301             size(SV* self_sv)
302             CODE:
303 2 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
304 2 50         RETVAL = (UV)shm_is_size(h);
305             OUTPUT:
306             RETVAL
307              
308             UV
309             max_entries(SV* self_sv)
310             CODE:
311 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
312 0 0         RETVAL = (UV)shm_is_max_entries(h);
313             OUTPUT:
314             RETVAL
315              
316             void
317             keys(SV* self_sv)
318             PPCODE:
319 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
320 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
321 0 0         for (uint32_t si = 0; si < ns; si++) {
322 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
323 0           ShmHeader *hdr = sh->hdr;
324 0           ShmNodeIS *nodes = (ShmNodeIS *)sh->nodes;
325 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
326 0           RDLOCK_GUARD(hdr);
327 0 0         EXTEND(SP, hdr->size);
328 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
329 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    0          
    0          
    0          
330 0 0         mXPUSHi(nodes[i].key);
331             }
332             }
333              
334             void
335             values(SV* self_sv)
336             PPCODE:
337 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
338 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
339 0 0         for (uint32_t si = 0; si < ns; si++) {
340 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
341 0           ShmHeader *hdr = sh->hdr;
342 0           ShmNodeIS *nodes = (ShmNodeIS *)sh->nodes;
343 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
344 0           RDLOCK_GUARD(hdr);
345 0 0         EXTEND(SP, hdr->size);
346 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
347 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
348             char _ib[SHM_INLINE_MAX]; uint32_t vlen;
349 0           const char *vp = shm_str_ptr(nodes[i].val_off, nodes[i].val_len, sh->arena, _ib, &vlen);
350 0           SV* sv = newSVpvn(vp, vlen);
351 0 0         if (SHM_UNPACK_UTF8(nodes[i].val_len)) SvUTF8_on(sv);
352 0 0         mXPUSHs(sv);
353             }
354             }
355             }
356              
357             void
358             items(SV* self_sv)
359             PPCODE:
360 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
361 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
362 0 0         for (uint32_t si = 0; si < ns; si++) {
363 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
364 0           ShmHeader *hdr = sh->hdr;
365 0           ShmNodeIS *nodes = (ShmNodeIS *)sh->nodes;
366 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
367 0           RDLOCK_GUARD(hdr);
368 0 0         EXTEND(SP, hdr->size * 2);
369 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
370 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
371 0 0         mXPUSHi(nodes[i].key);
372             char _ib[SHM_INLINE_MAX]; uint32_t vlen;
373 0           const char *vp = shm_str_ptr(nodes[i].val_off, nodes[i].val_len, sh->arena, _ib, &vlen);
374 0           SV* sv = newSVpvn(vp, vlen);
375 0 0         if (SHM_UNPACK_UTF8(nodes[i].val_len)) SvUTF8_on(sv);
376 0 0         mXPUSHs(sv);
377             }
378             }
379             }
380            
381              
382             void
383             each(SV* self_sv)
384             PPCODE:
385 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
386             int64_t out_key;
387             const char *out_val; uint32_t out_vlen; bool out_vutf8;
388 0 0         if (shm_is_each(h, &out_key, &out_val, &out_vlen, &out_vutf8)) {
389 0 0         EXTEND(SP, 2);
390 0 0         mXPUSHi(out_key);
391 0           SV* sv = newSVpvn(out_val, out_vlen);
392 0 0         if (out_vutf8) SvUTF8_on(sv);
393 0 0         mXPUSHs(sv);
394 0           XSRETURN(2);
395             }
396 0           shm_is_flush_deferred(h);
397 0           XSRETURN_EMPTY;
398              
399             void
400             iter_reset(SV* self_sv)
401             CODE:
402 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
403 0           shm_is_iter_reset(h);
404 0           shm_is_flush_deferred(h);
405              
406             void
407             clear(SV* self_sv)
408             CODE:
409 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
410 0           shm_is_clear(h);
411              
412             SV*
413             to_hash(SV* self_sv)
414             CODE:
415 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
416 0           HV* hv = newHV();
417 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
418 0 0         for (uint32_t si = 0; si < ns; si++) {
419 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
420 0           ShmHeader *hdr = sh->hdr;
421 0           ShmNodeIS *nodes = (ShmNodeIS *)sh->nodes;
422 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
423 0           RDLOCK_GUARD(hdr);
424 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
425 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
426             char _ib[SHM_INLINE_MAX]; uint32_t vlen;
427 0           const char *vp = shm_str_ptr(nodes[i].val_off, nodes[i].val_len, sh->arena, _ib, &vlen);
428 0           SV* val = newSVpvn(vp, vlen);
429 0 0         if (SHM_UNPACK_UTF8(nodes[i].val_len)) SvUTF8_on(val);
430             char kbuf[24];
431 0           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)nodes[i].key);
432 0 0         if (!hv_store(hv, kbuf, klen, val, 0)) SvREFCNT_dec(val);
433             }
434             }
435             }
436            
437 0           RETVAL = newRV_noinc((SV*)hv);
438             OUTPUT:
439             RETVAL
440              
441             SV*
442             get_or_set(SV* self_sv, int64_t key, SV* default_sv)
443             CODE:
444 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
445             const char *out_str; uint32_t out_len; bool out_utf8;
446 0 0         EXTRACT_STR_VAL(default_sv);
447 0           int rc = shm_is_get_or_set(h, key, _vstr, (uint32_t)_vlen, _vutf8, &out_str, &out_len, &out_utf8);
448 0 0         if (!rc) XSRETURN_UNDEF;
449 0           RETVAL = newSVpvn(out_str, out_len);
450 0 0         if (out_utf8) SvUTF8_on(RETVAL);
451             OUTPUT:
452             RETVAL
453              
454             SV*
455             ttl_remaining(SV* self_sv, int64_t key)
456             CODE:
457 1 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
458 1           int64_t remaining = shm_is_ttl_remaining(h, key);
459 1 50         if (remaining < 0) XSRETURN_UNDEF;
460 1           RETVAL = newSViv(remaining);
461             OUTPUT:
462             RETVAL
463              
464             UV
465             capacity(SV* self_sv)
466             CODE:
467 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
468 0 0         RETVAL = (UV)shm_is_capacity(h);
469             OUTPUT:
470             RETVAL
471              
472             UV
473             tombstones(SV* self_sv)
474             CODE:
475 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
476 0 0         RETVAL = (UV)shm_is_tombstones(h);
477             OUTPUT:
478             RETVAL
479              
480             SV*
481             cursor(SV* self_sv)
482             CODE:
483 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
484 0           ShmCursor* c = shm_cursor_create(h);
485 0 0         if (!c) croak("Failed to allocate cursor");
486 0           RETVAL = sv_setref_pv(newSV(0), "Data::HashMap::Shared::IS::Cursor", (void*)c);
487             OUTPUT:
488             RETVAL
489              
490             SV*
491             take(SV* self_sv, int64_t key)
492             CODE:
493 1 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
494             const char *out_str; uint32_t out_len; bool out_utf8;
495 1 50         if (!shm_is_take(h, key, &out_str, &out_len, &out_utf8)) XSRETURN_UNDEF;
496 1           RETVAL = newSVpvn(out_str, out_len);
497 1 50         if (out_utf8) SvUTF8_on(RETVAL);
498             OUTPUT:
499             RETVAL
500              
501             void
502             pop(SV* self_sv)
503             PPCODE:
504 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
505             int64_t out_key;
506             const char *out_val; uint32_t out_vlen; bool out_vutf8;
507 0 0         if (!shm_is_pop(h, &out_key, &out_val, &out_vlen, &out_vutf8)) XSRETURN_EMPTY;
508 0 0         EXTEND(SP, 2);
509 0           mPUSHi(out_key);
510 0           SV *vsv = newSVpvn(out_val, out_vlen);
511 0 0         if (out_vutf8) SvUTF8_on(vsv);
512 0           mPUSHs(vsv);
513              
514             void
515             shift(SV* self_sv)
516             PPCODE:
517 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
518             int64_t out_key;
519             const char *out_val; uint32_t out_vlen; bool out_vutf8;
520 0 0         if (!shm_is_shift(h, &out_key, &out_val, &out_vlen, &out_vutf8)) XSRETURN_EMPTY;
521 0 0         EXTEND(SP, 2);
522 0           mPUSHi(out_key);
523 0           SV *vsv = newSVpvn(out_val, out_vlen);
524 0 0         if (out_vutf8) SvUTF8_on(vsv);
525 0           mPUSHs(vsv);
526              
527             void
528             drain(SV* self_sv, UV limit)
529             PPCODE:
530 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
531 0 0         if (limit == 0) XSRETURN_EMPTY;
532             shm_is_drain_entry *entries;
533 0 0         Newxz(entries, limit, shm_is_drain_entry);
534            
535 0           SAVEFREEPV(entries);
536 0           char *buf = NULL; uint32_t buf_cap = 0;
537 0           uint32_t n = shm_is_drain(h, (uint32_t)limit, entries, &buf, &buf_cap);
538            
539 0 0         EXTEND(SP, n * 2);
540 0 0         for (uint32_t i = 0; i < n; i++) {
541 0           mPUSHi(entries[i].key);
542 0           SV *vsv = newSVpvn(buf + entries[i].val_off, entries[i].val_len);
543 0 0         if (entries[i].val_utf8) SvUTF8_on(vsv);
544 0           mPUSHs(vsv);
545             }
546 0 0         if (buf) free(buf);
547            
548              
549             UV
550             flush_expired(SV* self_sv)
551             CODE:
552 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
553 0 0         RETVAL = (UV)shm_is_flush_expired(h);
554             OUTPUT:
555             RETVAL
556              
557             void
558             flush_expired_partial(SV* self_sv, UV limit)
559             PPCODE:
560 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
561 0           int done = 0;
562 0           uint32_t flushed = shm_is_flush_expired_partial(h, (uint32_t)limit, &done);
563 0 0         EXTEND(SP, 2);
564 0           mPUSHu(flushed);
565 0           mPUSHi(done);
566              
567             UV
568             mmap_size(SV* self_sv)
569             CODE:
570 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
571 0           RETVAL = (UV)shm_is_mmap_size(h);
572             OUTPUT:
573             RETVAL
574              
575             bool
576             touch(SV* self_sv, int64_t key)
577             CODE:
578 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
579 0 0         RETVAL = shm_is_touch(h, key);
580             OUTPUT:
581             RETVAL
582              
583             bool
584             reserve(SV* self_sv, UV target)
585             CODE:
586 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
587 0 0         RETVAL = shm_is_reserve(h, (uint32_t)target);
588             OUTPUT:
589             RETVAL
590              
591             UV
592             stat_evictions(SV* self_sv)
593             CODE:
594 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
595 0           RETVAL = (UV)shm_is_stat_evictions(h);
596             OUTPUT:
597             RETVAL
598              
599             UV
600             stat_expired(SV* self_sv)
601             CODE:
602 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
603 0           RETVAL = (UV)shm_is_stat_expired(h);
604             OUTPUT:
605             RETVAL
606              
607             UV
608             stat_recoveries(SV* self_sv)
609             CODE:
610 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
611 0 0         RETVAL = (UV)shm_is_stat_recoveries(h);
612             OUTPUT:
613             RETVAL
614              
615             UV
616             arena_used(SV* self_sv)
617             CODE:
618 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
619 0           RETVAL = (UV)shm_is_arena_used(h);
620             OUTPUT:
621             RETVAL
622              
623             UV
624             arena_cap(SV* self_sv)
625             CODE:
626 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
627 0           RETVAL = (UV)shm_is_arena_cap(h);
628             OUTPUT:
629             RETVAL
630              
631             bool
632             add(SV* self_sv, int64_t key, SV* val_sv)
633             CODE:
634 2 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
635 2 50         EXTRACT_STR_VAL(val_sv);
636 2 100         RETVAL = shm_is_add(h, key, _vstr, (uint32_t)_vlen, _vutf8);
637             OUTPUT:
638             RETVAL
639              
640             bool
641             add_ttl(SV* self_sv, int64_t key, SV* val_sv, UV ttl_sec)
642             CODE:
643 2 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
644 2 50         EXTRACT_STR_VAL(val_sv);
645 2 50         REQUIRE_TTL(h);
    50          
646 2 100         RETVAL = shm_is_add_ttl(h, key, _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl_sec);
647             OUTPUT:
648             RETVAL
649              
650             bool
651             update(SV* self_sv, int64_t key, SV* val_sv)
652             CODE:
653 1 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
654 1 50         EXTRACT_STR_VAL(val_sv);
655 1 50         RETVAL = shm_is_update(h, key, _vstr, (uint32_t)_vlen, _vutf8);
656             OUTPUT:
657             RETVAL
658              
659             bool
660             update_ttl(SV* self_sv, int64_t key, SV* val_sv, UV ttl_sec)
661             CODE:
662 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
663 0 0         EXTRACT_STR_VAL(val_sv);
664 0 0         REQUIRE_TTL(h);
    0          
665 0 0         RETVAL = shm_is_update_ttl(h, key, _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl_sec);
666             OUTPUT:
667             RETVAL
668              
669             SV*
670             swap(SV* self_sv, int64_t key, SV* val_sv)
671             CODE:
672 2 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
673 2 50         EXTRACT_STR_VAL(val_sv);
674             const char *out_s; uint32_t out_l; bool out_u;
675 2           int rc = shm_is_swap(h, key, _vstr, (uint32_t)_vlen, _vutf8, &out_s, &out_l, &out_u);
676 2 100         if (rc != 1) XSRETURN_UNDEF;
677 1           RETVAL = newSVpvn(out_s, out_l);
678 1 50         if (out_u) SvUTF8_on(RETVAL);
679             OUTPUT:
680             RETVAL
681              
682             bool
683             cas(SV* self_sv, int64_t key, SV* expected_sv, SV* desired_sv)
684             CODE:
685 6 50         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    50          
    50          
686 6 50         EXTRACT_STR_EXPECTED_DESIRED(expected_sv, desired_sv);
    50          
687 6 100         RETVAL = shm_is_cas(h, key, _estr, (uint32_t)_elen, _dstr, (uint32_t)_dlen, _dutf8);
688             OUTPUT:
689             RETVAL
690              
691             SV*
692             cas_take(SV* self_sv, int64_t key, SV* expected_sv)
693             CODE:
694 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
695 0 0         EXTRACT_STR_EXPECTED(expected_sv);
696             const char *out_s; uint32_t out_l; bool out_u;
697 0 0         if (!shm_is_cas_take(h, key, _estr, (uint32_t)_elen, &out_s, &out_l, &out_u)) XSRETURN_UNDEF;
698 0           RETVAL = newSVpvn(out_s, out_l);
699 0 0         if (out_u) SvUTF8_on(RETVAL);
700             OUTPUT:
701             RETVAL
702              
703             SV*
704             path(SV* self_sv)
705             CODE:
706 0 0         EXTRACT_MAP("Data::HashMap::Shared::IS", self_sv);
    0          
    0          
707 0 0         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
708             OUTPUT:
709             RETVAL
710              
711             bool
712             unlink(SV* self_or_class, ...)
713             CODE:
714             const char *p;
715 0 0         if (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) {
    0          
716 0           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)));
717 0 0         if (!h) croak("Attempted to use a destroyed Data::HashMap::Shared::IS object");
718 0           p = h->path;
719             } else {
720 0 0         if (items < 2) croak("Usage: Data::HashMap::Shared::IS->unlink($path)");
721 0           p = SvPV_nolen(ST(1));
722             }
723 0 0         RETVAL = (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) ?
    0          
724 0 0         shm_unlink_sharded(INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)))) :
725 0           shm_unlink_path(p);
726             OUTPUT:
727             RETVAL
728              
729             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::IS::Cursor
730             PROTOTYPES: DISABLE
731              
732             void
733             DESTROY(SV* self_sv)
734             CODE:
735 0 0         if (!SvROK(self_sv)) return;
736 0           ShmCursor* c = INT2PTR(ShmCursor*, SvIV(SvRV(self_sv)));
737 0 0         if (!c) return;
738 0           ShmHandle* h = c->current;
739 0           shm_cursor_destroy(c);
740 0 0         if (h) shm_is_flush_deferred(h);
741 0           sv_setiv(SvRV(self_sv), 0);
742              
743             void
744             next(SV* self_sv)
745             PPCODE:
746 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::IS::Cursor", self_sv);
    0          
    0          
747             int64_t out_key;
748             const char *out_val; uint32_t out_vlen; bool out_vutf8;
749 0 0         if (shm_is_cursor_next(c, &out_key, &out_val, &out_vlen, &out_vutf8)) {
750 0 0         EXTEND(SP, 2);
751 0 0         mXPUSHi(out_key);
752 0           SV* sv = newSVpvn(out_val, out_vlen);
753 0 0         if (out_vutf8) SvUTF8_on(sv);
754 0 0         mXPUSHs(sv);
755 0           XSRETURN(2);
756             }
757 0           XSRETURN_EMPTY;
758              
759             void
760             reset(SV* self_sv)
761             CODE:
762 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::IS::Cursor", self_sv);
    0          
    0          
763 0           shm_is_cursor_reset(c);
764              
765             bool
766             seek(SV* self_sv, int64_t key)
767             CODE:
768 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::IS::Cursor", self_sv);
    0          
    0          
769 0 0         RETVAL = shm_is_cursor_seek(c, key);
770             OUTPUT:
771             RETVAL
772