static void setup(void) { unlink(TESTDB); memdb = memdb_open(TESTDB); fail_unless (memdb != NULL); struct statvfs stbuf; fail_unless(memdb_statfs(memdb, &stbuf) == 0); int count = stbuf.f_files - stbuf.f_ffree; fail_unless(count == 1); }
int main(int argc, char *argv[]) { cfs_status_init(); if (argc != 3) { usage_error(); } const char *dir_name = argv[1]; const char *dbfile = argv[2]; DIR *dh = opendir(dir_name); if (!dh) { perror("unable to open dir"); exit(-1); } memdb = memdb_open(dbfile); struct dirent *de; time_t ctime = time(NULL); while((de = readdir(dh))) { if (de->d_type != DT_REG) { continue; } char *cdata = NULL; gsize clen = 0; char *fn = g_strdup_printf("%s/%s", dir_name, de->d_name); if (g_file_get_contents(fn, &cdata, &clen, NULL)) { //printf("FOUND %ld %s\n", clen, fn); if (memdb_create(memdb, de->d_name, 0, ctime) != 0) { fprintf(stderr, "memdb_create '%s' failed\n", de->d_name); exit(-1); } if (memdb_write(memdb, de->d_name, 0, ctime, cdata, clen, 0, 1) != clen) { fprintf(stderr, "memdb_write '%s' failed\n", de->d_name); exit(-1); } } g_free(fn); } memdb_close(memdb); closedir(dh); }
END_TEST /* Nornmaly, parent inode number is always less than contained inode, * but this is not allways the case. A simple move can destroy that * ordering. This code test the placeholder algorithm in * bdb_backend_load_index() */ START_TEST (test_loaddb1) { time_t ctime = 1234; fail_unless(memdb_mkdir(memdb, "dir1", 0, ctime) == 0); fail_unless(memdb_create(memdb, "dir1/file1", 0, ctime) == 0); fail_unless(memdb_create(memdb, "dir1/file2", 0, ctime) == 0); fail_unless(memdb_mkdir(memdb, "dir2", 0, ctime) == 0); fail_unless(memdb_rename(memdb, "dir1/file1", "dir2/file1", 0, ctime) == 0); fail_unless(memdb_rename(memdb, "dir1/file2", "dir2/file2", 0, ctime) == 0); fail_unless(memdb_create(memdb, "dir2/file1", 0, ctime) == -EEXIST); fail_unless(memdb_create(memdb, "dir2/file2", 0, ctime) == -EEXIST); //memdb_dump(memdb); memdb_close(memdb); memdb = memdb_open(TESTDB); fail_unless (memdb != NULL); fail_unless(memdb_create(memdb, "dir2/file1", 0, ctime) == -EEXIST); fail_unless(memdb_create(memdb, "dir2/file2", 0, ctime) == -EEXIST); //memdb_dump(memdb); }
END_TEST START_TEST (test_loaddb2) { time_t ctime = 1234; fail_unless(memdb_mkdir(memdb, "dir1", 0, ctime) == 0); fail_unless(memdb_mkdir(memdb, "dir1/sd1", 0, ctime) == 0); fail_unless(memdb_create(memdb, "dir1/file1", 0, ctime) == 0); fail_unless(memdb_create(memdb, "dir1/file2", 0, ctime) == 0); fail_unless(memdb_mkdir(memdb, "dir2", 0, ctime) == 0); fail_unless(memdb_rename(memdb, "dir1/sd1", "dir2/sd1", 0, ctime) == 0); fail_unless(memdb_rename(memdb, "dir1/file1", "dir2/sd1/file1", 0, ctime) == 0); fail_unless(memdb_rename(memdb, "dir1/file2", "dir2/sd1/file2", 0, ctime) == 0); fail_unless(memdb_create(memdb, "dir2/file3", 0, ctime) == 0); fail_unless(memdb_mkdir(memdb, "dir2/sd1", 0, ctime) == -EEXIST); //memdb_dump(memdb); memdb_close(memdb); memdb = memdb_open(TESTDB); fail_unless (memdb != NULL); fail_unless(memdb_mkdir(memdb, "dir2/sd1", 0, ctime) == -EEXIST); //memdb_dump(memdb); }
int main(int argc, char *argv[]) { int ret = -1; int lockfd = -1; gboolean foreground = FALSE; gboolean force_local_mode = FALSE; gboolean wrote_pidfile = FALSE; memdb_t *memdb = NULL; dfsm_t *dcdb = NULL; dfsm_t *status_fsm = NULL; qb_log_init("pmxcfs", LOG_DAEMON, LOG_DEBUG); /* remove default filter */ qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_REMOVE, QB_LOG_FILTER_FILE, "*", LOG_DEBUG); qb_log_tags_stringify_fn_set(log_tags_stringify); qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); update_qb_log_settings(); g_set_print_handler(glib_print_handler); g_set_printerr_handler(glib_print_handler); g_log_set_default_handler(glib_log_handler, NULL); GOptionContext *context; GOptionEntry entries[] = { { "debug", 'd', 0, G_OPTION_ARG_NONE, &cfs.debug, "Turn on debug messages", NULL }, { "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Do not daemonize server", NULL }, { "local", 'l', 0, G_OPTION_ARG_NONE, &force_local_mode, "Force local mode (ignore cluster.conf, force quorum)", NULL }, { NULL }, }; context = g_option_context_new (""); g_option_context_add_main_entries (context, entries, NULL); GError *err = NULL; if (!g_option_context_parse (context, &argc, &argv, &err)) { cfs_critical("option parsing failed: %s", err->message); g_error_free (err); qb_log_fini(); exit (1); } g_option_context_free(context); if (optind < argc) { cfs_critical("too many arguments"); qb_log_fini(); exit(-1); } if (cfs.debug) { update_qb_log_settings(); } struct utsname utsname; if (uname(&utsname) != 0) { cfs_critical("Unable to read local node name"); qb_log_fini(); exit (-1); } for (int i=0; i < sizeof(utsname.nodename); i++) { if (utsname.nodename[i] =='.') utsname.nodename[i] = 0; } cfs.nodename = g_strdup(utsname.nodename); if (!(cfs.ip = lookup_node_ip(cfs.nodename))) { cfs_critical("Unable to get local IP address"); qb_log_fini(); exit(-1); } struct group *www_data = getgrnam("www-data"); if (!www_data) { cfs_critical("Unable to get www-data group ID"); qb_log_fini(); exit (-1); } cfs.gid = www_data->gr_gid; g_thread_init(NULL); umask(027); mkdir(VARLIBDIR, 0755); if ((lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_APPEND)) == -1) { cfs_critical("unable to create lock '%s': %s", LOCKFILE, strerror (errno)); goto err; } for (int i = 10; i >= 0; i--) { if (flock(lockfd, LOCK_EX|LOCK_NB) != 0) { if (!i) { cfs_critical("unable to aquire pmxcfs lock: %s", strerror (errno)); goto err; } if (i == 10) cfs_message("unable to aquire pmxcfs lock - trying again"); sleep(1); } } cfs_status_init(); gboolean create = !g_file_test(DBFILENAME, G_FILE_TEST_EXISTS); if (!(memdb = memdb_open (DBFILENAME))) { cfs_critical("memdb_open failed - unable to open database '%s'", DBFILENAME); goto err; } // automatically import cluster.conf from host if (create && !force_local_mode) { char *cdata = NULL; gsize clen = 0; if (g_file_get_contents(HOST_CLUSTER_CONF_FN, &cdata, &clen, NULL)) { guint32 mtime = time(NULL); memdb_create(memdb, "/cluster.conf", 0, mtime); if (memdb_write(memdb, "/cluster.conf", 0, mtime, cdata, clen, 0, 1) < 0) { cfs_critical("memdb_write failed - unable to import cluster.conf"); goto err; } } } // does cluster.conf exist? gpointer conf_data = NULL; int len = memdb_read(memdb, "cluster.conf", &conf_data); if (len >= 0) { if (force_local_mode) { cfs_message("forcing local mode (althought cluster.conf exists)"); cfs_set_quorate(1, TRUE); } else { if (!(dcdb = dcdb_new(memdb))) goto err; dcdb_sync_cluster_conf(memdb, 1); } } else { cfs_debug("using local mode (cluster.conf does not exist)"); cfs_set_quorate(1, TRUE); } if (conf_data) g_free(conf_data); cfs_plug_memdb_t *config = cfs_plug_memdb_new("memdb", memdb, dcdb); cfs_plug_base_t *bplug = cfs_plug_base_new("", (cfs_plug_t *)config); create_symlinks(bplug, cfs.nodename); root_plug = (cfs_plug_t *)bplug; system("umount -f " CFSDIR " >/dev/null 2>&1"); char *fa[] = { "-f", "-odefault_permissions", "-oallow_other", NULL}; struct fuse_args fuse_args = FUSE_ARGS_INIT(sizeof (fa)/sizeof(gpointer) - 1, fa); struct fuse_chan *fuse_chan = fuse_mount(CFSDIR, &fuse_args); if (!fuse_chan) { cfs_critical("fuse_mount error: %s", strerror(errno)); goto err; } if (!(fuse = fuse_new(fuse_chan, &fuse_args, &fuse_ops, sizeof(fuse_ops), NULL))) { cfs_critical("fuse_new error: %s", strerror(errno)); goto err; } fuse_set_signal_handlers(fuse_get_session(fuse)); if (!foreground) { pid_t cpid = fork(); if (cpid == -1) { cfs_critical("failed to daemonize program - %s", strerror (errno)); goto err; } else if (cpid) { write_pidfile(cpid); qb_log_fini(); _exit (0); } else { int nullfd; chroot("/"); if ((nullfd = open("/dev/null", O_RDWR, 0)) != -1) { dup2(nullfd, 0); dup2(nullfd, 1); dup2(nullfd, 2); if (nullfd > 2) close (nullfd); } // do not print to the console after this point qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE); setsid(); } } else { write_pidfile(getpid()); } wrote_pidfile = TRUE; cfs_loop_t *corosync_loop = cfs_loop_new(fuse); cfs_service_t *service_quorum = NULL; cfs_service_t *service_confdb = NULL; cfs_service_t *service_dcdb = NULL; cfs_service_t *service_status = NULL; if (dcdb) { service_quorum = service_quorum_new(); cfs_loop_add_service(corosync_loop, service_quorum, QB_LOOP_HIGH); service_confdb = service_confdb_new(); cfs_loop_add_service(corosync_loop, service_confdb, QB_LOOP_MED); service_dcdb = service_dfsm_new(dcdb); cfs_service_set_timer(service_dcdb, DCDB_VERIFY_TIME); cfs_loop_add_service(corosync_loop, service_dcdb, QB_LOOP_MED); status_fsm = cfs_status_dfsm_new(); service_status = service_dfsm_new(status_fsm); cfs_loop_add_service(corosync_loop, service_status, QB_LOOP_LOW); } cfs_loop_start_worker(corosync_loop); server_start(memdb); ret = fuse_loop_mt(fuse); cfs_message("teardown filesystem"); server_stop(); fuse_unmount(CFSDIR, fuse_chan); fuse_destroy(fuse); cfs_debug("set stop event loop flag"); cfs_loop_stop_worker(corosync_loop); cfs_loop_destroy(corosync_loop); cfs_debug("worker finished"); if (service_dcdb) service_dfsm_destroy(service_dcdb); if (service_confdb) service_confdb_destroy(service_confdb); if (service_quorum) service_quorum_destroy(service_quorum); if (service_status) service_dfsm_destroy(service_status); sleep(1); /* do not restart too fast */ ret: if (status_fsm) dfsm_destroy(status_fsm); if (dcdb) dfsm_destroy(dcdb); if (memdb) memdb_close(memdb); if (wrote_pidfile) unlink(CFS_PID_FN); cfs_message("exit proxmox configuration filesystem (%d)", ret); cfs_status_cleanup(); qb_log_fini(); exit(ret); err: goto ret; }