File Coverage

xs/i32s.xs
Criterion Covered Total %
statement 50 325 15.3
branch 54 610 8.8
condition n/a
subroutine n/a
pod n/a
total 104 935 11.1


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