File Coverage

xs/i16.xs
Criterion Covered Total %
statement 85 330 25.7
branch 113 660 17.1
condition n/a
subroutine n/a
pod n/a
total 198 990 20.0


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