⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 storage.c

📁 这是一个完全开放的
💻 C
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002-2003 Jeremie Miller, Thomas Muldowney, *                         Ryan Eatmon, Robert Norris * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA *//** @file sm/storage.c  * @brief storage manager  * @author Robert Norris  * $Date: 2004/11/13 16:08:33 $  * $Revision: 1.13.2.6 $  *//* these functions implement a multiplexor to get calls to the correct driver * for the given type */#include "sm.h"#include <ctype.h>/* if you add a driver, you'll need to update these arrays */#ifdef STORAGE_DBextern st_ret_t st_db_init(st_driver_t);#endif#ifdef STORAGE_FSextern st_ret_t st_fs_init(st_driver_t);#endif#ifdef STORAGE_MYSQLextern st_ret_t st_mysql_init(st_driver_t);#endif#ifdef STORAGE_PGSQLextern st_ret_t st_pgsql_init(st_driver_t);#endifstatic char *st_driver_names[] = {#ifdef STORAGE_DB    "db",#endif#ifdef STORAGE_FS    "fs",#endif#ifdef STORAGE_MYSQL    "mysql",#endif#ifdef STORAGE_PGSQL    "pgsql",#endif    NULL};static st_driver_init_fn st_driver_inits[] = {#ifdef STORAGE_DB    st_db_init,#endif#ifdef STORAGE_FS    st_fs_init,#endif#ifdef STORAGE_MYSQL    st_mysql_init,#endif#ifdef STORAGE_PGSQL    st_pgsql_init,#endif    NULL};storage_t storage_new(sm_t sm) {    storage_t st;    int i, j;    config_elem_t elem;    char *type;    st_ret_t ret;    st = (storage_t) malloc(sizeof(struct storage_st));    memset(st, 0, sizeof(struct storage_st));    st->sm = sm;    st->drivers = xhash_new(101);    st->types = xhash_new(101);    /* register types declared in the config file */    elem = config_get(sm->config, "storage.driver");    if(elem != NULL) {        for(i = 0; i < elem->nvalues; i++) {            type = j_attr((const char **) elem->attrs[i], "type");             for(j = 0; st_driver_names[j] != NULL; j++) {                if(strcmp(elem->values[i], st_driver_names[j]) == 0) {                    if(type == NULL)                        ret = storage_add_type(st, st_driver_names[j], NULL);                    else                        ret = storage_add_type(st, st_driver_names[j], type);                    /* Initialisation of storage type failed */                    if (ret != st_SUCCESS) {                      free(st);                      return NULL;                    }                }            }        }    }    return st;}static void _st_driver_reaper(xht drivers, const char *driver, void *val, void *arg) {    st_driver_t drv = (st_driver_t) val;    (drv->free)(drv);    free(drv);}void storage_free(storage_t st) {    /* close down drivers */    xhash_walk(st->drivers, _st_driver_reaper, NULL);    xhash_free(st->drivers);    free(st);}st_ret_t storage_add_type(storage_t st, const char *driver, const char *type) {    st_driver_t drv;    st_driver_init_fn init = NULL;    int i;    st_ret_t ret;    /* startup, see if we've already registered this type */    if(type == NULL) {        log_debug(ZONE, "adding arbitrary types to driver '%s'", driver);        /* see if we already have one */        if(st->default_drv != NULL) {            log_debug(ZONE, "we already have a default handler, ignoring this one");            return st_FAILED;        }    } else {        log_debug(ZONE, "adding type '%s' to driver '%s'", type, driver);        /* see if we already have one */        if(xhash_get(st->types, type) != NULL) {            log_debug(ZONE, "we already have a handler for type '%s', ignoring this one");            return st_FAILED;        }    }    /* get the driver */    drv = xhash_get(st->drivers, driver);    if(drv == NULL) {        log_debug(ZONE, "driver not loaded, trying to init");        /* find the init function */        for(i = 0; st_driver_names[i] != NULL; i++) {            if(strcmp(driver, st_driver_names[i]) == 0) {                init = st_driver_inits[i];                break;            }        }        /* d'oh */        if(init == NULL) {            log_debug(ZONE, "no init function for driver '%s'", driver);            return st_FAILED;        }        /* make a new driver structure */        drv = (st_driver_t) malloc(sizeof(struct st_driver_st));        memset(drv, 0, sizeof(struct st_driver_st));        drv->st = st;        log_debug(ZONE, "calling driver initializer");        /* init */        if((init)(drv) == st_FAILED) {            log_write(st->sm->log, LOG_NOTICE, "initialisation of storage driver '%s' failed", driver);            free(drv);            return st_FAILED;        }        /* add it to the drivers hash so we can find it later */        drv->name = pstrdup(xhash_pool(st->drivers), driver);        xhash_put(st->drivers, drv->name, (void *) drv);        log_write(st->sm->log, LOG_NOTICE, "initialised storage driver '%s'", driver);    }    /* if its a default, set it up as such */    if(type == NULL) {        st->default_drv = drv;        return st_SUCCESS;    }    /* its a real type, so let the driver know */    if(type != NULL && (ret = (drv->add_type)(drv, type)) != st_SUCCESS) {        log_debug(ZONE, "driver '%s' can't handle '%s' data", driver, type);        return ret;    }    /* register the type */    xhash_put(st->types, pstrdup(xhash_pool(st->types), type), (void *) drv);    return st_SUCCESS;}st_ret_t storage_put(storage_t st, const char *type, const char *owner, os_t os) {    st_driver_t drv;    st_ret_t ret;    log_debug(ZONE, "storage_put: type=%s owner=%s os=%X", type, owner, os);    /* find the handler for this type */    drv = xhash_get(st->types, type);    if(drv == NULL) {        /* never seen it before, so it goes to the default driver */        drv = st->default_drv;        if(drv == NULL) {            log_debug(ZONE, "no driver associated with type, and no default driver");            return st_NOTIMPL;        }        /* register the type */        ret = storage_add_type(st, drv->name, type);        if(ret != st_SUCCESS)            return ret;    }    return (drv->put)(drv, type, owner, os);}st_ret_t storage_get(storage_t st, const char *type, const char *owner, const char *filter, os_t *os) {    st_driver_t drv;    st_ret_t ret;    log_debug(ZONE, "storage_get: type=%s owner=%s filter=%s", type, owner, filter);    /* find the handler for this type */    drv = xhash_get(st->types, type);    if(drv == NULL) {        /* never seen it before, so it goes to the default driver */        drv = st->default_drv;        if(drv == NULL) {            log_debug(ZONE, "no driver associated with type, and no default driver");            return st_NOTIMPL;        }        /* register the type */        ret = storage_add_type(st, drv->name, type);        if(ret != st_SUCCESS)            return ret;    }    return (drv->get)(drv, type, owner, filter, os);}st_ret_t storage_delete(storage_t st, const char *type, const char *owner, const char *filter) {    st_driver_t drv;    st_ret_t ret;    log_debug(ZONE, "storage_zap: type=%s owner=%s filter=%s", type, owner, filter);    /* find the handler for this type */    drv = xhash_get(st->types, type);    if(drv == NULL) {        /* never seen it before, so it goes to the default driver */        drv = st->default_drv;        if(drv == NULL) {            log_debug(ZONE, "no driver associated with type, and no default driver");            return st_NOTIMPL;        }        /* register the type */        ret = storage_add_type(st, drv->name, type);        if(ret != st_SUCCESS)            return ret;    }    return (drv->delete)(drv, type, owner, filter);}st_ret_t storage_replace(storage_t st, const char *type, const char *owner, const char *filter, os_t os) {    st_driver_t drv;    st_ret_t ret;    log_debug(ZONE, "storage_replace: type=%s owner=%s filter=%s os=%X", type, owner, filter, os);    /* find the handler for this type */    drv = xhash_get(st->types, type);    if(drv == NULL) {        /* never seen it before, so it goes to the default driver */        drv = st->default_drv;        if(drv == NULL) {            log_debug(ZONE, "no driver associated with type, and no default driver");            return st_NOTIMPL;        }        /* register the type */        ret = storage_add_type(st, drv->name, type);        if(ret != st_SUCCESS)            return ret;    }    return (drv->replace)(drv, type, owner, filter, os);}static st_filter_t _storage_filter(pool p, const char *f, int len) {    char *c, *key, *val, *sub;    int vallen;    st_filter_t res, sf;        if(f[0] != '(' && f[len] != ')')        return NULL;    /* key/value pair */    /* if value is numeric, then represented as is.                                      */    /* if value is string, it is preceded by length: e.g. "key=5:abcde"                  */    /* (needed to pass values which include a closing bracket ')', e.g. in resourcenames */    if(isalpha(f[1])) {        key = strdup(f+1);        c = strchr(key, '=');        if(c == NULL) {		free(key);		return NULL;	}        *c = '\0'; c++;        val = c;	/* decide whether number or string by checking for ':' before ')' */        while (*c != ':' && *c != ')' && *c)           c++;        if (!*c) {		free(key);		return NULL;	}        if (*c == ':') {                /* string */                *c = '\0';                vallen = atoi(val);                c++;                val = c;                c += vallen;        }        *c = '\0';        log_debug(ZONE, "extracted key %s val %s", key, val);        res = pmalloco(p, sizeof(struct st_filter_st));        res->p = p;        res->type = st_filter_type_PAIR;        res->key = pstrdup(p, key);        res->val = pstrdup(p, val);	free(key);        return res;    }    /* operator */    if(f[1] != '&' && f[1] != '|' && f[2] != '!')        return NULL;    res = pmalloco(p, sizeof(struct st_filter_st));    res->p = p;    switch(f[1]) {        case '&': res->type = st_filter_type_AND; break;        case '|': res->type = st_filter_type_OR; break;        case '!': res->type = st_filter_type_NOT; break;    }    /* remove const for now, we will not change the string */    c = (char *) &f[2];    while(*c == '(') {        sub = c;        c = strchr(sub, ')');        c++;        sf = _storage_filter(p, (const char *) sub, c - sub);        sf->next = res->sub;        res->sub = sf;    }    return res;}st_filter_t storage_filter(const char *filter) {    pool p;    st_filter_t f;    if(filter == NULL)        return NULL;    p = pool_new();    f = _storage_filter(p, filter, strlen(filter));    if(f == NULL)        pool_free(p);    return f;}int _storage_match(st_filter_t f, os_object_t o, os_t os) {    void *val;    os_type_t ot;    st_filter_t scan;    switch(f->type) {        case st_filter_type_PAIR:            if(!os_object_get(os, o, f->key, &val, os_type_UNKNOWN, &ot))                return 0;            switch(ot) {                case os_type_BOOLEAN:                    if((atoi(f->val) != 0) == (((int) val) != 0))                        return 1;                    return 0;                case os_type_INTEGER:                    if(atoi(f->val) == (int) val)                        return 1;                    return 0;                case os_type_STRING:                    if(strcmp(f->val, val) == 0)                        return 1;                    return 0;                                case os_type_NAD:                    /* !!! this is hard, but probably not needed. if you need it, you implement it ;) */                    return 1;            }            return 0;        case st_filter_type_AND:            for(scan = f->sub; scan != NULL; scan = scan->next)                if(!_storage_match(scan, o, os))                    return 0;            return 1;        case st_filter_type_OR:            for(scan = f->sub; scan != NULL; scan = scan->next)                if(_storage_match(scan, o, os))                    return 1;            return 0;        case st_filter_type_NOT:            if(_storage_match(f->sub, o, os))                return 0;            return 1;    }    return 0;}int storage_match(st_filter_t filter, os_object_t o, os_t os) {    if(filter == NULL)        return 1;    return _storage_match(filter, o, os);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -