Skip to content

Commit d11d594

Browse files
author
Rob Mueller
committed
WIP: Add version to each cache object
1 parent 0a82821 commit d11d594

File tree

6 files changed

+194
-49
lines changed

6 files changed

+194
-49
lines changed

FastMmap.xs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,17 @@ fc_is_locked(obj)
156156

157157

158158
void
159-
fc_read(obj, hash_slot, key)
159+
fc_read(obj, hash_slot, key, no_val)
160160
SV * obj;
161161
unsigned long hash_slot;
162162
SV * key;
163+
unsigned long no_val;
163164
INIT:
164165
int key_len, val_len, found;
165166
void * key_ptr, * val_ptr;
166167
MU64 expire_on = 0;
167168
MU64 flags = 0;
169+
MU64 version = 0;
168170
STRLEN pl_key_len;
169171
SV * val;
170172

@@ -177,15 +179,15 @@ fc_read(obj, hash_slot, key)
177179
key_len = (int)pl_key_len;
178180

179181
/* Get value data pointer */
180-
found = mmc_read(cache, (MU64)hash_slot, key_ptr, key_len, &val_ptr, &val_len, &expire_on, &flags);
182+
found = mmc_read(cache, (MU64)hash_slot, key_ptr, key_len, &val_ptr, &val_len, &expire_on, &version, &flags);
181183

182184
/* If not found, use undef */
183185
if (found == -1) {
184186
val = &PL_sv_undef;
185187
} else {
186188

187-
/* Cached an undef value? */
188-
if (flags & FC_UNDEF) {
189+
/* Cached an undef value or don't want the actual value? */
190+
if (flags & FC_UNDEF || no_val) {
189191
val = &PL_sv_undef;
190192

191193
} else {
@@ -206,15 +208,17 @@ fc_read(obj, hash_slot, key)
206208
XPUSHs(sv_2mortal(newSViv((IV)flags)));
207209
XPUSHs(sv_2mortal(newSViv((IV)!found)));
208210
XPUSHs(sv_2mortal(newSViv((IV)expire_on)));
211+
XPUSHs(sv_2mortal(newSViv((IV)version)));
209212

210213

211214
int
212-
fc_write(obj, hash_slot, key, val, expire_on, in_flags)
215+
fc_write(obj, hash_slot, key, val, expire_on, version, in_flags)
213216
SV * obj;
214217
unsigned long hash_slot;
215218
SV * key;
216219
SV * val;
217220
unsigned long expire_on;
221+
unsigned long version;
218222
unsigned long in_flags;
219223
INIT:
220224
int key_len, val_len;
@@ -252,7 +256,7 @@ fc_write(obj, hash_slot, key, val, expire_on, in_flags)
252256
}
253257

254258
/* Write value to cache */
255-
RETVAL = mmc_write(cache, (MU64)hash_slot, key_ptr, key_len, val_ptr, val_len, (MU64)expire_on, (MU64)in_flags);
259+
RETVAL = mmc_write(cache, (MU64)hash_slot, key_ptr, key_len, val_ptr, val_len, (MU64)expire_on, (MU64)version, (MU64)in_flags);
256260

257261
OUTPUT:
258262
RETVAL
@@ -263,7 +267,7 @@ fc_delete(obj, hash_slot, key)
263267
unsigned long hash_slot;
264268
SV * key;
265269
INIT:
266-
MU64 out_flags;
270+
MU64 flags, version;
267271
int key_len, did_delete;
268272
void * key_ptr;
269273
STRLEN pl_key_len;
@@ -277,10 +281,11 @@ fc_delete(obj, hash_slot, key)
277281
key_len = (int)pl_key_len;
278282

279283
/* Write value to cache */
280-
did_delete = mmc_delete(cache, (MU64)hash_slot, key_ptr, key_len, &out_flags);
284+
did_delete = mmc_delete(cache, (MU64)hash_slot, key_ptr, key_len, &flags, &version);
281285

282286
XPUSHs(sv_2mortal(newSViv((IV)did_delete)));
283-
XPUSHs(sv_2mortal(newSViv((IV)out_flags)));
287+
XPUSHs(sv_2mortal(newSViv((IV)flags)));
288+
XPUSHs(sv_2mortal(newSViv((IV)version)));
284289

285290

286291
void
@@ -321,7 +326,7 @@ fc_expunge(obj, mode, wb, len)
321326

322327
void * key_ptr, * val_ptr;
323328
int key_len, val_len;
324-
MU64 last_access, expire_on, flags;
329+
MU64 last_access, expire_on, version, flags;
325330

326331
FC_ENTRY
327332

@@ -336,7 +341,7 @@ fc_expunge(obj, mode, wb, len)
336341
for (item = 0; item < num_expunge; item++) {
337342
mmc_get_details(cache, to_expunge[item],
338343
&key_ptr, &key_len, &val_ptr, &val_len,
339-
&last_access, &expire_on, &flags);
344+
&last_access, &expire_on, &version, &flags);
340345

341346
{
342347
HV * ih = (HV *)sv_2mortal((SV *)newHV());
@@ -365,6 +370,7 @@ fc_expunge(obj, mode, wb, len)
365370
hv_store(ih, "value", 5, val, 0);
366371
hv_store(ih, "last_access", 11, newSViv((IV)last_access), 0);
367372
hv_store(ih, "expire_on", 9, newSViv((IV)expire_on), 0);
373+
hv_store(ih, "version", 7, newSViv((IV)version), 0);
368374
hv_store(ih, "flags", 5, newSViv((IV)flags), 0);
369375

370376
/* Create reference to hash */
@@ -388,7 +394,7 @@ fc_get_keys(obj, mode)
388394
MU64 * entry_ptr;
389395
void * key_ptr, * val_ptr;
390396
int key_len, val_len;
391-
MU64 last_access, expire_on, flags;
397+
MU64 last_access, expire_on, version, flags;
392398

393399
FC_ENTRY
394400

@@ -401,7 +407,7 @@ fc_get_keys(obj, mode)
401407
SV * key;
402408
mmc_get_details(cache, entry_ptr,
403409
&key_ptr, &key_len, &val_ptr, &val_len,
404-
&last_access, &expire_on, &flags);
410+
&last_access, &expire_on, &version, &flags);
405411

406412
/* Create key SV, and set UTF8'ness if needed */
407413
key = newSVpvn((const char *)key_ptr, key_len);
@@ -422,6 +428,7 @@ fc_get_keys(obj, mode)
422428
hv_store(ih, "key", 3, key, 0);
423429
hv_store(ih, "last_access", 11, newSViv((IV)last_access), 0);
424430
hv_store(ih, "expire_on", 9, newSViv((IV)expire_on), 0);
431+
hv_store(ih, "version", 7, newSViv((IV)version), 0);
425432
hv_store(ih, "flags", 5, newSViv((IV)flags), 0);
426433

427434
/* Add value to hash-ref if mode 2 */
@@ -458,7 +465,7 @@ fc_get(obj, key)
458465
INIT:
459466
int key_len, val_len, found;
460467
void * key_ptr, * val_ptr;
461-
MU64 hash_page, hash_slot, expire_on, flags;
468+
MU64 hash_page, hash_slot, expire_on, version, flags;
462469
STRLEN pl_key_len;
463470
SV * val;
464471

@@ -477,7 +484,7 @@ fc_get(obj, key)
477484
mmc_lock(cache, hash_page);
478485

479486
/* Get value data pointer */
480-
found = mmc_read(cache, hash_slot, key_ptr, key_len, &val_ptr, &val_len, &expire_on, &flags);
487+
found = mmc_read(cache, hash_slot, key_ptr, key_len, &val_ptr, &val_len, &expire_on, &version, &flags);
481488

482489
/* If not found, use undef */
483490
if (found == -1) {
@@ -495,10 +502,11 @@ fc_get(obj, key)
495502

496503

497504
void
498-
fc_set(obj, key, val)
505+
fc_set(obj, key, val, version)
499506
SV * obj;
500507
SV * key;
501508
SV * val;
509+
unsigned long version;
502510
INIT:
503511
int key_len, val_len;
504512
void * key_ptr, * val_ptr;
@@ -524,7 +532,7 @@ fc_set(obj, key, val)
524532
mmc_lock(cache, hash_page);
525533

526534
/* Get value data pointer */
527-
mmc_write(cache, hash_slot, key_ptr, key_len, val_ptr, val_len, -1, flags);
535+
mmc_write(cache, hash_slot, key_ptr, key_len, val_ptr, val_len, -1, version, flags);
528536

529537
mmc_unlock(cache);
530538

lib/Cache/FastMmap.pm

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -787,15 +787,15 @@ sub get {
787787
# Hash value, lock page, read result
788788
my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
789789
my $Unlock = $Self->_lock_page($HashPage);
790-
my ($Val, $Flags, $Found, $ExpireOn) = fc_read($Cache, $HashSlot, $_[1]);
790+
my ($Val, $Flags, $Found, $ExpireOn, $Version) = fc_read($Cache, $HashSlot, $_[1], 0);
791791

792792
# Value not found, check underlying data store
793793
if (!$Found && (my $read_cb = $Self->{read_cb})) {
794794

795795
# Callback to read from underlying data store
796796
# (unlock page first if we allow recursive calls
797797
$Unlock = undef if $Self->{allow_recursive};
798-
$Val = eval { $read_cb->($Self->{context}, $_[1]); };
798+
($Val, my $Opts) = eval { $read_cb->($Self->{context}, $_[1]); };
799799
my $Err = $@;
800800
$Unlock = $Self->_lock_page($HashPage) if $Self->{allow_recursive};
801801

@@ -805,9 +805,6 @@ sub get {
805805
# If we found it, or want to cache not-found, store back into our cache
806806
if (defined $Val || $Self->{cache_not_found}) {
807807

808-
# Are we doing writeback's? If so, need to mark as dirty in cache
809-
my $write_back = $Self->{write_back};
810-
811808
$Val = $Self->{serialize}(\$Val) if $Self->{serialize};
812809
$Val = $Self->{compress}($Val) if $Self->{compress};
813810

@@ -816,7 +813,8 @@ sub get {
816813
my $KVLen = length($_[1]) + (defined($Val) ? length($Val) : 0);
817814
$Self->_expunge_page(2, 1, $KVLen);
818815

819-
fc_write($Cache, $HashSlot, $_[1], $Val, -1, 0);
816+
my $version = $Opts && defined $Opts->{version} ? int $Opts->{version} : 0;
817+
fc_write($Cache, $HashSlot, $_[1], $Val, -1, $version, 0);
820818
}
821819
}
822820

@@ -830,7 +828,9 @@ sub get {
830828
$Val = ${$Self->{deserialize}($Val)} if defined($Val) && $Self->{deserialize};
831829

832830
# If explicitly asked to skip unlocking, we return the reference to the unlocker
833-
return ($Val, $Unlock, { $Found ? (expire_on => $ExpireOn) : () }) if $SkipUnlock;
831+
if ($SkipUnlock) {
832+
return ($Val, $Unlock, { $Found ? (expire_on => $ExpireOn, version => $Version) : () });
833+
}
834834

835835
return $Val;
836836
}
@@ -870,6 +870,7 @@ sub set {
870870
defined $Opts->{expire_on} ? $Opts->{expire_on} :
871871
(defined $Opts->{expire_time} ? parse_expire_time($Opts->{expire_time}, _time()): -1)
872872
) : -1;
873+
my $version = defined $Opts->{version} ? int $Opts->{version} : 0;
873874

874875
# Hash value, lock page
875876
my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
@@ -893,7 +894,7 @@ sub set {
893894
$Self->_expunge_page(2, 1, $KVLen);
894895

895896
# Now store into cache
896-
my $DidStore = fc_write($Cache, $HashSlot, $_[1], $Val, $expire_on, $write_back ? FC_ISDIRTY : 0);
897+
my $DidStore = fc_write($Cache, $HashSlot, $_[1], $Val, $expire_on, $version, $write_back ? FC_ISDIRTY : 0);
897898

898899
# Unlock page
899900
$Unlock = undef;
@@ -907,6 +908,25 @@ sub set {
907908
return $DidStore;
908909
}
909910

911+
=item I<exists($Key, [ \%Options ])>
912+
913+
Search cache for given Key. Returns undef if not found. Does not
914+
check any I<read_cb>, only checks for in the actual cache right now
915+
916+
=cut
917+
sub exists {
918+
my ($Self, $Cache) = ($_[0], $_[0]->{Cache});
919+
920+
# Hash value, lock page, read result
921+
my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
922+
my $Unlock = $Self->_lock_page($HashPage);
923+
my (undef, $Flags, $Found, $ExpireOn, $Version) = fc_read($Cache, $HashSlot, $_[1], 1);
924+
925+
$Unlock = undef;
926+
927+
return $Found ? { expire_on => $ExpireOn, version => $Version } : undef;
928+
}
929+
910930
=item I<get_and_set($Key, $AtomicSub)>
911931
912932
Atomically retrieve and set the value of a Key.
@@ -1070,7 +1090,7 @@ sub expire {
10701090
# Hash value, lock page, read result
10711091
my ($HashPage, $HashSlot) = fc_hash($Cache, $_[1]);
10721092
my $Unlock = $Self->_lock_page($HashPage);
1073-
my ($Val, $Flags, $Found) = fc_read($Cache, $HashSlot, $_[1]);
1093+
my ($Val, $Flags, $Found, $Version) = fc_read($Cache, $HashSlot, $_[1], 0);
10741094

10751095
# If we found it, remove it
10761096
if ($Found) {
@@ -1250,7 +1270,7 @@ sub multi_get {
12501270
# Hash key to get slot in this page and read
12511271
my $FinalKey = "$_[1]-$_";
12521272
(undef, $HashSlot) = fc_hash($Cache, $FinalKey);
1253-
my ($Val, $Flags, $Found, $ExpireOn) = fc_read($Cache, $HashSlot, $FinalKey);
1273+
my ($Val, $Flags, $Found, $ExpireOn) = fc_read($Cache, $HashSlot, $FinalKey, 0);
12541274
next unless $Found;
12551275

12561276
# If not using raw values, use thaw() to turn data back into object
@@ -1302,7 +1322,7 @@ sub multi_set {
13021322

13031323
# Now hash key and store into page
13041324
(undef, $HashSlot) = fc_hash($Cache, $FinalKey);
1305-
my $DidStore = fc_write($Cache, $HashSlot, $FinalKey, $Val, $expire_on, 0);
1325+
my $DidStore = fc_write($Cache, $HashSlot, $FinalKey, $Val, $expire_on, 0, 0);
13061326
}
13071327

13081328
# Unlock page

mmap_cache.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ int mmc_hash(
406406
* cache_mmap * cache, MU64 hash_slot,
407407
* void *key_ptr, int key_len,
408408
* void **val_ptr, int *val_len,
409-
* MU64 *expire_on, MU64 *flags
409+
* MU64 *expire_on_p, MU64 * version_p, MU64 *flags_p
410410
* )
411411
*
412412
* Read key from current page
@@ -416,7 +416,7 @@ int mmc_read(
416416
mmap_cache *cache, MU64 hash_slot,
417417
void *key_ptr, int key_len,
418418
void **val_ptr, int *val_len,
419-
MU64 *expire_on_p, MU64 *flags_p
419+
MU64 *expire_on_p, MU64 *version_p, MU64 *flags_p
420420
) {
421421
MU64 * slot_ptr;
422422

@@ -458,8 +458,9 @@ int mmc_read(
458458
S_LastAccess(base_det) = now;
459459

460460
/* Copy values to pointers */
461-
*flags_p = S_Flags(base_det);
462461
*expire_on_p = expire_on;
462+
*version_p = S_Version(base_det);
463+
*flags_p = S_Flags(base_det);
463464
*val_len = S_ValLen(base_det);
464465
*val_ptr = S_ValPtr(base_det);
465466

@@ -478,7 +479,7 @@ int mmc_read(
478479
* cache_mmap * cache, MU64 hash_slot,
479480
* void *key_ptr, int key_len,
480481
* void *val_ptr, int val_len,
481-
* MU64 expire_on, MU64 flags
482+
* MU64 expire_on, MU64 version, MU64 flags
482483
* )
483484
*
484485
* Write key to current page
@@ -488,7 +489,7 @@ int mmc_write(
488489
mmap_cache *cache, MU64 hash_slot,
489490
void *key_ptr, int key_len,
490491
void *val_ptr, int val_len,
491-
MU64 expire_on, MU64 flags
492+
MU64 expire_on, MU64 version, MU64 flags
492493
) {
493494
int did_store = 0;
494495
MU64 kvlen = KV_SlotLen(key_len, val_len);
@@ -525,6 +526,7 @@ int mmc_write(
525526
S_LastAccess(base_det) = now;
526527
S_ExpireOn(base_det) = expire_on;
527528
S_SlotHash(base_det) = hash_slot;
529+
S_Version(base_det) = version;
528530
S_Flags(base_det) = flags;
529531
S_KeyLen(base_det) = (MU64)key_len;
530532
S_ValLen(base_det) = (MU64)val_len;
@@ -565,7 +567,7 @@ int mmc_write(
565567
int mmc_delete(
566568
mmap_cache *cache, MU64 hash_slot,
567569
void *key_ptr, int key_len,
568-
MU64 * flags
570+
MU64 * flags_p, MU64 * version_p
569571
) {
570572
/* Search slots for key */
571573
MU64 * slot_ptr = _mmc_find_slot(cache, hash_slot, key_ptr, key_len, 2);
@@ -581,7 +583,8 @@ int mmc_delete(
581583

582584
/* Store flags in output pointer */
583585
MU64 * base_det = S_Ptr(cache->p_base, *slot_ptr);
584-
*flags = S_Flags(base_det);
586+
*flags_p = S_Flags(base_det);
587+
*version_p = S_Version(base_det);
585588

586589
_mmc_delete_slot(cache, slot_ptr);
587590
return 1;
@@ -985,7 +988,7 @@ void mmc_get_details(
985988
MU64 * base_det,
986989
void ** key_ptr, int * key_len,
987990
void ** val_ptr, int * val_len,
988-
MU64 * last_access, MU64 * expire_on, MU64 * flags
991+
MU64 * last_access_p, MU64 * expire_on_p, MU64 * version_p, MU64 * flags_p
989992
) {
990993
cache = cache;
991994

@@ -995,9 +998,10 @@ void mmc_get_details(
995998
*val_ptr = S_ValPtr(base_det);
996999
*val_len = S_ValLen(base_det);
9971000

998-
*last_access = S_LastAccess(base_det);
999-
*expire_on = S_ExpireOn(base_det);
1000-
*flags = S_Flags(base_det);
1001+
*last_access_p = S_LastAccess(base_det);
1002+
*expire_on_p = S_ExpireOn(base_det);
1003+
*version_p = S_Version(base_det);
1004+
*flags_p = S_Flags(base_det);
10011005
}
10021006

10031007

0 commit comments

Comments
 (0)