diff options
author | JP Rosevear <jpr@src.gnome.org> | 2003-11-19 00:33:30 +0800 |
---|---|---|
committer | JP Rosevear <jpr@src.gnome.org> | 2003-11-19 00:33:30 +0800 |
commit | 58f1b46675ef29528f51e5c44fe0e087bda5d82d (patch) | |
tree | 725648cf84182762d9dc2ac5846b233203411d59 /libical/src/libicalss/icalbdbset.c | |
parent | b47685534d7e5738d712962334537bb329831b9e (diff) | |
download | gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.tar gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.tar.gz gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.tar.bz2 gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.tar.lz gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.tar.xz gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.tar.zst gsoc2013-evolution-58f1b46675ef29528f51e5c44fe0e087bda5d82d.zip |
Remove libical from this tree, it resides in e-d-s now.
svn path=/trunk/; revision=23417
Diffstat (limited to 'libical/src/libicalss/icalbdbset.c')
-rw-r--r-- | libical/src/libicalss/icalbdbset.c | 1598 |
1 files changed, 0 insertions, 1598 deletions
diff --git a/libical/src/libicalss/icalbdbset.c b/libical/src/libicalss/icalbdbset.c deleted file mode 100644 index 6b11e46741..0000000000 --- a/libical/src/libicalss/icalbdbset.c +++ /dev/null @@ -1,1598 +0,0 @@ -/* -*- Mode: C -*- - ====================================================================== - FILE: icalbdbset.c - ======================================================================*/ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "icalbdbset.h" -#include "icalgauge.h" -#include <errno.h> -#include <sys/stat.h> /* for stat */ -#include <stdio.h> - -#ifndef WIN32 -#include <unistd.h> /* for stat, getpid, unlink */ -#include <fcntl.h> /* for fcntl */ -#include <unistd.h> /* for fcntl */ -#else -#define S_IRUSR S_IREAD /* R for owner */ -#define S_IWUSR S_IWRITE /* W for owner */ -#endif -#include <stdlib.h> -#include <string.h> - -#include "icalbdbsetimpl.h" - -#define STRBUF_LEN 255 -#define MAX_RETRY 5 - -extern int errno; - - - -/* these are just stub functions */ -icalerrorenum icalbdbset_read_database(icalbdbset* bset, char *(*pfunc)(const DBT *dbt)); -icalerrorenum icalbdbset_create_cluster(const char *path); -int icalbdbset_cget(DBC *dbcp, DBT *key, DBT *data, int access_method); - -static int _compare_keys(DB *dbp, const DBT *a, const DBT *b); - - -/** Default options used when NULL is passed to icalset_new() **/ -icalbdbset_options icalbdbset_options_default = {ICALBDB_EVENTS, DB_BTREE, 0644, 0, NULL, NULL}; - - -static DB_ENV *ICAL_DB_ENV = 0; - -/** Initialize the db environment */ - -int icalbdbset_init_dbenv(char *db_env_dir, void (*logDbFunc)(const char*, char*)) { - int ret; - int flags; - - if (db_env_dir) { - struct stat env_dir_sb; - - if (stat(db_env_dir, &env_dir_sb)) { - fprintf(stderr, "The directory '%s' is missing, please create it.\n", db_env_dir); - return EINVAL; - } - } - - ret = db_env_create(&ICAL_DB_ENV, 0); - - if (ret) { - /* some kind of error... */ - return ret; - } - - /* Do deadlock detection internally */ - if ((ret = ICAL_DB_ENV->set_lk_detect(ICAL_DB_ENV, DB_LOCK_DEFAULT)) != 0) { - char * foo = db_strerror(ret); - fprintf(stderr, "Could not initialize the database locking environment\n"); - return ret; - } - - flags = DB_INIT_LOCK | DB_INIT_TXN | DB_CREATE | DB_THREAD | \ - DB_RECOVER | DB_INIT_LOG | DB_INIT_MPOOL; - ret = ICAL_DB_ENV->open(ICAL_DB_ENV, db_env_dir, flags, S_IRUSR|S_IWUSR); - - if (ret) { - char * foo = db_strerror(ret); - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "dbenv->open"); - return ret; - } - - /* display additional error messages */ - if (logDbFunc != NULL) { - ICAL_DB_ENV->set_errcall(ICAL_DB_ENV, logDbFunc); - } - - return ret; -} - -void icalbdbset_checkpoint(void) -{ - int ret; - char *err; - - switch (ret = ICAL_DB_ENV->txn_checkpoint(ICAL_DB_ENV, 0,0,0)) { - case 0: - case DB_INCOMPLETE: - break; - default: - err = db_strerror(ret); - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "checkpoint failed"); - abort(); - } -} - -void icalbdbset_rmdbLog(void) -{ - int ret = 0; - char** listp; - - /* remove log files that are archivable (ie. no longer needed) */ - if (ICAL_DB_ENV->log_archive(ICAL_DB_ENV, &listp, DB_ARCH_ABS) == 0) { - if (listp != NULL) { - int ii = 0; - while (listp[ii] != NULL) { - ret = unlink(listp[ii]); - ii++; - } - free(listp); - } - } -} - -int icalbdbset_cleanup(void) -{ - int ret = 0; - - /* one last checkpoint.. */ - icalbdbset_checkpoint(); - - /* remove logs that are not needed anymore */ - icalbdbset_rmdbLog(); - - if (ICAL_DB_ENV) - ret = ICAL_DB_ENV->close(ICAL_DB_ENV, 0); - - return ret; -} - -DB_ENV *icalbdbset_get_env(void) { - return ICAL_DB_ENV; -} - - -/** Initialize an icalbdbset. Also attempts to populate from the - * database (primary if only dbp is given, secondary if sdbp is - * given) and creates an empty object if retrieval is unsuccessful. - * pfunc is used to unpack data from the database. If not given, we - * assume data is a string. - */ - -icalset* icalbdbset_init(icalset* set, const char* dsn, void* options_in) -{ - icalbdbset *bset = (icalbdbset*)set; - icalbdbset_options *options = options_in; - int ret; - DB *cal_db; - char *subdb_name; - - if (options == NULL) - *options = icalbdbset_options_default; - - switch (options->subdb) { - case ICALBDB_CALENDARS: - subdb_name = "calendars"; - break; - case ICALBDB_EVENTS: - subdb_name = "events"; - break; - case ICALBDB_TODOS: - subdb_name = "todos"; - break; - case ICALBDB_REMINDERS: - subdb_name = "reminders"; - break; - } - - cal_db = icalbdbset_bdb_open(set->dsn, - subdb_name, - options->dbtype, - options->mode, - options->flag); - if (cal_db == NULL) - return NULL; - - bset->dbp = cal_db; - bset->sdbp = NULL; - bset->gauge = 0; - bset->cluster = 0; - - if ((ret = icalbdbset_read_database(bset, options->pfunc)) != ICAL_NO_ERROR) { - return NULL; - } - - return (icalset *)bset; -} - - -/** open a database and return a reference to it. Used only for - opening the primary index. - flag = set_flag() DUP | DUP_SORT - */ - -icalset* icalbdbset_new(const char* database_filename, - icalbdbset_subdb_type subdb_type, - int dbtype, int flag) -{ - icalbdbset_options options = icalbdbset_options_default; - - options.subdb = subdb_type; - options.dbtype = dbtype; - options.flag = flag; - - /* this will in turn call icalbdbset_init */ - return icalset_new(ICAL_BDB_SET, database_filename, &options); -} - -/** - * Open a secondary database, used for accessing secondary indices. - * The callback function tells icalbdbset how to associate secondary - * key information with primary data. See the BerkeleyDB reference - * guide for more information. - */ - -DB * icalbdbset_bdb_open_secondary(DB *dbp, - const char *database, - const char *sub_database, - int (*callback) (DB *db, - const DBT *dbt1, - const DBT *dbt2, - DBT *dbt3), - int type) -{ - int ret; - int flags; - DB *sdbp = NULL; - - if (!sub_database) - return NULL; - - if (!ICAL_DB_ENV) - icalbdbset_init_dbenv(NULL, NULL); - - /* Open/create secondary */ - if((ret = db_create(&sdbp, ICAL_DB_ENV, 0)) != 0) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "secondary index: %s", sub_database); - return NULL; - } - - if ((ret = sdbp->set_flags(sdbp, DB_DUP | DB_DUPSORT)) != 0) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "set_flags error for secondary index: %s", sub_database); - return NULL; - } - - flags = DB_CREATE | DB_THREAD; - if ((ret = sdbp->open(sdbp, database, sub_database, type, (u_int32_t) flags, 0644)) != 0) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "failed to open secondary index: %s", sub_database); - if (ret == DB_RUNRECOVERY) - abort(); - else - return NULL; - } - - /* Associate the primary index with a secondary */ - if((ret = dbp->associate(dbp, sdbp, callback, 0)) != 0) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "failed to associate secondary index: %s", sub_database); - return NULL; - } - - return sdbp; -} - -DB* icalbdbset_bdb_open(const char* path, - const char *subdb, - int dbtype, - mode_t mode, - int flag) -{ - DB *dbp = NULL; - int ret; - int flags; - - /* Initialize the correct set of db subsystems (see capdb.c) */ - flags = DB_CREATE | DB_THREAD; - - /* should just abort here instead of opening an env in the current dir.. */ - if (!ICAL_DB_ENV) - icalbdbset_init_dbenv(NULL, NULL); - - /* Create and initialize database object, open the database. */ - if ((ret = db_create(&dbp, ICAL_DB_ENV, 0)) != 0) { - return (NULL); - } - - /* set comparison function, if BTREE */ - if (dbtype == DB_BTREE) - dbp->set_bt_compare(dbp, _compare_keys); - - /* set DUP, DUPSORT */ - if (flag != 0) - dbp->set_flags(dbp, flag); - - if ((ret = dbp->open(dbp, path, subdb, dbtype, flags, mode)) != 0) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "%s (database: %s): open failed.", path, subdb); - if (ret == DB_RUNRECOVERY) - abort(); - else - return NULL; - } - - return (dbp); -} - - -/* icalbdbset_parse_data -- parses using pfunc to unpack data. */ -char *icalbdbset_parse_data(DBT *dbt, char *(*pfunc)(const DBT *dbt)) -{ - char *ret; - - if(pfunc) { - ret = (char *)pfunc(dbt); - } else { - ret = (char *) dbt->data; - } - - return (ret); -} - -/* This populates a cluster with the entire contents of a database */ -icalerrorenum icalbdbset_read_database(icalbdbset* bset, char *(*pfunc)(const DBT *dbt)) -{ - - DB *dbp; - DBC *dbcp; - DBT key, data; - char *str, *szpstr; - int ret; - char keystore[256]; - char datastore[1024]; - char *more_mem = NULL; - DB_TXN *tid; - - memset(&key, 0, sizeof(DBT)); - memset(&data, 0, sizeof(DBT)); - - if (bset->sdbp) { dbp = bset->sdbp; } - else { dbp = bset->dbp; } - - if(!dbp) { goto err1; } - - bset->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT); - - if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) { - char *foo = db_strerror(ret); - abort(); - } - - /* acquire a cursor for the database */ - if ((ret = dbp->cursor(dbp, tid, &dbcp, 0)) != 0) { - dbp->err(dbp, ret, "primary index"); - goto err1; - } - - key.flags = DB_DBT_USERMEM; - key.data = keystore; - key.ulen = sizeof(keystore); - - data.flags= DB_DBT_USERMEM; - data.data = datastore; - data.ulen = sizeof(datastore); - - - /* fetch the key/data pair */ - while (1) { - ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT); - if (ret == DB_NOTFOUND) { - break; - } else if (ret == ENOMEM) { - if (more_mem) free (more_mem); - more_mem = malloc(data.ulen+1024); - data.data = more_mem; - data.ulen = data.ulen+1024; - } else if (ret == DB_LOCK_DEADLOCK) { - char *foo = db_strerror(ret); - abort(); /* should retry in case of DB_LOCK_DEADLOCK */ - } else if (ret) { - char *foo = db_strerror(ret); - /* some other weird-ass error */ - dbp->err(dbp, ret, "cursor"); - abort(); - } else { - icalcomponent *cl; - - /* this prevents an array read bounds error */ - if((str = (char *)calloc(data.size + 1, sizeof(char)))==NULL) - goto err2; - memcpy(str, (char *)data.data, data.size); - - cl = icalparser_parse_string(str); - - icalcomponent_add_component(bset->cluster, cl); - free(str); - } - } - if(ret != DB_NOTFOUND) { - goto err2; - } - - - if (more_mem) { - free(more_mem); - more_mem = NULL; - } - - if ((ret = dbcp->c_close(dbcp)) != 0) { - char * foo = db_strerror(ret); - abort(); /* should retry in case of DB_LOCK_DEADLOCK */ - } - - if ((ret = tid->commit(tid, 0)) != 0) { - char * foo = db_strerror(ret); - abort(); - } - - return ICAL_NO_ERROR; - - err2: - if (more_mem) free(more_mem); - dbcp->c_close(dbcp); - abort(); /* should retry in case of DB_LOCK_DEADLOCK */ - return ICAL_INTERNAL_ERROR; - - err1: - dbp->err(dbp, ret, "cursor index"); - abort(); - return (ICAL_FILE_ERROR); -} - - -/* XXX add more to this */ -void icalbdbset_free(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - int ret; - - icalerror_check_arg_rv((bset!=0),"bset"); - - if (bset->cluster != 0){ - icalbdbset_commit(set); - icalcomponent_free(bset->cluster); - bset->cluster=0; - } - - if(bset->gauge !=0){ - icalgauge_free(bset->gauge); - } - - if(bset->path != 0){ - free((char *)bset->path); - bset->path = 0; - } - - if(bset->sindex != 0) { - free((char *)bset->sindex); - bset->sindex = 0; - } - - if (bset->dbp && - ((ret = bset->dbp->close(bset->dbp, 0)) != 0)) { - } - bset->dbp = NULL; -} - -/* return cursor is in rdbcp */ -int icalbdbset_acquire_cursor(DB *dbp, DB_TXN *tid, DBC **rdbcp) { - int ret=0; - - if((ret = dbp->cursor(dbp, tid, rdbcp, 0)) != 0) { - dbp->err(dbp, ret, "couldn't open cursor"); - goto err1; - } - - return ICAL_NO_ERROR; - - err1: - return ICAL_FILE_ERROR; - -} - -/* returns key/data in arguments */ -int icalbdbset_get_first(DBC *dbcp, DBT *key, DBT *data) { - return icalbdbset_cget(dbcp, key, data, DB_FIRST); -} - -int icalbdbset_get_next(DBC *dbcp, DBT *key, DBT *data) { - return icalbdbset_cget(dbcp, key, data, DB_NEXT); -} - -int icalbdbset_get_last(DBC *dbcp, DBT *key, DBT *data) { - return icalbdbset_cget(dbcp, key, data, DB_LAST); -} - -int icalbdbset_get_key(DBC *dbcp, DBT *key, DBT *data) { - return icalbdbset_cget(dbcp, key, data, DB_SET); -} - -int icalbdbset_delete(DB *dbp, DBT *key) { - DB_TXN *tid; - int ret; - int done = 0; - int retry = 0; - - while ((retry < MAX_RETRY) && !done) { - - if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - retry++; - continue; - } - else { - char *foo = db_strerror(ret); - abort(); - } - } - - if ((ret = dbp->del(dbp, tid, key, 0)) != 0) { - if (ret == DB_NOTFOUND) { - /* do nothing - not an error condition */ - } - else if (ret == DB_LOCK_DEADLOCK) { - tid->abort(tid); - retry++; - continue; - } - else { - char *strError = db_strerror(ret); - icalerror_warn("icalbdbset_delete faild: "); - icalerror_warn(strError); - tid->abort(tid); - return ICAL_FILE_ERROR; - } - } - - if ((ret = tid->commit(tid, 0)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - tid->abort(tid); - retry++; - continue; - } - else { - char * foo = db_strerror(ret); - abort(); - } - } - - done = 1; /* all is well */ - } - - if (!done) { - if (tid != NULL) tid->abort(tid); - } - - return ret; -} - -int icalbdbset_cget(DBC *dbcp, DBT *key, DBT *data, int access_method) { - int ret=0; - - key->flags |= DB_DBT_MALLOC; /* change these to DB_DBT_USERMEM */ - data->flags |= DB_DBT_MALLOC; - - /* fetch the key/data pair */ - if((ret = dbcp->c_get(dbcp, key, data, access_method)) != 0) { - goto err1; - } - - return ICAL_NO_ERROR; - - err1: - return ICAL_FILE_ERROR; -} - - -int icalbdbset_cput(DBC *dbcp, DBT *key, DBT *data, int access_method) { - int ret=0; - - key->flags |= DB_DBT_MALLOC; /* change these to DB_DBT_USERMEM */ - data->flags |= DB_DBT_MALLOC; - - /* fetch the key/data pair */ - if((ret = dbcp->c_put(dbcp, key, data, 0)) != 0) { - goto err1; - } - - return ICAL_NO_ERROR; - - err1: - return ICAL_FILE_ERROR; -} - - -int icalbdbset_put(DB *dbp, DBT *key, DBT *data, int access_method) -{ - int ret = 0; - DB_TXN *tid = NULL; - int retry = 0; - int done = 0; - - while ((retry < MAX_RETRY) && !done) { - - if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - retry++; - continue; - } - else { - char *foo = db_strerror(ret); - abort(); - } - } - - if ((ret = dbp->put(dbp, tid, key, data, access_method)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - tid->abort(tid); - retry++; - continue; - } - else { - char *strError = db_strerror(ret); - icalerror_warn("icalbdbset_put faild: "); - icalerror_warn(strError); - tid->abort(tid); - return ICAL_FILE_ERROR; - } - } - - if ((ret = tid->commit(tid, 0)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - tid->abort(tid); - retry++; - continue; - } - else { - char * foo = db_strerror(ret); - abort(); - } - } - - done = 1; /* all is well */ - } - - if (!done) { - if (tid != NULL) tid->abort(tid); - return ICAL_FILE_ERROR; - } - else - return ICAL_NO_ERROR; -} - -int icalbdbset_get(DB *dbp, DB_TXN *tid, DBT *key, DBT *data, int flags) -{ - return (dbp->get(dbp, tid, key, data, flags)); -} - -/** Return the path of the database file **/ - -const char* icalbdbset_path(icalset* set) -{ - icalerror_check_arg_rz((set!=0),"set"); - - return set->dsn; -} - -const char* icalbdbset_subdb(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rz((bset!=0),"bset"); - - return bset->subdb; -} - - -/** Write changes out to the database file. - */ - -icalerrorenum icalbdbset_commit(icalset *set) { - DB *dbp; - DBC *dbcp; - DBT key, data; - icalcomponent *c; - char *str; - int ret=0; - int reterr = ICAL_NO_ERROR; - char keystore[256]; - char uidbuf[256]; - char datastore[1024]; - char *more_mem = NULL; - DB_TXN *tid = NULL; - icalbdbset *bset = (icalbdbset*)set; - int bad_uid_counter = 0; - int retry = 0, done = 0, completed = 0, deadlocked = 0; - - icalerror_check_arg_re((bset!=0),"bset",ICAL_BADARG_ERROR); - - dbp = bset->dbp; - icalerror_check_arg_re((dbp!=0),"dbp is invalid",ICAL_BADARG_ERROR); - - if (bset->changed == 0) - return ICAL_NO_ERROR; - - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - - key.flags = DB_DBT_USERMEM; - key.data = keystore; - key.ulen = sizeof(keystore); - - data.flags = DB_DBT_USERMEM; - data.data = datastore; - data.ulen = sizeof(datastore); - - if (!ICAL_DB_ENV) - icalbdbset_init_dbenv(NULL, NULL); - - while ((retry < MAX_RETRY) && !done) { - - if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - retry++; - continue; - } - else if (ret == DB_RUNRECOVERY) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit: txn_begin failed"); - abort(); - } - else { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit"); - return ICAL_INTERNAL_ERROR; - } - } - - /* first delete everything in the database, because there could be removed components */ - if ((ret = dbp->cursor(dbp, tid, &dbcp, DB_DIRTY_READ)) != 0) { - tid->abort(tid); - if (ret == DB_LOCK_DEADLOCK) { - retry++; - continue; - } - else if (ret == DB_RUNRECOVERY) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed"); - abort(); - } - else { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed"); - /* leave bset->changed set to true */ - return ICAL_INTERNAL_ERROR; - } - } - - /* fetch the key/data pair, then delete it */ - completed = 0; - while (!completed && !deadlocked) { - ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT); - if (ret == DB_NOTFOUND) { - completed = 1; - } else if (ret == ENOMEM) { - if (more_mem) free(more_mem); - more_mem = malloc(data.ulen+1024); - data.data = more_mem; - data.ulen = data.ulen+1024; - } else if (ret == DB_LOCK_DEADLOCK) { - deadlocked = 1; - } else if (ret == DB_RUNRECOVERY) { - tid->abort(tid); - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_get failed."); - abort(); - } else if (ret == 0) { - if ((ret = dbcp->c_del(dbcp,0))!=0) { - dbp->err(dbp, ret, "cursor"); - if (ret == DB_KEYEMPTY) { - /* never actually created, continue onward.. */ - /* do nothing - break; */ - } else if (ret == DB_LOCK_DEADLOCK) { - deadlocked = 1; - } else { - char *foo = db_strerror(ret); - abort(); - } - } - } else { /* some other non-fatal error */ - dbcp->c_close(dbcp); - tid->abort(tid); - if (more_mem) { - free(more_mem); - more_mem = NULL; - } - return ICAL_INTERNAL_ERROR; - } - } - - if (more_mem) { - free(more_mem); - more_mem = NULL; - } - - if (deadlocked) { - dbcp->c_close(dbcp); - tid->abort(tid); - retry++; - continue; /* next retry */ - } - - deadlocked = 0; - for (c = icalcomponent_get_first_component(bset->cluster,ICAL_ANY_COMPONENT); - c != 0 && !deadlocked; - c = icalcomponent_get_next_component(bset->cluster,ICAL_ANY_COMPONENT)) { - - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - - /* Note that we're always inserting into a primary index. */ - if (icalcomponent_isa(c) != ICAL_VAGENDA_COMPONENT) { - char *uidstr = (char *)icalcomponent_get_uid(c); - if (!uidstr) { /* this shouldn't happen */ - /* no uid string, we need to add one */ - snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++); - key.data = uidbuf; - } else { - key.data = uidstr; - } - } else { - char *relcalid = NULL; - relcalid = (char*)icalcomponent_get_relcalid(c); - if (relcalid == NULL) { - snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++); - key.data = uidbuf; - } else { - key.data = relcalid; - } - } - key.size = strlen(key.data); - - str = icalcomponent_as_ical_string(c); - data.data = str; - data.size = strlen(str); - - if ((ret = dbcp->c_put(dbcp, &key, &data, DB_KEYLAST)) != 0) { - if (ret == DB_LOCK_DEADLOCK) { - deadlocked = 1; - } - else if (ret == DB_RUNRECOVERY) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed."); - abort(); - } - else { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed %s.", str); - /* continue to try to put as many icalcomponent as possible */ - reterr = ICAL_INTERNAL_ERROR; - } - } - } - - if (deadlocked) { - dbcp->c_close(dbcp); - tid->abort(tid); - retry++; - continue; - } - - if ((ret = dbcp->c_close(dbcp)) != 0) { - tid->abort(tid); - if (ret == DB_LOCK_DEADLOCK) { - retry++; - continue; - } - else if (ret == DB_RUNRECOVERY) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed."); - abort(); - } - else { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed."); - reterr = ICAL_INTERNAL_ERROR; - } - } - - if ((ret = tid->commit(tid, 0)) != 0) { - tid->abort(tid); - if (ret == DB_LOCK_DEADLOCK) { - retry++; - continue; - } - else if (ret == DB_RUNRECOVERY) { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed."); - abort(); - } - else { - ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed."); - reterr = ICAL_INTERNAL_ERROR; - } - } - - done = 1; - } - - bset->changed = 0; - return reterr; -} - - -void icalbdbset_mark(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rv((bset!=0),"bset"); - - bset->changed = 1; -} - - -icalcomponent* icalbdbset_get_component(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rz((bset!=0),"bset"); - - return bset->cluster; -} - - -/* manipulate the components in the cluster */ - -icalerrorenum icalbdbset_add_component(icalset *set, - icalcomponent* child) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_re((bset!=0),"bset", ICAL_BADARG_ERROR); - icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR); - - icalcomponent_add_component(bset->cluster,child); - - icalbdbset_mark(set); - - return ICAL_NO_ERROR; -} - - -icalerrorenum icalbdbset_remove_component(icalset *set, - icalcomponent* child) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_re((bset!=0),"bset", ICAL_BADARG_ERROR); - icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR); - - icalcomponent_remove_component(bset->cluster,child); - - icalbdbset_mark(set); - - return ICAL_NO_ERROR; -} - - -int icalbdbset_count_components(icalset *set, - icalcomponent_kind kind) -{ - icalbdbset *bset = (icalbdbset*)set; - - if(set == 0){ - icalerror_set_errno(ICAL_BADARG_ERROR); - return -1; - } - - return icalcomponent_count_components(bset->cluster,kind); -} - - -/** Set the gauge **/ - -icalerrorenum icalbdbset_select(icalset* set, icalgauge* gauge) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_re((bset!=0),"bset", ICAL_BADARG_ERROR); - icalerror_check_arg_re(gauge!=0,"gauge",ICAL_BADARG_ERROR); - - bset->gauge = gauge; - - return ICAL_NO_ERROR; -} - - -/** Clear the gauge **/ - -void icalbdbset_clear(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rv((bset!=0),"bset"); - - bset->gauge = 0; -} - - -icalcomponent* icalbdbset_fetch(icalset* set, icalcomponent_kind kind, const char* uid) -{ - icalcompiter i; - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rz((bset!=0),"bset"); - - for(i = icalcomponent_begin_component(bset->cluster, kind); - icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ - - icalcomponent *this = icalcompiter_deref(&i); - icalproperty *p = NULL; - const char *this_uid = NULL; - - if (this != 0){ - if (kind == ICAL_VAGENDA_COMPONENT) { - p = icalcomponent_get_first_property(this,ICAL_RELCALID_PROPERTY); - if (p != NULL) this_uid = icalproperty_get_relcalid(p); - } else { - p = icalcomponent_get_first_property(this,ICAL_UID_PROPERTY); - if (p != NULL) this_uid = icalproperty_get_uid(p); - } - - if(this_uid==NULL){ - icalerror_warn("icalbdbset_fetch found a component with no UID"); - continue; - } - - if (strcmp(uid,this_uid)==0){ - return this; - } - } - } - - return 0; -} - - -int icalbdbset_has_uid(icalset* store,const char* uid) -{ - assert(0); /* HACK, not implemented */ - return 0; -} - - -/******* support routines for icalbdbset_fetch_match *********/ - -struct icalbdbset_id { - char* uid; - char* recurrence_id; - int sequence; -}; - -void icalbdbset_id_free(struct icalbdbset_id *id) -{ - if(id->recurrence_id != 0){ - free(id->recurrence_id); - } - - if(id->uid != 0){ - free(id->uid); - } - -} - -struct icalbdbset_id icalbdbset_get_id(icalcomponent* comp) -{ - - icalcomponent *inner; - struct icalbdbset_id id; - icalproperty *p; - - inner = icalcomponent_get_first_real_component(comp); - - p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY); - - assert(p!= 0); - - id.uid = strdup(icalproperty_get_uid(p)); - - p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY); - - if(p == 0) { - id.sequence = 0; - } else { - id.sequence = icalproperty_get_sequence(p); - } - - p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY); - - if (p == 0){ - id.recurrence_id = 0; - } else { - icalvalue *v; - v = icalproperty_get_value(p); - id.recurrence_id = strdup(icalvalue_as_ical_string(v)); - - assert(id.recurrence_id != 0); - } - - return id; -} - -/* Find the component that is related to the given - component. Currently, it just matches based on UID and - RECURRENCE-ID */ - -icalcomponent* icalbdbset_fetch_match(icalset* set, icalcomponent *comp) -{ - icalbdbset *bset = (icalbdbset*)set; - icalcompiter i; - struct icalbdbset_id comp_id, match_id; - - icalerror_check_arg_rz((bset!=0),"bset"); - comp_id = icalbdbset_get_id(comp); - - for(i = icalcomponent_begin_component(bset->cluster,ICAL_ANY_COMPONENT); - icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ - - icalcomponent *match = icalcompiter_deref(&i); - - match_id = icalbdbset_get_id(match); - - if(strcmp(comp_id.uid, match_id.uid) == 0 && - ( comp_id.recurrence_id ==0 || - strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){ - - /* HACK. What to do with SEQUENCE? */ - - icalbdbset_id_free(&match_id); - icalbdbset_id_free(&comp_id); - return match; - - } - - icalbdbset_id_free(&match_id); - } - - icalbdbset_id_free(&comp_id); - return 0; - -} - - -icalerrorenum icalbdbset_modify(icalset* set, icalcomponent *old, - icalcomponent *newc) -{ - assert(0); /* HACK, not implemented */ - return ICAL_NO_ERROR; -} - -/* caller is responsible to cal icalbdbset_free_cluster first */ -icalerrorenum icalbdbset_set_cluster(icalset* set, icalcomponent* cluster) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rz((bset!=0),"bset"); - - bset->cluster = cluster; -} - -icalerrorenum icalbdbset_free_cluster(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rz((bset!=0),"bset"); - - if (bset->cluster != NULL) icalcomponent_free(bset->cluster); -} - -icalcomponent* icalbdbset_get_cluster(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalerror_check_arg_rz((bset!=0),"bset"); - - return (bset->cluster); -} - - -/** Iterate through components. */ -icalcomponent* icalbdbset_get_current_component (icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - - icalerror_check_arg_rz((bset!=0),"bset"); - - return icalcomponent_get_current_component(bset->cluster); -} - - -icalcomponent* icalbdbset_get_first_component(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalcomponent *c=0; - - icalerror_check_arg_rz((bset!=0),"bset"); - - do { - if (c == 0) - c = icalcomponent_get_first_component(bset->cluster, - ICAL_ANY_COMPONENT); - else - c = icalcomponent_get_next_component(bset->cluster, - ICAL_ANY_COMPONENT); - - if(c != 0 && (bset->gauge == 0 || - icalgauge_compare(bset->gauge,c) == 1)){ - return c; - } - - } while (c!=0); - - return 0; -} - - -icalsetiter icalbdbset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge, const char* tzid) -{ - icalsetiter itr = icalsetiter_null; - icalcomponent* comp = NULL; - icalcompiter citr; - icalbdbset *bset = (icalbdbset*) set; - struct icaltimetype start, next, end; - icalproperty *dtstart, *rrule, *prop, *due; - struct icalrecurrencetype recur; - icaltimezone *u_zone; - int g = 0; - int orig_time_was_utc = 0; - - icalerror_check_arg_re((set!=0), "set", icalsetiter_null); - - itr.gauge = gauge; - itr.tzid = tzid; - - citr = icalcomponent_begin_component(bset->cluster, kind); - comp = icalcompiter_deref(&citr); - - if (gauge == 0) { - itr.iter = citr; - return itr; - } - - /* if there is a gauge, the first matched component is returned */ - while (comp != 0) { - - /* check if it is a recurring component and with guage expand, if so - * we need to add recurrence-id property to the given component */ - rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); - g = icalgauge_get_expand(gauge); - - if (rrule != 0 - && g == 1) { - - /* it is a recurring event */ - - u_zone = icaltimezone_get_builtin_timezone(itr.tzid); - - /* use UTC, if that's all we have. */ - if (!u_zone) - u_zone = icaltimezone_get_utc_timezone(); - - - recur = icalproperty_get_rrule(rrule); - - if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) { - dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY); - if (dtstart) - start = icalproperty_get_dtstart(dtstart); - } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) { - due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY); - if (due) - start = icalproperty_get_due(due); - } - - /* Convert to the user's timezone in order to be able to compare - * the results from the rrule iterator. */ - if (icaltime_is_utc(start)) { - start = icaltime_convert_to_zone(start, u_zone); - orig_time_was_utc = 1; - } - - if (itr.last_component == NULL) { - itr.ritr = icalrecur_iterator_new(recur, start); - next = icalrecur_iterator_next(itr.ritr); - itr.last_component = comp; - } - else { - next = icalrecur_iterator_next(itr.ritr); - if (icaltime_is_null_time(next)){ - itr.last_component = NULL; - icalrecur_iterator_free(itr.ritr); - itr.ritr = NULL; - /* no matched occurence */ - goto getNextComp; - } else { - itr.last_component = comp; - } - } - - /* if it is excluded, do next one */ - if (icalproperty_recurrence_is_excluded(comp, &start, &next)) { - icalrecur_iterator_decrement_count(itr.ritr); - continue; - } - - /* add recurrence-id value to the property if the property already exist; - * add the recurrence id property and the value if the property does not exist */ - prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY); - if (prop == 0) - icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next)); - else - icalproperty_set_recurrenceid(prop, next); - - /* convert the next recurrence time into the user's timezone */ - if (orig_time_was_utc) - next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone()); - - } /* end of a recurring event */ - - if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) { - /* find a matched and return it */ - itr.iter = citr; - return itr; - } - - /* if it is a recurring but no matched occurrence has been found OR - * it is not a recurring and no matched component has been found, - * read the next component to find out */ -getNextComp: - if ((rrule != NULL && itr.last_component == NULL) || - (rrule == NULL)) { - comp = icalcompiter_next(&citr); - comp = icalcompiter_deref(&citr); - } - } /* while */ - - /* no matched component has found */ - return icalsetiter_null; -} - -icalcomponent* icalbdbset_form_a_matched_recurrence_component(icalsetiter* itr) -{ - icalcomponent* comp = NULL; - struct icaltimetype start, next, end; - icalproperty *dtstart, *rrule, *prop, *due; - struct icalrecurrencetype recur; - icaltimezone *u_zone; - int g = 0; - int orig_time_was_utc = 0; - - comp = itr->last_component; - - if (comp == NULL || itr->gauge == NULL) { - return NULL; - } - - - rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); - /* if there is no RRULE, simply return to the caller */ - if (rrule == NULL) - return NULL; - - u_zone = icaltimezone_get_builtin_timezone(itr->tzid); - - /* use UTC, if that's all we have. */ - if (!u_zone) - u_zone = icaltimezone_get_utc_timezone(); - - recur = icalproperty_get_rrule(rrule); - - if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) { - dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY); - if (dtstart) - start = icalproperty_get_dtstart(dtstart); - } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) { - due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY); - if (due) - start = icalproperty_get_due(due); - } - - /* Convert to the user's timezone in order to be able to compare the results - * from the rrule iterator. */ - if (icaltime_is_utc(start)) { - start = icaltime_convert_to_zone(start, u_zone); - orig_time_was_utc = 1; - } - - if (itr->ritr == NULL) { - itr->ritr = icalrecur_iterator_new(recur, start); - next = icalrecur_iterator_next(itr->ritr); - itr->last_component = comp; - } else { - next = icalrecur_iterator_next(itr->ritr); - if (icaltime_is_null_time(next)){ - /* no more recurrence, returns */ - itr->last_component = NULL; - icalrecur_iterator_free(itr->ritr); - itr->ritr = NULL; - /* no more pending matched occurence, - * all the pending matched occurences have been returned */ - return NULL; - } else { - itr->last_component = comp; - } - } - - /* if it is excluded, return NULL to the caller */ - if (icalproperty_recurrence_is_excluded(comp, &start, &next)) { - icalrecur_iterator_decrement_count(itr->ritr); - return NULL; - } - - /* set recurrence-id value to the property if the property already exist; - * add the recurrence id property and the value if the property does not exist */ - prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY); - if (prop == 0) - icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next)); - else - icalproperty_set_recurrenceid(prop, next); - - if (orig_time_was_utc) { - next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone()); - } - - - if (itr->gauge == 0 || icalgauge_compare(itr->gauge, comp) == 1) { - /* find a matched and return it */ - return comp; - } - - /* not matched */ - return NULL; - -} - -icalcomponent* icalbdbsetiter_to_next(icalset *set, icalsetiter* i) -{ - - icalcomponent* comp = NULL; - icalbdbset *bset = (icalbdbset*) set; - struct icaltimetype start, next, end; - icalproperty *dtstart, *rrule, *prop, *due; - struct icalrecurrencetype recur; - icaltimezone *u_zone; - int g = 0; - int orig_time_was_utc = 0; - - do { - - /* no pending occurence, read the next component */ - if (i->last_component == NULL) { - comp = icalcompiter_next(&(i->iter)); - } - else { - comp = i->last_component; - } - - /* no next component, simply return */ - if (comp == 0) return NULL; - if (i->gauge == 0) return comp; - - /* finding the next matched component and return it to the caller */ - - rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); - g = icalgauge_get_expand(i->gauge); - - /* a recurring component with expand query */ - if (rrule != 0 - && g == 1) { - - u_zone = icaltimezone_get_builtin_timezone(i->tzid); - - /* use UTC, if that's all we have. */ - if (!u_zone) - u_zone = icaltimezone_get_utc_timezone(); - - recur = icalproperty_get_rrule(rrule); - - if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) { - dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY); - if (dtstart) - start = icalproperty_get_dtstart(dtstart); - } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) { - due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY); - if (due) - start = icalproperty_get_due(due); - } - - /* Convert to the user's timezone in order to be able to compare - * the results from the rrule iterator. */ - if (icaltime_is_utc(start)) { - start = icaltime_convert_to_zone(start, u_zone); - orig_time_was_utc = 1; - } - - if (i->ritr == NULL) { - i->ritr = icalrecur_iterator_new(recur, start); - next = icalrecur_iterator_next(i->ritr); - i->last_component = comp; - } else { - next = icalrecur_iterator_next(i->ritr); - if (icaltime_is_null_time(next)) { - i->last_component = NULL; - icalrecur_iterator_free(i->ritr); - i->ritr = NULL; - /* no more occurence, should go to get next component */ - continue; - } else { - i->last_component = comp; - } - } - - /* if it is excluded, do next one */ - if (icalproperty_recurrence_is_excluded(comp, &start, &next)) { - icalrecur_iterator_decrement_count(i->ritr); - continue; - } - - /* set recurrence-id value to the property if the property already exist; - * add the recurrence id property and the value if the property does not exist */ - prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY); - if (prop == 0) - icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next)); - else - icalproperty_set_recurrenceid(prop, next); - - if (orig_time_was_utc) { - next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone()); - } - - } /* end of recurring event with expand query */ - - if(comp != 0 && (i->gauge == 0 || - icalgauge_compare(i->gauge, comp) == 1)){ - /* found a matched, return it */ - return comp; - } - } while (comp != 0); - - return 0; - -} - -icalcomponent* icalbdbset_get_next_component(icalset* set) -{ - icalbdbset *bset = (icalbdbset*)set; - icalcomponent *c=0; - - struct icaltimetype start, next; - icalproperty *dtstart, *rrule, *prop, *due; - struct icalrecurrencetype recur; - int g = 0; - - icalerror_check_arg_rz((bset!=0),"bset"); - - do { - c = icalcomponent_get_next_component(bset->cluster, - ICAL_ANY_COMPONENT); - if(c != 0 && (bset->gauge == 0 || - icalgauge_compare(bset->gauge,c) == 1)){ - return c; - } - - } while(c != 0); - - return 0; -} - -int icalbdbset_begin_transaction(DB_TXN* parent_tid, DB_TXN** tid) -{ - return (ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, parent_tid, tid, 0)); -} - -int icalbdbset_commit_transaction(DB_TXN* txnid) -{ - return (txnid->commit(txnid, 0)); -} - - -static int _compare_keys(DB *dbp, const DBT *a, const DBT *b) -{ -/* - * Returns: - * < 0 if a < b - * = 0 if a = b - * > 0 if a > b - */ - - char* ac = (char*)a->data; - char* bc = (char*)b->data; - return (strncmp(ac, bc, a->size)); -} - - - |