based on a discussion at a local postgresql user group last week..

Could we factor out the cache management routines in a sane generic library - for C, and then bind to it from language-Foo. (rather like libevent) ?

There are two major aspects to this - one is the cache replacement policies, the other is storage and indexing of data in the cache. Squids internals are best factored on the replacement policies, so lets start there.

Heres the current API for squids replacement 'library' :

struct _RemovalPolicy
{
    // string name for the policy style, for dynamic configuration
    const char *_type;
    // opaque policy owned storage
    void *_data;
    // free the policy
    void (*Free) (RemovalPolicy * policy);
    // inform the policy an item has been added.
    void (*Add) (RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node);
    // or removed
    void (*Remove) (RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node);
    // someone has referenced an item
    void (*Referenced) (RemovalPolicy * policy, const StoreEntry * entry, RemovalPolicyNode * node);
    // someone has dereferenced an item
    void (*Dereferenced) (RemovalPolicy * policy, const StoreEntry * entry, RemovalPolicyNode * node);
    // someone wants to iterate the cache in policy defined order
    RemovalPolicyWalker *(*WalkInit) (RemovalPolicy * policy);
    // remove purgable items please.
    RemovalPurgeWalker *(*PurgeInit) (RemovalPolicy * policy, int max_scan);
    // output statistics to a stream.
    void (*Stats) (RemovalPolicy * policy, StoreEntry * entry);
};

// syncronous iterator
struct _RemovalPolicyWalker
{   
    RemovalPolicy *_policy;
    void *_data;
    const StoreEntry *(*Next) (RemovalPolicyWalker * walker);
    void (*Done) (RemovalPolicyWalker * walker);
};  
   
// subclassed iterator for the purging code     
struct _RemovalPurgeWalker
{   
    RemovalPolicy *_policy;
    void *_data;
    int scanned, max_scan, locked;
    StoreEntry *(*Next) (RemovalPurgeWalker * walker);
    void (*Done) (RemovalPurgeWalker * walker);
};  

Now thats obviously not generic enough.

Heres a first cut at a generic one.

// generic parameterisation stuff
struct _LibraryParameters
{
  void *alloc(size_t bytes);
  void free (void *pointer);
  //... threads etc
  // may want to document a slab allocator interface as well/instead
};

struct _RemovalPolicy
{
    // string name for the policy style, for dynamic configuration
    const char *_type;
    // parameterisation for user functions
    LibraryParameters *systemcalls;
    // opaque policy specific and owned storage
    void *_data;
    // finalise the policy (allows static or on stack policies)
    void (*finalise) (RemovalPolicy * policy);
    // inform the policy an item has been added.
    void (*Add) (RemovalPolicy * policy, void const * entry, RemovalPolicyNode * node);
    // or removed
    void (*Remove) (RemovalPolicy * policy, void const * entry, RemovalPolicyNode * node);
    // someone has referenced an item
    void (*Referenced) (RemovalPolicy * policy, void const  * entry, RemovalPolicyNode * node);
    // someone has dereferenced an item
    void (*Dereferenced) (RemovalPolicy * policy, void const * entry, RemovalPolicyNode * node);
    // someone wants to iterate the cache in policy defined order
    RemovalPolicyWalker *(*WalkInit) (RemovalPolicy * policy);
    // someone wants to iterate to remove purgable items.
    RemovalPurgeWalker *(*PurgeInit) (RemovalPolicy * policy, int max_scan);
    // output statistics & internal details to a stream.
    void (*Stats) (RemovalPolicy * policy, void (*write)(void * closure, char const *string));
};

// factory function for default initialisation
typedef int init_policy (RemovalPolicy *policy, LibraryParameters *systemcalls);

// syncronous iterator
struct _RemovalPolicyWalker
{   
    RemovalPolicy *_policy;
    void *_data;
    void const *(*next) (RemovalPolicyWalker * walker);
    void (*done) (RemovalPolicyWalker * walker);
};  
   
// subclassed iterator for the purging code     
struct _RemovalPurgeWalker
{   
    _RemovalPolicyWalker walker;
    int scanned, max_scan, locked;
};  

LibCacheReplacement (last edited 2008-05-18 19:38:59 by localhost)