/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* $Id: memcached.h,v 1.21 2004/02/24 23:42:02 bradfitz Exp $ */ #define DATA_BUFFER_SIZE 2048 #if defined(TCP_CORK) && !defined(TCP_NOPUSH) #define TCP_NOPUSH TCP_CORK #endif struct stats { unsigned int curr_items; unsigned int total_items; unsigned long long curr_bytes; unsigned int curr_conns; unsigned int total_conns; unsigned int conn_structs; unsigned int get_cmds; unsigned int set_cmds; unsigned int get_hits; unsigned int get_misses; time_t started; /* when the process was started */ unsigned long long bytes_read; unsigned long long bytes_written; }; struct settings { unsigned int maxbytes; int maxconns; int port; struct in_addr interface; int verbose; time_t oldest_live; /* ignore existing items older than this */ int evict_to_free; }; extern struct stats stats; extern struct settings settings; #define ITEM_LINKED 1 #define ITEM_DELETED 2 /* temp */ #define ITEM_SLABBED 4 typedef struct _stritem { struct _stritem *next; struct _stritem *prev; struct _stritem *h_next; /* hash chain next */ unsigned short refcount; unsigned short flags; int nbytes; /* size of data */ time_t time; /* least recent access */ time_t exptime; /* expire time */ unsigned char it_flags; /* ITEM_* above */ unsigned char slabs_clsid; unsigned char nkey; /* key length, with terminating null and padding */ unsigned char dummy1; void * end[0]; } item; #define ITEM_key(item) ((char*)&((item)->end[0])) /* warning: don't use these macros with a function, as it evals its arg twice */ #define ITEM_data(item) ((char*) &((item)->end[0]) + (item)->nkey) #define ITEM_ntotal(item) (sizeof(struct _stritem) + (item)->nkey + (item)->nbytes) enum conn_states { conn_listening, /* the socket which listens for connections */ conn_read, /* reading in a command line */ conn_write, /* writing out a simple response */ conn_nread, /* reading in a fixed number of bytes */ conn_swallow, /* swallowing unnecessary bytes w/o storing */ conn_closing, /* closing this connection */ conn_mwrite /* writing out many items sequentially */ }; #define NREAD_ADD 1 #define NREAD_SET 2 #define NREAD_REPLACE 3 typedef struct { int sfd; int state; struct event event; short ev_flags; short which; /* which events were just triggered */ char *rbuf; int rsize; int rbytes; char *wbuf; char *wcurr; int wsize; int wbytes; int write_and_go; /* which state to go into after finishing current write */ void *write_and_free; /* free this memory after finishing writing */ char is_corked; /* boolean, connection is corked */ char *rcurr; int rlbytes; /* data for the nread state */ /* * item is used to hold an item structure created after reading the command * line of set/add/replace commands, but before we finished reading the actual * data. The data is read into ITEM_data(item) to avoid extra copying. */ void *item; /* for commands set/add/replace */ int item_comm; /* which one is it: set/add/replace */ /* data for the swallow state */ int sbytes; /* how many bytes to swallow */ /* data for the mwrite state */ item **ilist; /* list of items to write out */ int isize; item **icurr; int ileft; int ipart; /* 1 if we're writing a VALUE line, 2 if we're writing data */ char ibuf[300]; /* for VALUE lines */ char *iptr; int ibytes; } conn; /* listening socket */ extern int l_socket; /* temporary hack */ /* #define assert(x) if(!(x)) { printf("assert failure: %s\n", #x); pre_gdb(); } void pre_gdb (); */ /* * Functions */ /* * given time value that's either unix time or delta from current unix time, return * unix time. Use the fact that delta can't exceed one month (and real time value can't * be that low). */ time_t realtime(time_t exptime); /* slabs memory allocation */ /* Init the subsystem. The argument is the limit on no. of bytes to allocate, 0 if no limit */ void slabs_init(unsigned int limit); /* Given object size, return id to use when allocating/freeing memory for object */ /* 0 means error: can't store such a large object */ unsigned int slabs_clsid(unsigned int size); /* Allocate object of given length. 0 on error */ void *slabs_alloc(unsigned int size); /* Free previously allocated object */ void slabs_free(void *ptr, unsigned int size); /* Fill buffer with stats */ char* slabs_stats(int *buflen); /* Request some slab be moved between classes 1 = success 0 = fail -1 = tried. busy. send again shortly. */ int slabs_reassign(unsigned char srcid, unsigned char dstid); /* event handling, network IO */ void event_handler(int fd, short which, void *arg); conn *conn_new(int sfd, int init_state, int event_flags); void conn_close(conn *c); void conn_init(void); void drive_machine(conn *c); int new_socket(void); int server_socket(int port); int update_event(conn *c, int new_flags); int try_read_command(conn *c); int try_read_network(conn *c); void complete_nread(conn *c); void process_command(conn *c, char *command); /* stats */ void stats_reset(void); void stats_init(void); /* defaults */ void settings_init(void); /* associative array */ void assoc_init(void); item *assoc_find(char *key); int assoc_insert(char *key, item *item); void assoc_delete(char *key); void item_init(void); item *item_alloc(char *key, int flags, time_t exptime, int nbytes); void item_free(item *it); int item_link(item *it); /* may fail if transgresses limits */ void item_unlink(item *it); void item_remove(item *it); void item_update(item *it); /* update LRU time to current and reposition */ int item_replace(item *it, item *new_it); char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int *bytes); char *item_stats_sizes(int *bytes); void item_stats(char *buffer, int buflen);