int mboxkey_merge(const char *tmpfile, const char *tgtfile) { int r = 0; struct db *tmp = NULL, *tgt = NULL; struct mboxkey_merge_rock rock; /* xxx does this need to be CYRUSDB_CREATE? */ r = cyrusdb_open(DB, tmpfile, CYRUSDB_CREATE, &tmp); if(r) goto done; r = cyrusdb_open(DB, tgtfile, CYRUSDB_CREATE, &tgt); if(r) goto done; rock.db = tgt; rock.tid = NULL; r = cyrusdb_foreach(tmp, "", 0, NULL, mboxkey_merge_cb, &rock, &rock.tid); if(r) cyrusdb_abort(rock.db, rock.tid); else cyrusdb_commit(rock.db, rock.tid); done: if(tgt) cyrusdb_close(tgt); if(tmp) cyrusdb_close(tmp); return r; }
/* * Open the user deny database. If 'create' is true and the database * does not exist, create it. Returns 0 on success or an IMAP error * code. */ EXPORTED int denydb_open(int create) { const char *fname; int ret; char *tofree = NULL; fname = config_getstring(IMAPOPT_USERDENY_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_USERDENYDB, (char *)NULL); fname = tofree; } ret = cyrusdb_open(DENYDB, fname, (create ? CYRUSDB_CREATE : 0), &denydb); if (ret == CYRUSDB_NOTFOUND) { /* ignore non-existent DB, report all other errors */ ret = ENOENT; } else if (ret != CYRUSDB_OK) { syslog(LOG_WARNING, "DENYDB_ERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); ret = IMAP_IOERROR; } free(tofree); return ret; }
/* must be called after cyrus_init */ EXPORTED int duplicate_init(const char *fname) { int r = 0; char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_DUPLICATE_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_DELIVERDB, (char *)NULL); fname = tofree; } r = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &dupdb); if (r != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); goto out; } duplicate_dbopen = 1; out: free(tofree); return r; }
/* must be called after cyrus_init */ static int newsrc_init(const char *fname, int myflags __attribute__((unused))) { char buf[1024]; int r = 0; if (r != 0) syslog(LOG_ERR, "DBERROR: init %s: %s", buf, cyrusdb_strerror(r)); else { char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_NEWSRC_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_NEWSRCDB, (char *)NULL); fname = tofree; } r = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &newsrc_db); if (r != 0) syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); else newsrc_dbopen = 1; free(tofree); } return r; }
void statuscache_open(const char *fname) { int ret; char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_STATUSCACHE_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_STATUSCACHEDB, (char *)NULL); fname = tofree; } ret = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &statuscachedb); if (ret != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); syslog(LOG_ERR, "statuscache in degraded mode"); return; } free(tofree); statuscache_dbopen = 1; }
EXPORTED void quotadb_open(const char *fname) { int ret; char *tofree = NULL; int flags = CYRUSDB_CREATE; if (!fname) fname = config_getstring(IMAPOPT_QUOTA_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_QUOTADB, (char *)NULL); fname = tofree; } if (config_getswitch(IMAPOPT_IMPROVED_MBOXLIST_SORT)) flags |= CYRUSDB_MBOXSORT; ret = cyrusdb_open(QDB, fname, flags, &qdb); if (ret != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); /* Exiting TEMPFAIL because Sendmail thinks this EC_OSFILE == permanent failure. */ fatal("can't read quotas file", EC_TEMPFAIL); } free(tofree); quota_dbopen = 1; }
EXPORTED int jmapauth_open(struct db **dbptr, int db_flags, const char *fname) { int r = 0; char *tofree = NULL; assert(dbptr); if (!fname) { fname = config_getstring(IMAPOPT_JMAPAUTH_DB_PATH); } /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_JMAPAUTH, (char*)NULL); fname = tofree; } /* open the database */ r = cyrusdb_open(DB, fname, db_flags, dbptr); if (r) { if (r != CYRUSDB_NOTFOUND) { syslog(LOG_ERR, "JMAP auth: cannot open db %s: %s", fname, cyrusdb_strerror(r)); } return r; } free(tofree); return r; }
/* we want to merge records from "newfile" into * the already existing "currentfile", but only * if the record in newfile is actually newer * (or doesn't exist in currentfile yet) */ int seen_merge(struct seen *seendb, const char *newfile) { int r = 0; struct db *newdb = NULL; r = cyrusdb_open(DB, newfile, 0, &newdb); /* if it doesn't exist, there's nothing * to do, so abort without an error */ if (r == CYRUSDB_NOTFOUND) return 0; if (!r) r = cyrusdb_foreach(newdb, "", 0, NULL, seen_merge_cb, seendb, NULL); if (newdb) cyrusdb_close(newdb); return r; }
EXPORTED void statuscache_open(void) { char *fname = statuscache_filename(); int ret; ret = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &statuscachedb); if (ret != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); syslog(LOG_ERR, "statuscache in degraded mode"); goto out; } statuscache_dbopen = 1; out: free(fname); }
int seen_open(const char *user, int flags, struct seen **seendbptr) { struct seen *seendb = NULL; char *fname = NULL; int dbflags = (flags & SEEN_CREATE) ? CYRUSDB_CREATE : 0; int r; assert(user); assert(*seendbptr == NULL); /* create seendb */ seendb = (struct seen *) xmalloc(sizeof(struct seen)); if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: seen_open(%s)", user); } /* open the seendb corresponding to user */ fname = seen_getpath(user); if (flags & SEEN_CREATE) cyrus_mkdir(fname, 0755); r = cyrusdb_open(DB, fname, dbflags, &seendb->db); if (r) { if (!(flags & SEEN_SILENT)) { int level = (flags & SEEN_CREATE) ? LOG_ERR : LOG_DEBUG; syslog(level, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); } r = IMAP_IOERROR; free(seendb); free(fname); return r; } syslog(LOG_DEBUG, "seen_db: user %s opened %s", user, fname); free(fname); seendb->tid = NULL; seendb->user = xstrdup(user); *seendbptr = seendb; return r; }
/* Returns 0 on success */ static int ptload(const char *identifier, struct auth_state **state) { struct auth_state *fetched = NULL; size_t id_len; const char *data = NULL; size_t dsize; const char *fname = NULL; char *tofree = NULL; struct db *ptdb; int s; struct sockaddr_un srvaddr; int r, rc=0; static char response[1024]; struct iovec iov[10]; int niov, n; unsigned int start; const char *config_dir = libcyrus_config_getstring(CYRUSOPT_CONFIG_DIR); /* xxx this sucks, but it seems to be the only way to satisfy the linker */ if(the_ptscache_db == NULL) { the_ptscache_db = libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB); } if(!state || *state) { fatal("bad state pointer passed to ptload()", EC_TEMPFAIL); } fname = libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB_PATH); if (!fname) { tofree = strconcat(config_dir, PTS_DBFIL, (char *)NULL); fname = tofree; } r = cyrusdb_open(the_ptscache_db, fname, CYRUSDB_CREATE, &ptdb); if (r != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); free(tofree); *state = NULL; return -1; } free(tofree); tofree = NULL; id_len = strlen(identifier); if(id_len > PTS_DB_KEYSIZE) { syslog(LOG_ERR, "identifier too long in auth_newstate"); *state = NULL; return -1; } /* fetch the current record for the user */ r = cyrusdb_fetch(ptdb, identifier, id_len, &data, &dsize, NULL); if (r && r != CYRUSDB_NOTFOUND) { syslog(LOG_ERR, "auth_newstate: error fetching record: %s", cyrusdb_strerror(r)); rc = -1; goto done; } /* if it's expired (or nonexistent), * ask the ptloader to reload it and reread it */ fetched = (struct auth_state *) data; if(fetched) { time_t now = time(NULL); int timeout = libcyrus_config_getint(CYRUSOPT_PTS_CACHE_TIMEOUT); syslog(LOG_DEBUG, "ptload(): fetched cache record (%s)" \ "(mark %ld, current %ld, limit %ld)", identifier, fetched->mark, now, now - timeout); if (fetched->mark > (now - timeout)) { /* not expired; let's return it */ goto done; } } syslog(LOG_DEBUG, "ptload(): pinging ptloader"); s = socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { syslog(LOG_ERR, "ptload(): unable to create socket for ptloader: %m"); rc = -1; goto done; } fname = libcyrus_config_getstring(CYRUSOPT_PTLOADER_SOCK); if (!fname) { tofree = strconcat(config_dir, PTS_DBSOCKET, (char *)NULL); fname = tofree; } if (strlen(fname) >= sizeof(srvaddr.sun_path)) { syslog(LOG_ERR, "ptload(): socket filename %s too long for " SIZE_T_FMT "-byte buffer", fname, sizeof(srvaddr.sun_path)); rc = -1; goto done; } memset((char *)&srvaddr, 0, sizeof(srvaddr)); srvaddr.sun_family = AF_UNIX; strlcpy(srvaddr.sun_path, fname, sizeof(srvaddr.sun_path)); r = nb_connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr), PT_TIMEOUT_SEC); free(tofree); if (r == -1) { syslog(LOG_ERR, "ptload(): can't connect to ptloader server: %m"); close(s); rc = -1; goto done; } syslog(LOG_DEBUG, "ptload(): connected"); niov = 0; WRITEV_ADD_TO_IOVEC(iov, niov, (char *) &id_len, sizeof(id_len)); WRITEV_ADD_TO_IOVEC(iov, niov, (char *) identifier, id_len); if (timeout_select(s, TS_WRITE, PT_TIMEOUT_SEC) < 0) { syslog(LOG_ERR, "timeoutselect: writing to ptloader %m"); rc = -1; goto done; } retry_writev(s, iov, niov); syslog(LOG_DEBUG, "ptload sent data"); start = 0; while (start < sizeof(response) - 1) { if (timeout_select(s, TS_READ, PT_TIMEOUT_SEC) < 0) { syslog(LOG_ERR, "timeout_select: reading from ptloader: %m"); rc = -1; goto done; } n = read(s, response+start, sizeof(response) - 1 - start); if (n < 1) break; start += n; } response[sizeof(response)-1] = '\0'; close(s); syslog(LOG_DEBUG, "ptload read data back"); if (start <= 1 || strncmp(response, "OK", 2)) { if(start > 1) { syslog(LOG_ERR, "ptload(): bad response from ptloader server: %s", response); } else { syslog(LOG_ERR, "ptload(): empty response from ptloader server"); } rc = -1; goto done; } /* fetch the current record for the user */ r = cyrusdb_fetch(ptdb, identifier, id_len, &data, &dsize, NULL); if (r != 0 || !data) { syslog(LOG_ERR, "ptload(): error fetching record: %s" "(did ptloader add the record?)", cyrusdb_strerror(r)); data = NULL; rc = -1; goto done; } done: /* ok, we got real data, let's use it */ if (data != NULL) { fetched = (struct auth_state *) data; } if (fetched == NULL) { *state = NULL; syslog(LOG_DEBUG, "No data available at all from ptload()"); } else { /* copy it into our structure */ *state = (struct auth_state *)xmalloc(dsize); memcpy(*state, fetched, dsize); syslog(LOG_DEBUG, "ptload returning data"); } /* close and unlock the database */ (cyrusdb_close)(ptdb); return rc; }
int main(int argc, char *argv[]) { int iter; int seed; int i; char *key; char *val; struct db *db; int r; struct txn *txn; const char *data; int datalen; struct timeval t1, t2; int initsize; if (argc > 1) { iter = atoi(argv[1]); } else { printf("%s [iterations] [rndseed] [initsize]\n", argv[0]); printf("if iterations is negative, run forever and report every -iter\n"); exit(1); } TRY(DB->init(".", 0)); if (argc > 2) { srand(atoi(argv[2])); } TRY(cyrusdb_open(DB, "scratch", &db)); if (cyrusdb_consistent) { TRY(cyrusdb_consistent(db)); } if (argc > 3) { initsize = atoi(argv[3]); txn = NULL; for (i = 0; i < initsize; i++) { /* generate a random key */ key = genrand(10 + (rand() % 10)); /* generate a random value */ val = genrand(10 + (rand() % 100)); TRY(cyrusdb_store(db, key, strlen(key), val, strlen(val), &txn)); } TRY(cyrusdb_commit(db, txn)); if (cyrusdb_consistent) { TRY(cyrusdb_consistent(db)); } } printf("starting...\n"); /* repeat for ever if iter < 0 */ for (i = 0; iter > 0 ? (i < iter) : 1; i++) { int oper = rand() % 10; if (i > 0 && iter < 0 && ((i % -iter) == 0)) { do_report(); } switch (oper) { case 0: /* do an ADD */ if (verbose) printf("A"); /* insert it */ gettimeofday(&t1, NULL); /* generate a random key */ key = genrand(10 + (rand() % 10)); /* generate a random value */ val = genrand(10 + (rand() % 100)); txn = NULL; TRY(cyrusdb_store(db, key, strlen(key), val, strlen(val), &txn)); TRY(cyrusdb_commit(db, txn)); gettimeofday(&t2, NULL); ADDDIFF(t_add, t1, t2); c_add++; free(key); free(val); break; case 1: /* do a modify */ if (verbose) printf("M"); gettimeofday(&t1, NULL); /* pick a random victim */ count = 0; victim = NULL; txn = NULL; TRY(cyrusdb_foreach(db, NULL, 0, &countem, NULL, NULL, &txn)); if (count == 0) continue; TRY(cyrusdb_foreach(db, NULL, 0, &findvictim, NULL, NULL, &txn)); assert(victim != NULL); /* generate a random value */ val = genrand(10 + (rand() % 100)); /* do an add */ TRY(cyrusdb_store(db, victim, strlen(victim), val, strlen(val), &txn)); free(val); TRY(cyrusdb_commit(db, txn)); free(victim); victim = NULL; gettimeofday(&t2, NULL); ADDDIFF(t_mod, t1, t2); c_mod++; break; case 2: /* do a delete */ if (verbose) printf("D"); gettimeofday(&t1, NULL); /* pick a random victim */ count = 0; victim = NULL; txn = NULL; TRY(cyrusdb_foreach(db, NULL, 0, &countem, NULL, NULL, &txn)); if (count == 0) continue; TRY(cyrusdb_foreach(db, NULL, 0, &findvictim, NULL, NULL, &txn)); assert(victim != NULL); /* delete it */ TRY(cyrusdb_delete(db, victim, strlen(victim), &txn, 0)); TRY(cyrusdb_commit(db, txn)); free(victim); victim = NULL; gettimeofday(&t2, NULL); ADDDIFF(t_del, t1, t2); c_del++; break; default: /* do a "read" */ if (verbose) printf("R"); gettimeofday(&t1, NULL); /* generate a random key */ key = genrand(10 + (rand() % 10)); txn = NULL; TRY(cyrusdb_fetch(db, key, strlen(key), &data, &datalen, &txn)); TRY(cyrusdb_commit(db, txn)); gettimeofday(&t2, NULL); ADDDIFF(t_find, t1, t2); c_find++; free(key); } fflush(stdout); #if 0 /* run the consistency function, if any */ if (cyrusdb_consistent) { TRY(cyrusdb_consistent(db)); } #endif } TRY(cyrusdb_close(db)); TRY(DB->done()); do_report(); return 0; }
int mboxkey_open(const char *user, int flags, struct mboxkey **mboxkeydbptr) { struct mboxkey *mboxkeydb; struct stat sbuf; char *fname = NULL; int r; /* try to reuse the last db handle */ mboxkeydb = lastmboxkey; lastmboxkey = NULL; if (MBOXKEY_DEBUG) { syslog(LOG_DEBUG, "mboxkey_db: mboxkey_open(%s)", user); } /* if this is the db we've already opened, return it */ if (mboxkeydb && !strcmp(mboxkeydb->user, user) && !stat(mboxkeydb->fname, &sbuf)) { abortcurrent(mboxkeydb); *mboxkeydbptr = mboxkeydb; return 0; } *mboxkeydbptr = NULL; /* otherwise, close the existing database */ if (mboxkeydb) { abortcurrent(mboxkeydb); r = cyrusdb_close(mboxkeydb->db); if (r) { syslog(LOG_ERR, "DBERROR: error closing mboxkeydb: %s", cyrusdb_strerror(r)); } free(mboxkeydb->user); free(mboxkeydb->fname); } else { /* create mboxkeydb */ mboxkeydb = (struct mboxkey *) xmalloc(sizeof(struct mboxkey)); } /* open the mboxkeydb corresponding to user */ fname = mboxkey_getpath(user); r = cyrusdb_open(DB, fname, (flags & MBOXKEY_CREATE) ? CYRUSDB_CREATE : 0, &mboxkeydb->db); if (r != 0) { int level = (flags & MBOXKEY_CREATE) ? LOG_ERR : LOG_DEBUG; syslog(level, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); r = IMAP_IOERROR; free(mboxkeydb); free(fname); return r; } syslog(LOG_DEBUG, "mboxkey_db: user %s opened %s", user, fname); mboxkeydb->tid = NULL; mboxkeydb->user = xstrdup(user); mboxkeydb->fname = fname; *mboxkeydbptr = mboxkeydb; return r; }