Rafal Szczesniak
April 2003

# General cache mechanism and API

## Abstract

General cache (gencache) was designed to combine various kinds of caching mechanisms into one, defined by a simple API. This way, anyone can use it to create their own caching layer on top of gencache. An example of such approach is the netbios name cache.

## The mechanism

Gencache utilises tdb database, like many other parts of Samba. As its origins are in Berkeley DB implementation, it uses key/value pairs stored in binary file. The values gencache operates on are string-based, however. This makes very easy to use it in command line environment eg. to quickly take a look at what's in the cache or set some value.

All the data is stored in `gencache.tdb` file. Records put there are in key/value format as mentioned below, but as it's a cache, the timeout plays also important role and has a special place in the key/value pair, as well as API.

## The data structure

The record stored in `gencache.tdb` file consists of the key, the value and the expiration timeout. While the first part is stored completely independent from the others, the last two are kept together. The form the record has is:

    key:     <string>
    value:   <12-digit timeout>/<string>

The timeout part is the ASCII representation of time_t value of the time when the cache entry expires. Obviously the API, the programmer is provided with, hides this detail, so that you don't have to care about checking it. Simply watch carefully the return status of the function.

## The API

    BOOL gencache_init()

This is used to initialise to whole caching mechanism. It means opening the file or creating it if non-existing. If it's already been opened earlier, then the routine just does nothing and returns `true`. If something goes wrong, say the user doesn't have necessary rights, the function returns `false`.

    BOOL gencache_shutdown()

This is the proper way to close the cache file. It simply returns `true` after successful closing file and `false` upon a failure.

    BOOL gencache_set(const char* keystr, const char* value, time_t timeout)

This is one of the most basic functions. What it allows you to do is to set some particular cache entry. If the entry haven't existed yet, the function will act just as it was "gencache_add" function. If it's already been in the cache, the entry will be set to the new value. In either case, the cache entry will be set with given key, value and timeout. Thus it is comfortable way to just set the entry and not care about the details.

    BOOL gencache_set_only(const char* keystr, const char* value, time_t timeout)

    BOOL gencache_del(const char* keystr)

    BOOL gencache_get(const char* keystr, char** valstr, time_t* timeout)

    void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr),
                          void* data, const char* keystr_pattern)