diff options
| author | Shehjar Tikoo <shehjart@gluster.com> | 2009-06-25 14:31:27 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2009-06-29 10:42:04 -0700 | 
| commit | 76aa99422562a500c3b82cb826ce582576065a83 (patch) | |
| tree | 65df73305affbe658fd8e70c8c4a2e7dbb26a8d4 /booster/src/booster-fd.c | |
| parent | 4fd96085c5a029e7be9e24e0c33b13268b290d6b (diff) | |
booster: Add new booster-specific fd-table
The reason we need a booster specific fd-table is because
the libglusterfs fd-table has come to a point where it is
optimized for libglusterfs-style of fd allocations.
This conflicts with the way booster requires fds to be allocated
so this commit brings in a re-based version of a booster-specific
fd-table written by Raghu.
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
Diffstat (limited to 'booster/src/booster-fd.c')
| -rw-r--r-- | booster/src/booster-fd.c | 291 | 
1 files changed, 291 insertions, 0 deletions
diff --git a/booster/src/booster-fd.c b/booster/src/booster-fd.c new file mode 100644 index 00000000000..78cde44ddab --- /dev/null +++ b/booster/src/booster-fd.c @@ -0,0 +1,291 @@ +/* +  Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + + + +#include "booster-fd.h" +#include <logging.h> +#include <mem-pool.h> +#include <stdlib.h> +#include <errno.h> +#include <common-utils.h> +#include <string.h> + +#include <assert.h> + +extern fd_t * +fd_ref (fd_t *fd); + +extern void +fd_unref (fd_t *fd); +/* +   Allocate in memory chunks of power of 2 starting from 1024B +   Assumes fdtable->lock is held +   */ +static inline uint +gf_roundup_power_of_two (uint nr) +{ +        uint result = 1; + +        if (nr < 0) { +                gf_log ("server-protocol/fd", +                                GF_LOG_ERROR, +                                "Negative number passed"); +                return -1; +        } +         +        while (result <= nr) +                result *= 2; + +        return result; +} + +int +booster_fdtable_expand (booster_fdtable_t *fdtable, uint nr) +{ +        fd_t    **oldfds = NULL; +        uint    oldmax_fds = -1; +        uint    cpy = 0; +        int32_t ret = -1; + +        if (fdtable == NULL || nr < 0) { +                gf_log ("fd", GF_LOG_ERROR, "invalid argument"); +                errno = EINVAL; +                ret = -1; +                goto out; +        } + +        nr /= (1024 / sizeof (fd_t *)); +        nr = gf_roundup_power_of_two (nr + 1); +        nr *= (1024 / sizeof (fd_t *)); + +        oldfds = fdtable->fds; +        oldmax_fds = fdtable->max_fds; + +        fdtable->fds = CALLOC (nr, sizeof (fd_t *)); +        if (fdtable->fds == NULL) { +                fdtable->fds = oldfds; +                oldfds = NULL; +                ret = -1; +                goto out; +        } + +        fdtable->max_fds = nr; + +        if (oldfds) { +                cpy = oldmax_fds * sizeof (fd_t *); +                memcpy (fdtable->fds, oldfds, cpy); +        } + +        ret = 0; +out: +        FREE (oldfds); + +        return ret; +} + +booster_fdtable_t * +booster_fdtable_alloc (void) +{ +        booster_fdtable_t *fdtable = NULL; +        int32_t            ret = -1; + +        fdtable = CALLOC (1, sizeof (*fdtable)); +        GF_VALIDATE_OR_GOTO ("booster-fd", fdtable, out); + +        LOCK_INIT (&fdtable->lock); + +        LOCK (&fdtable->lock); +        { +                ret = booster_fdtable_expand (fdtable, 0); +        } +        UNLOCK (&fdtable->lock); + +        if (ret == -1) { +                FREE (fdtable); +                fdtable = NULL; +        } + +out: +        return fdtable; +} + +fd_t ** +__booster_fdtable_get_all_fds (booster_fdtable_t *fdtable, uint *count) +{ +        fd_t **fds = NULL; + +        if (count == NULL) +                goto out; + +        fds = fdtable->fds; +        fdtable->fds = calloc (fdtable->max_fds, sizeof (fd_t *)); +        *count = fdtable->max_fds; + +out: +        return fds; +} + +fd_t ** +booster_fdtable_get_all_fds (booster_fdtable_t *fdtable, uint *count) +{ +        fd_t **fds = NULL; +        if (!fdtable) +                return NULL; + +        LOCK (&fdtable->lock); +        { +                fds = __booster_fdtable_get_all_fds (fdtable, count); +        } +        UNLOCK (&fdtable->lock); + +        return fds; +} + +void +booster_fdtable_destroy (booster_fdtable_t *fdtable) +{ +        fd_t                    *fd = NULL; +        fd_t                    **fds = NULL; +        uint                    fd_count = 0; +        int                     i = 0; + +        if (!fdtable) +                return; + +        LOCK (&fdtable->lock); +        { +                fds = __booster_fdtable_get_all_fds (fdtable, &fd_count); +                FREE (fdtable->fds); +        } +        UNLOCK (&fdtable->lock); + +        if (!fds) +                goto free_table; +         +        for (i = 0; i < fd_count; i++) { +                fd = fds[i]; +                if (fd != NULL) +                        fd_unref (fd); +        } +        FREE (fds); +free_table: +        LOCK_DESTROY (&fdtable->lock); +        FREE (fdtable); +} + +int +booster_fd_unused_get (booster_fdtable_t *fdtable, fd_t *fdptr, int fd) +{ +        int ret = -1; +        int error = 0; + +        if (fdtable == NULL || fdptr == NULL || fd < 0) { +                gf_log ("fd", GF_LOG_ERROR, "invalid argument"); +                errno = EINVAL; +                return -1; +        } + +        LOCK (&fdtable->lock); +        { +                while (fdtable->max_fds < fd) { +                        error = 0; +                        error = booster_fdtable_expand (fdtable, +                                                        fdtable->max_fds + 1); +                        if (error) { +                                gf_log ("booster-fd", GF_LOG_ERROR, +                                        "Cannot expand fdtable:%s", +                                        strerror (error)); +                                goto err; +                        } +                } + +                if (!fdtable->fds[fd]) { +                        fdtable->fds[fd] = fdptr; +                        fd_ref (fdptr); +                        ret = fd; +                } else +                        gf_log ("booster-fd", GF_LOG_ERROR, "Cannot allocate fd" +                                " %d (slot not empty in fdtable)", fd); +        } +err: +        UNLOCK (&fdtable->lock); + +        return ret; +} + +void +booster_fd_put (booster_fdtable_t *fdtable, int fd) +{ +        fd_t *fdptr = NULL; +        if (fdtable == NULL || fd < 0) { +                gf_log ("booster-fd", GF_LOG_ERROR, "invalid argument"); +                return; +        } + +        if (!(fd < fdtable->max_fds)) { +                gf_log ("fd", GF_LOG_ERROR, "invalid argument"); +                return; +        } + +        LOCK (&fdtable->lock); +        { +                fdptr = fdtable->fds[fd]; +                fdtable->fds[fd] = NULL; +        } +        UNLOCK (&fdtable->lock); + +        if (fdptr) +                fd_unref (fdptr); +} + +fd_t * +booster_fdptr_get (booster_fdtable_t *fdtable, int fd) +{ +        fd_t *fdptr = NULL; + +        if (fdtable == NULL || fd < 0) { +                gf_log ("booster-fd", GF_LOG_ERROR, "invalid argument"); +                errno = EINVAL; +                return NULL; +        } + +        if (!(fd < fdtable->max_fds)) { +                gf_log ("booster-fd", GF_LOG_ERROR, "invalid argument"); +                errno = EINVAL; +                return NULL; +        } + +        LOCK (&fdtable->lock); +        { +                fdptr = fdtable->fds[fd]; +                if (fdptr) +                        fd_ref (fdptr); +        } +        UNLOCK (&fdtable->lock); + +        return fdptr; +} + +void +booster_fdptr_put (fd_t *booster_fd) +{ +        if (!booster_fd) +                fd_unref (booster_fd); +}  | 
