From: rousskov <> Date: Thu, 26 Feb 1998 14:06:14 +0000 (+0000) Subject: Spread MemBuf.h among .h monsters. X-Git-Tag: SQUID_3_0_PRE1~3978 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1a3db59cb44b558412cb8435ec6c7175a8c3c03a;p=thirdparty%2Fsquid.git Spread MemBuf.h among .h monsters. --- diff --git a/src/MemBuf.cc b/src/MemBuf.cc index fe0f27aa2a..d1c72e86f8 100644 --- a/src/MemBuf.cc +++ b/src/MemBuf.cc @@ -1,5 +1,5 @@ /* - * $Id: MemBuf.cc,v 1.3 1998/02/21 18:46:34 rousskov Exp $ + * $Id: MemBuf.cc,v 1.4 1998/02/26 07:06:14 rousskov Exp $ * * DEBUG: section 59 auto-growing Memory Buffer with printf * AUTHOR: Alex Rousskov @@ -28,20 +28,93 @@ * */ -/* see MemBuf.h for documentation */ - /* * To-Do: uses memory pools for .buf recycling @?@ */ +/* + Rationale: + ---------- + + Here is how one would comm_write an object without MemBuffer: + + { + -- allocate: + buf = malloc(big_enough); + + -- "pack": + snprintf object(s) piece-by-piece constantly checking for overflows + and maintaining (buf+offset); + ... + + -- write + comm_write(buf, free, ...); + } + + The whole "packing" idea is quite messy: We are given a buffer of fixed + size and we have to check all the time that we still fit. Sounds logical. + However, what happens if we have more data? If we are lucky to be careful + to stop before we overrun any buffers, we still may have garbage (e.g. + half of ETag) in the buffer. + + MemBuffer: + ---------- + + MemBuffer is a memory-resident buffer with printf()-like interface. It + hides all offest handling and overflow checking. Moreover, it has a + build-in control that no partial data has been written. + + MemBuffer is designed to handle relatively small data. It starts with a + small buffer of configurable size to avoid allocating huge buffers all the + time. MemBuffer doubles the buffer when needed. It assert()s that it will + not grow larger than a configurable limit. MemBuffer has virtually no + overhead (and can even reduce memory consumption) compared to old + "packing" approach. + + MemBuffer eliminates both "packing" mess and truncated data: + + { + -- setup + MemBuf buf; + + -- required init with optional size tuning (see #defines for defaults) + memBufInit(&buf, initial-size, absolute-maximum); + + -- "pack" (no need to handle offsets or check for overflows) + memBufPrintf(&buf, ...); + ... + + -- write + comm_write(buf.buf, memBufFreeFunc(&buf), ...); + + -- *iff* you did not give the buffer away, free it yourself + -- memBufFree(&buf); + } +*/ + #include "squid.h" +/* local constants */ + +/* default values for buffer sizes, used by memBufDefInit */ +#define MEM_BUF_INIT_SIZE (2*1024) +#define MEM_BUF_MAX_SIZE (32*1024) + + /* local routines */ static void memBufGrow(MemBuf *mb, mb_size_t min_cap); +/* init with defaults */ +void +memBufDefInit(MemBuf *mb) +{ + memBufInit(mb, MEM_BUF_INIT_SIZE, MEM_BUF_MAX_SIZE); +} + +/* init with specific sizes */ void memBufInit(MemBuf *mb, mb_size_t szInit, mb_size_t szMax) { @@ -57,6 +130,10 @@ memBufInit(MemBuf *mb, mb_size_t szInit, mb_size_t szMax) memBufGrow(mb, szInit); } +/* + * cleans the mb; last function to call if you do not give .buf away with + * memBufFreeFunc + */ void memBufClean(MemBuf *mb) { @@ -69,6 +146,7 @@ memBufClean(MemBuf *mb) mb->size = mb->capacity = 0; } +/* calls memcpy, appends exactly size bytes, extends buffer if needed */ void memBufAppend(MemBuf *mb, const char *buf, mb_size_t sz) { @@ -85,6 +163,7 @@ memBufAppend(MemBuf *mb, const char *buf, mb_size_t sz) } } +/* calls snprintf, extends buffer if needed */ #ifdef __STDC__ void memBufPrintf(MemBuf *mb, const char *fmt, ...) @@ -109,6 +188,7 @@ memBufPrintf(va_alist) } +/* vprintf for other printf()'s to use */ void memBufVPrintf(MemBuf *mb, const char *fmt, va_list vargs) { @@ -131,6 +211,13 @@ memBufVPrintf(MemBuf *mb, const char *fmt, va_list vargs) mb->size += sz-1; /* note that we cut 0-terminator as store does @?@ @?@ */ } +/* + * returns free() function to be used. + * Important: + * calling this function "freezes" mb, + * do not _update_ mb after that in any way + * (you still can read-access .buf and .size) + */ FREE * memBufFreeFunc(MemBuf *mb) { @@ -178,6 +265,10 @@ memBufGrow(MemBuf *mb, mb_size_t min_cap) mb->capacity = new_cap; } + +/* Reports */ + +/* puts report on MemBuf _module_ usage into mb */ void memBufReport(MemBuf *mb) { diff --git a/src/protos.h b/src/protos.h index b13ac7158b..df13188d78 100644 --- a/src/protos.h +++ b/src/protos.h @@ -306,6 +306,28 @@ extern ipcache_addrs *ipcacheCheckNumeric(const char *name); extern void ipcache_restart(void); extern int ipcacheUnregister(const char *name, void *data); +/* MemBuf */ +/* init with specific sizes */ +extern void memBufInit(MemBuf *mb, mb_size_t szInit, mb_size_t szMax); +/* init with defaults */ +extern void memBufDefInit(MemBuf *mb); +/* cleans the mb; last function to call if you do not give .buf away */ +extern void memBufClean(MemBuf *mb); +/* calls memcpy, appends exactly size bytes, extends buffer if needed */ +extern void memBufAppend(MemBuf *mb, const char *buf, mb_size_t size); +/* calls snprintf, extends buffer if needed */ +#ifdef __STDC__ +extern void memBufPrintf(MemBuf *mb, const char *fmt, ...); +#else +extern void memBufPrintf(); +#endif +/* vprintf for other printf()'s to use */ +extern void memBufVPrintf(MemBuf *mb, const char *fmt, va_list ap); +/* returns free() function to be used, _freezes_ the object! */ +extern FREE *memBufFreeFunc(MemBuf *mb); +/* puts report on MemBuf _module_ usage into mb */ +extern void memBufReport(MemBuf *mb); + extern char *mime_get_header(const char *mime, const char *header); extern char *mime_headers_end(const char *mime); extern int mk_mime_hdr(char *result, const char *type, int size, time_t ttl, time_t lmt); diff --git a/src/structs.h b/src/structs.h index 916f49831f..01203a455b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -444,9 +444,6 @@ struct _hash_table { hash_link *current_ptr; }; -#include "MemBuf.h" -#include "Packer.h" - /* server cache control */ struct _HttpScc { int mask; @@ -800,6 +797,19 @@ struct _iostats { } Http, Ftp, Gopher, Wais; }; +/* auto-growing memory-resident buffer with printf interface */ +struct _MemBuf { + /* public, read-only */ + char *buf; + mb_size_t size; /* used space, does not count 0-terminator */ + + /* private, stay away; use interface function instead */ + mb_size_t max_capacity; /* when grows: assert(new_capacity <= max_capacity) */ + mb_size_t capacity; /* allocated space */ + FREE *freefunc; /* what to use to free the buffer, NULL after memBufFreeFunc() is called */ +}; + + struct _mem_node { char *data; int len; @@ -827,6 +837,8 @@ struct _store_client { struct _store_client *next; }; +#include "Packer.h" + /* This structure can be freed while object is purged out from memory */ struct _MemObject { method_t method; @@ -842,11 +854,7 @@ struct _MemObject { int fd; void *ctrl; } swapout; -#if 0 - struct _http_reply *reply; -#else HttpReply *reply; -#endif request_t *request; struct timeval start_ping; IRCB *icp_reply_callback; diff --git a/src/typedefs.h b/src/typedefs.h index 95eab48ad1..d8a8b94e96 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -72,6 +72,7 @@ typedef struct _pingerReplyData pingerReplyData; typedef struct _icp_common_t icp_common_t; typedef struct _Meta_data Meta_data; typedef struct _iostats iostats; +typedef struct _MemBuf MemBuf; typedef struct _mem_node mem_node; typedef struct _mem_hdr mem_hdr; typedef struct _store_client store_client; @@ -129,3 +130,6 @@ typedef unsigned char cache_key; /* context-based debugging, the actual type is subject to change */ typedef int Ctx; + +/* in case we want to change it later */ +typedef size_t mb_size_t;