*** empty log message ***
authorMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 28 Mar 2003 21:09:29 +0000 (21:09 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 28 Mar 2003 21:09:29 +0000 (21:09 +0000)
33 files changed:
mmsoftware/bot/zenbot.c
mmsoftware/install.sh
mmsoftware/mmftpd/ChangeLog
mmsoftware/mmftpd/install.sh
mmsoftware/mmftpd/src/mmftpd.c
mmsoftware/mmftpd/src/mmftpd.h
mmsoftware/mmlib/Makefile
mmsoftware/mmlib/makepart.sh
mmsoftware/mmlib/mmfifo.3
mmsoftware/mmlib/mmfifo.h
mmsoftware/mmlib/mmlifo.3
mmsoftware/mmlib/mmlifo.h
mmsoftware/mmlib/mmlist.3
mmsoftware/mmlib/mmlist.h
mmsoftware/mmlib/mmpool.3 [new file with mode: 0644]
mmsoftware/mmlib/mmpool.c [new file with mode: 0644]
mmsoftware/mmlib/mmpool.h [new file with mode: 0644]
mmsoftware/mmlib/mmserver.c
mmsoftware/mmlib/mmserver.h
mmsoftware/mmlib/mmstat.h
mmsoftware/mmlib/mmstr.c
mmsoftware/mmlib/mmstr.h
mmsoftware/mmmail/ChangeLog
mmsoftware/mmmail/install.sh
mmsoftware/mmmail/src/mmpop3d/mmpop3d.c
mmsoftware/mmmail/src/mmpop3d/mmpop3d.h
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.c
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.h
mmsoftware/mmstatd/install.sh
mmsoftware/mmstatd/src/mmstat.c
mmsoftware/mmstatd/src/mmstatd.c
mmsoftware/mmstatd/src/mmstatd.h
mmsoftware/mmsucom/mmsucomd.c

index 5529332..def70cc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zenbot.c,v 1.3 2003/01/08 20:57:46 mmondor Exp $ */
+/* $Id: zenbot.c,v 1.4 2003/03/28 21:09:28 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
@@ -55,6 +55,7 @@
 #include <mmreadcfg.h>
 #include <mmfd.h>
 #include <mmlist.h>
+#include <mmpool.h>
 #include <mmlog.h>
 #include <mmstring.h>
 
@@ -63,7 +64,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: zenbot.c,v 1.3 2003/01/08 20:57:46 mmondor Exp $");
+MMRCSID("$Id: zenbot.c,v 1.4 2003/03/28 21:09:28 mmondor Exp $");
 
 
 
@@ -72,7 +73,7 @@ MMRCSID("$Id: zenbot.c,v 1.3 2003/01/08 20:57:46 mmondor Exp $");
 
 /* Defines a flood protection entry in a hash table */
 struct freq {
-    node nod;
+    pnode_t node;
     time_t expires;
     bool ignore;
     u_int64_t hash;
@@ -81,23 +82,24 @@ struct freq {
 
 /* An entry in the delayed output queue */
 struct cron {
-    node nod;
+    pnode_t node;
     time_t expires;
     char data[512];
 };
 
 /* A channel we joined */
 struct channel {
-    node nod;
+    pnode_t node;
     u_int64_t channel_hash;
-    list *channel_users;
+    pool_t pchannel_users;
+    list_t channel_users;
     int channel_limit, channel_mode;
     char channel_name[64], channel_key[16];
 };
 
 /* A user on a channel */
 struct user {
-    node nod;
+    pnode_t node;
     u_int64_t user_hash;
     int user_mode;
     char user_nick[64];
@@ -157,7 +159,7 @@ struct state {
 #define PING_RATE              10
 #define ALLOW_VER              1
 #define VER_RATE               10
-#define VER_STRING "$Id: zenbot.c,v 1.3 2003/01/08 20:57:46 mmondor Exp $"
+#define VER_STRING "$Id: zenbot.c,v 1.4 2003/03/28 21:09:28 mmondor Exp $"
 #define ANSWER_RATE            120     /* For zenbot replies frequency */
 #define INITIAL_UMODE          "+iw"
 
@@ -170,7 +172,7 @@ struct state {
 
 int main(int, char **);
 static void main_loop(struct info *);
-static int allow_entry(list *, char *, unsigned long, int, long);
+static int allow_entry(pool_t *, list_t *, char *, unsigned long, int, long);
 static bool irc_match(char *, char *);
 static void irc_parse(struct info *);
 static void user_add(char *, char *);
@@ -202,7 +204,8 @@ static char *zen(void);
 /* GLOBALS */
 
 /* Various slab-buffered linked lists */
-static list *lusers, *lhosts, *lcron, *lchans;
+static pool_t plusers, plhosts, plcron, plchans;
+static list_t lusers, lhosts, lcron, lchans;
 
 /* To map umode to bit number in umode bitfield */
 /* Modes which can be applied to ourself globally */
@@ -423,14 +426,15 @@ static void main_joined(struct info *data)
        /* We have joined a new channel, create new channel node with it's
         * users list
         */
-       if ((ch = (struct channel *)allocnode(lchans, TRUE))) {
-           if ((ch->channel_users = openlist(malloc, free,
-                                             sizeof(struct channel), 8192,
-                                             0))) {
+       if ((ch = (struct channel *)pool_alloc(&plchans, TRUE))) {
+           if (pool_init(&ch->pchannel_users, malloc, free,
+                       sizeof(struct user), 4096 / sizeof(struct user),
+                       0, 0)) {
+               LIST_INIT(&ch->channel_users);
                ch->channel_hash = mm_strhash64(data->text);
                mm_strcpy(ch->channel_name, data->text);
+               LIST_APPEND(&lchans, (node_t *)ch);
            }
-           APPENDNODE(lchans, (node *)ch);
        }
     } else {
        /* Another user joined one of the channels we are in, update
@@ -450,9 +454,9 @@ static void main_kicked(struct info *data)
        /* We have been kicked out of the channel, free all channel
         * info and send a delayed join request
         */
-       UNLINKNODE(lchans, (node *)ch);
-       closelist(ch->channel_users);
-       freenode((node *)ch);
+       LIST_UNLINK(&lchans, (node_t *)ch);
+       pool_destroy(&ch->pchannel_users);
+       pool_free((pnode_t *)ch);
        cron_add(REJOIN_DELAY, "JOIN :%s\r\n", data->param[0]);
     }
 }
@@ -465,9 +469,9 @@ static void main_parted(struct info *data)
     ch = user_del(data->param[0], data->nick);
     if (!mm_strcmp(data->nick, data->nickname)) {
        /* We have left a channel, free all channel info */
-       UNLINKNODE(lchans, (node *)ch);
-       closelist(ch->channel_users);
-       freenode((node *)ch);
+       LIST_UNLINK(&lchans, (node_t *)ch);
+       pool_destroy(&ch->pchannel_users);
+       pool_free((pnode_t *)ch);
     }
 }
 
@@ -478,12 +482,11 @@ static void main_quitted(struct info *data)
     user_del(NULL, data->nick);
     if (!mm_strcmp(data->nick, data->nickname)) {
        /* We have quitted, free all channel info */
-       ch = (struct channel *)lchans->top;
+       ch = (struct channel *)lchans.top;
        while (ch) {
-           tmp = (struct channel *)ch->nod.next;
-           closelist(ch->channel_users);
-           UNLINKNODE(lchans, (node *)ch);
-           freenode((node *)ch);
+           tmp = (struct channel *)ch->node.node.next;
+           LIST_UNLINK(&lchans, (node_t *)ch);
+           pool_free((pnode_t *)ch);
            ch = tmp;
        }
     }
@@ -502,19 +505,19 @@ static void main_nick(struct info *data)
     hash = mm_strhash64(data->nick);
     nhash = mm_strhash64(data->text);
 
-    ch = (struct channel *)lchans->top;
+    ch = (struct channel *)lchans.top;
     while (ch) {
-       us = (struct user *)ch->channel_users->top;
+       us = (struct user *)ch->channel_users.top;
        while (us) {
            if (us->user_hash == hash)
                break;
-           us = (struct user *)us->nod.next;
+           us = (struct user *)us->node.node.next;
        }
        if (us) {
            us->user_hash = nhash;
            mm_strcpy(us->user_nick, data->text);
        }
-       ch = (struct channel *)ch->nod.next;
+       ch = (struct channel *)ch->node.node.next;
     }
     /*
     if (!mm_strcmp(data->nick, data->nickname)) {
@@ -600,18 +603,23 @@ int main(int argc, char **argv)
     /* Zen setup */
     zen_init();
 
-    /* Setup our hash table buffers for user and host flood quotas */
-    if ((lusers = openlist(malloc, free, sizeof(struct freq), 8192, 0))) {
-       if ((lhosts = openlist(malloc, free, sizeof(struct freq), 8192, 0))) {
-           if ((lcron = openlist(malloc, free, sizeof(struct cron), 8192,
-                           0))) {
-               if ((lchans = openlist(malloc, free, sizeof(struct channel),
-                               8192, 0))) {
+    if (pool_init(&plusers, malloc, free, sizeof(struct freq),
+               8192 / sizeof(struct freq), 0, 0)) {
+       LIST_INIT(&lusers);
+       if (pool_init(&plhosts, malloc, free, sizeof(struct freq),
+                   8192 / sizeof(struct freq), 0, 0)) {
+           LIST_INIT(&lhosts);
+           if (pool_init(&plcron, malloc, free, sizeof(struct cron),
+                       8192 / sizeof(struct cron), 0, 0)) {
+               LIST_INIT(&lcron);
+               if (pool_init(&plchans, malloc, free,
+                           sizeof(struct channel),
+                           8192 / sizeof(struct channel), 0, 0)) {
+                   LIST_INIT(&lchans);
                    /* Prepare our fd buffering wrapper */
-                   if ((data.fdb =
-                        fdbopen(&fdf, NULL, -1, 4096, 4096, 1024, 1024,
-                                INPUT_TIMEOUT * 1000,
-                                INPUT_TIMEOUT * 1000))) {
+                   if ((data.fdb = fdbopen(&fdf, NULL, -1, 4096, 4096, 1024,
+                                   1024, INPUT_TIMEOUT * 1000,
+                                   INPUT_TIMEOUT * 1000))) {
                        /* Loop indefinitely */
                        while (TRUE) {
                            /* Connect to server */
@@ -622,18 +630,17 @@ int main(int argc, char **argv)
                                    client.sin_addr.s_addr = iaddr.s_addr;
                                    client.sin_port = htons(port);
                                    if ((connect(fd,
-                                        (struct sockaddr *)&client,
-                                        sizeof(struct sockaddr_in))) != -1) {
+                                           (struct sockaddr *)&client,
+                                           sizeof(struct sockaddr_in)))
+                                           != -1) {
                                        fcntl(fd, F_SETFL, O_NONBLOCK);
-                                       fdbparam_set(data.fdb, fd,
-                                                    FDBP_FD);
+                                       fdbparam_set(data.fdb, fd, FDBP_FD);
                                        /* Serve our purpose */
                                        data.state = &states[STATE_IDENT];
                                        main_loop(&data);
                                        fdbflushr(data.fdb);
                                        fdbflushw(data.fdb);
-                                       fdbparam_set(data.fdb, -1,
-                                                    FDBP_FD);
+                                       fdbparam_set(data.fdb, -1, FDBP_FD);
                                    } else
                                        sleep(30);
                                }
@@ -642,13 +649,13 @@ int main(int argc, char **argv)
                        }
                        fdbclose(data.fdb);
                    }
-                   closelist(lchans);
+                   pool_destroy(&plchans);
                }
-               closelist(lcron);
+               pool_destroy(&plcron);
            }
-           closelist(lhosts);
+           pool_destroy(&plhosts);
        }
-       closelist(lusers);
+       pool_destroy(&plusers);
     }
 
     exit(0);
@@ -685,13 +692,13 @@ static void main_loop(struct info *data)
         * on multiple channels.
         */
        t = time(NULL);
-       nod = (struct cron *)lcron->top;
+       nod = (struct cron *)lcron.top;
        while (nod) {
-           tmp = (struct cron *)nod->nod.next;
+           tmp = (struct cron *)nod->node.node.next;
            if (nod->expires < t) {
-               UNLINKNODE(lcron, (node *)nod);
+               LIST_UNLINK(&lcron, (node_t *)nod);
                fdbputs(data->fdb, nod->data);
-               freenode((node *)nod);
+               pool_free((pnode_t *)nod);
            }
            nod = tmp;
        }
@@ -735,10 +742,10 @@ static void main_loop(struct info *data)
                bool allow = FALSE;
 
                /* Check against flood by ident and hostname */
-               if (!(res = allow_entry(lhosts, data->host, FLOOD_HOST_MAX,
-                                       FLOOD_HOST_TIME,
+               if (!(res = allow_entry(&plhosts, &lhosts, data->host,
+                               FLOOD_HOST_MAX, FLOOD_HOST_TIME,
                                        FLOOD_HOST_IGNORE))) {
-                   if (!(res = allow_entry(lusers, data->ident,
+                   if (!(res = allow_entry(&plusers, &lusers, data->ident,
                                    FLOOD_USER_MAX, FLOOD_USER_TIME,
                                    FLOOD_USER_IGNORE)))
                        allow = TRUE;
@@ -789,45 +796,45 @@ static void main_loop(struct info *data)
  * it just started to be ignored.
  */
 static int
-allow_entry(list *lst, char *entry, unsigned long max, int secs,
-           long igndelay)
+allow_entry(pool_t *pool, list_t *lst, char *entry, unsigned long max,
+       int secs, long igndelay)
 {
     u_int64_t hash = mm_strhash64(entry);
     int ret = 0;
-    struct freq *nod, *tmp;
+    struct freq *node, *tmp;
     time_t t = time(NULL);
 
     /* Locate if entry exists */
-    nod = (struct freq *)lst->top;
-    while (nod) {
-       tmp = (struct freq *)nod->nod.next;
-       if (nod->expires < t) {
+    node = (struct freq *)lst->top;
+    while (node) {
+       tmp = (struct freq *)node->node.node.next;
+       if (node->expires < t) {
            /* Expired, drop this entry */
-           UNLINKNODE(lst, (node *)nod);
-           freenode((node *)nod);
-       } else if (nod->hash == hash)
+           LIST_UNLINK(lst, (node_t *)node);
+           pool_free((pnode_t *)node);
+       } else if (node->hash == hash)
            break;
-       nod = tmp;
+       node = tmp;
     }
-    if (nod) {
+    if (node) {
        /* Entry existed, increase frequency and optionally toggle ignore */
-       nod->freq++;
-       if (!nod->ignore) {
-           if (nod->freq > max) {
-               nod->ignore = TRUE;
-               nod->expires += igndelay;
+       node->freq++;
+       if (!node->ignore) {
+           if (node->freq > max) {
+               node->ignore = TRUE;
+               node->expires += igndelay;
                ret = 2;
            }
        } else
            ret = 1;
     } else {
        /* Add new entry */
-       if ((nod = (struct freq *)allocnode(lst, FALSE))) {
-           nod->expires = t + secs;
-           nod->ignore = FALSE;
-           nod->hash = hash;
-           nod->freq = 1;
-           APPENDNODE(lst, (node *)nod);
+       if ((node = (struct freq *)pool_alloc(pool, FALSE))) {
+           node->expires = t + secs;
+           node->ignore = FALSE;
+           node->hash = hash;
+           node->freq = 1;
+           LIST_APPEND(lst, (node_t *)node);
        }
     }
 
@@ -965,22 +972,22 @@ static void user_add(char *chan, char *nick)
     nickhash = mm_strhash64(nick);
 
     /* Find channel user should be added to */
-    ch = (struct channel *)lchans->top;
+    ch = (struct channel *)lchans.top;
     while (ch) {
        if (ch->channel_hash == chanhash)
            break;
-       ch = (struct channel *)ch->nod.next;
+       ch = (struct channel *)ch->node.node.next;
     }
     if (ch) {
        /* We found channel */
-       if ((us = (struct user *)allocnode(ch->channel_users, FALSE))) {
+       if ((us = (struct user *)pool_alloc(&ch->pchannel_users, FALSE))) {
            mm_strcpy(us->user_nick, nick);
            us->user_hash = nickhash;
            us->user_mode = mode;
 #ifdef DEBUG
            printf("ADDED USER '%s' TO CHANNEL '%s'\n", nick, chan);
 #endif
-           APPENDNODE(ch->channel_users, (node *)us);
+           LIST_APPEND(&ch->channel_users, (node_t *)us);
        }
     }
 }
@@ -1001,24 +1008,24 @@ static struct channel *user_del(char *chan, char *nick)
        /* Delete user on specified channel */
        mm_strlower(chan);
        chanhash = mm_strhash64(chan);
-       ch = (struct channel *)lchans->top;
+       ch = (struct channel *)lchans.top;
        while (ch) {
            if (ch->channel_hash == chanhash)
                break;
-           ch = (struct channel *)ch->nod.next;
+           ch = (struct channel *)ch->node.node.next;
        }
        if (ch) {
            /* We found channel */
-           us = (struct user *)ch->channel_users->top;
+           us = (struct user *)ch->channel_users.top;
            while (us) {
                if (us->user_hash == nickhash)
                    break;
-               us = (struct user *)us->nod.next;
+               us = (struct user *)us->node.node.next;
            }
            if (us) {
                /* We found nick */
-               UNLINKNODE(ch->channel_users, (node *)us);
-               freenode((node *)us);
+               LIST_UNLINK(&ch->channel_users, (node_t *)us);
+               pool_free((pnode_t *)us);
 #ifdef DEBUG
                printf("DELETED USER '%s' FROM CHANNEL '%s'\n", nick,
                       chan);
@@ -1027,18 +1034,18 @@ static struct channel *user_del(char *chan, char *nick)
        }
     } else {
        /* Delete user on all channels */
-       ch = (struct channel *)lchans->top;
+       ch = (struct channel *)lchans.top;
        while (ch) {
-           us = (struct user *)ch->channel_users->top;
+           us = (struct user *)ch->channel_users.top;
            while (us) {
                if (us->user_hash == nickhash) {
-                   UNLINKNODE(ch->channel_users, (node *)us);
-                   freenode((node *)us);
+                   LIST_UNLINK(&ch->channel_users, (node_t *)us);
+                   pool_free((pnode_t *)us);
                    break;
                }
-               us = (struct user *)us->nod.next;
+               us = (struct user *)us->node.node.next;
            }
-           ch = (struct channel *)ch->nod.next;
+           ch = (struct channel *)ch->node.node.next;
        }
 #ifdef DEBUG
        printf("DELETED USER '%s' FROM ALL CHANNELS\n", nick);
@@ -1056,12 +1063,12 @@ static void cron_add(int secs, char *fmt, ...)
     time_t t = time(NULL);
     va_list arg_ptr;
 
-    if ((nod = (struct cron *)allocnode(lcron, FALSE))) {
+    if ((nod = (struct cron *)pool_alloc(&plcron, FALSE))) {
        nod->expires = t + secs;
        va_start(arg_ptr, fmt);
        vsnprintf(nod->data, 1023, fmt, arg_ptr);
        va_end(arg_ptr);
-       APPENDNODE(lcron, (node *)nod);
+       LIST_APPEND(&lcron, (node_t *)nod);
     }
 }
 
index 8843bcd..7f98805 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: install.sh,v 1.5 2003/02/18 11:54:03 mmondor Exp $
+# $Id: install.sh,v 1.6 2003/03/28 21:09:28 mmondor Exp $
 
 if [ "$1" = "help" ]; then
        echo
@@ -113,6 +113,7 @@ instman mmfd.3 3
 instman mmfifo.3 3
 instman mmlifo.3 3
 instman mmlist.3 3
+instman mmpool.3 3
 instman mmpath.3 3
 instman mmstat.3 3
 cd ../
@@ -182,8 +183,8 @@ echo "all users: mmstat(8), mmstatd(8), mmstatd.conf(5) mmpasswd(8)"
 echo "mmftpd users: mmftpd(8), mmftpd.conf(5), mmftpdpasswd(5)"
 echo "mmmail users: mmmail(8), mmsmtpd(8), mmsmtpd.conf(5), mmpop3d(8),"
 echo "              mmpop3d.conf(5)"
-echo "source auditors: mmstat(3), mmfd(3), mmlist(3), mmfifo(3), mmlifo(3),"
-echo "                 mmpath(3)"
+echo "source auditors: mmstat(3), mmfd(3), mmlist(3), mmpool(3), mmfifo(3),"
+echo "                 mmlifo(3), mmpath(3)"
 echo
 echo "Thank you for using mmsoftware."
 echo
index 5293b6a..99c0080 100644 (file)
@@ -1,9 +1,9 @@
-$Id: ChangeLog,v 1.11 2003/03/02 20:30:43 mmondor Exp $
+$Id: ChangeLog,v 1.12 2003/03/28 21:09:28 mmondor Exp $
 
 
 
 Release: mmftpd 0.0.16 devl
-Date   : Febuary 23, 2003
+Date   : March 28, 2003
 By     : Matthew Mondor
 
 * Miscelaneous new features
@@ -17,8 +17,10 @@ By     : Matthew Mondor
     startup and disconnection. These FIFOs are used to remember which
     directories were visited recently to not flood the user with README file
     contents, when enabled.
-  - Fixed ALIGN_FLOOR alignment macros which used to always add bytes even
-    of the value was already aligned properly.
+  - Fixed ALIGN_CEIL alignment macros which used to always add bytes even
+    if the value was already aligned properly.
+  - Interface of various lower layer functions and macros were improved, and
+    mmftpd was migrated to use the new ones.
 
 
 
index 7b6a963..0310bda 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: install.sh,v 1.3 2003/01/10 03:52:36 mmondor Exp $
+# $Id: install.sh,v 1.4 2003/03/28 21:09:28 mmondor Exp $
 
 if [ "$1" = "help" ]; then
        echo
@@ -99,6 +99,7 @@ cd ../mmlib/
 instman mmfd.3 3
 instman mmfifo.3 3
 instman mmlist.3 3
+instman mmpool.3 3
 instman mmpath.3 3
 instman mmstat.3 3
 cd ../
@@ -144,7 +145,8 @@ echo "*** Please read the following man pages ***"
 echo
 echo "mmstat(8), mmstatd(8), mmstatd.conf(5) mmpasswd(8)"
 echo "mmftpd(8), mmftpd.conf(5), mmftpdpasswd(5)"
-echo "source auditors: mmstat(3), mmfd(3), mmlist(3), mmfifo(3), mmpath(3)"
+echo "source auditors: mmstat(3), mmfd(3), mmlist(3), mmpool(3), mmfifo(3),
+echo "                 mmpath(3)"
 echo
 echo "Thank you for using mmsoftware."
 echo
index 36ade47..0389949 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmftpd.c,v 1.13 2003/02/13 00:12:31 mmondor Exp $ */
+/* $Id: mmftpd.c,v 1.14 2003/03/28 21:09:28 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
@@ -62,6 +62,7 @@
 #include <mmreadcfg.h>
 #include <mmfd.h>
 #include <mmlist.h>
+#include <mmpool.h>
 #include <mmserver.h>
 #include <mmpath.h>
 #include <mmlog.h>
@@ -76,7 +77,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmftpd.c,v 1.13 2003/02/13 00:12:31 mmondor Exp $");
+MMRCSID("$Id: mmftpd.c,v 1.14 2003/03/28 21:09:28 mmondor Exp $");
 
 
 
@@ -105,16 +106,17 @@ static pth_attr_t tthreadattr;
 
 /* List of logged in users and optionally current home directory size */
 static pth_mutex_t lusers_lock;
-static list *lusers;
+static pool_t plusers;
+static list_t lusers;
 
 /* This is used so that clientenv structures be allocated/freed fast */
 static pth_mutex_t clenvs_lock;
-static list *clenvs;
-static list *fifos;
+static pool_t pclenvs;
+static pool_t pfifos;
 
 /* Pool used to optimize creatiing/destroying mmfd mutexes */
 static pth_mutex_t mutexes_lock;
-static list *mutexes;
+static pool_t pmutexes;
 
 /* Global bandwidth shaping context */
 static fdbcontext fdbc;
@@ -606,8 +608,8 @@ auth_pass(clientenv *clenv)
        pth_mutex_acquire(&lusers_lock, FALSE, NULL);
 
        /* Verify if user in list */
-       for (lun = (lusernode *)lusers->top, uhash = mm_strhash64(clenv->user);
-               lun; lun = (lusernode *)lun->nod.next)
+       for (lun = (lusernode *)&lusers.top, uhash = mm_strhash64(clenv->user);
+               lun; lun = (lusernode *)lun->node.node.next)
            if (uhash == lun->hash) break;
        if (lun) {
            /* Yes, make sure we observe limits if any */
@@ -627,7 +629,7 @@ auth_pass(clientenv *clenv)
            if (!clenv->maxlogins || 1 <= clenv->maxlogins) {
                /* Add new user entry, and optionally record current tree size
                 */
-               if ((lun = (lusernode *)allocnode(lusers, FALSE))) {
+               if ((lun = (lusernode *)pool_alloc(&plusers, FALSE))) {
                    lun->hash = uhash;
                    pth_mutex_init(&lun->lock);
                    lun->logins = 1;
@@ -638,18 +640,18 @@ auth_pass(clientenv *clenv)
                                    "* auth_pass() - treesize(%s)",
                                    clenv->home);
                            nextstate = STATE_ERROR;
-                           lun = (lusernode *)freenode((node *)lun);
+                           lun = (lusernode *)pool_free((pnode_t *)lun);
                        }
                    } else
                        lun->homesize = 0;
                } else {
                    mmsyslog(0, LOGLEVEL,
-                           "* auth_pass() - allocnode(lusers)");
+                           "* auth_pass() - pool_alloc(plusers)");
                    nextstate = STATE_ERROR;
                }
                if (lun) {
                    clenv->unode = lun;
-                   APPENDNODE(lusers, (node *)lun);
+                   LIST_APPEND(&lusers, (node_t *)lun);
                    if (clenv->anonymous)
                        reply(fdb, 230, FALSE,
                                "Restricted anonymous login ok");
@@ -2506,20 +2508,23 @@ main(int argc, char **argv)
 
     /* Initialize our pools */
     /* Client environment nodes */
-    clenvs = openlist(malloc, free, sizeof(clientenv),
-           65535 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&pclenvs, malloc, free, sizeof(clientenv),
+           (65536 * CONF.ALLOC_BUFFERS) / sizeof(clientenv), 0, 0);
     /* User-shared state nodes */
-    lusers = openlist(malloc, free, sizeof(lusernode),
-           32768 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&plusers, malloc, free, sizeof(lusernode),
+           (32768 * CONF.ALLOC_BUFFERS) / sizeof(lusernode), 0, 0);
+    LIST_INIT(&lusers);
     /* Mutexes pool for mmfd */
-    mutexes = openlist(malloc, free, sizeof(struct mutexnode),
-           16386 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&pmutexes, malloc, free, sizeof(struct mutexnode),
+           (16384 * CONF.ALLOC_BUFFERS) / sizeof(struct mutexnode), 0, 0);
     /* FIFO buffer nodes */
-    fifos = openlist(malloc, free, sizeof(struct fifonode) +
-           (sizeof(u_int64_t) * (CONF.REMEMBER_CWDS + 1)),
-           16386 * CONF.ALLOC_BUFFERS, 0);
+    if (*CONF.DISPLAY_FILE)
+       pool_init(&pfifos, malloc, free, sizeof(struct fifonode) +
+               (CONF.REMEMBER_CWDS * sizeof(u_int64_t)),
+               CONF.ALLOC_BUFFERS * 64, 0, 0);
 
-    if (clenvs && lusers && mutexes && fifos) {
+    if (POOL_VALID(&pclenvs) && POOL_VALID(&plusers) && POOL_VALID(&pmutexes)
+           && (!*CONF.DISPLAY_FILE || POOL_VALID(&pfifos))) {
        fdbcinit(&gfdf, &fdbc, CONF.GBANDWIDTH_IN * 1024,
                CONF.GBANDWIDTH_OUT * 1024);
        /* Finally start our TCP main daemon */
@@ -2535,9 +2540,10 @@ main(int argc, char **argv)
     }
 
     mmfreegidarray(gids);
-    if (mutexes) closelist(mutexes);
-    if (lusers) closelist(lusers);
-    if (clenvs) closelist(clenvs);
+    if (POOL_VALID(&pfifos)) pool_destroy(&pfifos);
+    if (POOL_VALID(&pmutexes)) pool_destroy(&pmutexes);
+    if (POOL_VALID(&plusers)) pool_destroy(&plusers);
+    if (POOL_VALID(&pclenvs)) pool_destroy(&pclenvs);
 
     exit(ret);
 }
@@ -2810,16 +2816,16 @@ alloc_clientenv(void)
     struct fifonode *fnode = NULL;
 
     pth_mutex_acquire(&clenvs_lock, FALSE, NULL);
-    clenv = (clientenv *)allocnode(clenvs, TRUE);
+    clenv = (clientenv *)pool_alloc(&pclenvs, TRUE);
     if (*CONF.DISPLAY_FILE)
-       fnode = (struct fifonode *)allocnode(fifos, FALSE);
+       fnode = (struct fifonode *)pool_alloc(&pfifos, FALSE);
     pth_mutex_release(&clenvs_lock);
 
     if (clenv) {
        if (!(*CONF.DISPLAY_FILE) || fnode) {
            if (fnode) {
                clenv->fifobuf = fnode;
-               INITFIFO(&clenv->visited, fnode->buf, CONF.REMEMBER_CWDS);
+               FIFO_INIT(&clenv->visited, fnode->buf, CONF.REMEMBER_CWDS);
            } else clenv->fifobuf = NULL;
            mmstat_init(&clenv->vstat, TRUE, TRUE);
            mmstat_init(&clenv->pstat, TRUE, FALSE);
@@ -2829,7 +2835,7 @@ alloc_clientenv(void)
     } else {
        if (fnode) {
            pth_mutex_acquire(&clenvs_lock, FALSE, NULL);
-           freenode((node *)fnode);
+           pool_free((pnode_t *)fnode);
            pth_mutex_release(&clenvs_lock);
        }
     }
@@ -2855,17 +2861,17 @@ free_clientenv(clientenv *clenv)
        pth_mutex_acquire(&lusers_lock, FALSE, NULL);
        clenv->unode->logins--;
        if (clenv->unode->logins < 1) {
-           UNLINKNODE(lusers, (node *)clenv->unode);
+           LIST_UNLINK(&lusers, (node_t *)clenv->unode);
            /* May be required by some POSIX thread implementations */
            /* pth_mutex_destroy(&clenv->unode->lock); */
-           freenode((node *)clenv->unode);
+           pool_free((pnode_t *)clenv->unode);
        }
        pth_mutex_release(&lusers_lock);
     }
 
     pth_mutex_acquire(&clenvs_lock, FALSE, NULL);
-    if (fnode) freenode((node *)fnode);
-    freenode((node *)clenv);
+    if (fnode) pool_free((pnode_t *)fnode);
+    pool_free((pnode_t *)clenv);
     pth_mutex_release(&clenvs_lock);
 
     return (NULL);
@@ -2989,56 +2995,30 @@ file_out(fdbuf *fdb, char *filename)
 static bool
 directory_message(clientenv *clenv, int code)
 {
-    bool res = TRUE, found;
+    bool res = TRUE;
     char path[MMPATH_MAX];
-    u_int64_t dhash, tmp;
+    u_int64_t dhash;
 
     if (*CONF.DISPLAY_FILE) {
        if (valid_path(path, NULL, clenv->home, clenv->cwd,
                    CONF.DISPLAY_FILE, FALSE, FALSE)
                && exists(path, NULL, NULL, clenv->checkowner)
                == MMPATH_FILE) {
+           u_int64_t *ptr;
+
            /* Make sure that this directory was not visited recently. */
            dhash = mm_strhash64(clenv->cwd);
-           found = FALSE;
-           {
-               /* Cache in registers pointers to data that need to be used
-                * every loop instance for faster lookup
-                */
-               register u_int64_t *h, *b, *e, *p, *t;
-               register int cnt;
-
-               h = &dhash;
-               b = clenv->visited.buffer;
-               e = clenv->visited.endbuffer;
-               p = clenv->visited.tail;
-               t = clenv->visited.head;
-               cnt = 0;
-               while (p != t) {
-                   if (*p == *h) {
-                       found = TRUE;
-                       break;
-                   }
-                   p++;
-                   if (p == e) p = b;
-                   cnt++;
-                   if (cnt > 64) {
-                       cnt = 0;
-                       pth_yield(NULL);
-                   }
-               }
-           }
-           if (!found) {
+           FIFO_FIND(&clenv->visited, &ptr, &dhash);
+           if (ptr == NULL) {
                /* This directory was not visited recently, send out file */
                if (!reply(clenv->fdb, code, TRUE, NULL))
                    res = FALSE;
                file_out(clenv->fdb, path);
            }
-           /* Store current directory hash at end of FIFO, free an entry
-            * if required.
+           /* Store current directory hash at end of FIFO, freeing the oldest
+            * entry automatically if required (buffer full).
             */
-           if (FULLFIFO(&clenv->visited)) GETFIFO(&clenv->visited, &tmp);
-           PUTFIFO(&clenv->visited, &dhash);
+           FIFO_PUT(&clenv->visited, &dhash);
        }
     }
 
@@ -4072,7 +4052,7 @@ _pth_mutex_create(void)
     struct mutexnode *mnod;
 
     pth_mutex_acquire(&mutexes_lock, FALSE, NULL);
-    mnod = (struct mutexnode *)allocnode(mutexes, FALSE);
+    mnod = (struct mutexnode *)pool_alloc(&pmutexes, FALSE);
     pth_mutex_release(&mutexes_lock);
 
     if (mnod)
@@ -4089,7 +4069,7 @@ _pth_mutex_destroy(void *mtx)
 
     /* pth_mutex_destroy(&mnod->mutex); */
     pth_mutex_acquire(&mutexes_lock, FALSE, NULL);
-    freenode(mtx);
+    pool_free(mtx);
     pth_mutex_release(&mutexes_lock);
 
     return (NULL);
index fcf6f98..c9aeee2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmftpd.h,v 1.8 2003/02/18 11:54:03 mmondor Exp $ */
+/* $Id: mmftpd.h,v 1.9 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -48,6 +48,8 @@
 #include <mmfd.h>
 #include <mmpath.h>
 #include <mmserver.h>
+#include <mmlist.h>
+#include <mmpool.h>
 #include <mmfifo.h>
 #include <mmstat.h>
 #include <mmserver.h>
@@ -161,7 +163,7 @@ typedef struct transfermsg {
  * functions of all states
  */
 typedef struct clientenv {
-    node nod;
+    pnode_t node;
     unsigned long id;            /* Our unique connection ID */
     int timeout;                 /* Control connection timeout in ms */
     int gid;                     /* Group set to new files */
@@ -211,7 +213,7 @@ typedef struct clientenv {
  * to share a common current home directory size value.
  */
 typedef struct lusernode {
-    node nod;
+    pnode_t node;
     u_int64_t hash;              /* User name hash */
     pth_mutex_t lock;            /* For treesize_edit() */
     long logins;                 /* Simultanious current logins for user */
@@ -220,14 +222,15 @@ typedef struct lusernode {
 
 /* Used for mmfd thread support delegation/abstraction */
 struct mutexnode {
-    node nod;
+    pnode_t node;
     pth_mutex_t mutex;
 };
 
 /* Used to efficiently allocate FIFO buffers */
 struct fifonode {
-    node nod;
+    pnode_t node;
     u_int64_t buf[1];
+    /* Will be expanded here */
 };
 
 /* This defines a state */
index 2ff38d3..abe6ca3 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 2003/01/08 20:57:46 mmondor Exp $
+# $Id: Makefile,v 1.4 2003/03/28 21:09:29 mmondor Exp $
 
 CC = gcc
 MAKE = make
@@ -14,7 +14,7 @@ PTH != $(ECHO) `pth-config --cflags`
 MYSQL != $(ECHO) `mysql_config --cflags`
 INCDIR = -I/usr/include -I/usr/local/include -I. $(PTH) $(MYSQL)
 
-OBJS = mmlist.o mmfd.o mmrc4.o mmserver.o mmpath.o mmlog.o mmstr.o mmsql.o mmfifo.o mmreadcfg.o mmstring.o mmloadarray.o mmstat.o mmbstring.o
+OBJS = mmpool.o mmfd.o mmrc4.o mmserver.o mmpath.o mmlog.o mmstr.o mmsql.o mmreadcfg.o mmstring.o mmloadarray.o mmstat.o mmbstring.o
 
 CCOBJ = $(CC) $(CFLAGS) -c $(INCDIR)
 
@@ -32,8 +32,8 @@ clean:
 
 
 
-mmlist.o:
-       $(CCOBJ) mmlist.c
+mmpool.o:
+       $(CCOBJ) mmpool.c
 
 mmfd.o:
        $(CCOBJ) mmfd.c
@@ -56,9 +56,6 @@ mmstr.o:
 mmsql.o:
        $(CCOBJ) mmsql.c
 
-mmfifo.o:
-       $(CCOBJ) mmfifo.c
-
 mmreadcfg.o:
        $(CCOBJ) mmreadcfg.c
 
index e4fc6ae..a771f57 100755 (executable)
@@ -1,10 +1,10 @@
 #!/bin/sh
-# $Id: makepart.sh,v 1.3 2003/01/08 20:57:46 mmondor Exp $
+# $Id: makepart.sh,v 1.4 2003/03/28 21:09:29 mmondor Exp $
 
 . ./makedefs.sh
 
-OBJS="mmlist.o mmfd.o mmrc4.o mmserver.o mmpath.o mmlog.o mmstr.o \
-mmsql.o mmfifo.o mmreadcfg.o mmstring.o mmloadarray.o mmstat.o mmbstring.o"
+OBJS="mmpool.o mmfd.o mmrc4.o mmserver.o mmpath.o mmlog.o mmstr.o \
+mmsql.o mmreadcfg.o mmstring.o mmloadarray.o mmstat.o mmbstring.o"
 
 if [ "$1" = "clean" ]; then
        show $RM $OBJS libmmondor.a
index 937f10a..bff2610 100644 (file)
@@ -1,41 +1,49 @@
-.\" $Id: mmfifo.3,v 1.3 2003/02/13 00:12:31 mmondor Exp $
+.\" $Id: mmfifo.3,v 1.4 2003/03/28 21:09:29 mmondor Exp $
 .Dd Feb 11, 2003
 .Os
 .Dt MMFIFO 3
 .Sh NAME
 .Nm mmfifo
-.Nd General purpose portable FIFO buffers library.
+.Nd General purpose portable and versatile FIFO buffers library.
 .Sh SYNOPSIS
 .Fd #include <sys/types.h>
 .Fd #include <mmtypes.h>
 .Fd #include <mmfifo.h>
 .Ft void
-.Fn DEFINEFIFO "fifotype_t" "objecttype"
+.Fn FIFO_DEFINE "fifotype_t" "objecttype"
 .Ft void
-.Fn INITFIFO "fifotype_t *fifo" "void *buffer" "u_int32_t size"
+.Fn FIFO_INIT "fifotype_t *fifo" "void *buffer" "u_int32_t size"
 .Ft bool
-.Fn FULLFIFO "fifotype_t *fifo"
+.Fn FIFO_FULL "fifotype_t *fifo"
+.Ft bool
+.Fn FIFO_EMPTY "fifotype_t *fifo"
+.Ft u_int32_t
+.Fn FIFO_STAT "fifotype_t *fifo"
 .Ft u_int32_t
-.Fn STATFIFO "fifotype_t *fifo"
+.Fn FIFO_AVAIL "fifotype_t *fifo"
+.Ft void
+.Fn FIFO_FLUSH "fifotype_t *fifo"
+.Ft void
+.Fn FIFO_PUT "fifotype_t *fifo" "objecttype *element"
 .Ft void
-.Fn FLUSHFIFO "fifotype_t *fifo"
+.Fn FIFO_GET "fifotype_t *fifo" "objecttype *element"
 .Ft void
-.Fn GETFIFO "fifotype_t *fifo, objecttype *element"
+.Fn FIFO_FIND "fifotype_t *fifo" "objecttype **pointer" "objecttype *element"
 .Ft void
-.Fn PUTFIFO "fifotype_t *fifo, objecttype *element"
-.Ft size_t
-.Fn getnfifo8 "u_int8_t *buffer" "fifo8_t *fifo" "size_t max"
-.Ft size_t
-.Fn putnfifo8 "fifo8_t *fifo" "u_int8_t *buffer" "size_t size"
+.Fn FIFO_ALLOC "fifotype_t *fifo" "objecttype **pointer" "u_int32_t *actual" \
+"u_int32_t size"
+.Ft void
+.Fn FIFO_FREE "fifotype_t *fifo" "objecttype **pointer" "u_int32_t *actual" \
+"u_int32_t size"
 .Sh DESCRIPTION
-FIFO buffers (First In First Out) are usually especially useful when
+FIFO buffers (First In First Out) are especially useful when
 implementing asynchronous systems. For instance in the implementation of
 serial RS-232 read/write functions, a trap or interrupt occurs when a byte
 is available to read or when the device is ready to be written more data to.
 The user API has to be able to be used at anytime however so that the
 application may read and write bytes at any time (in fact queueing them for
 the trap handler). So two FIFO buffers are required, user API and the trap
-handler each share one side of each queue. Unlike a simple buffer, each side
+handler, each share one side of each queue. Unlike a simple buffer, each side
 do not know when the other side will insert or unqueue elements at the other
 end. It therefore is extremely useful to synchronize two asynchonous
 applications.
@@ -46,10 +54,10 @@ objects. These are not implemented as linked lists but as fixed buffers
 which can hold a maximum number of fixed-sized elements. They also leave
 the user application the responsibility to allocate and free the buffers
 (explained in the
-.Fn INITFIFO
+.Fn FIFO_INIT
 section).
 .Pp
-.Fn DEFINEFIFO
+.Fn FIFO_DEFINE
 permits to create a new type of FIFO buffer to hold custom objects. This
 in fact only is a macro to create a new fifo*_t structure and typedef it.
 .Fa fifotype_t
@@ -59,7 +67,7 @@ specifies the type of object that this fifo structure should allow to buffer.
 For instance, to create a new fifo type to hold file descriptors, one could
 use:
 .Bd -literal -offset indent
-DEFINEFIFO(fdfifo_t, int);
+FIFO_DEFINE(fdfifo_t, int);
 .Ed
 .Pp
 It then would be possible to use the
@@ -67,12 +75,12 @@ It then would be possible to use the
 type, initialize it, and use it.
 .Bd -literal -offset indent
 fdfifo_t f;
-int buf[1025];
+int buf[1024];
 int fd;
 
-INITFIFO(&f, buf, 1024);
-PUTFIFO(&f, &fd);
-GETFIFO(&f, &fd);
+FIFO_INIT(&f, buf, 1024);
+FIFO_PUT(&f, &fd);
+FIFO_GET(&f, &fd);
 .Ed
 .Pp
 Predefined FIFO buffer types are
@@ -89,13 +97,13 @@ and
 .Nm u_int64_t ,
 respectively.
 .Pp
-.Fn INITFIFO
+.Fn FIFO_INIT
 allows to initialize a FIFO buffer.
 .Fa fifo
 consists of a pointer to the FIFO buffer to initialize,
 .Fa buffer
 is the user supplied buffer which should be able to hold the wanted number
-of elements.
+of elements, minus one.
 .Fa size
 specifies the maximum number of elements that the buffer can hold. This is
 not expressed in bytes, but in number of elements.
@@ -104,90 +112,124 @@ When a buffer is done with, it is the responsibility of the user application
 to free the supplied
 .Fa buffer .
 .Pp
-.Fn FULLFIFO
+.Fn FIFO_FULL
 is a useful macro to determine if a FIFO buffer is full and cannot take
 new elements.
 .Fa fifo
-is a pointer to the FIFO buffer. When full,
-.Fn PUTFIFO
-will have no effect;
-.Fn GETFIFO
-or
-.Fn FLUSHFIFO
-should be used first.
-.Pp
-.Fn STATFIFO
+is a pointer to the FIFO buffer. This is useful if for instance one does not
+want the FIFO buffer to loose the oldest element if it is full and
+.Fn FIFO_PUT
+is used.
+.Pp
+.Fn FIFO_EMPTY
+allows to determine if a FIFO buffer is currently empty, that is, does not hold
+any elements.
+.Pp
+.Fn FIFO_STAT
 permits to know how many elements are currently buffered into the specified
 .Fa fifo
-buffer, and which can be read using
-.Fn GETFIFO .
+buffer, which can be read using
+.Fn FIFO_GET .
 .Pp
-.Fn FLUSHFIFO
+.Fn FIFO_AVAIL
+evaluates the number of free elements in the buffer.
+.Pp
+.Fn FIFO_FLUSH
 allows to get rid of all the current contents, if any, of the specified
 .Fa fifo
-buffer. The buffer as a result becomes empty instantly.
+buffer. The buffer as a result becomes empty, instantly.
+.Pp
+.Fn FIFO_PUT
+inserts the element to which supplied
+.Fa element
+points, into the supplied FIFO buffer
+.Fa fifo .
+If the buffer is full, the oldest element is automatically discarded, allowing
+an automatic rotation within the buffer, but loosing bytes. If this behavior
+is not wanted, the
+.Fn FIFO_FULL
+macro should be used first to detect the buffer full condition.
 .Pp
-.Fn GETFIFO
+.Fn FIFO_GET
 attempts to read and obtain an element from the supplied FIFO buffer
 .Fa fifo ,
 and place it into
 .Fa element
 supplied pointer. This can transparently fail; If it is unsure that the
-FIFO buffer holds any data,
-.Fn STATFIFO
-should be used first. The obtained element, if it could be read, always
-consists of the older element that was inserted using
-.Fn PUTFIFO ,
-that is, the First element In is the First element Out.
-.Pp
-.Fn PUTFIFO
-inserts the element to which supplied
+FIFO buffer holds any data, the
+.Fn FIFO_EMPTY
+macro may be used before calling this macro.  The obtained element, if it
+could be read, always consists of the oldest element that was inserted using
+.Fn FIFO_PUT ,
+that is, the First element In is the First element Out. It is also immediately
+forgotten afterwards.
+.Pp
+.Fn FIFO_FIND
+attempts to locate
 .Fa element
-points, into the supplied FIFO buffer
-.Fa fifo .
-This can transparently fail if the buffer is full, if it is uncertain that
-room exists in the buffer,
-.Fn FIFOFULL
-should be used first, unless element loss is desired.
+within the current
+.Fa fifo
+buffer contents, and fills
+.Fa pointer
+with the element pointer if found, or NULL if the element could not be found.
 .Pp
-The
-.Fn getnfifo8
-and
-.Fn putnfifo8
-functions can process multiple elements (bytes in this case) at once. They are
-more efficient than looping while inserting or extracting single elements
-from the queue.
-.Fa buffer
-points to the location where data should be read from or written to.
-.Fa max
-parameter to
-.Fn getnfifo8
-specifies the size of the supplied read buffer to prevent overflowing it.
-The
+.Fn FIFO_ALLOC
+macro is useful for operations which need to insert several elements at once,
+as it allows them to allocate the required room and use
+.Fn memcpy
+or other user-specific method to write in the data. Attempts to allocate room
+for
 .Fa size
-argument to
-.Fn putnfifo8
-instructs the function about how many elements (bytes) should be queued.
+elements in
+.Fa fifo .
+The pointer to the buffer where elements can be written is placed into
+.Fa pointer ,
+and the number of elements which could be allocated in
+.Fa actual ,
+which may be smaller than the requested size, in which case the caller may
+perform other calls to this function. This can return smaller results for two
+reasons: 1) The internal head pointer reached the end of the buffer, and
+as such a single contiguous buffer cannot be provided, in which case two
+calls will be required to this macro to complete the operation. 2) The buffer
+did not contain enough room for the requested number of elements. The caller
+should not attempt to use the returned pointer if the returned size is zero.
+.Pp
+.Fn FIFO_FREE
+contrary to
+.Fn FIFO_ALLOC ,
+permits to free back a certain number of elements at once from the buffer.
+.Fa pointer
+is set to the location where the elements can be found, and
+.Fa actual
+to the number of elements which could be freed. Like it's companion, it can
+return a smaller number of elements than that requested, and multiple calls
+may then be performed to complete the operation.
 .Sh RETURN VALUES
-.Fn DEFINEFIFO ,
-.Fn INITFIFO ,
-.Fn FLUSHFIFO ,
-.Fn GETFIFO ,
+.Fn FIFO_DEFINE ,
+.Fn FIFO_INIT ,
+.Fn FIFO_FLUSH ,
+.Fn FIFO_PUT ,
 and
-.Fn PUTFIFO
+.Fn FIFO_GET
 return nothing.
 .Pp
-.Fn FULLFIFO
-returns TRUE or FALSE.
+.Fn FIFO_FULL
+and
+.Fn FIFO_EMPTY
+return TRUE or FALSE.
+.Pp
+.Fn FIFO_STAT
+and
+.Fn FIFO_AVAIL
+return a number of elements.
 .Pp
-.Fn STATFIFO
-returns the number of elements that are currently buffered.
+.Fn FIFO_FIND
+returns a pointer to an element into the provided pointer.
 .Pp
-.Fn getnfifo8
+.Fn FIFO_ALLOC
 and
-.Fn putnfifo8
-return the number of elements (bytes) that could be extracted or inserted.
-Zero will be returned if nothing could be done.
+.Fn FIFO_FREE
+return their result pointers and size into the provided pointers.
 .Sh SEE ALSO
 .Xr malloc 3 ,
 .Xr free 3
index a138c32..3a20068 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmfifo.h,v 1.4 2003/02/18 11:54:03 mmondor Exp $ */
+/* $Id: mmfifo.h,v 1.5 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
 
 
 
-/* DEFINEFIFO(fifotypename, objecttype); */
-#define DEFINEFIFO(n, o)       typedef struct n { \
-    u_int32_t size, elements; \
-    o *buffer, *endbuffer, *head, *tail; \
+/* Allows to create a new fifo_t type structure, to fit any data type */
+#define FIFO_DEFINE(n, o)      typedef struct n { \
+    o *top, *bottom, *head, *tail; \
+    u_int32_t size; \
 } n
 
-/* Because of the way this is implemented using macros, it would also be
- * possible to provide fifo types to hold structures.
- */
-DEFINEFIFO(fifo8_t, u_int8_t);
-DEFINEFIFO(fifo16_t, u_int16_t);
-DEFINEFIFO(fifo32_t, u_int32_t);
-DEFINEFIFO(fifo64_t, u_int64_t);
-
+FIFO_DEFINE(fifo8_t, u_int8_t);
+FIFO_DEFINE(fifo16_t, u_int16_t);
+FIFO_DEFINE(fifo32_t, u_int32_t);
+FIFO_DEFINE(fifo64_t, u_int64_t);
 
 
 
-/* void INITFIFO(fifo*_t *, u_int*_t *, u_int32_t); */
-#define INITFIFO(f, b, s)      do { \
-    (f)->size = (s); \
-    (f)->elements = 0; \
-    (f)->buffer = (f)->endbuffer = (f)->head = (f)->tail = (b); \
+/* Initializes a FIFO */
+#define FIFO_INIT(f, b, s)     do { \
+    (f)->top = (f)->head = (f)->tail = (b); \
+    (f)->bottom = &((b)[(s)]); \
+    (f)->size = (s) - 1; \
 } while (FALSE)
 
-/* bool FULLFIFO(fifo*_t *); */
-#define FULLFIFO(f)    ((f)->elements == (f)->size)
+/* Used to compute the next location of a tail or head pointer, accounting
+ * for the necessary occasional rotation.
+ */
+#define FIFO_NEXT(f, p)        (&((p)[1]) == (f)->bottom ? (f)->top : &((p)[1]))
+
+/* Returns TRUE if the FIFO is full, that is, cannot hold more elements */
+#define FIFO_FULL(f)           (FIFO_NEXT((f), (f)->head) == (f)->tail)
 
-/* u_int32_t STATFIFO(fifo*_t *); */
-#define STATFIFO(f)    ((f)->elements)
+/* Returns TRUE if the FIFO is empty */
+#define FIFO_EMPTY(f)          ((f)->head == (f)->tail)
 
-/* void FLUSHFIFO(fifo*_t *); */
-#define FLUSHFIFO(f)   do { \
-    (f)->tail = (f)->head = (f)->buffer; \
-    (f)->elements = 0; \
+/* Returns the number of currently held elements into a FIFO */
+#define FIFO_STAT(f)           \
+    (FIFO_EMPTY(f) ? 0 : \
+     (f)->head - (f)->tail > 0 ? \
+     ((f)->head - (f)->tail) / sizeof(*(f)->head) : \
+     ((f)->size - ((f)->tail - (f)->head)) / sizeof(*(f)->head))
+
+#define FIFO_AVAIL(f)          ((f)->size - FIFO_STAT(f))
+
+#define FIFO_FLUSH(f)          ((f)->tail = (f)->head)
+
+/* If no available room the oldest element is lost. The caller may verify
+ * with FIFO_FULL() first if needed.
+ */
+#define FIFO_PUT(f, e)         do { \
+    *(f)->head = *(e); \
+    (f)->head = FIFO_NEXT((f), (f)->head); \
+    if (FIFO_EMPTY(f)) \
+       (f)->tail = FIFO_NEXT((f), (f)->tail); \
 } while (FALSE)
 
-/* void PUTFIFO(fifo*_t *, u_int*_t *); */
-#define PUTFIFO(f, e)  do { \
-    if ((f)->elements < (f)->size) { \
-       *((f)->head++) = *(e); \
-       if ((f)->head == (f)->endbuffer) \
-           (f)->head = (f)->buffer; \
-       (f)->elements++; \
+/* Has no action if the buffer has no more elements, but does not return any
+ * result to say so. The caller may use FIFO_EMPTY() to check if needed.
+ */
+#define FIFO_GET(f, e)         do { \
+    if (!FIFO_EMPTY(f)) { \
+       *(e) = *(f)->tail; \
+       (f)->tail = FIFO_NEXT((f), (f)->tail); \
     } \
 } while (FALSE)
 
-/* void GETFIFO(fifo*_t *, u_int*_t *); */
-#define GETFIFO(f, e)  do { \
-    if ((f)->tail != (f)->head) { \
-       *(e) = *((f)->tail++); \
-       if ((f)->tail == (f)->endbuffer) \
-           (f)->tail = (f)->buffer; \
-       (f)->elements--; \
-    } \
+#define FIFO_FIND(f, p, e)     do { \
+    register typeof(*(e)) *r; \
+    *(p) = NULL; \
+    for (r = (f)->tail; r != (f)->head; r = FIFO_NEXT(f, r)) \
+       if (*r == *(e)) { \
+           *(p) = r; \
+           break; \
+       } \
 } while (FALSE)
 
+/* XXX Those are bugged for now */
+#define FIFO_ALLOC(f, p, a, s) do { \
+    register int r; \
+    if ((r = (f)->tail - (f)->head) != 0) { \
+       if (r < 1) \
+           r = (f)->bottom - (f)->head; \
+       if ((r /= sizeof(*(f)->head)) > (int)(s)) \
+           r = (int)(s); \
+       *(p) = (f)->head; \
+       (f)->head = (&((f)->head[r]) == (f)->bottom ? (f)->top : \
+           &((f)->head[r])); \
+    } \
+    *(a) = (size_t)r; \
+} while (FALSE)
 
+#define FIFO_FREE(f, p, a, s)  do { \
+    register int r; \
+    if ((r = (f)->head - (f)->tail) != 0) { \
+       if (r < 1) \
+           r = (f)->bottom - (f)->tail; \
+       if ((r /= sizeof(*(f)->tail)) > (int)(s)) \
+           r = (int)(s); \
+       *(p) = (f)->tail; \
+       (f)->tail = (&((f)->tail[r]) == (f)->bottom ? (f)->top : \
+           &((f)->tail[r])); \
+    } \
+    *(a) = (size_t)r; \
+} while (FALSE)
 
+#define FIFO_WRITE(f, p, a, s) do { \
+} while (FALSE)
 
-size_t putnfifo8(fifo8_t *, u_int8_t *, size_t);
-size_t getnfifo8(u_int8_t *, fifo8_t *, size_t);
+#define FIFO_READ(f, p, a, s)  do { \
+} while (FALSE)
 
 
 
index e82fffe..0988502 100644 (file)
@@ -1,4 +1,4 @@
-.\" $Id: mmlifo.3,v 1.1 2003/02/13 00:12:31 mmondor Exp $
+.\" $Id: mmlifo.3,v 1.2 2003/03/28 21:09:29 mmondor Exp $
 .Dd Feb 12, 2003
 .Os
 .Dt MMLIFO 3
 .Fd #include <mmtypes.h>
 .Fd #include <mmlifo.h>
 .Ft void
-.Fn DEFINELIFO "lifotype_t" "objecttype"
+.Fn LIFO_DEFINE "lifotype_t" "objecttype"
 .Ft void
-.Fn INITLIFO "lifotype_t *lifo" "void *buffer" "u_int32_t size"
+.Fn LIFO_INIT "lifotype_t *lifo" "void *buffer" "u_int32_t size"
 .Ft bool
-.Fn FULLLIFO "lifotype_t *lifo"
+.Fn LIFO_FULL "lifotype_t *lifo"
+.Ft bool
+.Fn LIFO_EMPTY "lifotype_t *lifo"
+.Ft u_int32_t
+.Fn LIFO_STAT "lifotype_t *lifo"
 .Ft u_int32_t
-.Fn STATLIFO "lifotype_t *lifo"
+.Fn LIFO_AVAIL "lifotype_t *lifo"
+.Ft void
+.Fn LIFO_FLUSH "lifotype_t *lifo"
+.Ft void
+.Fn LIFO_PUT "lifotype_t *lifo" "objecttype *element"
 .Ft void
-.Fn FLUSHLIFO "lifotype_t *lifo"
+.Fn LIFO_GET "lifotype_t *lifo" "objecttype *element"
 .Ft void
-.Fn GETLIFO "lifotype_t *lifo, objecttype *element"
+.Fn LIFO_FIND "lifotype_t *lifo" "objecttype **pointer" "objecttype *element"
 .Ft void
-.Fn PUTLIFO "lifotype_t *lifo, objecttype *element"
+.Fn LIFO_ALLOC "lifotype_t *lifo" "objecttype **pointer" "u_int32_t *actual" \
+"u_int32_t size"
+.Ft void
+.Fn LIFO_FREE "lifotype_t *lifo" "objecttype **pointer" "u_int32_t *actual" \
+"u_int32_t size"
 .Sh DESCRIPTION
 LIFO buffers (Last In First Out) are usually useful to implement stacks
 when the processor stack is not desired to use, for temporary storage, or to
@@ -32,7 +44,7 @@ a fixed memory buffer, with entries corresponding to the stack type. The
 library is entirely implemented as macros, which also allows to create new
 user LIFO buffer types to hold user supplied objects.
 .Pp
-.Fn DEFINELIFO
+.Fn LIFO_DEFINE
 permits to create a new type of LIFO buffer to hold custom objects. This
 in fact only is a macro to create a new lifo*_t structure and typedef it.
 .Fa lifotype_t
@@ -42,7 +54,7 @@ specifies the type of object that this lifo structure should allow to buffer.
 For instance, to create a new lifo type to hold file descriptors, one could
 use:
 .Bd -literal -offset indent
-DEFINELIFO(fdlifo_t, int);
+LIFO_DEFINE(fdlifo_t, int);
 .Ed
 .Pp
 It then would be possible to use the
@@ -50,12 +62,12 @@ It then would be possible to use the
 type, initialize it, and use it.
 .Bd -literal -offset indent
 fdlifo_t f;
-int buf[1025];
+int buf[1024];
 int fd;
 
-INITLIFO(&f, buf, 1024);
-PUTLIFO(&f, &fd);
-GETLIFO(&f, &fd);
+LIFO_INIT(&f, buf, 1024);
+LIFO_PUT(&f, &fd);
+LIFO_GET(&f, &fd);
 .Ed
 .Pp
 Predefined LIFO buffer types are
@@ -72,7 +84,7 @@ and
 .Nm u_int64_t ,
 respectively.
 .Pp
-.Fn INITLIFO
+.Fn LIFO_INIT
 allows to initialize a LIFO buffer.
 .Fa lifo
 consists of a pointer to the LIFO buffer to initialize,
@@ -87,65 +99,77 @@ When a buffer is done with, it is the responsibility of the user application
 to free the supplied
 .Fa buffer .
 .Pp
-.Fn FULLLIFO
+.Fn LIFO_FULL
 is a useful macro to determine if a LIFO buffer is full and cannot take
 new elements.
 .Fa lifo
 is a pointer to the LIFO buffer. When full,
-.Fn PUTLIFO
+.Fn LIFO_PUT
 will have no effect;
-.Fn GETLIFO
+.Fn LIFO_GET
 or
-.Fn FLUSHLIFO
+.Fn LIFO_FLUSH
 should be used first.
 .Pp
-.Fn STATLIFO
+.Fn LIFO_EMPTY
+returns true if the supplied
+.Ft lifo
+buffer currently holds no elements.
+.Pp
+.Fn LIFO_STAT
 permits to know how many elements are currently buffered into the specified
 .Fa lifo
 buffer, and which can be read using
-.Fn GETLIFO .
+.Fn LIFO_GET .
+.Pp
+.Fn LIFO_AVAIL
+tells the number of additional entries which the supplied buffer can hold.
 .Pp
-.Fn FLUSHLIFO
+.Fn LIFO_FLUSH
 allows to get rid of all the current contents, if any, of the specified
 .Fa lifo
 buffer. The buffer as a result becomes empty instantly.
 .Pp
-.Fn GETLIFO
+.Fn LIFO_PUT
+inserts the element to which supplied
+.Fa element
+points, into the supplied LIFO buffer
+.Fa lifo .
+This can transparently fail if the buffer is full, if it is uncertain that
+room exists in the buffer,
+.Fn LIFO_FULL
+should be used first, unless element loss is desired.
+.Pp
+.Fn LIFO_GET
 attempts to read and obtain an element from the supplied LIFO buffer
 .Fa lifo ,
 and place it into
 .Fa element
 supplied pointer. This can transparently fail; If it is unsure that the
 LIFO buffer holds any data,
-.Fn STATLIFO
+.Fn LIFO_EMPTY
 should be used first. The obtained element, if it could be read, always
 consists of the most recent element that was inserted using
-.Fn PUTLIFO ,
+.Fn LIFO_PUT ,
 that is, the Last element In is the First element Out.
-.Pp
-.Fn PUTLIFO
-inserts the element to which supplied
-.Fa element
-points, into the supplied LIFO buffer
-.Fa lifo .
-This can transparently fail if the buffer is full, if it is uncertain that
-room exists in the buffer,
-.Fn LIFOFULL
-should be used first, unless element loss is desired.
 .Sh RETURN VALUES
-.Fn DEFINELIFO ,
-.Fn INITLIFO ,
-.Fn FLUSHLIFO ,
-.Fn GETLIFO ,
+.Fn LIFO_DEFINE ,
+.Fn LIFO_INIT ,
+.Fn LIFO_FLUSH ,
+.Fn LIFO_GET ,
 and
-.Fn PUTLIFO
+.Fn LIFO_PUT
 return nothing.
 .Pp
-.Fn FULLLIFO
-returns TRUE or FALSE.
+.Fn LIFO_FULL
+and
+.Fn LIFO_EMPTY
+return TRUE or FALSE.
 .Pp
-.Fn STATLIFO
-returns the number of elements that are currently buffered.
+.Fn LIFO_STAT
+and
+.Fn LIFO_AVAIL
+return a number of elements.
 .Sh SEE ALSO
 .Xr malloc 3 ,
 .Xr free 3
index 252a4d3..d33f864 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmlifo.h,v 1.2 2003/02/18 11:54:03 mmondor Exp $ */
+/* $Id: mmlifo.h,v 1.3 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 1999-2003, Matthew Mondor
@@ -43,7 +43,7 @@
 
 
 /* DEFINELIFO(lifotypename, objecttype); */
-#define DEFINELIFO(n, o)       typedef struct n { \
+#define LIFO_DEFINE(n, o)      typedef struct n { \
     u_int32_t size, elements; \
     o *buffer, *endbuffer, *head; \
 } n
 /* Because of the way this is implemented using macros, it would also be
  * possible to provide lifo types to hold structures.
  */
-DEFINELIFO(lifo8_t, u_int8_t);
-DEFINELIFO(lifo16_t, u_int16_t);
-DEFINELIFO(lifo32_t, u_int32_t);
-DEFINELIFO(lifo64_t, u_int64_t);
+LIFO_DEFINE(lifo8_t, u_int8_t);
+LIFO_DEFINE(lifo16_t, u_int16_t);
+LIFO_DEFINE(lifo32_t, u_int32_t);
+LIFO_DEFINE(lifo64_t, u_int64_t);
 
 
 
 /* XXX Although it's great to use macros for these operations, it also prevents
  * assembly functions to be provided to replace them.
  */
-/* void INITLIFO(lifo*_t *, u_int*_t *, u_int32_t); */
+/* void LIFO_INIT(lifo*_t *, u_int*_t *, u_int32_t); */
 #define INITLIFO(f, b, s)      do { \
     (f)->size = (s); \
     (f)->elements = 0; \
     (f)->buffer = (f)->endbuffer = (f)->head = (b); \
 } while (FALSE)
 
-/* bool FULLLIFO(lifo*_t *); */
-#define FULLLIFO(f)    ((f)->elements == (f)->size)
+/* bool LIFO_FULL(lifo*_t *); */
+#define LIFO_FULL(f)   ((f)->elements == (f)->size)
 
-/* u_int32_t STATLIFO(lifo*_t *); */
-#define STATLIFO(f)    ((f)->elements)
+/* u_int32_t LIFO_STAT(lifo*_t *); */
+#define LIFO_STAT(f)   ((f)->elements)
 
-/* void FLUSHLIFO(lifo*_t *); */
-#define FLUSHLIFO(f)   do { \
+/* void LIFO_FLUSH(lifo*_t *); */
+#define LIFO_FLUSH(f)  do { \
     (f)->head = (f)->buffer; \
     (f)->elements = 0; \
 } while (FALSE)
 
-/* void PUTLIFO(lifo*_t *, void *); */
-#define PUTLIFO(s, e)  do { \
+/* void LIFO_PUT(lifo*_t *, u_int*_t *); */
+#define LIFO_PUT(s, e) do { \
     if ((s)->elements < (s)->size) { \
        *((s)->head++) = *(e); \
        (s)->elements++; \
     } \
 } while (FALSE)
 
-/* void GETLIFO(lifo*_t *, void *); */
-#define GETLIFO(s, e)  do { \
+/* void LIFO_GET(lifo*_t *, u_int*_t *); */
+#define LIFO_GET(s, e) do { \
     if ((s)->elements > 0) { \
        *(e) = *(--(s)->head); \
        (s)->elements--; \
     } \
 } while (FALSE)
 
+/* LIFO_ALLOC(lifo*_t *, u_int*_t **, size_t *); */
+
+/* LIFO_FREE(lifo*_t, u_int*_t **, size_t *); */
+
 
 
 #endif
index 2865097..3036fe2 100644 (file)
@@ -1,4 +1,4 @@
-.\" $Id: mmlist.3,v 1.4 2003/01/08 20:57:46 mmondor Exp $
+.\" $Id: mmlist.3,v 1.5 2003/03/28 21:09:29 mmondor Exp $
 .\"
 .\" Copyright (C) 2002-2003, Matthew Mondor
 .\" All rights reserved.
 .Dt MMLIST 3
 .Sh NAME
 .Nm mmlist
-.Nd General purpose doubly linked list library with pool support.
+.Nd General purpose doubly linked list library of macros.
 .Sh SYNOPSIS
 .Fd #include <sys/types.h>
 .Fd #include <mmtypes.h>
 .Fd #include <mmlist.h>
 .Ft void
-.Fn INITLIST "list *list"
-.Ft list *
-.Fn openlist "void *(*malloc)(size_t)" "void (*free)(void *)" \
-"size_t nodelen" "size_t pagesize" "long maxpages"
-.Ft list *
-.Fn blocklist "void *(*malloc)(size_t)" "void (*free)(void *)" \
-"size_t nodelen" "long nodes"
-.Ft list *
-.Fn closelist "list *list"
-.Ft node *
-.Fn allocnode "list *list" "bool zero"
-.Ft node *
-.Fn freenode "node *node"
+.Fn LIST_INIT "list_t *list"
 .Ft void
-.Fn APPENDNODE "list *list" "node *node"
+.Fn LIST_APPEND "list_t *list" "node_t *node"
 .Ft void
-.Fn INSERTNODE "list *list" "node *node"
+.Fn LIST_INSERT "list_t *list" "node_t *node"
 .Ft void
-.Fn INSERTNODEAT "list *list" "node *atnode" "node *node"
+.Fn LIST_INSERTAT "list_t *list" "node_t *atnode" "node_t *node"
 .Ft void
-.Fn SWAPNODE "list *dest" "list *source" "node *node" "bool insert"
+.Fn LIST_SWAP "list_t *dest" "list_t *source" "node_t *node" "bool insert"
 .Ft void
-.Fn UNLINKNODE "list *list" "node *node"
+.Fn LIST_UNLINK "list_t *list" "node_t *node"
 .Sh DESCRIPTION
 This library provides a useful set of functions to manipulate doubly linked
-lists. We also optionally allow pre-buffering node pools allowing to very
-efficiently allocate/free nodes for a particular list.
-All nodes in a pool are
-.Ar long
-word aligned and are thus suitable for
-.Ar long *
-referencing. The pools ensure to minimize calls to the supplied allocation
-functions (such as
-.Xr malloc 3
-and
-.Xr free 3 ) ,
-preparing buffered pages. Even those pages are buffered as required and
-statistics are maintained to monitor average current usage so that the
-number of pre-buffered pages for a pool remain available even when most
-nodes have been freed back. An application can then alternate size properly
-in a very fast manner using these pools. Of course the statistics are updated
-which will also allow those buffered pages to really be freed back when
-it is noticeable that the pool does not grow large again for some while.
+lists.
 .Pp
 The following structures and fields of interest which are left for the user
 to reference are described below (only fields of user interest are shown),
 declared in
-.Aq Pa mmfd.h
+.Aq Pa mmlist.h
 .Bd -literal -offset indent
-typedef struct node {
-    struct node *prev, *next;
-} node;
+typedef struct node     node_t;
+typedef struct list     list_t;
 
-typedef struct list {
-    struct node *top, *bottom;
-    long nodes;
-} list;
+struct node {
+    node_t *prev, *next;
+};
+
+struct list {
+    node_t *top, *bottom;
+    u_int32_t nodes;
+};
 .Ed
 .Pp
 A custom node has to be declared as a structure using the node structure as
 it's first field, as in the following:
 .Bd -literal -offset indent
 struct mynode {
-    node nod;
-    int i;
-    /*...other custom fields...*/
+    node_t node;
+    /* custom fields... */
 };
 .Ed
 .Pp
-.Fn INITLIST
+.Fn LIST_INIT
 initializes a
 .Nm list
-object in such a way that it can be used to store nodes. This does not
-setup any memory pool and thus
-.Fn allocnode
-and
-.Fn freenode
-will not work with this type of list.
-.Pp
-.Fn openlist
-allocates required resources to create a list handle with a node pre-buffering
-pool. The supplied
-.Fa malloc
-and
-.Fa free
-arguments can either be
-.Fn malloc ,
-.Fn free
-respectively, but custom functions may also be provided.
-.Fa nodelen
-consists of sizeof(struct mynode) in the previous example and should be
-the size of the node which may then later on be allocated using
-.Fn allocnode
-at will.
-.Fa pagesize
-specifies the smallest amount of memory, in bytes, which will be initially
-prepared to be used as buffered nodes for
-.Fn allocnode
-calls.
-.Fa maxpages
-specifies the maximum number of
-.Fa pagesize
-bytes blocks that will be allocated for this pool/list.
-.Fn allocnode
-will no longer be able to allocate new nodes if this is reached. 0 may also
-be specified for this option to specify that no limit is wanted. Using this
-pool mechanism minimizes calls to
-.Fn malloc
-and optimizes things considerably. Typical
-.Fa pagesize
-values are 4096, 8192, 16384 or 65536 bytes. Any size may be used as long as
-at least two nodes may fit in a page. Note that if no pool is wanted it often
-can be useful to simply define a
-.Fa list
-object and clear it to zeros using
-.Fn bzero ,
-.Fn memset ,
-or
-.Fn mm_memclr .
-The allocation functions will not be available, and such a list should not
-be closed using
-.Fn closelist ,
-but it will be available to hold nodes.
-.Pp
-.Fn blocklist
-also prepares a list handle to be used by other functions, but allocates in one
-block the requested number of maximum nodes to be available for
-.Fn allocnode
-calls.
-.Pp
-.Fn closelist
-calls the provided
-.Fn free
-function to free all resources allocated for the specified
-.Fa list *
-handle. Any
-.Fn allocnode
-allocated memory is also freed. You should be sure to not have to reference
-or use anymore any node that has been allocated for this list using
-.Fn allocnode
-before calling this function. If needed, custom allocated nodes may be used
-instead of pre-buffered ones, and unlinked from the list before it's freed
-using
-.Fn UNLINKNODE
-function, so they then remain useable by other lists.
+object in such a way that it can be used to store nodes. This should be called
+before starting to append nodes into it.
 .Pp
-.Fn allocnode
-attempts to allocate a pre-buffered node from the pool reserved to the
-specified
-.Fa list *
-and optionally zeros allocated memory like
-.Fn calloc
-would if
-.Fa zero
-is TRUE. If required a new page of pre-buffered nodes will be allocated
-and prepared, if within allowed page limits, to make other nodes available
-for allocation. If the list was created using
-.Fn blocklist
-function, only a single page is available allowing to allocate the maximum
-number of nodes that was specified.
-.Pp
-.Fn freenode
-restores specified
-.Fa node *
-to the list pool
-.Fn allocnode
-allocated node from, making it available for re-allocating later. Of course
-if all nodes of a particular page have been freed, the page is internally
-released into a pool, and eventually back to the system if it is not recycled
-soon enough. If the list was created using
-.Fn blocklist
-function, the buffer will never shrink as it handles a fixed amount of nodes
-to be available for allocation.
-.Pp
-.Fn APPENDNODE
+.Fn LIST_APPEND
 links node pointed to by
 .Fa node
 after all elements in list specified by
 .Fa list
 .Pp
-.Fn INSERTNODE
+.Fn LIST_INSERT
 links node
 .Fa node
 before all elements of list
 .Fa list
 .Pp
-.Fn INSERTNODEAT
+.Fn LIST_INSERTAT
 links node
 .Fa node
 before node
@@ -234,55 +108,26 @@ before node
 into
 .Fa list
 .Pp
-.Fn SWAPNODE
+.Fn LIST_SWAP
 unlinks node
 .Fa node
 from
-.Fa source
-and appends or inserts it into list
+.Fa source ,
+and appends or inserts it into list
 .Fa dest
 depending on weither
 .Fa insert
 is TRUE or FALSE.
 .Pp
-.Fn UNLINKNODE
+.Fn LIST_UNLINK
 unlinks node
 .Fa node
 from
-.Fa list
-but does not free the node in any way.
+.Fa list .
 .Sh RETURN VALUES
-.Fn openlist
-and
-.Fn blocklist
-return a
-.Fa list *
-or NULL pointer on error (out of memory).
-.Pp
-.Fn closelist
-always returns a NULL pointer of type
-.Fa list *
-.Pp
-.Fn allocnode
-returns a
-.Fa node *
-or NULL on error (no more memory allowed for this pool, or out of memory).
-.Pp
-.Fn freenode
-always returns a NULL pointer of type
-.Fa node *
-.Pp
-.Fn INITLIST ,
-.Fn APPENDNODE ,
-.Fn INSERTNODE ,
-.Fn INSERTNODEAT ,
-.Fn SWAPNODE
-and
-.Fn UNLINKNODE
-don't return anything.
+These macros do not return anything.
 .Sh SEE ALSO
-.Xr malloc 3 ,
-.Xr free 3
+.Xr mmpool 3 .
 .Sh STANDARDS
 None
 .Sh HISTORY
index 932e75a..f73499c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmlist.h,v 1.4 2003/02/18 11:54:03 mmondor Exp $ */
+/* $Id: mmlist.h,v 1.5 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
+ *      This product includes software developed by Matthew Mondor.
  * 4. The name of Matthew Mondor may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
+ * 5. Redistribution of source code may not be released under the terms of
+ *    any GNU Public License derivate.
  *
  * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
 
 
-
 #ifndef MM_LIST_H
 #define MM_LIST_H
 
 
 
-
 #include <sys/types.h>
 #include <mmtypes.h>
 
 
 
+typedef struct list    list_t;
+typedef struct node    node_t;
+
 
-typedef struct node {
-    struct node *prev, *next;
-    struct bpage *page;
-} node;
 
-typedef struct bpage {
-    struct node nod;
-    struct bpool *pool;
-    long used;
-} bpage;
+struct node {
+    node_t *prev, *next;
+};
 
-typedef struct list {
-    struct node *top, *bottom;
-    struct bpool *pool;
-    long nodes;
-} list;
+struct list {
+    node_t *top, *bottom;
+    u_int32_t nodes;
+};
 
-typedef struct bpool {
-    void * (*malloc)(size_t);
-    void (*free)(void *);
-    long maxpages, avgtotal, avgcnt;
-    size_t nodesize, pagesize;
-    struct list bpages, bfpages, bnodes;
-    bool block;
-} bpool;
 
-/* Some macros to optimize operations */
-#define INITLIST(lst) do { \
+
+/* Some macros to optimize operations on doubly linked lists */
+#define LIST_INIT(lst) do { \
     (lst)->top = (lst)->bottom = NULL; \
-    (lst)->pool = NULL; \
     (lst)->nodes = 0; \
 } while (FALSE)
 
-#define UNLINKNODE(lst, nod) do { \
-    register node *prev = (nod)->prev, *next = (nod)->next; \
+#define LIST_UNLINK(lst, nod) do { \
+    register node_t *prev = (nod)->prev, *next = (nod)->next; \
     if (prev) prev->next = next; \
     else (lst)->top = next; \
     if (next) next->prev = prev; \
@@ -88,8 +76,8 @@ typedef struct bpool {
     (lst)->nodes--; \
 } while (FALSE)
 
-#define APPENDNODE(lst, nod) do { \
-    register node *tmp = (lst)->bottom; \
+#define LIST_APPEND(lst, nod) do { \
+    register node_t *tmp = (lst)->bottom; \
     if (tmp) { \
        tmp->next = (nod); \
        (nod)->prev = tmp; \
@@ -102,8 +90,8 @@ typedef struct bpool {
     (lst)->nodes++; \
 } while (FALSE)
 
-#define INSERTNODE(lst, nod) do { \
-    register node *tmp = (lst)->top; \
+#define LIST_INSERT(lst, nod) do { \
+    register node_t *tmp = (lst)->top; \
     if (tmp) { \
        tmp->prev = (nod); \
        (nod)->prev = NULL; \
@@ -116,8 +104,8 @@ typedef struct bpool {
     (lst)->nodes++; \
 } while (FALSE)
 
-#define INSERTNODEAT(lst, atnode, nod) do { \
-    register node *prev = (atnode)->prev, *next = (atnode); \
+#define LIST_INSERTAT(lst, atnode, nod) do { \
+    register node_t *prev = (atnode)->prev, *next = (atnode); \
     (nod)->next = next; \
     next->prev = (nod); \
     if (prev) { \
@@ -130,8 +118,8 @@ typedef struct bpool {
     (lst)->nodes++; \
 } while (FALSE)
 
-#define SWAPNODE(dst, src, nod, ins) do { \
-    register node *prev = (nod)->prev, *next = (nod)->next; \
+#define LIST_SWAP(dst, src, nod, ins) do { \
+    register node_t *prev = (nod)->prev, *next = (nod)->next; \
     if (prev) prev->next = next; \
     else (src)->top = next; \
     if (next) next->prev = prev; \
@@ -163,15 +151,4 @@ typedef struct bpool {
 
 
 
-
-/* General allocation/free functions */
-list *openlist(void * (*)(size_t), void (*)(void *), size_t, size_t, long);
-list *blocklist(void * (*)(size_t), void (*)(void *), size_t, long);
-list *closelist(list *);
-node *allocnode(list *, bool);
-node *freenode(node *);
-
-
-
-
 #endif
diff --git a/mmsoftware/mmlib/mmpool.3 b/mmsoftware/mmlib/mmpool.3
new file mode 100644 (file)
index 0000000..14146eb
--- /dev/null
@@ -0,0 +1,262 @@
+.\" $Id: mmpool.3,v 1.1 2003/03/28 21:09:29 mmondor Exp $
+.\"
+.\" Copyright (C) 2001-2003, Matthew Mondor
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software written by Matthew Mondor.
+.\" 4. The name of Matthew Mondor may not be used to endorse or promote
+.\"    products derived from this software without specific prior written
+.\"    permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd Mars 26, 2003
+.Os
+.Dt MMPOOL 3
+.Sh NAME
+.Nm mmpool
+.Nd General purpose efficient memory pools
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <mmtypes.h>
+.Fd #include <mmpool.h>
+.Ft bool
+.Fn pool_init "pool_t *pool" "void *(*malloc)(void)" "void (*free)(void *)" \
+"size_t nodesize" "u_int32_t nodesperpage" "u_int32_t minpages" \
+"u_int32_t maxpages"
+.Ft bool
+.Fn pool_destroy "pool_t *pool"
+.Ft pnode_t *
+.Fn pool_alloc "pool_t *pool" "bool zero"
+.Ft pnode_t *
+.Fn pool_free "pnode_t *pnode"
+.Ft bool
+.Fn POOL_VALID "pool_t *pool"
+.Ft bool
+.Fn PNODE_VALID "pnode_t *pnode"
+.Sh DESCRIPTION
+This library provides a useful set of functions to minimize the frequency of
+calls to
+.Xr malloc 3
+and
+.Xr free 3
+functions. These pools internally use buffers, and evaluate when they should
+shrink the buffers, using statistics on the current general memory useage.
+Using it can significantly speed up programs which need to often allocate and
+free objects, especially on systems on which the general purpose allocation
+functions are unefficienty implemented.
+This library is compatible with
+.Xr mmlist 3
+in that the
+.Nm pnode_t
+object header internally begins with an
+.Xr mmlist 3
+.Nm node_t
+header. It is thus safe to use the
+.Xr mmlist 3
+doubly linked list manipulation macros directly on the allocated
+.Xr mmpool 3
+objects.
+.Pp
+.Nm pool_t ,
+for simple efficient fixed-sized objects allocation: A custom user-specified
+object type has to be defined as a structure, which needs to begin using a
+field of
+.Nm pnode_t
+type, as in the following:
+.Bd -literal -offset indent
+struct myobject {
+    pnode_t node;
+    /* custom fields... */
+};
+.Ed
+.Pp
+.Fn pool_init
+is necessary to use before a
+.Nm pool_t
+can be used.
+.Fa pool
+specifies the pointer to the
+.Nm pool_t
+structure which is to be initialized to later serve to allocate objects.
+.Fa malloc
+and
+.Fa free
+specify the functions which are to be called when new buffers need to be
+allocated by the pool, or when it needs to shrink the buffers, and can consist
+of
+.Xr malloc 3
+and
+.Xr free 3 ,
+respectively, or to custom functions which are expected to behave the same
+API-wise.
+.Fa nodesize
+tells the individual size of the fixed-sized objects which are to be allocated
+and freed by this pool.
+.Fa nodesperpage
+consists of the number of wanted elements per internal buffer. New buffers
+of
+.Fa nodesperpage
+*
+.Fa nodesize
+will be dynamically allocated if no more objects are prebuffered at a future
+node allocation request by calling the user-supplied
+.Fa malloc .
+Although the 'page' termination is used, it does not correspond to an actual
+physical or virtual memory page, but to a buffer.
+When the system evaluates that it should shrink because the current buffers
+largely exceed the current useage for some time, those will be freed back as
+necessary calling the user-supplied
+.Fa free
+function.
+.Fa minpages
+is useful to make sure that a pool never frees back totally it's buffers.
+This may be wanted for instance when critical code will be used which needs
+to allocate and/or free objects from the pool, but which cannot call the
+higher-level
+.Xr malloc 3
+or
+.Xr free 3
+functions. This number of buffers are immediately allocated and setup as
+available pre-buffered nodes at initialization.
+If
+.Fa minpages
+is 0, it will be able to shrink completely as the system notices that no
+buffers are required.
+.Fa maxpages ,
+similarily to
+.Fa minpages
+can set a boundary on the maximum number of pages (buffers) which are to be
+allowed into the pool. Using 0 here allows the pool to always dynamically grow
+as required. Using for instance a value of 2 for both
+.Fa minpages
+and
+.Fa maxpages
+causes the pool to be fixed to
+.Fa nodesperpage
+*
+.Fa minpages
+available elements, and the higher-level
+.Xr malloc 3
+and
+.Xr free 3
+functions will never be called, except at
+.Fn pool_init
+and
+.Fn pool_destroy .
+.Pp
+.Fn pool_destroy
+can be called on a pre-initialized
+.Nm pool_t
+to totally free any remaining buffers and elements it may hold, and mark it as
+invalid.
+.Fa pool
+will no longer be able to serve allocation or freeing requests until it is
+re-initialized again using
+.Fn pool_init
+again (if so). Note that any currently allocated objects from this pool which
+have not yet been freed back are also immediately freed, and become invalid.
+.Pp
+.Fn pool_alloc
+attempts to allocate a
+.Nm pnode_t
+prefixed object from the specified
+.Fa pool ,
+and optionally clears it with zeros if
+.Fa zero
+is TRUE. The size of the object is always fixed to the
+.Fa nodesize
+argument which was specified at
+.Fn pool_init
+for this pool. The returned object is guaranteed to be long-word aligned.
+.Pp
+.Fn pool_free
+attempts to free a
+.Nm pnode_t
+prefixed object back to the
+.Nm pool_t
+it belongs to, which is internally remembered.
+.Pp
+.Fn POOL_VALID
+can be useful to determine if the supplied
+.Fa pool
+pointer was previously successfully initialized and was not destroyed since.
+.Pp
+.Fn PNODE_VALID
+can also be useful when it is necessary to determine if an
+.Nm pnode_t
+expected prefixed object to which
+.Fa pnode
+points is valid, that is, was successfully allocated, and originates from a
+.Nm pool_t
+which is also still valid.
+.Sh RETURN VALUES
+.Fn pool_init
+returns TRUE on success, or FALSE on failure (our of memory or invalid
+parameters).
+.Pp
+.Fn pool_destroy
+returns TRUE on success, or FALSE if the supplied
+.Fa pool
+pointer points to an invalid
+.Nm pool_t ,
+which either was previously destroyed already, or was never initialized.
+.Pp
+.Fn pool_alloc
+returns a pointer of
+.Nm pnode_t
+type corresponding to the header of the newly allocated object, or NULL
+(invalid
+.Fn pool ,
+out of memory, or out of pre-buffered elements if
+.Fa maxpages
+was set at
+.Fn pool_init .
+.Pp
+.Fn pool_free
+always returns NULL, and internally makes sure to not attempt to free
+already freed or invalid objects.
+.Pp
+.Fn POOL_VALID
+and
+.Fn PNODE_VALID
+macros return TRUE or FALSE.
+.Sh SEE ALSO
+.Xr malloc 3 ,
+.Xr free 3 ,
+.Xr mmlist 3 .
+.Sh STANDARDS
+None
+.Sh HISTORY
+This
+.Nm pool_t
+system  was originally developped on NetBSD 1.5 for the Xisop
+portable microkernel project from Matthew Mondor, which also served behind
+the more general
+.Nm mpool_t
+system. It later on was adapted so part of it could be used by mmserver,
+mmftpd and mmmail daemons.
+.Sh AUTHORS
+The mmpool library was written by Matthew Mondor and is
+Copyright (c) 2001-2003, Matthew Mondor, All rights reserved.
+.Sh BUGS
+Please report any bug to mmondor@gobot.ca
diff --git a/mmsoftware/mmlib/mmpool.c b/mmsoftware/mmlib/mmpool.c
new file mode 100644 (file)
index 0000000..a10ef81
--- /dev/null
@@ -0,0 +1,278 @@
+/* $Id: mmpool.c,v 1.1 2003/03/28 21:09:29 mmondor Exp $ */
+
+/*
+ * Copyright (C) 2001-2003, Matthew Mondor
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software written by Matthew Mondor.
+ * 4. The name of Matthew Mondor may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <mmtypes.h>
+#include <mmstring.h>
+#include <mmlist.h>
+#include <mmpool.h>
+
+
+
+
+MMCOPYRIGHT("@(#) Copyright (c) 2001-2003\n\
+\tMatthew Mondor. All rights reserved.\n");
+MMRCSID("$Id: mmpool.c,v 1.1 2003/03/28 21:09:29 mmondor Exp $");
+
+
+
+
+bool pool_init(pool_t *pool, void *(*mallocfunc)(size_t),
+       void (*freefunc)(void *), size_t nodesize, u_int32_t nodesperpage,
+       u_int32_t minpages, u_int32_t maxpages)
+{
+    bool ok = FALSE;
+
+    if (pool != NULL && mallocfunc != NULL && freefunc != NULL &&
+           nodesize != 0 && nodesperpage > 0) {
+       register size_t bps = (size_t)OALIGN_CEIL(sizeof(bpage_t), long);
+       register size_t ns = (size_t)OALIGN_CEIL(nodesize, long);
+       register size_t ps = (bps + ((nodesperpage + 1) * ns));
+
+       pool->magic = 0;
+       pool->malloc = mallocfunc;
+       pool->free = freefunc;
+       pool->nodesize = ns;
+       pool->minpages = minpages;
+       pool->maxpages = maxpages;
+       pool->nodesperpage = nodesperpage;
+       pool->pagesize = ps;
+       pool->avgtotal = pool->avgcnt = minpages;
+       LIST_INIT(&pool->pages);
+       LIST_INIT(&pool->fpages);
+       LIST_INIT(&pool->nodes);
+       /* Allocate minimum number of pages, if needed */
+       for (; minpages > 0; minpages--) {
+           register bpage_t *p;
+
+           if ((p = mallocfunc(ps)) != NULL) {
+               register u_int8_t *ptr, *toptr;
+
+               p->pool = pool;
+               p->magic = MAGIC_PAGE;
+               p->pnodes = nodesperpage;
+               LIST_APPEND(&pool->pages, (node_t *)p);
+               for (ptr = toptr = (u_int8_t *)p, ptr += bps, toptr += ps;
+                       ptr + ns < toptr; ptr += ns) {
+                   ((pnode_t *)ptr)->page = p;
+                   ((pnode_t *)ptr)->magic = 0;
+                   LIST_APPEND(&pool->nodes, (node_t *)ptr);
+               }
+           } else
+               break;
+       }
+       pool->magic = MAGIC_POOL;
+       if (minpages == 0)
+           ok = TRUE;
+       else if (minpages < pool->minpages) {
+           pool_destroy(pool);
+           syslog(LOG_NOTICE, "* pool_init() - Out of memory");
+       }
+    } else
+       syslog(LOG_NOTICE, "* pool_init() - Invalid parameters");
+
+    return ok;
+}
+
+
+bool pool_destroy(pool_t *pool)
+{
+    bool ok = FALSE;
+
+    if (POOL_VALID(pool)) {
+       register node_t *p, *t;
+
+       for (p = pool->pages.top; p != NULL; p = t) {
+           t = p->next;
+           ((bpage_t *)p)->magic = 0;
+           pool->free(p);
+       }
+       for (p = pool->fpages.top; p != NULL; p = t) {
+           t = p->next;
+           ((bpage_t *)p)->magic = 0;
+           pool->free(p);
+       }
+       pool->magic = 0;
+       ok = TRUE;
+    } else
+       syslog(LOG_NOTICE, "- pool_destroy() - Invalid pool_t pointer");
+
+    return ok;
+}
+
+
+pnode_t *pool_alloc(pool_t *pool, bool zero)
+{
+    pnode_t *pnode = NULL;
+
+    if (POOL_VALID(pool)) {
+       register pnode_t *pn;
+
+       /* If there are pre-buffered nodes, simply return the first one. */
+       if ((pn = (pnode_t *)pool->nodes.top) != NULL) {
+           LIST_UNLINK(&pool->nodes, (node_t *)pn);
+           pn->page->pnodes--;
+           if (zero) {
+               register bpage_t *p;
+
+               p = pn->page;
+               mm_memclr(pn, pool->nodesize);
+               pn->page = p;
+           }
+           pn->magic = MAGIC_PNODE;
+           pnode = pn;
+       } else {
+           register bpage_t *p = NULL;
+
+           /* No pnode_t left, we need to allocate a new bpage_t to grow and
+            * initialize the new bnode_t objects. First verify if there is
+            * any available page already in our cache, which pool_free()
+            * maintains using statistics, to minimize calls to page
+            * primitives functions. If there are none, allocate a new bpage_t.
+            */
+           if (pool->maxpages == 0 || pool->pages.nodes < pool->maxpages) {
+               if ((p = (bpage_t *)pool->fpages.top) != NULL)
+                   LIST_UNLINK(&pool->fpages, (node_t *)p);
+               else
+                   p = pool->malloc(pool->pagesize);
+               if (p != NULL) {
+                   register u_int8_t *ptr, *toptr;
+                   register size_t ns = pool->nodesize;
+                   register size_t ps = pool->pagesize;
+                   register size_t bps = (size_t)OALIGN_CEIL(sizeof(bpage_t),
+                           long);
+
+                   p->pool = pool;
+                   p->magic = MAGIC_PAGE;
+                   p->pnodes = pool->nodesperpage;
+                   LIST_APPEND(&pool->pages, (node_t *)p);
+                   for (ptr = toptr = (u_int8_t *)p, ptr += bps, toptr += ps;
+                           ptr + ns < toptr; ptr += ns) {
+                       ((pnode_t *)ptr)->page = p;
+                       ((pnode_t *)ptr)->magic = 0;
+                       LIST_APPEND(&pool->nodes, (node_t *)ptr);
+                   }
+                   /* Now grab first pnode_t */
+                   pn = (pnode_t *)pool->nodes.top;
+                   LIST_UNLINK(&pool->nodes, (node_t *)pn);
+                   p->pnodes--;
+                   if (zero)
+                       mm_memclr(pn, ns);
+                   pn->magic = MAGIC_PNODE;
+                   pn->page = p;
+                   pnode = pn;
+               } else
+                   syslog(LOG_NOTICE, "* pool_alloc() - Out of memory");
+           } else
+               syslog(LOG_NOTICE, "- pool_alloc() - Out of nodes (%u total)",
+                       pool->nodesperpage * pool->maxpages);
+       }
+    } else
+       syslog(LOG_NOTICE, "* pool_alloc() - Invalid pool_t pointer");
+
+    return pnode;
+}
+
+
+pnode_t *pool_free(pnode_t *pnode)
+{
+    if (PNODE_VALID(pnode)) {
+       register bpage_t *p = pnode->page;
+       register pool_t *pool = p->pool;
+       register u_int32_t exceeding;
+
+       /* Efficiently return this node in the free list. Insert it so that
+        * we favor reusing recently used ones.
+        */
+       pnode->magic = 0;
+       LIST_INSERT(&pool->nodes, (node_t *)pnode);
+       p->pnodes++;
+       if ((pool->minpages < pool->maxpages) ||
+               (pool->minpages == 0 && pool->maxpages == 0)) {
+           register u_int32_t pages = pool->pages.nodes; 
+
+           /* This is a pool_t which can shrink, book-keep statistics on
+            * average pages usage.
+            */
+           pool->avgtotal += pages;
+           pool->avgcnt++;
+           if (pool->avgcnt > pool->nodesperpage * 3) {
+               pool->avgcnt = 1;
+               pool->avgtotal = pages;
+           }
+
+           if (p->pnodes == pool->nodesperpage && pool->minpages < pages) {
+               register u_int8_t *ptr, *toptr;
+               register size_t ns = pool->nodesize;
+
+               /* All pnode_t objects belonging to this bpage_t were freed.
+                * Swap the page to the cache to be freed. We also need
+                * to sequencially unlink all the pnode_t objects this page
+                * supplied in the free nodes list_t.
+                */
+               for (ptr = toptr = (u_int8_t *)p,
+                       ptr += (size_t)OALIGN_CEIL(sizeof(bpage_t), long),
+                       toptr += pool->pagesize; ptr + ns < toptr;
+                       ptr += ns)
+                   LIST_UNLINK(&pool->nodes, (node_t *)ptr);
+               /* Insert to preferably reuse recently used pages */
+               p->magic = 0;
+               LIST_SWAP(&pool->fpages, &pool->pages, (node_t *)p, TRUE);
+           }
+           /* Do statistics suggest that we should shrink the pool? If so,
+            * free pages from our cache back to the system.
+            */
+           if ((exceeding = (pool->pages.nodes + pool->fpages.nodes) -
+                       (pool->avgtotal / pool->avgcnt)) > 0) {
+               register list_t *fpages = &pool->fpages;
+               register node_t *n;
+
+               /* Preferably free pages which haven't been used recently */
+               for (; exceeding > 0 && (n = fpages->bottom) != NULL;
+                       exceeding--) {
+                   LIST_UNLINK(fpages, n);
+                   pool->free(p);
+               }
+           }
+       }
+    } else
+       syslog(LOG_NOTICE, "* pool_free() - Invalid pnode_t pointer");
+
+    return NULL;
+}
diff --git a/mmsoftware/mmlib/mmpool.h b/mmsoftware/mmlib/mmpool.h
new file mode 100644 (file)
index 0000000..16e1457
--- /dev/null
@@ -0,0 +1,99 @@
+/* $Id: mmpool.h,v 1.1 2003/03/28 21:09:29 mmondor Exp $ */
+
+/*
+ * Copyright (C) 2000-2003, Matthew Mondor
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software written by Matthew Mondor.
+ * 4. The name of Matthew Mondor may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+
+#ifndef MM_POOL_H
+#define MM_POOL_H
+
+
+
+#include <sys/types.h>
+#include <mmtypes.h>
+#include <mmlist.h>
+
+
+
+typedef struct pnode   pnode_t;
+typedef struct bpage   bpage_t;
+typedef struct pool    pool_t;
+
+
+
+#define MAGIC_POOL     0x504f4f4c      /* POOL */
+#define MAGIC_PAGE     0x50414745      /* PAGE */
+#define MAGIC_PNODE    0x504e4f44      /* PNOD */
+
+#define POOL_VALID(p)  ((p) != NULL && (p)->magic == MAGIC_POOL)
+#define PNODE_VALID(p) ((p) != NULL && (p)->magic == MAGIC_PNODE && \
+       (p)->page != NULL && (p)->page->magic == MAGIC_PAGE && \
+       (p)->page->pool != NULL && (p)->page->pool->magic == MAGIC_POOL)
+
+
+
+struct bpage {
+    node_t node;
+    pool_t *pool;
+    u_int32_t magic;
+    u_int32_t pnodes;
+};
+
+struct pnode {
+    node_t node;
+    u_int32_t magic;
+    bpage_t *page;
+};
+
+struct pool {
+    pnode_t node;              /* Hey, we never know, a pool_t of pool_t */
+    u_int32_t magic;
+    void *(*malloc)(size_t);
+    void (*free)(void *);
+    size_t nodesize, pagesize;
+    u_int32_t minpages, maxpages, nodesperpage;
+    u_int32_t avgtotal, avgcnt;
+    list_t pages, fpages, nodes;
+};
+
+
+
+bool pool_init(pool_t *, void *(*)(size_t), void (*)(void *), size_t,
+       u_int32_t, u_int32_t, u_int32_t);
+bool pool_destroy(pool_t *);
+pnode_t *pool_alloc(pool_t *, bool);
+pnode_t *pool_free(pnode_t *);
+
+
+
+#endif
index 4c4d81e..dbbf1d6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmserver.c,v 1.4 2003/03/02 20:30:43 mmondor Exp $ */
+/* $Id: mmserver.c,v 1.5 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -73,7 +73,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmserver.c,v 1.4 2003/03/02 20:30:43 mmondor Exp $");
+MMRCSID("$Id: mmserver.c,v 1.5 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
@@ -101,8 +101,9 @@ static void async_resolvehostname(struct async_msg *);
 
 static int (*handleclientfunc)(unsigned long, int, clientlistnode *,
        struct iface *, struct async_clenv *);
-static pth_mutex_t clist_lock, plist_lock;
-static list *clist, *plist;
+static pth_mutex_t cpool_lock, ppool_lock;
+static pool_t cpool, ppool;
+static list_t clist;
 static struct async_env *async = NULL;
 
 /* Useful so that daemons can log standard disconnection status easily */
@@ -163,11 +164,12 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
     /* Pth related */
     threadattr = pth_attr_new();
     pth_attr_set(threadattr, PTH_ATTR_JOINABLE, FALSE);
-    pth_mutex_init(&clist_lock);
-    pth_mutex_init(&plist_lock);
+    pth_mutex_init(&cpool_lock);
+    LIST_INIT(&clist);
+    pth_mutex_init(&ppool_lock);
 
     /* Used by resolve_hostname() */
-    if (!mmstrinit(malloc, free, 16384, 0)) {
+    if (!mmstrinit(malloc, free, 16384)) {
        syslog(LOG_NOTICE, "* mmserver() - mmstrinit()");
        closelog();
        exit(-1);
@@ -179,9 +181,10 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
        exit(-1);
     }
 
-    if ((clist = openlist(malloc, free, sizeof(clientlistnode), 65535, 0))
-           == NULL || (plist = openlist(malloc, free, sizeof(phandleinfo),
-                   16384, 0)) == NULL) {
+    if (!pool_init(&cpool, malloc, free, sizeof(clientlistnode),
+               65536 / sizeof(clientlistnode), 0, 0) ||
+           !pool_init(&ppool, malloc, free, sizeof(phandleinfo),
+               16384 / sizeof(phandleinfo), 0, 0)) {
        syslog(LOG_NOTICE, "* mmserver() - Out of memory");
        closelog();
        mmstrexit();
@@ -268,8 +271,8 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
     if (ret) {
        free(ifaces);
        mmstrexit();
-       plist = closelist(plist);
-       clist = closelist(clist);
+       if (POOL_VALID(&ppool)) pool_destroy(&ppool);
+       if (POOL_VALID(&cpool)) pool_destroy(&cpool);
        exit(ret);
     }
 
@@ -289,7 +292,7 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
                        register clientlistnode *nclnode;
                        time_t tim;
 
-                       pth_mutex_acquire(&clist_lock, FALSE, NULL);
+                       pth_mutex_acquire(&cpool_lock, FALSE, NULL);
 
                        /* Try to locate the IP address of the new connection
                         * in our clientlist. Doing so, we also garbage
@@ -299,9 +302,9 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
                         */
                        cnt = 0;
                        tim = time(NULL);
-                       clnode = (clientlistnode *)clist->top;
+                       clnode = (clientlistnode *)clist.top;
                        while (clnode) {
-                           nclnode = (clientlistnode *)clnode->nod.next;
+                           nclnode = (clientlistnode *)clnode->node.node.next;
                            /* Has the period expired? If so, reset it */
                            if (clnode->period < tim) {
                                clnode->period = tim + rateper;
@@ -317,8 +320,8 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
                                /* Free from cache */
                                if (clnode->hostname)
                                    mmstrfree(clnode->hostname);
-                               UNLINKNODE(clist, (node *)clnode);
-                               freenode((node *)clnode);
+                               LIST_UNLINK(&clist, (node_t *)clnode);
+                               pool_free((pnode_t *)clnode);
                            }
                            cnt++;
                            if (cnt > 32) {
@@ -344,17 +347,17 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
                            } else reason = MMS_CONPERADDRESS_EXCEEDED;
                        } else {
                            /* Make sure we don't exceed maxips */
-                           if (clist->nodes < maxips) {
+                           if (clist.nodes < maxips) {
                                /* Allocate a new ip-address shared node */
-                               if ((clnode = (clientlistnode *)allocnode(
-                                               clist, FALSE)) != NULL) {
+                               if ((clnode = (clientlistnode *)pool_alloc(
+                                               &cpool, FALSE)) != NULL) {
                                    clnode->hostname = NULL;
                                    clnode->connections = clnode->rate = 0;
                                    clnode->period = tim + rateper;
                                    clnode->timeout = (timeout * 1000);
                                    clnode->client = addr;
                                    clnode->resolve = resolve;
-                                   APPENDNODE(clist, (node *)clnode);
+                                   LIST_APPEND(&clist, (node_t *)clnode);
                                    ok = TRUE;
                                } else
                                    syslog(LOG_NOTICE,
@@ -366,9 +369,9 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
                            phandleinfo *phi;
 
                            /* Start thread to serve the client */
-                           pth_mutex_acquire(&plist_lock, FALSE, NULL);
-                           phi = (phandleinfo *)allocnode(plist, FALSE);
-                           pth_mutex_release(&plist_lock);
+                           pth_mutex_acquire(&ppool_lock, FALSE, NULL);
+                           phi = (phandleinfo *)pool_alloc(&ppool, FALSE);
+                           pth_mutex_release(&ppool_lock);
                            if (phi != NULL) {
                                id++;
                                phi->id = id;
@@ -382,10 +385,10 @@ tcp_server(char *message, char *server_names, char *listen_ips, uid_t uid,
                                    clnode->connections++;
                                else {
                                    if (phi != NULL) {
-                                       pth_mutex_acquire(&plist_lock, FALSE,
+                                       pth_mutex_acquire(&ppool_lock, FALSE,
                                                NULL);
-                                       freenode((node *)phi);
-                                       pth_mutex_release(&plist_lock);
+                                       pool_free((pnode_t *)phi);
+                                       pth_mutex_release(&ppool_lock);
                                    }
                                    syslog(LOG_NOTICE,
                                            "* mmserver() - Error starting \
@@ -411,7 +414,7 @@ thread to serve client");
                                        ipaddr, MMS_RSTRING(reason));
                        }
 
-                       pth_mutex_release(&clist_lock);
+                       pth_mutex_release(&cpool_lock);
 
                    } else
                        syslog(LOG_NOTICE,
@@ -423,12 +426,12 @@ thread to serve client");
 
     free(ifaces);
     mmstrexit();
-    plist = closelist(plist);
-    clist = closelist(clist);
+    pool_destroy(&ppool);
+    pool_destroy(&cpool);
     /* Unrequired for Pth (non-existing even)
-     * pth_mutex_destroy(&alist_lock);
-     * pth_mutex_destroy(&clist_lock);
-     * pth_mutex_destroy(&plist_lock);
+     * pth_mutex_destroy(&apool_lock);
+     * pth_mutex_destroy(&cpool_lock);
+     * pth_mutex_destroy(&ppool_lock);
      */
 
     exit(ret);
@@ -611,9 +614,9 @@ phandleclient(void *args)
     socket = phi->socket;
     clnode = phi->clnode;
     iface = phi->iface;
-    pth_mutex_acquire(&plist_lock, FALSE, NULL);
-    freenode((node *)phi);
-    pth_mutex_release(&plist_lock);
+    pth_mutex_acquire(&ppool_lock, FALSE, NULL);
+    pool_free((pnode_t *)phi);
+    pth_mutex_release(&ppool_lock);
 
     ret = 0;
 
@@ -631,11 +634,11 @@ phandleclient(void *args)
            }
            if (tmp) {
                /* Lock the mutex for a very short moment */
-               pth_mutex_acquire(&clist_lock, FALSE, NULL);
+               pth_mutex_acquire(&cpool_lock, FALSE, NULL);
                /* Verify again for NULL to avoid a potential memory leak */
                if(clnode->hostname == NULL) clnode->hostname = tmp;
                else tmp = mmstrfree(tmp);
-               pth_mutex_release(&clist_lock);
+               pth_mutex_release(&cpool_lock);
            }
        }
 
@@ -657,9 +660,9 @@ phandleclient(void *args)
     /* Decrease our connection/refcount counter, and let mmserver()
      * garbage-collect or recycle our clnode as required.
      */
-    pth_mutex_acquire(&clist_lock, FALSE, NULL);
+    pth_mutex_acquire(&cpool_lock, FALSE, NULL);
     if (clnode->connections > 0) clnode->connections--;
-    pth_mutex_release(&clist_lock);
+    pth_mutex_release(&cpool_lock);
 
     /* kthxbye :) */
     pth_exit(&ret);
@@ -701,7 +704,7 @@ phandleclient(void *args)
 static void *
 async_thread(void *args)
 {
-    list queue, *freeprocs = async->freeprocs;
+    list_t queue, *freeprocs = &async->freeprocs;
     struct async_idx *idx = NULL;
     struct async_proc *proc;
     struct pollfd *pfds = NULL;
@@ -716,9 +719,9 @@ async_thread(void *args)
      */
 
     /* Initialize our queue, fd->process index and poll array */
-    INITLIST(&queue);
+    LIST_INIT(&queue);
     for (i = 0, proc = (struct async_proc *)freeprocs->top; proc;
-           proc = (struct async_proc *)proc->nod.next)
+           proc = (struct async_proc *)proc->node.node.next)
        if (i < proc->sock) i = proc->sock;
     nfds = freeprocs->nodes;
     idx_size = (size_t)OALIGN_CEIL(sizeof(struct async_idx) * (i + 1), long);
@@ -733,7 +736,7 @@ async_thread(void *args)
        pth_exit(NULL);
     }
     for (i = 0, proc = (struct async_proc *)freeprocs->top; proc;
-           proc = (struct async_proc *)proc->nod.next, i++) {
+           proc = (struct async_proc *)proc->node.node.next, i++) {
        idx[proc->sock].aproc = proc;
        pfds[i].fd = proc->sock;
        pfds[i].events = POLLIN | POLLERR;
@@ -749,11 +752,11 @@ async_thread(void *args)
         */
        if ((pth_msgport_pending(async->port))) {
            while ((omsg = (char *)pth_msgport_get(async->port)) != NULL)
-               APPENDNODE(&queue, (node *)(omsg - sizeof(node)));
+               LIST_APPEND(&queue, (node_t *)(omsg - sizeof(pnode_t)));
        } else if (freeprocs->nodes == async->nprocs) {
            pth_wait(async->ring);
            while ((omsg = (char *)pth_msgport_get(async->port)) != NULL)
-               APPENDNODE(&queue, (node *)(omsg - sizeof(node)));
+               LIST_APPEND(&queue, (node_t *)(omsg - sizeof(pnode_t)));
        }
 
        /* Verify for any available processes to dispatch requests to, and
@@ -771,14 +774,14 @@ async_thread(void *args)
                    len = async->funcs[m->func_id].msg_len;
                    idx[p->sock].aclenv = m->aclenv;
                    if ((pth_send(p->sock, m, len, 0)) == len)
-                       UNLINKNODE(freeprocs, (node *)p);
+                       LIST_UNLINK(freeprocs, (node_t *)p);
                    else
                        syslog(LOG_NOTICE, "* async_thread() - send()");
                } else
                    syslog(LOG_NOTICE,
                            "* async_thread() - Invalid function %u",
                            m->func_id);
-               UNLINKNODE(&queue, (node *)m);
+               LIST_UNLINK(&queue, (node_t *)m);
            }
        }
 
@@ -814,7 +817,7 @@ async_thread(void *args)
                           syslog(LOG_NOTICE, "* async_thread() - recv(%d)",
                                   fd);
                       pth_msgport_reply(&(e->msg->msg));
-                      APPENDNODE(freeprocs, (node *)p);
+                      LIST_APPEND(freeprocs, (node_t *)p);
                       selr--;
                   }
               }
@@ -863,8 +866,8 @@ async_init(struct async_func *funcs, int procs, uid_t uid, gid_t *gids,
     funcs_len = (size_t)OALIGN_CEIL(funcs_len, long);
     msg_len = (size_t)OALIGN_CEIL(msg_len, long);
     if ((async = calloc(env_len + funcs_len + msg_len, 1)) != NULL) {
-       if ((async->freeprocs = blocklist(malloc, free,
-                       sizeof(struct async_proc), procs)) != NULL) {
+       if (pool_init(&async->freeprocs_pool, malloc, free,
+                   sizeof(struct async_proc), procs, 1, 1)) {
            register char *ptr = (char *)async;
 
            ptr += env_len;
@@ -881,9 +884,10 @@ async_init(struct async_func *funcs, int procs, uid_t uid, gid_t *gids,
                async->funcs[i + 1].func = funcs[i].func;
                async->funcs[i + 1].msg_len = funcs[i].msg_len;
            }
+           LIST_INIT(&async->freeprocs);
            res = TRUE;
        } else
-           syslog(LOG_NOTICE, "* async_init() - blocklist(freeprocs)");
+           syslog(LOG_NOTICE, "* async_init() - pool_init(freeprocs_pool)");
     } else
        syslog(LOG_NOTICE, "* async_init() - calloc()");
 
@@ -897,8 +901,7 @@ async_init(struct async_func *funcs, int procs, uid_t uid, gid_t *gids,
 
     if (!res) {
        if (async) {
-           if (async->freeprocs)
-               async->freeprocs = closelist(async->freeprocs);
+           pool_destroy(&async->freeprocs_pool);
            free(async);
            async = NULL;
        }
@@ -922,13 +925,12 @@ async_init_pth(void)
     if (async) {
 
        res = TRUE;
-       pth_mutex_init(&async->alist_lock);
+       pth_mutex_init(&async->apool_lock);
        /* Setup our fast-allocation pool for client-side async environments */
        env_len = (size_t)OALIGN_CEIL(sizeof(struct async_clenv), long);
-       if ((async->alist = openlist(malloc, free,
-                       env_len + async->msg_len, 16384, 0))
-               == NULL) {
-           syslog(LOG_NOTICE, "* async_init_pth() - openlist(alist)");
+       if (!pool_init(&async->apool, malloc, free, env_len + async->msg_len,
+                   16384 / (env_len + async->msg_len), 0, 0)) {
+           syslog(LOG_NOTICE, "* async_init_pth() - pool_init(apool)");
            res = FALSE;
        }
 
@@ -963,8 +965,7 @@ async_init_pth(void)
                pth_msgport_destroy(async->port);
                async->port = NULL;
            }
-           if (async->alist)
-               async->alist = closelist(async->alist);
+           pool_destroy(&async->apool);
        }
 
     } else
@@ -983,11 +984,11 @@ async_open_clenv(void)
 {
     struct async_clenv *aclenv;
 
-    if (async && async->alist) {
+    if (async && POOL_VALID(&async->apool)) {
        /* Optimized for speed using a pool of pre-allocated nodes */
-       pth_mutex_acquire(&async->alist_lock, FALSE, NULL);
-       aclenv = (struct async_clenv *)allocnode(async->alist, FALSE);
-       pth_mutex_release(&async->alist_lock);
+       pth_mutex_acquire(&async->apool_lock, FALSE, NULL);
+       aclenv = (struct async_clenv *)pool_alloc(&async->apool, FALSE);
+       pth_mutex_release(&async->apool_lock);
        if (aclenv) {
            if ((aclenv->port = pth_msgport_create("XXX(NULL)"))) {
                if ((aclenv->ring = pth_event(PTH_EVENT_MSG, aclenv->port))) {
@@ -1004,9 +1005,9 @@ async_open_clenv(void)
                }
                pth_msgport_destroy(aclenv->port);
            }
-           pth_mutex_acquire(&async->alist_lock, FALSE, NULL);
-           freenode((node *)aclenv);
-           pth_mutex_release(&async->alist_lock);
+           pth_mutex_acquire(&async->apool_lock, FALSE, NULL);
+           pool_free((pnode_t *)aclenv);
+           pth_mutex_release(&async->apool_lock);
        }
     } else
        syslog(LOG_NOTICE, "* async_open_clenv() - Initialize first");
@@ -1024,9 +1025,9 @@ async_close_clenv(struct async_clenv *aclenv)
     pth_event_free(aclenv->ring, PTH_FREE_ALL);
     pth_msgport_destroy(aclenv->port);
 
-    pth_mutex_acquire(&async->alist_lock, FALSE, NULL);
-    freenode((node *)aclenv);
-    pth_mutex_release(&async->alist_lock);
+    pth_mutex_acquire(&async->apool_lock, FALSE, NULL);
+    pool_free((pnode_t *)aclenv);
+    pth_mutex_release(&async->apool_lock);
 
     return (NULL);
 }
@@ -1084,11 +1085,11 @@ spawn_async_procs(uid_t uid, gid_t *gids, int ngids)
     int s[2];
     bool ret = FALSE;
 
-    if (!async)
-       return(ret);
+    if (async == NULL)
+       return ret;
 
     do {
-       if ((aproc = (struct async_proc *)allocnode(async->freeprocs,
+       if ((aproc = (struct async_proc *)pool_alloc(&async->freeprocs_pool,
                        TRUE))) {
            if ((socketpair(PF_UNIX, SOCK_DGRAM, 0, s)) == 0) {
                aproc->sock = s[0];
@@ -1104,10 +1105,10 @@ spawn_async_procs(uid_t uid, gid_t *gids, int ngids)
                    if (mmdropprivs(uid, gids, ngids)) {
                        close(s[0]);
                        while ((aproc =
-                               (struct async_proc *)async->freeprocs->top)) {
+                               (struct async_proc *)async->freeprocs.top)) {
                            close(aproc->sock);
-                           UNLINKNODE(async->freeprocs,
-                                   (node *)aproc);
+                           /* XXX ??? */
+                           LIST_UNLINK(&async->freeprocs, (node_t *)aproc);
                        }
                        async_proc_main(s[1]);
                    } else
@@ -1115,7 +1116,7 @@ spawn_async_procs(uid_t uid, gid_t *gids, int ngids)
                                "* spawn_async_procs() - mmdropprivs()");
 
                } else if (aproc->pid == -1) {
-                   freenode((node *)aproc);
+                   pool_free((pnode_t *)aproc);
                    aproc = NULL;
                    syslog(LOG_NOTICE, "* spawn_async_procs() - fork()");
                    close(s[0]);
@@ -1126,7 +1127,7 @@ spawn_async_procs(uid_t uid, gid_t *gids, int ngids)
        }
        if (aproc) {
            close(s[1]);
-           APPENDNODE(async->freeprocs, (node *)aproc);
+           LIST_APPEND(&async->freeprocs, (node_t *)aproc);
        }
        else ret = TRUE;
     } while (aproc);
index e4a3306..44865e4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmserver.h,v 1.2 2003/01/01 14:54:10 mmondor Exp $ */
+/* $Id: mmserver.h,v 1.3 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -44,6 +44,7 @@
 #include <pth.h>
 
 #include <mmtypes.h>
+#include <mmpool.h>
 
 
 
@@ -63,7 +64,7 @@
 #define MMS_CONPERADDRESS_EXCEEDED     10
 #define MMS_UNKNOWN                    11
 
-#define MMS_RSTRING(x) (mms_reasons[x])
+#define MMS_RSTRING(x)                 (mms_reasons[x])
 
 /* Asynchroneous functions */
 #define ASYNC_RESOLVEHOSTNAME          0
@@ -79,7 +80,7 @@
  * no connections are left and occurred for connection rate period.
  */
 typedef struct clientlistnode {
-    node nod;
+    pnode_t node;
     char *hostname;
     long connections, rate;
     time_t period;
@@ -92,7 +93,7 @@ typedef struct clientlistnode {
  * done with (internally, the user thread function does not need to free it).
  */
 typedef struct phandleinfo {
-    node nod;
+    pnode_t node;
     clientlistnode *clnode;
     struct iface *iface;
     unsigned long id;
@@ -122,7 +123,7 @@ struct ifacendx {
  */
 
 /* A message which is to pass arguments to the async thread for a function,
- * And to receive the function results. The user structure is usually
+ * and to receive the function results. The user structure is usually
  * different for both sides. The msg and func_id fields will be transfered
  * back unchanged. Generally the user provides a fixed size structure using
  * a union to be transfered both ways (results and arguments parts). As the
@@ -130,7 +131,7 @@ struct ifacendx {
  * AmigaOs, this is ideal.
  */
 struct async_msg {
-    node nod;
+    pnode_t node;
     pth_message_t msg;
     struct async_clenv *aclenv;
     unsigned int func_id;
@@ -147,7 +148,7 @@ struct async_func {
 
 /* Node used for each process in our async process pool */
 struct async_proc {
-    node nod;
+    pnode_t node;
     pid_t pid;
     int sock;
 };
@@ -157,11 +158,12 @@ struct async_env {
     pth_t slave;
     pth_msgport_t port;
     pth_event_t ring;
-    pth_mutex_t alist_lock;
+    pth_mutex_t apool_lock;
     struct async_func *funcs;
     unsigned int nfuncs, nprocs;
     size_t msg_len;
-    list *freeprocs, *alist;
+    pool_t freeprocs_pool, apool;
+    list_t freeprocs;
     struct async_msg *msg;
 };
 
@@ -173,7 +175,7 @@ struct async_idx {
 
 /* Client/thread specific async context */
 struct async_clenv {
-    node nod;
+    pnode_t node;
     pth_msgport_t port;
     pth_event_t ring;
     struct async_msg *msg;
index a3ffe3f..a57dccd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmstat.h,v 1.2 2003/01/01 14:54:11 mmondor Exp $ */
+/* $Id: mmstat.h,v 1.3 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
@@ -46,6 +46,7 @@
 
 #include <mmtypes.h>
 #include <mmlist.h>
+#include <mmpool.h>
 
 
 
@@ -87,11 +88,11 @@ typedef struct mmstat_entry {
  * speed up allocation/deallocation.
  */
 struct data_node {
-    node nod;
+    pnode_t node;
     struct mmstat_entry entry;
 };
 struct key_node {
-    node nod;
+    pnode_t node;
     u_int64_t hash;
     struct data_node *data;
 };
index cb74e24..df53ec4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmstr.c,v 1.2 2003/01/01 14:54:11 mmondor Exp $ */
+/* $Id: mmstr.c,v 1.3 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmstr.c,v 1.2 2003/01/01 14:54:11 mmondor Exp $");
+MMRCSID("$Id: mmstr.c,v 1.3 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
 
 /* GLOBALS */
 
-static list *mmstrl = NULL;
-static pth_mutex_t mmstrl_lock = PTH_MUTEX_INIT;
+static pool_t mmstrp;
+static pth_mutex_t mmstrp_lock = PTH_MUTEX_INIT;
 
 
 
@@ -70,16 +70,19 @@ static pth_mutex_t mmstrl_lock = PTH_MUTEX_INIT;
  */
 bool
 mmstrinit(void *(*allocfunc)(size_t), void (*freefunc)(void *),
-         size_t buffer, size_t max)
+         size_t buffer)
 {
-    pth_mutex_acquire(&mmstrl_lock, FALSE, NULL);
-    if (mmstrl == NULL)
-       mmstrl = openlist(allocfunc, freefunc, sizeof(mmstrnode), buffer, max);
-    pth_mutex_release(&mmstrl_lock);
-
-    if (mmstrl != NULL)
-       return (TRUE);
-    return (FALSE);
+    bool ok = FALSE;
+
+    pth_mutex_acquire(&mmstrp_lock, FALSE, NULL);
+    if (!POOL_VALID(&mmstrp))
+       ok = pool_init(&mmstrp, allocfunc, freefunc, sizeof(mmstrnode),
+               buffer / sizeof(mmstrnode), 0, 0);
+    else
+       ok = TRUE;
+    pth_mutex_release(&mmstrp_lock);
+
+    return ok;
 }
 
 
@@ -87,10 +90,9 @@ mmstrinit(void *(*allocfunc)(size_t), void (*freefunc)(void *),
 void
 mmstrexit(void)
 {
-    pth_mutex_acquire(&mmstrl_lock, FALSE, NULL);
-    if (mmstrl != NULL)
-       mmstrl = closelist(mmstrl);
-    pth_mutex_release(&mmstrl_lock);
+    pth_mutex_acquire(&mmstrp_lock, FALSE, NULL);
+    pool_destroy(&mmstrp);
+    pth_mutex_release(&mmstrp_lock);
 }
 
 
@@ -112,9 +114,9 @@ mmstrdup(char *str)
        ptr++;
     ptr++;
     if ((i = ptr - str) < 256) {
-       pth_mutex_acquire(&mmstrl_lock, FALSE, NULL);
-       nod = (mmstrnode *)allocnode(mmstrl, FALSE);
-       pth_mutex_release(&mmstrl_lock);
+       pth_mutex_acquire(&mmstrp_lock, FALSE, NULL);
+       nod = (mmstrnode *)pool_alloc(&mmstrp, FALSE);
+       pth_mutex_release(&mmstrp_lock);
        if (nod != NULL) {
            mm_memcpy(nod->string, str, i);
            return (nod->string);
@@ -134,9 +136,9 @@ mmstralloc(size_t size)
     register mmstrnode *nod;
 
     if (size < 256) {
-       pth_mutex_acquire(&mmstrl_lock, FALSE, NULL);
-       nod = (mmstrnode *)allocnode(mmstrl, FALSE);
-       pth_mutex_release(&mmstrl_lock);
+       pth_mutex_acquire(&mmstrp_lock, FALSE, NULL);
+       nod = (mmstrnode *)pool_alloc(&mmstrp, FALSE);
+       pth_mutex_release(&mmstrp_lock);
        if (nod != NULL) {
            *nod->string = 0;
            return (nod->string);
@@ -152,11 +154,11 @@ char *
 mmstrfree(char *str)
 {
     /* Evaluate actual node pointer from supplied string pointer and free it */
-    str -= sizeof(node);
+    str -= sizeof(pnode_t);
 
-    pth_mutex_acquire(&mmstrl_lock, FALSE, NULL);
-    freenode((node *)str);
-    pth_mutex_release(&mmstrl_lock);
+    pth_mutex_acquire(&mmstrp_lock, FALSE, NULL);
+    pool_free((pnode_t *)str);
+    pth_mutex_release(&mmstrp_lock);
 
     return (NULL);
 }
index 5f83dd7..58910a6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmstr.h,v 1.2 2003/01/01 14:54:11 mmondor Exp $ */
+/* $Id: mmstr.h,v 1.3 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -45,7 +45,7 @@
 #include <sys/types.h>
 
 #include <mmtypes.h>
-#include <mmlist.h>
+#include <mmpool.h>
 
 
 
@@ -53,7 +53,7 @@
 /* STRUCTURES */
 
 typedef struct mmstrnode {
-    node nod;
+    pnode_t node;
     char string[256];
 } mmstrnode;
 
@@ -62,7 +62,7 @@ typedef struct mmstrnode {
 
 /* PROTOTYPES */
 
-bool mmstrinit(void * (*)(size_t), void(*)(void *), size_t, size_t);
+bool mmstrinit(void * (*)(size_t), void(*)(void *), size_t);
 void mmstrexit(void);
 char *mmstrdup(char *);
 char *mmstralloc(size_t);
index 324012c..1d47cb6 100644 (file)
@@ -1,14 +1,16 @@
-$Id: ChangeLog,v 1.12 2003/03/02 20:30:43 mmondor Exp $
+$Id: ChangeLog,v 1.13 2003/03/28 21:09:29 mmondor Exp $
 
 
 
 Release: mmmail 0.0.22 devl
-Date   : Febuary 23, 2003
+Date   : March 28, 2003
 By     : Matthew Mondor
 
 * Various
-  - Fixed ALIGN_FLOOR alignment macros which used to always add bytes even
-    of the value was already aligned properly.
+  - Fixed ALIGN_CEIL alignment macros which used to always add bytes even
+    if the value was already aligned properly.
+  - Interface of various lower layer functions and macros were improved, and
+    mmftpd was migrated to use the new ones.
 
 
 
index 3820184..1f917f7 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: install.sh,v 1.3 2003/01/10 03:52:36 mmondor Exp $
+# $Id: install.sh,v 1.4 2003/03/28 21:09:29 mmondor Exp $
 
 if [ "$1" = "help" ]; then
        echo
@@ -97,6 +97,7 @@ instgroup $MMADMINGROUP
 cd ../mmlib/
 instman mmfd.3 3
 instman mmlist.3 3
+instman mmpool.3 3
 instman mmstat.3 3
 cd ../
 
@@ -148,7 +149,7 @@ echo "*** Please read the following man pages ***"
 echo
 echo "mmstat(8), mmstatd(8), mmstatd.conf(5) mmpasswd(8)"
 echo "mmmail(8), mmsmtpd(8), mmsmtpd.conf(5), mmpop3d(8) mmpop3d.conf(5)"
-echo "source auditors: mmstat(3), mmfd(3), mmlist(3)"
+echo "source auditors: mmstat(3), mmfd(3), mmlist(3), mmpool(3)"
 echo
 echo "Thank you for using mmsoftware."
 echo
index 9cd5132..4b7a48f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmpop3d.c,v 1.8 2003/01/09 08:07:08 mmondor Exp $ */
+/* $Id: mmpop3d.c,v 1.9 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -72,7 +72,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmpop3d.c,v 1.8 2003/01/09 08:07:08 mmondor Exp $");
+MMRCSID("$Id: mmpop3d.c,v 1.9 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
@@ -142,13 +142,13 @@ static struct state states[] = {
 /* Used for mmsyslog() */
 static int LOGLEVEL;
 
-/* List used to allocate clientenv nodes */
-static list *clist;
-static pth_mutex_t clist_lock;
+/* Pool used to allocate clientenv nodes */
+static pth_mutex_t cpool_lock;
+static pool_t cpool;
 
-/* Pool used to optimize creatiing/destroying mmfd mutexes */
+/* Pool used to optimize creating/destroying mmfd mutexes */
 static pth_mutex_t mutexes_lock;
-static list *mutexes;
+static pool_t pmutexes;
 
 /* Global bandwidth shaping fdb context */
 static fdbcontext fdbc;
@@ -364,20 +364,20 @@ main(int argc, char **argv)
     packcommands(commands, 3);
     pth_init();
     async_init_pth();
-    pth_mutex_init(&clist_lock);
+    pth_mutex_init(&cpool_lock);
     pth_mutex_init(&mutexes_lock);
 
     /* Allocate necessary pools */
     /* Client nodes */
-    clist = openlist(malloc, free, sizeof(clientenv),
-           16384 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&cpool, malloc, free, sizeof(clientenv),
+           (16384 * CONF.ALLOC_BUFFERS) / sizeof(clientenv), 0, 0);
     /* Mutexes pool for mmfd */
-    mutexes = openlist(malloc, free, sizeof(struct mutexnode),
-           16386 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&pmutexes, malloc, free, sizeof(struct mutexnode),
+           (16384 * CONF.ALLOC_BUFFERS) / sizeof(struct mutexnode), 0, 0);
     /* mmstr nodes */
-    strlist = mmstrinit(malloc, free, 65536 * CONF.ALLOC_BUFFERS, 0);
+    strlist = mmstrinit(malloc, free, 16384 * CONF.ALLOC_BUFFERS);
 
-    if (clist && mutexes && strlist) {
+    if (POOL_VALID(&cpool) && POOL_VALID(&pmutexes) && strlist) {
        fdbcinit(&gfdf, &fdbc, CONF.GBANDWIDTH_IN * 1024,
                CONF.GBANDWIDTH_OUT * 1024);
        mmsql_init(&mmsqlfuncs);
@@ -398,8 +398,8 @@ main(int argc, char **argv)
     }
 
     if (strlist) mmstrexit();
-    if (mutexes) closelist(mutexes);
-    if (clist) closelist(clist);
+    if (POOL_VALID(&pmutexes)) pool_destroy(&pmutexes);
+    if (POOL_VALID(&cpool)) pool_destroy(&cpool);
 
     fdbcdestroy(&fdbc);
     kill(0, SIGTERM);
@@ -826,9 +826,9 @@ alloc_clientenv(void)
 {
     clientenv *clenv;
 
-    pth_mutex_acquire(&clist_lock, FALSE, NULL);
-    clenv = (clientenv *)allocnode(clist, TRUE);
-    pth_mutex_release(&clist_lock);
+    pth_mutex_acquire(&cpool_lock, FALSE, NULL);
+    clenv = (clientenv *)pool_alloc(&cpool, TRUE);
+    pth_mutex_release(&cpool_lock);
 
     if (clenv) {
        mmstat_init(&clenv->pstat, TRUE, FALSE);
@@ -877,9 +877,9 @@ free_clientenv(clientenv *clenv)
     if (clenv->mailbox) mmstrfree(clenv->mailbox);
     if (clenv->index) free(clenv->index);
 
-    pth_mutex_acquire(&clist_lock, FALSE, NULL);
-    freenode((node *)clenv);
-    pth_mutex_release(&clist_lock);
+    pth_mutex_acquire(&cpool_lock, FALSE, NULL);
+    pool_free((pnode_t *)clenv);
+    pth_mutex_release(&cpool_lock);
 
     return (NULL);
 }
@@ -1546,7 +1546,7 @@ _pth_mutex_create(void)
     struct mutexnode *mnod;
 
     pth_mutex_acquire(&mutexes_lock, FALSE, NULL);
-    mnod = (struct mutexnode *)allocnode(mutexes, FALSE);
+    mnod = (struct mutexnode *)pool_alloc(&pmutexes, FALSE);
     pth_mutex_release(&mutexes_lock);
 
     if (mnod)
@@ -1563,7 +1563,7 @@ _pth_mutex_destroy(void *mtx)
 
     /* pth_mutex_destroy(&mnod->mutex); */
     pth_mutex_acquire(&mutexes_lock, FALSE, NULL);
-    freenode(mtx);
+    pool_free(mtx);
     pth_mutex_release(&mutexes_lock);
 
     return (NULL);
index 21587d4..d25420b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmpop3d.h,v 1.4 2003/01/01 14:54:11 mmondor Exp $ */
+/* $Id: mmpop3d.h,v 1.5 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -47,6 +47,7 @@
 #include <pth.h>
 
 #include <mmtypes.h>
+#include <mmpool.h>
 #include <mmserver.h>
 #include <mmlist.h>
 #include <mmfd.h>
@@ -102,7 +103,7 @@ typedef struct msgnode {
 } msgnode;
 
 typedef struct clientenv {
-    node nod;
+    pnode_t node;
     fdbuf *fdb;                        /* Buffered handler around our fd */
     char *buffer;              /* Buffer that points to last command line */
     char *c_hostname;          /* Pointer to client's hostname */
@@ -126,7 +127,7 @@ typedef struct clientenv {
 
 /* Used for mmfd thread support delegation/abstraction */
 struct mutexnode {
-    node nod;
+    pnode_t node;
     pth_mutex_t mutex;
 };
 
index c24abcc..512fafd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsmtpd.c,v 1.11 2003/02/13 00:12:31 mmondor Exp $ */
+/* $Id: mmsmtpd.c,v 1.12 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2001-2003, Matthew Mondor
@@ -74,7 +74,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmsmtpd.c,v 1.11 2003/02/13 00:12:31 mmondor Exp $");
+MMRCSID("$Id: mmsmtpd.c,v 1.12 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
@@ -122,20 +122,21 @@ static struct state states[] = {
 static int LOGLEVEL;
 
 /* Used for clenv allocation buffering */
-static list *clist;
-static pth_mutex_t clist_lock;
+static pool_t cpool;
+static pth_mutex_t cpool_lock;
 
 /* Used for flood protection cache */
-static list *mlist;
+static pool_t mpool;
+static list_t mlist;
 static pth_mutex_t mlist_lock;
 
 /* Used for rcpt allocation buffering */
-static list *rlist;
-static pth_mutex_t rlist_lock;
+static pool_t rpool;
+static pth_mutex_t rpool_lock;
 
 /* Pool used to optimize creatiing/destroying mmfd mutexes */
 static pth_mutex_t mutexes_lock;
-static list *mutexes;
+static pool_t pmutexes;
 
 /* Global bandwidth shaping fdb context */
 static fdbcontext fdbc;
@@ -419,30 +420,31 @@ main(int argc, char **argv)
     packcommands(commands, 4);
     pth_init();
     async_init_pth();
-    pth_mutex_init(&clist_lock);
+    pth_mutex_init(&cpool_lock);
     pth_mutex_init(&mlist_lock);
-    pth_mutex_init(&rlist_lock);
+    pth_mutex_init(&rpool_lock);
     pth_mutex_init(&mutexes_lock);
 
     /* Allocate necessary pools */
     /* Client nodes */
-    clist = openlist(malloc, free, sizeof(clientenv),
-           16384 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&cpool, malloc, free, sizeof(clientenv),
+           (16384 * CONF.ALLOC_BUFFERS) / sizeof(clientenv), 0, 0);
     /* RCPT nodes */
-    rlist = openlist(malloc, free, sizeof(rcptnode),
-           16384 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&rpool, malloc, free, sizeof(rcptnode),
+           (16384 * CONF.ALLOC_BUFFERS) / sizeof(rcptnode), 0, 0);
     /* Mutexes pool for mmfd */
-    mutexes = openlist(malloc, free, sizeof(struct mutexnode),
-           16386 * CONF.ALLOC_BUFFERS, 0);
+    pool_init(&pmutexes, malloc, free, sizeof(struct mutexnode),
+           (16384 * CONF.ALLOC_BUFFERS) / sizeof(struct mutexnode), 0, 0);
     /* Rate nodes */
-    if (CONF.FLOOD_PROTECTION)
-       mlist = blocklist(malloc, free, sizeof(mnode), CONF.FLOOD_CACHE);
-    else mlist = NULL;
+    if (CONF.FLOOD_PROTECTION) {
+       pool_init(&mpool, malloc, free, sizeof(mnode), CONF.FLOOD_CACHE, 1, 1);
+       LIST_INIT(&mlist);
+    }
     /* mmstr nodes */
-    strlist = mmstrinit(malloc, free, 65536 * CONF.ALLOC_BUFFERS, 0);
+    strlist = mmstrinit(malloc, free, 65536 * CONF.ALLOC_BUFFERS);
 
-    if (clist && rlist && mutexes && strlist &&
-           (!CONF.FLOOD_PROTECTION || mlist)) {
+    if (POOL_VALID(&cpool) && POOL_VALID(&rpool) && POOL_VALID(&pmutexes) &&
+           strlist && (!CONF.FLOOD_PROTECTION || POOL_VALID(&mpool))) {
        fdbcinit(&gfdf, &fdbc, CONF.GBANDWIDTH_IN * 1024,
                CONF.GBANDWIDTH_OUT * 1024);
        mmsql_init(&mmsqlfuncs);
@@ -463,10 +465,10 @@ main(int argc, char **argv)
     }
 
     if (strlist) mmstrexit();
-    if (mutexes) closelist(mutexes);
-    if (mlist) closelist(mlist);
-    if (rlist) closelist(rlist);
-    if (clist) closelist(clist);
+    if (POOL_VALID(&pmutexes)) pool_destroy(&pmutexes);
+    if (POOL_VALID(&mpool)) pool_destroy(&mpool);
+    if (POOL_VALID(&rpool)) pool_destroy(&rpool);
+    if (POOL_VALID(&cpool)) pool_destroy(&cpool);
 
     fdbcdestroy(&fdbc);
     kill(0, SIGTERM);
@@ -739,7 +741,7 @@ all_rcpt(clientenv *clenv)
        ahash = mm_strhash64(addr);
        cnt = 0;
        for (rnode = (rcptnode *)clenv->rcpt.top; rnode;
-               rnode = (rcptnode *)rnode->nod.next) {
+               rnode = (rcptnode *)rnode->node.node.next) {
            if (rnode->hash == ahash) {
                valid = FALSE;
                reason = RCPT_EXISTS;
@@ -756,7 +758,7 @@ all_rcpt(clientenv *clenv)
     /* If CONF.FLOOD_PROTECTION is on, make sure that we respect the rate
      * of CONF.FLOOD_MESSAGES within CONF.FLOOD_EXPIRES for this client
      */
-    if (valid && mlist != NULL) {
+    if (valid && CONF.FLOOD_PROTECTION) {
        register mnode *mnod, *next;
        register int cnt;
        register u_int64_t hash;
@@ -769,13 +771,13 @@ all_rcpt(clientenv *clenv)
 
        pth_mutex_acquire(&mlist_lock, FALSE, NULL);
        /* First acquire our mnode, or create it if required */
-       mnod = (mnode *)mlist->top;
+       mnod = (mnode *)mlist.top;
        while (mnod) {
-           next = (mnode *)mnod->nod.next;
+           next = (mnode *)mnod->node.node.next;
            if (mnod->expires < t) {
                /* This entry has expired, expunge it */
-               UNLINKNODE(mlist, (node *)mnod);
-               freenode((node *)mnod);
+               LIST_UNLINK(&mlist, (node_t *)mnod);
+               pool_free((pnode_t *)mnod);
            } else if (mnod->hash == hash) break;
            /* Of course as we still are holding the mutex another
             * thread in the same state would wait still...
@@ -790,11 +792,11 @@ all_rcpt(clientenv *clenv)
 
        if (!mnod) {
            /* Create a new mnode since none matched */
-           if ((mnod = (mnode *)allocnode(mlist, FALSE)) != NULL) {
+           if ((mnod = (mnode *)pool_alloc(&mpool, FALSE)) != NULL) {
                mnod->hash = hash;
                mnod->expires = t + (CONF.FLOOD_EXPIRES * 60);
                mnod->posts = 1;
-               APPENDNODE(mlist, (node *)mnod);
+               LIST_APPEND(&mlist, (node_t *)mnod);
            } else {
                valid = FALSE;
                reason = RCPT_FLOOD;
@@ -826,14 +828,14 @@ within last %ld minute(s))", clenv->id, mnod->posts,
        register rcptnode *rnode;
 
        reason = RCPT_ERROR;
-       pth_mutex_acquire(&rlist_lock, FALSE, NULL);
-       rnode = (rcptnode *)allocnode(rlist, FALSE);
-       pth_mutex_release(&rlist_lock);
+       pth_mutex_acquire(&rpool_lock, FALSE, NULL);
+       rnode = (rcptnode *)pool_alloc(&rpool, FALSE);
+       pth_mutex_release(&rpool_lock);
        if (rnode) {
            mm_strcpy(rnode->address, addr);
            mm_strcpy(rnode->foraddress, foraddr);
            rnode->hash = ahash;
-           APPENDNODE(&clenv->rcpt, (node *)rnode);
+           LIST_APPEND(&clenv->rcpt, (node_t *)rnode);
            reason = RCPT_OK;
            clenv->rcpts++;
        } else {
@@ -940,9 +942,9 @@ alloc_clientenv(void)
 {
     clientenv *clenv;
 
-    pth_mutex_acquire(&clist_lock, FALSE, NULL);
-    clenv = (clientenv *)allocnode(clist, TRUE);
-    pth_mutex_release(&clist_lock);
+    pth_mutex_acquire(&cpool_lock, FALSE, NULL);
+    clenv = (clientenv *)pool_alloc(&cpool, TRUE);
+    pth_mutex_release(&cpool_lock);
 
     if (clenv) {
        mmstat_init(&clenv->vstat, TRUE, TRUE);
@@ -975,26 +977,28 @@ free_clientenv(clientenv *clenv)
     if (clenv->from) mmstrfree(clenv->from);
     empty_rcpts(&clenv->rcpt);
 
-    pth_mutex_acquire(&clist_lock, FALSE, NULL);
-    freenode((node *)clenv);
-    pth_mutex_release(&clist_lock);
+    pth_mutex_acquire(&cpool_lock, FALSE, NULL);
+    pool_free((pnode_t *)clenv);
+    pth_mutex_release(&cpool_lock);
 
     return (NULL);
 }
 
 
-/* Useful to free all rcpts for a clientenv */
+/* Useful to free all rcpts for a clientenv.
+ * XXX If we used a pool_t per clientenv for these we would simply destroy
+ */
 static void
-empty_rcpts(list *lst)
+empty_rcpts(list_t *lst)
 {
-    node *nod;
+    node_t *nod;
 
-    pth_mutex_acquire(&rlist_lock, FALSE, NULL);
+    pth_mutex_acquire(&rpool_lock, FALSE, NULL);
     while ((nod = lst->top)) {
-       UNLINKNODE(lst, nod);
-       freenode(nod);
+       LIST_UNLINK(lst, nod);
+       pool_free((pnode_t *)nod);
     }
-    pth_mutex_release(&rlist_lock);
+    pth_mutex_release(&rpool_lock);
 }
 
 
@@ -1471,7 +1475,7 @@ do_data(clientenv *clenv)
 
            /* For each RCPT, create query and execute it */
            for (rnode = (rcptnode *)clenv->rcpt.top; rnode;
-                   rnode = (rcptnode *)rnode->nod.next) {
+                   rnode = (rcptnode *)rnode->node.node.next) {
                /* Use the common message buffer, but append the query and
                 * message line before it (in it's 2048 bytes free area)
                 */
@@ -1737,7 +1741,7 @@ _pth_mutex_create(void)
     struct mutexnode *mnod;
 
     pth_mutex_acquire(&mutexes_lock, FALSE, NULL);
-    mnod = (struct mutexnode *)allocnode(mutexes, FALSE);
+    mnod = (struct mutexnode *)pool_alloc(&pmutexes, FALSE);
     pth_mutex_release(&mutexes_lock);
 
     if (mnod)
@@ -1754,7 +1758,7 @@ _pth_mutex_destroy(void *mtx)
 
     /* pth_mutex_destroy(&mnod->mutex); */
     pth_mutex_acquire(&mutexes_lock, FALSE, NULL);
-    freenode(mtx);
+    pool_free(mtx);
     pth_mutex_release(&mutexes_lock);
 
     return (NULL);
index c5ecdce..4e412f0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsmtpd.h,v 1.8 2003/01/10 03:52:36 mmondor Exp $ */
+/* $Id: mmsmtpd.h,v 1.9 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2003, Matthew Mondor
@@ -49,6 +49,7 @@
 
 #include <mmtypes.h>
 #include <mmlist.h>
+#include <mmpool.h>
 #include <mmserver.h>
 #include <mmfd.h>
 #include <mmstat.h>
@@ -123,7 +124,7 @@ typedef struct config {
 
 /* This consists of the state-shared clientenv structure */
 typedef struct clientenv {
-    node nod;
+    pnode_t node;
     fdbuf *fdb;                        /* Buffered handler around our fd */
     char *buffer;              /* Buffer that points to last command line */
     char *helo;                        /* Cached helo hostname */
@@ -138,13 +139,13 @@ typedef struct clientenv {
     unsigned long rcpts;       /* Number of RCPT accepted */
     struct iface *iface;       /* Current interface user connected through */
     struct async_clenv *aclenv;        /* Thread context for async_call() */
-    list rcpt;                 /* Cached recepients to send mail to */
+    list_t rcpt;               /* Cached recepients to send mail to */
     MMSTAT vstat, pstat;       /* mmstat(3) handles */
 } clientenv;
 
 /* Used for RCPT addresses */
 typedef struct rcptnode {
-    node nod;
+    pnode_t node;
     char address[64], foraddress[64];
     u_int64_t hash;
 } rcptnode;
@@ -154,7 +155,7 @@ typedef struct rcptnode {
  * is too high.
  */
 typedef struct mnode {
-    node nod;
+    pnode_t node;
     u_int64_t hash;            /* 64-bit hash of host address or name */
     time_t expires;            /* Time entry will expire */
     long posts;                        /* How many posts since entry creation */
@@ -162,7 +163,7 @@ typedef struct mnode {
 
 /* Used for mmfd thread support delegation/abstraction */
 struct mutexnode {
-    node nod;
+    pnode_t node;
     pth_mutex_t mutex;
 };
 
@@ -230,7 +231,7 @@ static bool reply(fdbuf *, int, bool, const char *, ...);
 static clientenv *alloc_clientenv(void);
 static bool init_clientenv(clientenv *, bool);
 static clientenv *free_clientenv(clientenv *);
-static void empty_rcpts(list *);
+static void empty_rcpts(list_t *);
 static bool check_alias(char *);
 static bool check_nofrom(const char *, const char *);
 static int best_match(const char *, const char *);
index b9fb819..372b386 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: install.sh,v 1.2 2003/01/10 03:52:36 mmondor Exp $
+# $Id: install.sh,v 1.3 2003/03/28 21:09:29 mmondor Exp $
 
 if [ "$1" = "help" ]; then
        echo
@@ -83,6 +83,7 @@ instgroup $MMADMINGROUP
 
 cd ../mmlib/
 instman mmlist.3 3
+instman mmpool.3 3
 instman mmstat.3 3
 cd ../
 
@@ -106,7 +107,7 @@ echo
 echo "*** Please read the following man pages ***"
 echo
 echo "mmstat(8), mmstatd(8), mmstatd.conf(5)"
-echo "source auditors: mmstat(3), mmlist(3)"
+echo "source auditors: mmstat(3), mmlist(3), mmpool(3)"
 echo
 echo "Thank you for using mmsoftware."
 echo
index 81b0bcb..cd02df0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmstat.c,v 1.6 2003/03/02 20:30:44 mmondor Exp $ */
+/* $Id: mmstat.c,v 1.7 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
 #include <mmstat.h>
 #include <mmstring.h>
 #include <mmlist.h>
+#include <mmpool.h>
 
 
 
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmstat.c,v 1.6 2003/03/02 20:30:44 mmondor Exp $");
+MMRCSID("$Id: mmstat.c,v 1.7 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
@@ -59,7 +60,7 @@ MMRCSID("$Id: mmstat.c,v 1.6 2003/03/02 20:30:44 mmondor Exp $");
 /* STRUCTURES */
 
 struct entnode {
-    node nod;
+    pnode_t node;
     MMSTATENT ent;
 };
 
@@ -127,7 +128,8 @@ void usage(void)
 static
 int stat_report(int argc, char **argv)
 {
-    list *lst;
+    list_t list;
+    pool_t pool;
     struct entnode *entnod;
     MMSTATRES *res;
     MMSTATENT *ent;
@@ -138,41 +140,43 @@ int stat_report(int argc, char **argv)
        mm_memclr(key, KEY_SIZE);
        if (argc == 3) mm_strncpy(key, argv[2], KEY_SIZE - 1);
 
-       if ((res = mmstat_report(key))) {
-           /* Cache all results as fast as possible to free the librarian */
-           if ((lst = openlist(malloc, free, sizeof(struct entnode), 8192,
-                           0))) {
+       if (pool_init(&pool, malloc, free, sizeof(struct entnode),
+                   32768 / sizeof(struct entnode), 1, 0)) {
+           LIST_INIT(&list);
+           if ((res = mmstat_report(key))) {
+               /* Cache all results as fast as possible to free the librarian.
+                * Note that we also pre-buffered a 32768 bytes of nodes too,
+                * but which can grow if needed.
+                */
                while ((ent = mmstat_nextres(res))) {
-                   if ((entnod = (struct entnode *)allocnode(lst, FALSE))) {
+                   if ((entnod = (struct entnode *)pool_alloc(&pool,
+                                   FALSE))) {
                        mm_memcpy(&entnod->ent, ent, sizeof(MMSTATENT));
-                       APPENDNODE(lst, (node *)entnod);
-                   } else {
-                       lst = closelist(lst);
+                       LIST_APPEND(&list, (node_t *)entnod);
+                   } else
                        break;
-                   }
                }
-           }
-           mmstat_freeres(res);
-           if (lst) {
+               mmstat_freeres(res);
                /* Now output list of results to stdout, which could be piped
                 * and processed at an arbitrary rate without hogging the
                 * librarian.
                 */
-               for (entnod = (struct entnode *)lst->top; entnod;
-                       entnod = (struct entnode *)entnod->nod.next) {
+               for (entnod = (struct entnode *)list.top; entnod;
+                       entnod = (struct entnode *)entnod->node.node.next) {
                    ent = &entnod->ent;
                    printf("%c %d %ld %ld %lld %s\n",
                           ent->persistant ? 'p' : 'v', ent->uid,
                           (long)ent->created, (long)ent->modified,
                           ent->value, ent->key);
                }
-               closelist(lst);
            } else {
-               printf("Error allocating memory for results\n");
+               printf("Error connecting to mmstatd\n");
                ret = -1;
            }
+           pool_destroy(&pool);
+           LIST_INIT(&list);
        } else {
-           printf("Error connecting to mmstatd\n");
+           printf("Error allocating memory for results\n");
            ret = -1;
        }
     } else {
@@ -187,34 +191,37 @@ int stat_report(int argc, char **argv)
 static
 int stat_hreport(int argc, char **argv)
 {
-    list *lst;
+    pool_t pool;
+    list_t list;
     struct entnode *entnod;
     MMSTATRES *res;
     MMSTATENT *ent;
     int ret = 0;
     char key[KEY_SIZE];
+    bool nomem = FALSE;
 
     if (argc == 2 || argc == 3) {
        mm_memclr(key, KEY_SIZE);
        if (argc == 3) mm_strncpy(key, argv[2], KEY_SIZE - 1);
 
-       if ((res = mmstat_report(key))) {
-           /* Cache all results as fast as possible to free the librarian */
-           if ((lst = openlist(malloc, free, sizeof(struct entnode), 8192,
-                           0))) {
+       if (pool_init(&pool, malloc, free, sizeof(struct entnode),
+                   32768 / sizeof(struct entnode), 1, 0)) {
+           LIST_INIT(&list);
+           if ((res = mmstat_report(key))) {
+               struct entnode **index;
+               struct tm modifiedt;
+               char modified[15];
+
+               /* Cache all results as fast as possible to free librarian */
                while ((ent = mmstat_nextres(res))) {
-                   if ((entnod = (struct entnode *)allocnode(lst, FALSE))) {
+                   if ((entnod = (struct entnode *)pool_alloc(&pool,
+                                   FALSE))) {
                        mm_memcpy(&entnod->ent, ent, sizeof(MMSTATENT));
-                       memcpy(&entnod->ent, ent, sizeof(MMSTATENT));
-                       APPENDNODE(lst, (node *)entnod);
-                   } else {
-                       lst = closelist(lst);
+                       LIST_APPEND(&list, (node_t *)entnod);
+                   } else
                        break;
-                   }
                }
-           }
-           mmstat_freeres(res);
-           if (lst) {
+               mmstat_freeres(res);
                /* Now output list of results to stdout, which could be piped
                 * and processed at an arbitrary rate without hogging the
                 * librarian.
@@ -222,20 +229,16 @@ int stat_hreport(int argc, char **argv)
                /* We want to sort the results by key name; We thus need to
                 * setup an index array.
                 */
-               struct entnode **index;
-               struct tm modifiedt;
-               char modified[15];
-
                if ((index = malloc(sizeof(struct entnode *) *
-                               (lst->nodes + 1))) != NULL) {
+                               (list.nodes + 1))) != NULL) {
                    int i;
 
-                   for (entnod = (struct entnode *)lst->top, i = 0; entnod;
-                           entnod = (struct entnode *)entnod->nod.next)
+                   for (entnod = (struct entnode *)list.top, i = 0; entnod;
+                           entnod = (struct entnode *)entnod->node.node.next)
                        index[i++] = entnod;
                    index[i] = NULL;
 
-                   qsort(index, lst->nodes, sizeof(struct entnode *),
+                   qsort(index, list.nodes, sizeof(struct entnode *),
                            compar_entnode);
 
                    for (i = 0; index[i] != NULL; i++) {
@@ -247,15 +250,18 @@ int stat_hreport(int argc, char **argv)
                    }
 
                    free(index);
-               }
-
-               closelist(lst);
+               } else
+                   nomem = TRUE;
            } else {
-               printf("Error allocating memory for results\n");
+               printf("Error connecting to mmstatd\n");
                ret = -1;
            }
-       } else {
-           printf("Error connecting to mmstatd\n");
+           pool_destroy(&pool);
+           LIST_INIT(&list);
+       } else
+           nomem = TRUE;
+       if (nomem) {
+           printf("Error allocating memory for results\n");
            ret = -1;
        }
     } else {
index 473e160..420b576 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmstatd.c,v 1.5 2003/01/10 03:52:36 mmondor Exp $ */
+/* $Id: mmstatd.c,v 1.6 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
@@ -68,6 +68,7 @@
 
 #include <mmtypes.h>
 #include <mmlist.h>
+#include <mmpool.h>
 #include <mmstring.h>
 #include <mmstat.h>
 #include <mmstatd.h>
@@ -78,7 +79,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmstatd.c,v 1.5 2003/01/10 03:52:36 mmondor Exp $");
+MMRCSID("$Id: mmstatd.c,v 1.6 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
@@ -121,7 +122,8 @@ static void logger_main(int, int, int, long *, off_t *);
 
 static struct mmstat_config CONF;
 static pid_t librarian_pid = -1, logger_pid = -1;
-static list *key_list, *data_list;
+static pool_t key_pool, data_pool;
+static list_t key_list, data_list;
 static int pipefds[2], syncbytes = 0;
 static bool run = TRUE, pipesend = TRUE, kdirection = TRUE, ddirection = TRUE;
 
@@ -538,12 +540,12 @@ processlogentry(struct log_entry *entry, bool tmp)
             */
            hash = mm_strhash64(entry->key);
            if (kdirection) {
-               for (knod = (struct key_node *)key_list->top; knod;
-                       knod = (struct key_node *)knod->nod.next)
+               for (knod = (struct key_node *)key_list.top; knod;
+                       knod = (struct key_node *)knod->node.node.next)
                    if (knod->hash == hash) break;
            } else {
-               for (knod = (struct key_node *)key_list->bottom; knod;
-                       knod = (struct key_node *)knod->nod.prev)
+               for (knod = (struct key_node *)key_list.bottom; knod;
+                       knod = (struct key_node *)knod->node.node.prev)
                    if (knod->hash == hash) break;
            }
            kdirection = !kdirection;
@@ -559,10 +561,10 @@ processlogentry(struct log_entry *entry, bool tmp)
                if (ok) {
                    if (type == STAT_DELETE) {
                        /* Delete entry */
-                       UNLINKNODE(data_list, (node *)knod->data);
-                       freenode((node *)knod->data);
-                       UNLINKNODE(key_list, (node *)knod);
-                       freenode((node *)knod);
+                       LIST_UNLINK(&data_list, (node_t *)knod->data);
+                       pool_free((pnode_t *)knod->data);
+                       LIST_UNLINK(&key_list, (node_t *)knod);
+                       pool_free((pnode_t *)knod);
                        return (TRUE);
                    }
                }
@@ -576,10 +578,10 @@ processlogentry(struct log_entry *entry, bool tmp)
                        register struct data_node *dnod;
 
                        /* Create new entry */
-                       if ((dnod = (struct data_node *)allocnode(data_list,
+                       if ((dnod = (struct data_node *)pool_alloc(&data_pool,
                                        FALSE))) {
-                           if ((knod = (struct key_node *)allocnode(key_list,
-                                           FALSE))) {
+                           if ((knod = (struct key_node *)pool_alloc(
+                                           &key_pool, FALSE))) {
                                mm_strncpy(dnod->entry.key, entry->key,
                                        KEY_SIZE - 1);
                                dnod->entry.value = type == STAT_UPDATE ?
@@ -589,13 +591,13 @@ processlogentry(struct log_entry *entry, bool tmp)
                                dnod->entry.created = dnod->entry.modified =
                                    time(NULL);
                                dnod->entry.persistant = entry->persistant;
-                               APPENDNODE(data_list, (node *)dnod);
+                               LIST_APPEND(&data_list, (node_t *)dnod);
                                knod->hash = hash;
                                knod->data = dnod;
-                               APPENDNODE(key_list, (node *)knod);
+                               LIST_APPEND(&key_list, (node_t *)knod);
                            } else
-                               dnod = (struct data_node *)freenode(
-                                       (node *)dnod);
+                               dnod = (struct data_node *)pool_free(
+                                       (pnode_t *)dnod);
                        }
                        if (!dnod || !knod)
                            return (FALSE);
@@ -611,10 +613,10 @@ processlogentry(struct log_entry *entry, bool tmp)
                    knod->data->entry.value = entry->un.reset.value;
                if (knod->data->entry.value == 0 && entry->autoflush) {
                    /* autoflush entry which reached zero, delete it */
-                   UNLINKNODE(data_list, (node *)knod->data);
-                   freenode((node *)knod->data);
-                   UNLINKNODE(key_list, (node *)knod);
-                   freenode((node *)knod);
+                   LIST_UNLINK(&data_list, (node_t *)knod->data);
+                   pool_free((pnode_t *)knod->data);
+                   LIST_UNLINK(&key_list, (node_t *)knod);
+                   pool_free((pnode_t *)knod);
                } else
                    knod->data->entry.modified = time(NULL);
            }
@@ -626,9 +628,9 @@ processlogentry(struct log_entry *entry, bool tmp)
            /* Perform operation on all matching keys which belong to us
             * in an atomic manner.
             */
-           knod = (struct key_node *)key_list->top;
+           knod = (struct key_node *)key_list.top;
            while (knod) {
-               tknod = (struct key_node *)knod->nod.next;
+               tknod = (struct key_node *)knod->node.node.next;
                dnod = knod->data;
                if (dnod->entry.uid == entry->uid &&
                        log_match(dnod->entry.key, entry->key)) {
@@ -638,10 +640,10 @@ processlogentry(struct log_entry *entry, bool tmp)
                        dnod->entry.value += entry->un.update.modifier;
                    if ((dnod->entry.value == 0 && entry->autoflush) ||
                            type == STAT_DELETE) {
-                       UNLINKNODE(data_list, (node *)dnod);
-                       freenode((node *)dnod);
-                       UNLINKNODE(key_list, (node *)knod);
-                       freenode((node *)knod);
+                       LIST_UNLINK(&data_list, (node_t *)dnod);
+                       pool_free((pnode_t *)dnod);
+                       LIST_UNLINK(&key_list, (node_t *)knod);
+                       pool_free((pnode_t *)knod);
                    }
                }
                knod = tknod;
@@ -729,10 +731,11 @@ load_db(long *lognum, off_t *logpos)
     *logpos = 0;
 
     snprintf(filename, 255, "%s/mmstatd.db", CONF.ENV_DIR);
-    if ((data_list = openlist(malloc, free, sizeof(struct data_node), 16384,
-                   0))) {
-       if ((key_list = openlist(malloc, free, sizeof(struct key_node), 16384,
-                       0))) {
+    if (pool_init(&data_pool, malloc, free, sizeof(struct data_node),
+               16384 / sizeof(struct data_node), 0, 0)) {
+       if (pool_init(&key_pool, malloc, free, sizeof(struct key_node),
+                   16384 / sizeof(struct key_node), 0, 0)) {
+           LIST_INIT(&key_list);
            if ((fh = fopen(filename, "rb"))) {
                /* We now remember how to load old mmstatd database files,
                 * since at times the format changes accross versions.
@@ -797,9 +800,9 @@ load_db_v0_0_1(FILE *fh, long *lognum, long *logpos)
        ok = FALSE;
     while (ok) {
        if (fread(&hash, sizeof(u_int64_t), 1, fh) == 1) {
-           if ((dnod = (struct data_node *)allocnode(data_list, FALSE))) {
+           if ((dnod = (struct data_node *)pool_alloc(&data_pool, FALSE))) {
                dnod->entry.persistant = TRUE;
-               if ((knod = (struct key_node *)allocnode(key_list, FALSE))) {
+               if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
                    knod->hash = hash;
                    knod->data = dnod;
                    if (fread(&dnod->entry.value, sizeof(int64_t), 1, fh) != 1
@@ -813,16 +816,16 @@ load_db_v0_0_1(FILE *fh, long *lognum, long *logpos)
                            || fread(&dnod->entry.key, len + 1, 1, fh) != 1)
                        ok = FALSE;
                    else {
-                       APPENDNODE(data_list, (node *)dnod);
-                       APPENDNODE(key_list, (node *)knod);
+                       LIST_APPEND(&data_list, (node_t *)dnod);
+                       LIST_APPEND(&key_list, (node_t *)knod);
                    }
                } else
                    ok = FALSE;
            } else
                ok = FALSE;
            if (!ok) {
-               if (dnod) freenode((node *)dnod);
-               if (knod) freenode((node *)knod);
+               if (dnod) pool_free((pnode_t *)dnod);
+               if (knod) pool_free((pnode_t *)knod);
            }
        } else
            break;
@@ -846,9 +849,9 @@ load_db_v0_0_2(FILE *fh, long *lognum, off_t *logpos)
        ok = FALSE;
     while (ok) {
        if (fread(&hash, sizeof(u_int64_t), 1, fh) == 1) {
-           if ((dnod = (struct data_node *)allocnode(data_list, FALSE))) {
+           if ((dnod = (struct data_node *)pool_alloc(&data_pool, FALSE))) {
                dnod->entry.persistant = TRUE;
-               if ((knod = (struct key_node *)allocnode(key_list, FALSE))) {
+               if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
                    knod->hash = hash;
                    knod->data = dnod;
                    if (fread(&dnod->entry.value, sizeof(int64_t), 1, fh) != 1
@@ -862,16 +865,16 @@ load_db_v0_0_2(FILE *fh, long *lognum, off_t *logpos)
                            || fread(&dnod->entry.key, len + 1, 1, fh) != 1)
                        ok = FALSE;
                    else {
-                       APPENDNODE(data_list, (node *)dnod);
-                       APPENDNODE(key_list, (node *)knod);
+                       LIST_APPEND(&data_list, (node_t *)dnod);
+                       LIST_APPEND(&key_list, (node_t *)knod);
                    }
                } else
                    ok = FALSE;
            } else
                ok = FALSE;
            if (!ok) {
-               if (dnod) freenode((node *)dnod);
-               if (knod) freenode((node *)knod);
+               if (dnod) pool_free((pnode_t *)dnod);
+               if (knod) pool_free((pnode_t *)knod);
            }
        } else
            break;
@@ -895,9 +898,9 @@ load_db_v0_0_3(FILE *fh, long *lognum, off_t *logpos)
        ok = FALSE;
     while (ok) {
        if (fread(&hash, sizeof(u_int64_t), 1, fh) == 1) {
-           if ((dnod = (struct data_node *)allocnode(data_list, FALSE))) {
+           if ((dnod = (struct data_node *)pool_alloc(&data_pool, FALSE))) {
                dnod->entry.persistant = TRUE;
-               if ((knod = (struct key_node *)allocnode(key_list, FALSE))) {
+               if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
                    knod->hash = hash;
                    knod->data = dnod;
                    if (fread(&dnod->entry.value, sizeof(int64_t), 1, fh) != 1
@@ -911,16 +914,16 @@ load_db_v0_0_3(FILE *fh, long *lognum, off_t *logpos)
                            || fread(&dnod->entry.key, len + 1, 1, fh) != 1)
                        ok = FALSE;
                    else {
-                       APPENDNODE(data_list, (node *)dnod);
-                       APPENDNODE(key_list, (node *)knod);
+                       LIST_APPEND(&data_list, (node_t *)dnod);
+                       LIST_APPEND(&key_list, (node_t *)knod);
                    }
                } else
                    ok = FALSE;
            } else
                ok = FALSE;
            if (!ok) {
-               if (dnod) freenode((node *)dnod);
-               if (knod) freenode((node *)knod);
+               if (dnod) pool_free((pnode_t *)dnod);
+               if (knod) pool_free((pnode_t *)knod);
            }
        } else
            break;
@@ -963,8 +966,8 @@ sync_db(long lognum, off_t logpos, bool all)
                fwrite(&lognum, sizeof(long), 1, fh) == 1 &&
                fwrite(&logpos, sizeof(off_t), 1, fh) == 1) {
            /* DB contents */
-           for (knod = (struct key_node *)key_list->top; knod && ok;
-                   knod = (struct key_node *)knod->nod.next) {
+           for (knod = (struct key_node *)key_list.top; knod && ok;
+                   knod = (struct key_node *)knod->node.node.next) {
                len = mm_strlen(knod->data->entry.key);
                if (knod->data->entry.persistant) {
                    if (fwrite(&knod->hash, sizeof(u_int64_t), 1, fh)
@@ -1023,8 +1026,10 @@ sync_db(long lognum, off_t logpos, bool all)
 static void
 free_db(void)
 {
-    if (data_list) data_list = closelist(data_list);
-    if (key_list) key_list = closelist(key_list);
+    if (POOL_VALID(&data_pool)) pool_destroy(&data_pool);
+    LIST_INIT(&data_list);
+    if (POOL_VALID(&key_pool)) pool_destroy(&key_pool);
+    LIST_INIT(&key_list);
 }
 
 
@@ -1092,8 +1097,8 @@ writestats(int fd, char *key)
         */
        if (*key == '\0') {
            /* Full statistics report request */
-           for (dnod = (struct data_node *)data_list->top; dnod && pipesend;
-                   dnod = (struct data_node *)dnod->nod.next)
+           for (dnod = (struct data_node *)data_list.top; dnod && pipesend;
+                   dnod = (struct data_node *)dnod->node.node.next)
                write(fd, &dnod->entry, sizeof(MMSTATENT));
            ddirection = 0;
        } else {
@@ -1101,9 +1106,9 @@ writestats(int fd, char *key)
                if (*ptr == '*' || *ptr == '?') break;
            if (*ptr) {
                /* Key pattern matching report request */
-               for (dnod = (struct data_node *)data_list->top;
+               for (dnod = (struct data_node *)data_list.top;
                        dnod && pipesend;
-                       dnod = (struct data_node *)dnod->nod.next) {
+                       dnod = (struct data_node *)dnod->node.node.next) {
                    if (log_match(dnod->entry.key, key))
                        write(fd, &dnod->entry, sizeof(MMSTATENT));
                }
@@ -1112,12 +1117,12 @@ writestats(int fd, char *key)
                /* Absolute key report request */
                hash = mm_strhash64(key);
                if (kdirection) {
-                   for (knod = (struct key_node *)key_list->top; knod;
-                           knod = (struct key_node *)knod->nod.next)
+                   for (knod = (struct key_node *)key_list.top; knod;
+                           knod = (struct key_node *)knod->node.node.next)
                        if (knod->hash == hash) break;
                } else {
-                   for (knod = (struct key_node *)key_list->bottom; knod;
-                           knod = (struct key_node *)knod->nod.prev)
+                   for (knod = (struct key_node *)key_list.bottom; knod;
+                           knod = (struct key_node *)knod->node.node.prev)
                        if (knod->hash == hash) break;
                }
                kdirection = !kdirection;
@@ -1139,8 +1144,8 @@ rotatestats(char *pattern, char *prefix)
 
     /* Sanity check */
     if (pattern[KEY_SIZE - 1] == '\0' && prefix[KEY_SIZE - 1] == '\0') {
-       for (knod = (struct key_node *)key_list->top; knod;
-               knod = (struct key_node *)knod->nod.next) {
+       for (knod = (struct key_node *)key_list.top; knod;
+               knod = (struct key_node *)knod->node.node.next) {
            if (knod->data->entry.persistant &&
                    log_match(knod->data->entry.key, pattern)) {
                snprintf(key, KEY_SIZE - 1, "%s%s", prefix,
@@ -1282,7 +1287,8 @@ main(int argc, char **argv)
 
     /* Initialization */
     librarian_pid = logger_pid = -1;
-    key_list = data_list = NULL;
+    LIST_INIT(&key_list);
+    LIST_INIT(&data_list);
     pipefds[0] = pipefds[1] = -1;
 
     printf("\r\n+++ %s (%s)\r\n\r\n", DAEMON_NAME, DAEMON_VERSION);
index 40998da..3b68937 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmstatd.h,v 1.3 2003/01/10 03:52:36 mmondor Exp $ */
+/* $Id: mmstatd.h,v 1.4 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
@@ -41,7 +41,7 @@
 
 
 #define DAEMON_NAME    "mmstatd"
-#define DAEMON_VERSION "0.0.6/mmondor"
+#define DAEMON_VERSION "0.0.7/mmondor"
 
 
 
index 256da4a..3c20031 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsucomd.c,v 1.3 2003/01/08 20:57:47 mmondor Exp $ */
+/* $Id: mmsucomd.c,v 1.4 2003/03/28 21:09:29 mmondor Exp $ */
 
 /*
  * Copyright (C) 2002-2003, Matthew Mondor
@@ -56,6 +56,7 @@
 
 #include <mmtypes.h>
 #include <mmlist.h>
+#include <mmpool.h>
 #include <mmstring.h>
 
 
@@ -63,7 +64,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmsucomd.c,v 1.3 2003/01/08 20:57:47 mmondor Exp $");
+MMRCSID("$Id: mmsucomd.c,v 1.4 2003/03/28 21:09:29 mmondor Exp $");
 
 
 
@@ -86,7 +87,7 @@ struct request {
 };
 
 struct conf_node {
-    node nod;
+    pnode_t node;
     u_int64_t id;
     int uid, gid;
     char command[256];
@@ -101,13 +102,13 @@ static pid_t spawn_process(int (*)(void *), void *);
 static bool drop_privs(int, int);
 static void sighandler(int);
 static int unix_init(char *, int, int, int);
-static bool conf_read(list **);
+static bool conf_read(void);
 static void exec_command(struct conf_node *);
 
 int main(void);
 
 static int sucomd_init(void *);
-static void sucomd_main(int, list **);
+static void sucomd_main(int);
 
 
 
@@ -119,6 +120,10 @@ static pid_t sucomd_pid;
 /* This is set to FALSE when a process receives a SIGTERM */
 static bool run = TRUE, conf = FALSE;
 
+/* Configuration */
+static pool_t cpool;
+static list_t clist;
+
 
 
 
@@ -249,7 +254,7 @@ unix_init(char *name, int group, int mode, int backlog)
 }
 
 
-static bool conf_read(list **lst)
+static bool conf_read(void)
 {
     u_int64_t id;
     bool ok = FALSE;
@@ -260,11 +265,11 @@ static bool conf_read(list **lst)
     struct group *tgid;
     struct conf_node *cnod;
 
-    if (*lst) *lst = closelist(*lst);
-
-    if ((fh = fopen(CONFFILE, "r")) != NULL) {
-       if ((*lst = openlist(malloc, free, sizeof(struct conf_node),
-                       4096, 0))) {
+    LIST_INIT(&clist);
+    if (POOL_VALID(&cpool))
+       pool_destroy(&cpool);
+    if (pool_init(&cpool, malloc, free, sizeof(struct conf_node), 64, 0, 0)) {
+       if ((fh = fopen(CONFFILE, "r")) != NULL) {
            ok = TRUE;
            l = 0;
            while ((fgets(buf, 256, fh))) {
@@ -276,20 +281,20 @@ static bool conf_read(list **lst)
                        if ((tgid = getgrnam(args[2])) != NULL) {
                            gid = tgid->gr_gid;
                            id = mm_strhash64(args[0]);
-                           for (cnod = (struct conf_node *)(*lst)->top; cnod;
-                                   cnod = (struct conf_node *)cnod->nod.next)
+                           for (cnod = (struct conf_node *)clist.top; cnod;
+                             cnod = (struct conf_node *)cnod->node.node.next)
                                if (cnod->id == id) break;
                            if (!cnod) {
-                               if ((cnod = (struct conf_node *)allocnode(
-                                               *lst, FALSE))) {
+                               if ((cnod = (struct conf_node *)pool_alloc(
+                                               &cpool, FALSE))) {
                                    cnod->id = id;
                                    cnod->uid = uid;
                                    cnod->gid = gid;
                                    mm_strncpy(cnod->command, args[3], 255);
-                                   APPENDNODE(*lst, (node *)cnod);
+                                   LIST_APPEND(&clist, (node_t *)cnod);
                                } else
                                    syslog(LOG_NOTICE,
-                                           "conf_read() - allocnode()");
+                                           "conf_read() - pool_alloc()");
                            } else
                                syslog(LOG_NOTICE,
                                        "conf_read() - Duplicate key '%s'",
@@ -307,7 +312,7 @@ static bool conf_read(list **lst)
                            l);
            }
        } else
-           syslog(LOG_NOTICE, "conf_read() - openlist()");
+           syslog(LOG_NOTICE, "conf_read() - pool_init()");
        fclose(fh);
     }
 
@@ -357,7 +362,6 @@ static int
 sucomd_init(void *args)
 {
     int fd, ufd;
-    list *conf_list;
 
     /* Write PID file */
     if ((fd = open(PIDFILE, O_CREAT | O_TRUNC | O_WRONLY,
@@ -370,12 +374,11 @@ sucomd_init(void *args)
        syslog(LOG_NOTICE, "* sucomd_init() - Can't write pid file");
 
     /* Read configuration */
-    conf_list = NULL;
-    if (conf_read(&conf_list)) {
+    if (conf_read()) {
        /* Init and start main loop */
        if ((ufd = unix_init(REQSOCKET, REQGROUP, 0660, 1)) != -1) {
            syslog(LOG_NOTICE, "Launching sucomd");
-           sucomd_main(ufd, &conf_list);
+           sucomd_main(ufd);
            close(ufd);
            unlink(REQSOCKET);
        } else
@@ -385,7 +388,8 @@ sucomd_init(void *args)
        syslog(LOG_NOTICE, "sucomd_init() - Can't read config file '%s'",
                CONFFILE);
 
-    if (conf_list) conf_list = closelist(conf_list);
+    if (POOL_VALID(&cpool))
+       pool_destroy(&cpool);
     unlink(PIDFILE);
 
     return (0);
@@ -398,7 +402,7 @@ sucomd_init(void *args)
  * database to disk at fixed intervals, cleaning up obsolete recovery logs.
  */
 static void
-sucomd_main(int ufd, list **conf_list)
+sucomd_main(int ufd)
 {
     int len;
     time_t otim, tim;
@@ -413,7 +417,7 @@ sucomd_main(int ufd, list **conf_list)
     while (run) {
        if (conf) {
            conf = FALSE;
-           if (!conf_read(conf_list)) {
+           if (!conf_read()) {
                syslog(LOG_NOTICE,
                        "sucomd_main() - Couldn't reload config! Exiting");
                break;
@@ -429,9 +433,9 @@ sucomd_main(int ufd, list **conf_list)
                        sizeof(struct request)) {
                    if ((tim = time(NULL)) > otim + MAX_RATE) {
                        otim = tim;
-                       for (cnod = (struct conf_node *)(*conf_list)->top;
-                               cnod;
-                               cnod = (struct conf_node *)cnod->nod.next)
+                       for (cnod = (struct conf_node *)clist.top;
+                               cnod != NULL; cnod =
+                               (struct conf_node *)cnod->node.node.next)
                            if (cnod->id == req.id) break;
                        if (cnod) exec_command(cnod);
                        else