]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Generic buffer allocator on top of the MEM_X_BUF memory pools. Simplifies
authorhno <>
Thu, 14 Feb 2002 02:34:01 +0000 (02:34 +0000)
committerhno <>
Thu, 14 Feb 2002 02:34:01 +0000 (02:34 +0000)
many parts of the code.

src/MemBuf.cc
src/client_side.cc
src/enums.h
src/ftp.cc
src/mem.cc
src/protos.h
src/structs.h

index d131f706411f633f59f5a0aa6bf2503b0fbea297..237f11c944fbdc7c05216cd21fce522c7f895c98 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: MemBuf.cc,v 1.28 2001/04/20 21:26:22 hno Exp $
+ * $Id: MemBuf.cc,v 1.29 2002/02/13 19:34:02 hno Exp $
  *
  * DEBUG: section 59    auto-growing Memory Buffer with printf
  * AUTHOR: Alex Rousskov
@@ -131,7 +131,7 @@ memBufInit(MemBuf * mb, mb_size_t szInit, mb_size_t szMax)
     mb->size = 0;
     mb->max_capacity = szMax;
     mb->capacity = 0;
-    mb->freefunc = NULL;
+    mb->stolen = 0;
 
     memBufGrow(mb, szInit);
 }
@@ -145,10 +145,9 @@ memBufClean(MemBuf * mb)
 {
     assert(mb);
     assert(mb->buf);
-    assert(mb->freefunc);      /* not frozen */
+    assert(!mb->stolen);       /* not frozen */
 
-    (*mb->freefunc) (mb->buf); /* free */
-    mb->freefunc = NULL;       /* freeze */
+    memFreeBuf(mb->capacity, mb->buf);
     mb->buf = NULL;
     mb->size = mb->capacity = 0;
 }
@@ -163,7 +162,7 @@ memBufReset(MemBuf * mb)
     if (memBufIsNull(mb)) {
        memBufDefInit(mb);
     } else {
-       assert(mb->freefunc);   /* not frozen */
+       assert(!mb->stolen);    /* not frozen */
        /* reset */
        memset(mb->buf, 0, mb->capacity);
        mb->size = 0;
@@ -188,7 +187,7 @@ memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz)
 {
     assert(mb && buf && sz >= 0);
     assert(mb->buf);
-    assert(mb->freefunc);      /* not frozen */
+    assert(!mb->stolen);       /* not frozen */
 
     if (sz > 0) {
        if (mb->size + sz > mb->capacity)
@@ -231,7 +230,7 @@ memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs)
     int sz = 0;
     assert(mb && fmt);
     assert(mb->buf);
-    assert(mb->freefunc);      /* not frozen */
+    assert(!mb->stolen);       /* not frozen */
     /* assert in Grow should quit first, but we do not want to have a scary infinite loop */
     while (mb->capacity <= mb->max_capacity) {
        mb_size_t free_space = mb->capacity - mb->size;
@@ -269,10 +268,10 @@ memBufFreeFunc(MemBuf * mb)
     FREE *ff;
     assert(mb);
     assert(mb->buf);
-    assert(mb->freefunc);      /* not frozen */
+    assert(!mb->stolen);       /* not frozen */
 
-    ff = mb->freefunc;
-    mb->freefunc = NULL;       /* freeze */
+    ff = memFreeBufFunc((size_t)mb->capacity);
+    mb->stolen = 1;    /* freeze */
     return ff;
 }
 
@@ -280,79 +279,34 @@ memBufFreeFunc(MemBuf * mb)
 static void
 memBufGrow(MemBuf * mb, mb_size_t min_cap)
 {
-    mb_size_t new_cap;
-    MemBuf old_mb;
+    size_t new_cap;
+    size_t buf_cap;
 
     assert(mb);
+    assert(!mb->stolen);
     assert(mb->capacity < min_cap);
 
     /* determine next capacity */
-    new_cap = mb->capacity;
-    if (new_cap > 0)
-       while (new_cap < min_cap)
-           new_cap *= 2;       /* double */
-    else
-       new_cap = min_cap;
+    if (min_cap > 64*1024) {
+       new_cap = 64*1024;
+       while (new_cap < (size_t)min_cap)
+           new_cap += 64*1024; /* increase in reasonable steps */
+    } else {
+       new_cap = (size_t)min_cap;
+    }
 
     /* last chance to fit before we assert(!overflow) */
-    if (new_cap > mb->max_capacity)
-       new_cap = mb->max_capacity;
-
-    assert(new_cap <= mb->max_capacity);       /* no overflow */
-    assert(new_cap > mb->capacity);    /* progress */
-
-    old_mb = *mb;
-
-    /* allocate new memory */
-    switch (new_cap) {
-    case 2048:
-       mb->buf = memAllocate(MEM_2K_BUF);
-       mb->freefunc = &memFree2K;
-       break;
-    case 4096:
-       mb->buf = memAllocate(MEM_4K_BUF);
-       mb->freefunc = &memFree4K;
-       break;
-    case 8192:
-       mb->buf = memAllocate(MEM_8K_BUF);
-       mb->freefunc = &memFree8K;
-       break;
-    case 16384:
-       mb->buf = memAllocate(MEM_16K_BUF);
-       mb->freefunc = &memFree16K;
-       break;
-    case 32768:
-       mb->buf = memAllocate(MEM_32K_BUF);
-       mb->freefunc = &memFree32K;
-       break;
-    case 65536:
-       mb->buf = memAllocate(MEM_64K_BUF);
-       mb->freefunc = &memFree64K;
-       break;
-    default:
-       /* recycle if old buffer was not "pool"ed */
-       if (old_mb.freefunc == &xfree) {
-           mb->buf = xrealloc(old_mb.buf, new_cap);
-           old_mb.buf = NULL;
-           old_mb.freefunc = NULL;
-           /* init tail, just in case */
-           memset(mb->buf + mb->size, 0, new_cap - mb->size);
-       } else {
-           mb->buf = xcalloc(1, new_cap);
-           mb->freefunc = &xfree;
-       }
-    }
+    if (new_cap > (size_t)mb->max_capacity)
+       new_cap = (size_t)mb->max_capacity;
 
-    /* copy and free old buffer if needed */
-    if (old_mb.buf && old_mb.freefunc) {
-       xmemcpy(mb->buf, old_mb.buf, old_mb.size);
-       (*old_mb.freefunc) (old_mb.buf);
-    } else {
-       assert(!old_mb.buf && !old_mb.freefunc);
-    }
+    assert(new_cap <= (size_t)mb->max_capacity);       /* no overflow */
+    assert(new_cap > (size_t)mb->capacity);    /* progress */
+
+    buf_cap = (size_t)mb->capacity;
+    mb->buf = memReallocBuf(mb->buf, new_cap, &buf_cap);
 
     /* done */
-    mb->capacity = new_cap;
+    mb->capacity = (mb_size_t)buf_cap;
 }
 
 
index 9369036fee8b1c3e6db8b1d1a934dae3883794b8..ba5721dfef809aa0f3515139ba71fe015caef72e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.561 2001/12/12 23:44:18 hno Exp $
+ * $Id: client_side.cc,v 1.562 2002/02/13 19:34:01 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -868,11 +868,7 @@ connStateFree(int fd, void *data)
        authenticateAuthUserRequestUnlock(connState->auth_user_request);
     connState->auth_user_request = NULL;
     authenticateOnCloseConnection(connState);
-    if (connState->in.size == CLIENT_REQ_BUF_SZ)
-       memFree(connState->in.buf, MEM_CLIENT_REQ_BUF);
-    else
-       safe_free(connState->in.buf);
-    /* XXX account connState->in.buf */
+    memFreeBuf(connState->in.size, connState->in.buf);
     pconnHistCount(0, connState->nrequests);
     cbdataFree(connState);
 #ifdef _SQUID_LINUX_
@@ -2722,7 +2718,6 @@ clientReadRequest(int fd, void *data)
     int parser_return_code = 0;
     request_t *request = NULL;
     int size;
-    void *p;
     method_t method;
     clientHttpRequest *http = NULL;
     clientHttpRequest **H = NULL;
@@ -2734,15 +2729,7 @@ clientReadRequest(int fd, void *data)
     commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, conn, 0);
     if (len == 0) {
        /* Grow the request memory area to accomodate for a large request */
-       conn->in.size += CLIENT_REQ_BUF_SZ;
-       if (conn->in.size == 2 * CLIENT_REQ_BUF_SZ) {
-           p = conn->in.buf;   /* get rid of fixed size Pooled buffer */
-           conn->in.buf = xcalloc(2, CLIENT_REQ_BUF_SZ);
-           xmemcpy(conn->in.buf, p, CLIENT_REQ_BUF_SZ);
-           memFree(p, MEM_CLIENT_REQ_BUF);
-       } else
-           conn->in.buf = xrealloc(conn->in.buf, conn->in.size);
-       /* XXX account conn->in.buf */
+       conn->in.buf = memReallocBuf(conn->in.buf, conn->in.size * 2, &conn->in.size);
        debug(33, 2) ("growing request buffer: offset=%ld size=%ld\n",
            (long) conn->in.offset, (long) conn->in.size);
        len = conn->in.size - conn->in.offset - 1;
@@ -3198,9 +3185,7 @@ httpAccept(int sock, void *data)
        connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
        connState->me = me;
        connState->fd = fd;
-       connState->in.size = CLIENT_REQ_BUF_SZ;
-       connState->in.buf = memAllocate(MEM_CLIENT_REQ_BUF);
-       /* XXX account connState->in.buf */
+       connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size);
        comm_add_close_handler(fd, connStateFree, connState);
        if (Config.onoff.log_fqdn)
            fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS);
@@ -3313,8 +3298,7 @@ httpsAccept(int sock, void *data)
        connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
        connState->me = me;
        connState->fd = fd;
-       connState->in.size = CLIENT_REQ_BUF_SZ;
-       connState->in.buf = memAllocate(MEM_CLIENT_REQ_BUF);
+       connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size);
        /* XXX account connState->in.buf */
        comm_add_close_handler(fd, connStateFree, connState);
        if (Config.onoff.log_fqdn)
index 97734ce3a026c836fdf11975b6b229bd434848c8..0cab6b20a51f513683e365adadce9ce431546177 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.203 2001/12/21 09:47:34 hno Exp $
+ * $Id: enums.h,v 1.204 2002/02/13 19:34:01 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -611,7 +611,6 @@ typedef enum {
     MEM_EVENT,
     MEM_TLV,
     MEM_SWAP_LOG_DATA,
-    MEM_CLIENT_REQ_BUF,
     MEM_MAX
 } mem_type;
 
index 3c647f48144924208eb2fe4ff0faf8383229a9d8..be0aecc49b746b0c2e750a70cf403675ffef1482 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.cc,v 1.316 2001/11/09 07:05:00 hno Exp $
+ * $Id: ftp.cc,v 1.317 2002/02/13 19:34:02 hno Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -112,7 +112,6 @@ typedef struct _Ftpdata {
        char *buf;
        size_t size;
        off_t offset;
-       FREE *freefunc;
        wordlist *message;
        char *last_command;
        char *last_reply;
@@ -123,7 +122,6 @@ typedef struct _Ftpdata {
        char *buf;
        size_t size;
        off_t offset;
-       FREE *freefunc;
        char *host;
        u_short port;
     } data;
@@ -274,21 +272,15 @@ ftpStateFree(int fdnotused, void *data)
     storeUnlockObject(ftpState->entry);
     if (ftpState->reply_hdr) {
        memFree(ftpState->reply_hdr, MEM_8K_BUF);
-       /* this seems unnecessary, but people report SEGV's
-        * when freeing memory in this function */
        ftpState->reply_hdr = NULL;
     }
     requestUnlink(ftpState->request);
     if (ftpState->ctrl.buf) {
-       ftpState->ctrl.freefunc(ftpState->ctrl.buf);
-       /* this seems unnecessary, but people report SEGV's
-        * when freeing memory in this function */
+       memFreeBuf(ftpState->ctrl.size, ftpState->ctrl.buf);
        ftpState->ctrl.buf = NULL;
     }
     if (ftpState->data.buf) {
-       ftpState->data.freefunc(ftpState->data.buf);
-       /* this seems unnecessary, but people report SEGV's
-        * when freeing memory in this function */
+       memFreeBuf(ftpState->data.size, ftpState->data.buf);
        ftpState->data.buf = NULL;
     }
     if (ftpState->pathcomps)
@@ -1094,13 +1086,9 @@ ftpStart(FwdState * fwd)
        ftpState->user, ftpState->password);
     ftpState->state = BEGIN;
     ftpState->ctrl.last_command = xstrdup("Connect to server");
-    ftpState->ctrl.buf = memAllocate(MEM_4K_BUF);
-    ftpState->ctrl.freefunc = memFree4K;
-    ftpState->ctrl.size = 4096;
+    ftpState->ctrl.buf = memAllocBuf(4096, &ftpState->ctrl.size);
     ftpState->ctrl.offset = 0;
-    ftpState->data.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
-    ftpState->data.size = SQUID_TCP_SO_RCVBUF;
-    ftpState->data.freefunc = xfree;
+    ftpState->data.buf = memAllocBuf(SQUID_TCP_SO_RCVBUF, &ftpState->data.size);
     ftpScheduleReadControlReply(ftpState, 0);
 }
 
@@ -1282,7 +1270,6 @@ ftpReadControlReply(int fd, void *data)
 static void
 ftpHandleControlReply(FtpStateData * ftpState)
 {
-    char *oldbuf;
     wordlist **W;
     int bytes_used = 0;
     wordlistDestroy(&ftpState->ctrl.message);
@@ -1291,12 +1278,7 @@ ftpHandleControlReply(FtpStateData * ftpState)
     if (ftpState->ctrl.message == NULL) {
        /* didn't get complete reply yet */
        if (ftpState->ctrl.offset == ftpState->ctrl.size) {
-           oldbuf = ftpState->ctrl.buf;
-           ftpState->ctrl.buf = xcalloc(ftpState->ctrl.size << 1, 1);
-           xmemcpy(ftpState->ctrl.buf, oldbuf, ftpState->ctrl.size);
-           ftpState->ctrl.size <<= 1;
-           ftpState->ctrl.freefunc(oldbuf);
-           ftpState->ctrl.freefunc = xfree;
+           ftpState->ctrl.buf = memReallocBuf(ftpState->ctrl.buf, ftpState->ctrl.size << 1, &ftpState->ctrl.size);
        }
        ftpScheduleReadControlReply(ftpState, 0);
        return;
index e8fa6b9775efcad24625afb999e91cd04fd30adf..f2da9c69deb17a9ee8700feef23b8430c69dbbc1 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mem.cc,v 1.60 2002/02/13 17:22:36 hno Exp $
+ * $Id: mem.cc,v 1.61 2002/02/13 19:34:02 hno Exp $
  *
  * DEBUG: section 13    High Level Memory Pool Management
  * AUTHOR: Harvest Derived
@@ -62,6 +62,8 @@ static struct {
 static MemMeter StrCountMeter;
 static MemMeter StrVolumeMeter;
 
+static MemMeter HugeBufCountMeter;
+static MemMeter HugeBufVolumeMeter;
 
 /* local routines */
 
@@ -92,6 +94,15 @@ memStringStats(StoreEntry * sentry)
        "Other Strings",
        xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level),
        xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level));
+    storeAppendPrintf(sentry, "\n");
+}
+
+static void
+memBufStats(StoreEntry *sentry)
+{
+    storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n",
+       HugeBufCountMeter.level,
+       HugeBufVolumeMeter.level / 1024);
 }
 
 static void
@@ -100,6 +111,7 @@ memStats(StoreEntry * sentry)
     storeBuffer(sentry);
     memReport(sentry);
     memStringStats(sentry);
+    memBufStats(sentry);
     storeBufferFlush(sentry);
 }
 
@@ -173,6 +185,86 @@ memFreeString(size_t size, void *buf)
     pool ? memPoolFree(pool, buf) : xfree(buf);
 }
 
+/* Find the best fit MEM_X_BUF type */
+static mem_type
+memFindBufSizeType(size_t net_size, size_t * gross_size)
+{
+    mem_type type;
+    size_t size;
+    if (net_size <= 2*1024) {
+       type = MEM_2K_BUF;
+       size = 2*1024;
+    } else if (net_size <= 4*1024) {
+       type = MEM_4K_BUF;
+       size = 4*1024;
+    } else if (net_size <= 8*1024) {
+       type = MEM_8K_BUF;
+       size = 8*1024;
+    } else if (net_size <= 16*1024) {
+       type = MEM_16K_BUF;
+       size = 16*1024;
+    } else if (net_size <= 32*1024) {
+       type = MEM_32K_BUF;
+       size = 32*1024;
+    } else if (net_size <= 64*1024) {
+       type = MEM_64K_BUF;
+       size = 64*1024;
+    } else {
+       type = MEM_NONE;
+       size = net_size;
+    }
+    if (gross_size)
+       *gross_size = size;
+    return type;
+}
+
+/* allocate a variable size buffer using best-fit pool */
+void *
+memAllocBuf(size_t net_size, size_t * gross_size)
+{
+    mem_type type = memFindBufSizeType(net_size, gross_size);
+    if (type != MEM_NONE)
+       return memAllocate(type);
+    else {
+       memMeterInc(HugeBufCountMeter);
+       memMeterAdd(HugeBufVolumeMeter, *gross_size);
+       return xcalloc(1, net_size);
+    }
+}
+
+/* resize a variable sized buffer using best-fit pool */
+void *
+memReallocBuf(void *oldbuf, size_t net_size, size_t * gross_size)
+{
+    /* XXX This can be optimized on very large buffers to use realloc() */
+    int new_gross_size;
+    void *newbuf = memAllocBuf(net_size, &new_gross_size);
+    if (oldbuf) {
+       int data_size = *gross_size;
+       if (data_size > net_size)
+           data_size = net_size;
+       memcpy(newbuf, oldbuf, data_size);
+       memFreeBuf(*gross_size, oldbuf);
+    }
+    *gross_size = new_gross_size;
+    return newbuf;
+}
+
+/* free buffer allocated with memAllocBuf() */
+void
+memFreeBuf(size_t size, void *buf)
+{
+    mem_type type = memFindBufSizeType(size, NULL);
+    if (type != MEM_NONE)
+       memFree(buf, type);
+    else {
+       xfree(buf);
+       memMeterDec(HugeBufCountMeter);
+       memMeterDel(HugeBufVolumeMeter, size);
+    }
+}
+
+
 void
 memInit(void)
 {
@@ -240,7 +332,6 @@ memInit(void)
     memDataInit(MEM_HELPER_STATEFUL_REQUEST, "helper_stateful_request",
        sizeof(helper_stateful_request), 0);
     memDataInit(MEM_TLV, "storeSwapTLV", sizeof(tlv), 0);
-    memDataInit(MEM_CLIENT_REQ_BUF, "clientRequestBuffer", CLIENT_REQ_BUF_SZ, 0);
     memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0);
 
     /* init string pools */
@@ -284,7 +375,7 @@ memInUse(mem_type type)
 
 /* ick */
 
-void
+static void
 memFree2K(void *p)
 {
     memFree(p, MEM_2K_BUF);
@@ -302,20 +393,44 @@ memFree8K(void *p)
     memFree(p, MEM_8K_BUF);
 }
 
-void
+static void
 memFree16K(void *p)
 {
     memFree(p, MEM_16K_BUF);
 }
 
-void
+static void
 memFree32K(void *p)
 {
     memFree(p, MEM_32K_BUF);
 }
 
-void
+static void
 memFree64K(void *p)
 {
     memFree(p, MEM_64K_BUF);
 }
+
+FREE *
+memFreeBufFunc(size_t size)
+{
+    switch(size)
+    {
+    case 2*1024:
+       return memFree2K;
+    case 4*1024:
+       return memFree4K;
+    case 8*1024:
+       return memFree8K;
+    case 16*1024:
+       return memFree16K;
+    case 32*1024:
+       return memFree32K;
+    case 64*1024:
+       return memFree64K;
+    default:
+       memMeterDec(HugeBufCountMeter);
+       memMeterDel(HugeBufVolumeMeter, size);
+       return xfree;
+    }
+}
index 737114c9ad59aad744e735073acb9c544404ebf8..6ef763503e4f0a4e00bca2c90fd2eaac9ccd0237 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.424 2002/02/13 17:22:36 hno Exp $
+ * $Id: protos.h,v 1.425 2002/02/13 19:34:02 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -840,14 +840,14 @@ extern void memCleanModule(void);
 extern void memConfigure(void);
 extern void *memAllocate(mem_type);
 extern void *memAllocString(size_t net_size, size_t * gross_size);
+extern void *memAllocBuf(size_t net_size, size_t * gross_size);
+extern void *memReallocBuf(void *buf, size_t net_size, size_t * gross_size);
 extern void memFree(void *, int type);
-extern void memFreeString(size_t size, void *);
-extern void memFree2K(void *);
 extern void memFree4K(void *);
 extern void memFree8K(void *);
-extern void memFree16K(void *);
-extern void memFree32K(void *);
-extern void memFree64K(void *);
+extern void memFreeString(size_t size, void *);
+extern void memFreeBuf(size_t size, void *);
+extern FREE *memFreeBufFunc(size_t size);
 extern int memInUse(mem_type);
 extern size_t memTotalAllocated(void);
 extern void memDataInit(mem_type, const char *, size_t, int);
index 0151ca99630008b5f0c252a833e30abe36454915..5885ddf02191030fa58047df7b2a357d6f5cd8cc 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.408 2001/12/01 18:03:10 hno Exp $
+ * $Id: structs.h,v 1.409 2002/02/13 19:34:02 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -814,7 +814,7 @@ struct _MemBuf {
     /* 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 */
+    unsigned stolen:1;         /* the buffer has been stolen for use by someone else */
 };
 
 /* see Packer.c for description */