File Coverage

xs/i32s.xs
Criterion Covered Total %
statement 50 315 15.8
branch 53 580 9.1
condition n/a
subroutine n/a
pod n/a
total 103 895 11.5


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