Ejemplo n.º 1
0
int main(void)
{
    check(mdb_env_create(&env));
    check(mdb_env_set_mapsize(env, 1048576UL*1024UL*3UL));
    check(mdb_env_set_maxreaders(env, 126));
    check(mdb_env_set_maxdbs(env, 1));
    if(! access(DB_PATH, X_OK)) {
        system("rm -rf " DB_PATH);
    }
    check(mkdir(DB_PATH, 0777));
    check(mdb_env_open(env, DB_PATH, MDB_MAPASYNC|MDB_NOSYNC|MDB_NOMETASYNC, 0644));
    new_txn();
    check(mdb_dbi_open(txn, NULL, 0, &dbi));

    put("a");
    put("b");
    put("baa");
    put("d");

    new_txn();

    check(mdb_cursor_open(txn, dbi, &c1));
    check(mdb_cursor_get(c1, &keyv, &valv, MDB_LAST));
    check(mdb_cursor_del(c1, 0));
    check(mdb_cursor_del(c1, 0));
    new_txn();
}
Ejemplo n.º 2
0
static int mystore(struct dbengine *db,
                   const char *key, size_t keylen,
                   const char *data, size_t datalen,
                   struct txn **mytid, int overwrite)
{
    int r = 0;
    char fnamebuf[1024];
    int offset;
    unsigned long len;
    const char *lockfailaction;
    int writefd;
    struct iovec iov[10];
    int niov;
    struct stat sbuf;
    struct buf keybuf = BUF_INITIALIZER;
    struct buf databuf = BUF_INITIALIZER;

    /* lock file, if needed */
    if (!mytid || !*mytid) {
        r = lock_reopen(db->fd, db->fname, &sbuf, &lockfailaction);
        if (r < 0) {
            syslog(LOG_ERR, "IOERROR: %s %s: %m", lockfailaction, db->fname);
            return CYRUSDB_IOERROR;
        }

        if (sbuf.st_ino != db->ino) {
            db->ino = sbuf.st_ino;
            map_free(&db->base, &db->len);
            map_refresh(db->fd, 0, &db->base, &db->len,
                        sbuf.st_size, db->fname, 0);
            db->size = sbuf.st_size;
        }

        if (mytid) {
            *mytid = new_txn();
        }
    }

    encode(key, keylen, &keybuf);

    /* find entry, if it exists */
    offset = bsearch_mem_mbox(keybuf.s, db->base, db->size, 0, &len);

    /* overwrite? */
    if (len && !overwrite) {
        if (mytid) abort_txn(db, *mytid);
        buf_free(&keybuf);
        buf_free(&databuf);
        return CYRUSDB_EXISTS;
    }

    /* write new file */
    if (mytid && (*mytid)->fnamenew) {
        strlcpy(fnamebuf, (*mytid)->fnamenew, sizeof(fnamebuf));
    } else {
        strlcpy(fnamebuf, db->fname, sizeof(fnamebuf));
        strlcat(fnamebuf, ".NEW", sizeof(fnamebuf));
    }

    unlink(fnamebuf);
    r = writefd = open(fnamebuf, O_RDWR | O_CREAT, 0666);
    if (r < 0) {
        syslog(LOG_ERR, "opening %s for writing failed: %m", fnamebuf);
        if (mytid) abort_txn(db, *mytid);
        buf_free(&keybuf);
        buf_free(&databuf);
        return CYRUSDB_IOERROR;
    }

    niov = 0;
    if (offset) {
        WRITEV_ADD_TO_IOVEC(iov, niov, (char *) db->base, offset);
    }

    if (data) {
        /* new entry */
        encode(data, datalen, &databuf);
        WRITEV_ADD_TO_IOVEC(iov, niov, keybuf.s, keybuf.len);
        WRITEV_ADD_TO_IOVEC(iov, niov, "\t", 1);
        WRITEV_ADD_TO_IOVEC(iov, niov, databuf.s, databuf.len);
        WRITEV_ADD_TO_IOVEC(iov, niov, "\n", 1);
    }

    if (db->size - (offset + len) > 0) {
        WRITEV_ADD_TO_IOVEC(iov, niov, (char *) db->base + offset + len,
                            db->size - (offset + len));
    }

    /* do the write */
    r = retry_writev(writefd, iov, niov);
    if (r == -1) {
        syslog(LOG_ERR, "IOERROR: writing %s: %m", fnamebuf);
        close(writefd);
        if (mytid) abort_txn(db, *mytid);
        buf_free(&keybuf);
        buf_free(&databuf);
        return CYRUSDB_IOERROR;
    }
    r = 0;

    if (mytid) {
        /* setup so further accesses will be against fname.NEW */
        if (fstat(writefd, &sbuf) == -1) {
            /* xxx ? */
        }

        if (!(*mytid)->fnamenew) (*mytid)->fnamenew = xstrdup(fnamebuf);
        if ((*mytid)->fd) close((*mytid)->fd);
        (*mytid)->fd = writefd;
        map_free(&db->base, &db->len);
        map_refresh(writefd, 0, &db->base, &db->len, sbuf.st_size,
                    fnamebuf, 0);
        db->size = sbuf.st_size;
    } else {
        /* commit immediately */
        if (fsync(writefd) ||
            fstat(writefd, &sbuf) == -1 ||
            rename(fnamebuf, db->fname) == -1) {
            syslog(LOG_ERR, "IOERROR: writing %s: %m", fnamebuf);
            close(writefd);
            buf_free(&keybuf);
            buf_free(&databuf);
            return CYRUSDB_IOERROR;
        }

        close(db->fd);
        db->fd = writefd;

        /* release lock */
        r = lock_unlock(db->fd, db->fname);
        if (r == -1) {
            syslog(LOG_ERR, "IOERROR: unlocking db %s: %m", db->fname);
            r = CYRUSDB_IOERROR;
        }

        db->ino = sbuf.st_ino;
        map_free(&db->base, &db->len);
        map_refresh(writefd, 0, &db->base, &db->len, sbuf.st_size,
            db->fname, 0);
        db->size = sbuf.st_size;
    }

    buf_free(&keybuf);
    buf_free(&databuf);

    return r;
}
Ejemplo n.º 3
0
static int starttxn_or_refetch(struct dbengine *db, struct txn **mytid)
{
    int r = 0;
    struct stat sbuf;

    assert(db);

    if (mytid && !*mytid) {
        const char *lockfailaction;

        /* start txn; grab lock */

        r = lock_reopen(db->fd, db->fname, &sbuf, &lockfailaction);
        if (r < 0) {
            syslog(LOG_ERR, "IOERROR: %s %s: %m", lockfailaction, db->fname);
            return CYRUSDB_IOERROR;
        }
        *mytid = new_txn();

        if (db->ino != sbuf.st_ino) {
            map_free(&db->base, &db->len);
        }
        map_refresh(db->fd, 0, &db->base, &db->len, sbuf.st_size,
                    db->fname, 0);

        /* we now have the latest & greatest open */
        db->size = sbuf.st_size;
        db->ino = sbuf.st_ino;
    }

    if (!mytid) {
        /* no txn, but let's try to be reasonably up-to-date */

        if (stat(db->fname, &sbuf) == -1) {
            syslog(LOG_ERR, "IOERROR: stating flat %s: %m", db->fname);
            return CYRUSDB_IOERROR;
        }

        if (sbuf.st_ino != db->ino) {
            /* reopen */
            int newfd = open(db->fname, O_RDWR);

            if (newfd == -1) {
                /* fail! */
                syslog(LOG_ERR, "couldn't reopen %s: %m", db->fname);
                return CYRUSDB_IOERROR;
            }
            dup2(newfd, db->fd);
            close(newfd);
            if (stat(db->fname, &sbuf) == -1) {
                syslog(LOG_ERR, "IOERROR: stating flat %s: %m", db->fname);
                return CYRUSDB_IOERROR;
            }

            db->ino = sbuf.st_ino;
            map_free(&db->base, &db->len);
        }
        map_refresh(db->fd, 0, &db->base, &db->len,
                    sbuf.st_size, db->fname, 0);
        db->size = sbuf.st_size;
    }

    return 0;
}