module Cache_client:sig
..end
e_bucket
component
of the entries. Functions for doing this can be found in
Cache_util
:
let e_key = Cache_util.hash_of_key k in
let e_bucket = Cache_util.bucket_of_hash n e_key
The number n
is the number of buckets.
Expiration. Entries can have a timestamp that says when the entries
are removed from the cache. It is ensured that the get
operation never
returns an expired entry when both client and server have the same clock.
Independent of expiration by time, the cache may also expire entries
because the cache becomes too large. The cache implements a LRU semantics:
The least recently used entries are removed first. As "use" any get
or set
operation qualifies.
Deletion. There is a third mechanism for removing
entries: One can also actively delete entries. The delete
operation
takes a delete timestamp as argument. If this timestamp is in the past
(e.g. 0), the deletion is performed immediately. Otherwise the entry
is scheduled for deletion at the given time. The e_delete_flag
says
whether such a deletion will happen.
In order to coordinate parallel accesses to the cache, all entries
that are scheduled for deletion are locked for overwriting. Any
set
operation is refused by default. You can break this lock by
setting the opt_undelete
option. In this case, set
not only overwrites
but also cancels the scheduled deletion.
The delete
operation has effectively a higher precedence than the
set
operation unless you specify opt_undelete
. This makes delete
different from setting a new expiration timestamp in the entry by
calling set
. The higher precedence is useful if you have new knowledge
about the validity period of entries, and you want to prevent that
restricting the validity period interfers with the regular use of set
.
Note that a scheduled deletion does not prevent the entry from expiring
because of the expiration timestamp or because of exceeding the maximum
size of the cache.
Atomicity. The operations set
and delete
are either fully
conducted, or not conducted at all. For example, if you call set
with opt_setifchanged
, there are only two outcomes:
set
operation is done: The value
is overwritten, the
new modification timestamp is set, the expiration timestamp is
set to the passed value, and any delete flag is removed.set
operation is not done: The entry is not modified at all.opt_setifchanged
causes that set
is only performed for
value changes, you get implicitly the effect of only setting
the modification and expiration timestamps when the value is
distinct from the previous one.typekey =
[ `Hash of Digest.t | `String of string ]
`Hash dg
: As digest of a string`String s
: As string (to be digested)typetimestamp =
int64
typeentry =
Cache_aux.entry
= {
|
mutable e_key : |
(* | The key in hashed form | *) |
|
mutable e_creation : |
(* | Time of first addition to the cache | *) |
|
mutable e_modification : |
(* | Time of last modification in the cache | *) |
|
mutable e_expiration : |
(* | Time when the entry will expire; 0 = never | *) |
|
mutable e_delete_flag : |
(* | Whether this entry is scheduled for deletion | *) |
|
mutable e_value : |
(* | The value of the entry, an arbitrary string | *) |
|
mutable e_value_hash : |
(* | The MD5 sum of the value | *) |
|
mutable e_value_length : |
(* | The length of the value | *) |
|
mutable e_counter : |
(* | The number of get accesses to this entry | *) |
|
mutable e_bucket : |
(* | The bucket number of this entry | *) |
typeset_options =
Cache_aux.set_options
= {
|
mutable opt_overwrite : |
(* | Allow overwriting existing entries | *) |
|
mutable opt_add : |
(* | Allow adding new entries | *) |
|
mutable opt_undelete : |
(* | Allow the modification of entries that are scheduled for deletion. Such entries are revived, and count no longer as deleted | *) |
|
mutable opt_setifchanged : |
(* | Modifies opt_overwrite :
Overwriting is only permitted if the new value is distinct from
the old one | *) |
set
operationtypeget_options =
Cache_aux.get_options
= {
|
mutable opt_novalue : |
(* | Do not return the e_value
component of entries, but an empty string as replacement (for
getting meta data only) | *) |
|
mutable opt_getifmodifiedsince : |
(* | When Some t : Only return
entries that have e_modification >= t . When None : No
restriction. | *) |
|
mutable opt_getifnotmd5 : |
(* | When Some dg : Only return
entries when e_value_hash <> dg . When None : No restriction. | *) |
get
operationtypedelete_options =
Cache_aux.delete_options
= {
|
mutable opt_strictlock : |
(* | Forces that the entry is even
scheduled for deletion if it does not exist. Unless
opt_undelete is given, a set operation cannot be successful
for the key while the entry is in the delete queue, i.e. the
key is locked until the deletion is really conducted. | *) |
|
mutable opt_delifolderthan : |
(* | When Some t : It is required
that e_modification < t in order to schedule an entry for
deletion. When None : no such requirement. | *) |
|
mutable opt_delifmd5 : |
(* | When Some dg : It is required
that e_value_hash = dg in order to schedule an entry for
deletion. When None : no such requirement. | *) |
|
mutable opt_delifnotmd5 : |
(* | When Some dg : It is required
that e_value_hash <> dg in order to schedule an entry for
deletion. When None : no such requirement. | *) |
delete
operationtypeconfig =
Cache_aux.config
= {
|
mutable max_size : |
(* | The maximum size in bytes | *) |
|
mutable save_cache_period : |
(* | Save the cache to disk every this number of seconds. 0 or negative number disables saving to disk entirely | *) |
|
mutable save_cache_speed : |
(* | How fast to save to disk in bytes per second. Setting this to a reasonable value increases the responsiveness of the cache server while a save operation is in progress. Setting to 0 means as fast as possible. | *) |
typestats =
Cache_aux.stats
= {
|
mutable num_entries : |
(* | The number of entries in the cache, including entries scheduled for deletion. | *) |
|
mutable num_bytes : |
(* | The size of the cache in bytes, excluding overhead space | *) |
|
mutable num_calls_get : |
(* | The number of get calls | *) |
|
mutable num_calls_set : |
(* | The number of set calls | *) |
|
mutable num_calls_delete : |
(* | The number of delete calls | *) |
|
mutable num_hits : |
(* | The number of get calls
returning `Found . | *) |
|
mutable counters_reset_on : |
(* | When the counters were last reset | *) |
type'a
async_reply =(unit -> 'a) -> unit
let process_result get_result =
try
let result = get_result() in (* May raise exception *)
...
with error -> ...
exception Server_not_alive
false
for the
is_alive
test.class type client_config =object
..end
class type async_client =object
..end
class type sync_client =object
..end
val create_async_client : client_config ->
Unixqueue.event_system -> async_client
Unixqueue.run
the event system in
order to conduct the requested operations.val create_sync_client : client_config -> sync_client