Skip to content

Instantly share code, notes, and snippets.

@dim
Created July 31, 2013 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dim/6122131 to your computer and use it in GitHub Desktop.
Save dim/6122131 to your computer and use it in GitHub Desktop.
/* mtest8.c - memory-mapped database tester/toy */
/*
* Copyright 2013 Dimitrij Denissenko, Black Square Media
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* Tests for multi-process access */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "lmdb.h"
int createEnv(MDB_env **env, MDB_dbi *dbi) {
int rc;
MDB_txn *txn;
if ((rc = mdb_env_create(env))) return rc;
if ((rc = mdb_env_set_mapsize(*env, 2048LL*1024*1024))) return rc;
if ((rc = mdb_env_set_maxdbs(*env, 4))) return rc;
if ((rc = mdb_env_open(*env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664))) return rc;
if ((rc = mdb_txn_begin(*env, NULL, 0, &txn))) return rc;
if ((rc = mdb_open(txn, NULL, MDB_CREATE, dbi))) return rc;
if ((rc = mdb_txn_commit(txn))) return rc;
return rc;
}
int bulkWrite(int mode) {
char skey[32];
char sval[64];
MDB_env *env = NULL;
MDB_dbi dbi;
MDB_txn *txn;
MDB_val key, data;
pid_t childpid = 0;
int rc = MDB_SUCCESS;
int keys = 10000;
if ((rc = createEnv(&env, &dbi))) goto cleanup;
while (keys--) {
sprintf(skey, "%08x", keys);
key.mv_size = 8;
key.mv_data = skey;
data.mv_size = sizeof(sval);
data.mv_data = sval;
if ((rc = mdb_txn_begin(env, NULL, 0, &txn))) goto cleanup;
if ((rc = mdb_put(txn,dbi,&key,&data,0))) goto cleanup;
if ((rc = mdb_txn_commit(txn))) goto cleanup;
if ((keys % 1000) == 0) {
mdb_env_close(env);
env = NULL;
/* Wait for previous children */
if (childpid) {
int status;
waitpid(childpid, &status, 0);
childpid = 0;
}
/* Child */
if (mode && (childpid = fork()) == 0) {
char *tmpfile = "./testdb/backup.mdb";
unlink(tmpfile);
int fd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644);
if (fd == -1) {
printf("Error in child: %s\n",strerror(errno));
exit(1);
}
rc = createEnv(&env, &dbi);
if (mode == 2 && !rc) rc = mdb_env_copyfd(env, fd);
close(fd);
if (rc) printf("Error in child: %s\n", mdb_strerror(rc));
if (env) mdb_env_close(env);
exit(0);
} else {
if ((rc = createEnv(&env, &dbi))) goto cleanup;
}
}
}
cleanup:
if (env) mdb_env_close(env);
return rc;
}
int main(int argc,char * argv[]) {
int rc;
struct stat sb;
unlink("./testdb/data.mdb");
if ((rc = bulkWrite(0))) {
printf("Error: %s\n", mdb_strerror(rc));
return 1;
}
if (stat("./testdb/data.mdb", &sb) == -1) {
printf("Error: %s\n", strerror(errno));
return 1;
}
printf("NO FORK : %zu\n", sb.st_size);
unlink("./testdb/data.mdb");
if ((rc = bulkWrite(1))) {
printf("Error: %s\n", mdb_strerror(rc));
return 1;
}
if (stat("./testdb/data.mdb", &sb) == -1) {
printf("Error: %s\n", strerror(errno));
return 1;
}
printf("FORK & OPEN : %zu\n", sb.st_size);
unlink("./testdb/data.mdb");
if ((rc = bulkWrite(2))) {
printf("Error: %s\n", mdb_strerror(rc));
return 1;
}
if (stat("./testdb/data.mdb", &sb) == -1) {
printf("Error: %s\n", strerror(errno));
return 1;
}
printf("FORK & COPY : %zu\n", sb.st_size);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment