int ctable_factory_base::setup(int dfd, const char * name, const params & config, dtype::ctype key_type) { istr base; params base_config; if(!config.get("base", &base) || !config.get("base_config", &base_config)) return NULL; return setup(base, dfd, name, base_config, key_type); }
int exist_dtable::create(int dfd, const char * file, const params & config, dtable::iter * source, const ktable * shadow) { int e_dfd, r; params base_config, dnebase_config; const dtable_factory * base = dtable_factory::lookup(config, "base"); const dtable_factory * dnebase = dtable_factory::lookup(config, "dnebase"); if(!base || !dnebase) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("dnebase_config", &dnebase_config, params())) return -EINVAL; if(!source_shadow_ok(source, shadow)) return -EINVAL; r = mkdirat(dfd, file, 0755); if(r < 0) return r; e_dfd = openat(dfd, file, O_RDONLY); if(e_dfd < 0) goto fail_open; /* just to be sure */ source->first(); { dtable_skip_iter<dne_skip_test> base_source(source); r = base->create(e_dfd, "base", base_config, &base_source, NULL); if(r < 0) goto fail_base; } source->first(); { full_ktable full_shadow(source); nonshadow_skip_test skip_test(shadow); dtable_skip_iter<nonshadow_skip_test> dnebase_source(source, skip_test); r = dnebase->create(e_dfd, "dnebase", dnebase_config, &dnebase_source, &full_shadow); if(r < 0) goto fail_dnebase; } close(e_dfd); return 0; fail_dnebase: util::rm_r(e_dfd, "base"); fail_base: close(e_dfd); fail_open: unlinkat(dfd, file, AT_REMOVEDIR); return (r < 0) ? r : -1; }
int deltaint_dtable::init(int dfd, const char * file, const params & config, sys_journal * sysj) { const dtable_factory * base_factory; const dtable_factory * ref_factory; params base_config, ref_config; int di_dfd; if(base) deinit(); base_factory = dtable_factory::lookup(config, "base"); ref_factory = dtable_factory::lookup(config, "ref"); if(!base_factory || !ref_factory) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("ref_config", &ref_config, params())) return -EINVAL; di_dfd = openat(dfd, file, O_RDONLY); if(di_dfd < 0) return di_dfd; base = base_factory->open(di_dfd, "base", base_config, sysj); if(!base) goto fail_base; reference = ref_factory->open(di_dfd, "ref", ref_config, sysj); if(!reference) goto fail_reference; ktype = base->key_type(); cmp_name = base->get_cmp_name(); assert(ktype == reference->key_type()); scan_iter = base->iterator(); if(!scan_iter) goto fail_scan; ref_iter = reference->iterator(); if(!ref_iter) goto fail_iter; close(di_dfd); return 0; fail_iter: delete scan_iter; scan_iter = NULL; fail_scan: reference->destroy(); reference = NULL; fail_reference: base->destroy(); base = NULL; fail_base: close(di_dfd); return -1; }
amg( const Matrix &A, const params &prm = params(), const backend_params &backend_prm = backend_params() ) : coarsening(prm.get("coarsening.type", runtime::coarsening::smoothed_aggregation)), relaxation(prm.get("relaxation.type", runtime::relaxation::spai0)), handle(0) { runtime::detail::process_amg<Backend>( coarsening, relaxation, runtime::detail::amg_create<Backend, Matrix>(handle, A, prm, backend_prm) ); }
int exception_dtable::init(int dfd, const char * file, const params & config, sys_journal * sysj) { const dtable_factory * base_factory; const dtable_factory * alt_factory; params base_config, alt_config; int excp_dfd; if(base || alt) deinit(); base_factory = dtable_factory::lookup(config, "base"); alt_factory = dtable_factory::lookup(config, "alt"); if(!base_factory || !alt_factory) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("alt_config", &alt_config, params())) return -EINVAL; if(!config.get_blob_or_string("reject_value", &reject_value)) return -EINVAL; /* the reject value must exist, because nonexistent values * can get pruned out if the shadow does not require them */ if(!reject_value.exists()) return -EINVAL; excp_dfd = openat(dfd, file, O_RDONLY); if(excp_dfd < 0) return excp_dfd; base = base_factory->open(excp_dfd, "base", base_config, sysj); if(!base) goto fail_base; alt = alt_factory->open(excp_dfd, "alt", alt_config, sysj); if(!alt) goto fail_alt; ktype = base->key_type(); if(ktype != alt->key_type()) goto fail_ktype; cmp_name = base->get_cmp_name(); close(excp_dfd); return 0; fail_ktype: alt->destroy(); alt = NULL; fail_alt: base->destroy(); base = NULL; fail_base: close(excp_dfd); return -1; }
wrapper(size_t n, params prm = params(), const backend_params &bprm = backend_params(), const InnerProduct &inner_product = InnerProduct() ) : s(prm.get("type", runtime::solver::bicgstab)), handle(0) { if (!prm.erase("type")) AMGCL_PARAM_MISSING("type"); switch(s) { #define AMGCL_RUNTIME_SOLVER(type) \ case type: \ handle = static_cast<void*>(new amgcl::solver::type<Backend, InnerProduct>(n, prm, bprm, inner_product)); \ break AMGCL_RUNTIME_SOLVER(cg); AMGCL_RUNTIME_SOLVER(bicgstab); AMGCL_RUNTIME_SOLVER(bicgstabl); AMGCL_RUNTIME_SOLVER(gmres); AMGCL_RUNTIME_SOLVER(lgmres); AMGCL_RUNTIME_SOLVER(fgmres); AMGCL_RUNTIME_SOLVER(idrs); #undef AMGCL_RUNTIME_SOLVER default: throw std::invalid_argument("Unsupported solver type"); } }
int btree_dtable::init(int dfd, const char * file, const params & config, sys_journal * sysj) { const dtable_factory * factory; params base_config; int r, bt_dfd; if(base) deinit(); factory = dtable_factory::lookup(config, "base"); if(!factory) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!factory->indexed_access(base_config)) return -ENOSYS; bt_dfd = openat(dfd, file, O_RDONLY); if(bt_dfd < 0) return bt_dfd; base = factory->open(bt_dfd, "base", base_config, sysj); if(!base) goto fail_base; ktype = base->key_type(); assert(ktype == dtype::UINT32); cmp_name = base->get_cmp_name(); /* open the btree */ btree = rofile::open<BTREE_PAGE_KB, 8>(bt_dfd, "btree"); if(!btree) goto fail_open; r = btree->read_type(0, &header); if(r < 0) goto fail_format; /* check the header */ if(header.magic != BTREE_DTABLE_MAGIC || header.version != BTREE_DTABLE_VERSION) goto fail_format; if(header.page_size != BTREE_PAGE_SIZE || header.pageno_size != BTREE_PAGENO_SIZE) goto fail_format; if(header.key_size != BTREE_KEY_SIZE || header.index_size != BTREE_INDEX_SIZE) goto fail_format; /* 1 -> uint32, and even with an empty table there will be a root page */ if(header.key_type != 1 || !header.root_page) goto fail_format; close(bt_dfd); return 0; fail_format: delete btree; fail_open: base->destroy(); base = NULL; fail_base: close(bt_dfd); return -1; }
int simple_stable::create(int dfd, const char * name, const params & config, dtype::ctype key_type) { int md_dfd, r; params meta_config, data_config; const dtable_factory * meta = dtable_factory::lookup(config, "meta"); const ctable_factory * data = ctable_factory::lookup(config, "data"); if(!meta || !data) return -ENOENT; if(!config.get("meta_config", &meta_config, params())) return -EINVAL; if(!config.get("data_config", &data_config, params())) return -EINVAL; r = mkdirat(dfd, name, 0755); if(r < 0) return r; md_dfd = openat(dfd, name, O_RDONLY); if(md_dfd < 0) { r = md_dfd; goto fail_open; } /* the metadata is keyed by named properties (strings) */ r = meta->create(md_dfd, "st_meta", meta_config, dtype::STRING); if(r < 0) goto fail_meta; r = data->create(md_dfd, "st_data", data_config, key_type); if(r < 0) goto fail_data; close(md_dfd); return 0; fail_data: util::rm_r(md_dfd, "st_meta"); fail_meta: close(md_dfd); fail_open: unlinkat(dfd, name, AT_REMOVEDIR); return r; }
int simple_stable::init(int dfd, const char * name, const params & config, sys_journal * sysj) { int r = -1; params meta_config, data_config; const dtable_factory * meta = dtable_factory::lookup(config, "meta"); const ctable_factory * data = ctable_factory::lookup(config, "data"); if(md_dfd >= 0) deinit(); assert(column_map.empty()); if(!meta || !data) return -ENOENT; if(!config.get("meta_config", &meta_config, params())) return -EINVAL; if(!config.get("data_config", &data_config, params())) return -EINVAL; md_dfd = openat(dfd, name, O_RDONLY); if(md_dfd < 0) return md_dfd; dt_meta = meta->open(md_dfd, "st_meta", meta_config, sysj); if(!dt_meta) goto fail_meta; ct_data = data->open(md_dfd, "st_data", data_config, sysj); if(!ct_data) goto fail_data; /* check sanity? */ r = load_columns(); if(r < 0) goto fail_check; return 0; fail_check: delete ct_data; fail_data: dt_meta->destroy(); fail_meta: close(md_dfd); md_dfd = -1; return r; }
preconditioner( const Matrix &A, params prm = params(), const backend_params &bprm = backend_params()) : _class(prm.get("class", runtime::precond_class::amg)), handle(0) { if (!prm.erase("class")) AMGCL_PARAM_MISSING("class"); switch(_class) { case precond_class::amg: { typedef runtime::amg<Backend> Precond; handle = static_cast<void*>(new Precond(A, prm, bprm)); } break; case precond_class::relaxation: { typedef runtime::relaxation::as_preconditioner<Backend> Precond; handle = static_cast<void*>(new Precond(A, prm, bprm)); } break; case precond_class::dummy: { typedef amgcl::preconditioner::dummy<Backend> Precond; handle = static_cast<void*>(new Precond(A, prm, bprm)); } break; case precond_class::nested: { typedef make_solver< preconditioner, runtime::iterative_solver<Backend> > Precond; handle = static_cast<void*>(new Precond(A, prm, bprm)); } break; default: throw std::invalid_argument("Unsupported preconditioner class"); } }
int cache_dtable::init(int dfd, const char * file, const params & config, sys_journal * sysj) { int r; const dtable_factory * factory; params base_config; if(base) deinit(); if(!config.get("cache_size", &r, 0) || r < 0) return -EINVAL; cache_size = r; factory = dtable_factory::lookup(config, "base"); if(!factory) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; base = factory->open(dfd, file, base_config, sysj); if(!base) return -1; ktype = base->key_type(); cmp_name = base->get_cmp_name(); return 0; }
int btree_dtable::create(int dfd, const char * file, const params & config, dtable::iter * source, const ktable * shadow) { int bt_dfd, r; params base_config; dtable * base_dtable; const dtable_factory * base = dtable_factory::lookup(config, "base"); if(!base) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!base->indexed_access(base_config)) return -ENOSYS; if(!source_shadow_ok(source, shadow)) return -EINVAL; r = mkdirat(dfd, file, 0755); if(r < 0) return r; bt_dfd = openat(dfd, file, O_RDONLY); if(bt_dfd < 0) goto fail_open; r = base->create(bt_dfd, "base", base_config, source, shadow); if(r < 0) goto fail_create; base_dtable = base->open(bt_dfd, "base", base_config, NULL); if(!base_dtable) goto fail_reopen; r = write_btree(bt_dfd, "btree", base_dtable); if(r < 0) goto fail_write; base_dtable->destroy(); close(bt_dfd); return 0; fail_write: base_dtable->destroy(); fail_reopen: util::rm_r(bt_dfd, "base"); fail_create: close(bt_dfd); fail_open: unlinkat(dfd, file, AT_REMOVEDIR); return (r < 0) ? r : -1; }
wrapper(const amgcl::mpi::distributed_matrix<Backend> &A, params prm, const backend_params &bprm = backend_params()) : r(prm.get("type", runtime::relaxation::spai0)), handle(0) { if (!prm.erase("type")) AMGCL_PARAM_MISSING("type"); switch(r) { #define AMGCL_RELAX_DISTR(type) \ case runtime::relaxation::type: \ handle = static_cast<void*>(new amgcl::mpi::relaxation::type<Backend>(A, prm, bprm)); \ break #define AMGCL_RELAX_LOCAL_DISTR(type) \ case runtime::relaxation::type: \ handle = call_constructor<amgcl::relaxation::type>(A, prm, bprm); \ break; #define AMGCL_RELAX_LOCAL_LOCAL(type) \ case runtime::relaxation::type: \ handle = call_constructor<amgcl::relaxation::type>(*A.local(), prm, bprm); \ break; AMGCL_RELAX_DISTR(spai0); AMGCL_RELAX_LOCAL_DISTR(chebyshev); AMGCL_RELAX_LOCAL_LOCAL(damped_jacobi); AMGCL_RELAX_LOCAL_LOCAL(ilu0); AMGCL_RELAX_LOCAL_LOCAL(iluk); AMGCL_RELAX_LOCAL_LOCAL(ilut); AMGCL_RELAX_LOCAL_LOCAL(spai1); AMGCL_RELAX_LOCAL_LOCAL(gauss_seidel); #undef AMGCL_RELAX_LOCAL_LOCAL #undef AMGCL_RELAX_LOCAL_DISTR #undef AMGCL_RELAX_DISTR default: throw std::invalid_argument("Unsupported relaxation type"); } }
int simple_ctable::create(int dfd, const char * file, const params & config, dtype::ctype key_type) { int ct_dfd, columns, r; params base_config; std::set<istr, strcmp_less> names; ctable_header meta; rwfile meta_file; const dtable_factory * base = dtable_factory::lookup(config, "base"); if(!base) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("columns", &columns, 0)) return -EINVAL; if(columns < 1) return -EINVAL; /* check that we have all the names */ for(int i = 0; i < columns; i++) { char string[32]; istr column_name; sprintf(string, "column%d_name", i); if(!config.get(string, &column_name) || !column_name) return -EINVAL; if(names.count(column_name)) return -EEXIST; names.insert(column_name); } names.clear(); r = mkdirat(dfd, file, 0755); if(r < 0) return r; ct_dfd = openat(dfd, file, O_RDONLY); if(ct_dfd < 0) goto fail_open; meta.magic = SIMPLE_CTABLE_MAGIC; meta.version = SIMPLE_CTABLE_VERSION; meta.columns = columns; r = meta_file.create(ct_dfd, "sct_meta"); if(r < 0) goto fail_meta; r = meta_file.append(&meta); if(r < 0) goto fail_create; /* record column names */ for(int i = 0; i < columns; i++) { uint32_t length; char string[32]; istr column_name; sprintf(string, "column%d_name", i); r = config.get(string, &column_name); assert(r && column_name); length = column_name.length(); r = meta_file.append(&length); if(r < 0) goto fail_create; r = meta_file.append(column_name); if(r < 0) goto fail_create; } r = base->create(ct_dfd, "base", base_config, key_type); if(r < 0) goto fail_create; meta_file.close(); close(ct_dfd); return 0; fail_create: meta_file.close(); unlinkat(dfd, "sct_meta", 0); fail_meta: close(ct_dfd); fail_open: unlinkat(dfd, file, AT_REMOVEDIR); return -1; }
int simple_ctable::init(int dfd, const char * file, const params & config, sys_journal * sysj) { const dtable_factory * factory; params base_config; int ct_dfd, r; off_t offset; ctable_header meta; rofile * meta_file; if(base) deinit(); factory = dtable_factory::lookup(config, "base"); if(!factory) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; ct_dfd = openat(dfd, file, O_RDONLY); if(ct_dfd < 0) return ct_dfd; meta_file = rofile::open<4, 2>(ct_dfd, "sct_meta"); if(!meta_file) goto fail_open; r = meta_file->read_type(0, &meta); if(r < 0) goto fail_header; if(meta.magic != SIMPLE_CTABLE_MAGIC || meta.version != SIMPLE_CTABLE_VERSION) goto fail_header; column_count = meta.columns; column_name = new istr[column_count]; if(!column_name) goto fail_header; offset = sizeof(meta); for(size_t i = 0; i < column_count; i++) { uint32_t length; r = meta_file->read_type(offset, &length); if(r < 0) goto fail_names; offset += sizeof(length); column_name[i] = meta_file->read_string(offset, length); if(!column_name[i]) goto fail_names; offset += length; column_map[column_name[i]] = i; } base = factory->open(ct_dfd, "base", base_config, sysj); if(!base) goto fail_names; ktype = base->key_type(); cmp_name = base->get_cmp_name(); delete meta_file; close(ct_dfd); return 0; fail_names: column_map.empty(); delete[] column_name; fail_header: delete meta_file; fail_open: close(ct_dfd); return -1; }
int keydiv_dtable::create(int dfd, const char * name, const params & config, dtype::ctype key_type) { int r, kdd_dfd, meta; divider_list dividers; const dtable_factory * base; params base_config; kddtable_header header; header.magic = KDDTABLE_MAGIC; header.version = KDDTABLE_VERSION; switch(key_type) { case dtype::UINT32: header.key_type = 1; r = load_dividers<int, uint32_t>(config, 0, ÷rs); break; case dtype::DOUBLE: header.key_type = 2; r = load_dividers<float, double>(config, 0, ÷rs); break; case dtype::STRING: header.key_type = 3; r = load_dividers<istr, istr>(config, 0, ÷rs); break; case dtype::BLOB: header.key_type = 4; r = load_dividers<blob, blob>(config, 0, ÷rs, true); break; default: return -EINVAL; } header.dt_count = dividers.size() + 1; /* make sure we don't overflow the header field */ if(header.dt_count != dividers.size() + 1) return -EINVAL; base = dtable_factory::lookup(config, "base"); if(!base) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; r = mkdirat(dfd, name, 0755); if(r < 0) return r; kdd_dfd = openat(dfd, name, O_RDONLY); if(kdd_dfd < 0) { unlinkat(dfd, name, AT_REMOVEDIR); return kdd_dfd; } for(uint32_t i = 0; i < header.dt_count; i++) { char name[32]; sprintf(name, "kdd_data.%u", i); r = base->create(kdd_dfd, name, base_config, key_type); if(r < 0) goto fail; } meta = openat(kdd_dfd, "kdd_meta", O_WRONLY | O_CREAT, 0644); if(meta < 0) { r = meta; goto fail; } r = pwrite(meta, &header, sizeof(header), 0); close(meta); if(r != sizeof(header)) goto fail; close(kdd_dfd); return 0; fail: close(kdd_dfd); util::rm_r(dfd, name); return (r < 0) ? r : -1; }
int keydiv_dtable::init(int dfd, const char * name, const params & config, sys_journal * sysj) { abortable_tx atx; int r, kdd_dfd, meta; const dtable_factory * base; params base_config; if(sub.size() >= 0) deinit(); base = dtable_factory::lookup(config, "base"); if(!base) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; kdd_dfd = openat(dfd, name, O_RDONLY); if(kdd_dfd < 0) return kdd_dfd; meta = openat(kdd_dfd, "kdd_meta", O_RDONLY); if(meta < 0) goto fail_meta; if(pread(meta, &header, sizeof(header), 0) != sizeof(header)) { close(meta); goto fail_meta; } close(meta); if(header.magic != KDDTABLE_MAGIC || header.version != KDDTABLE_VERSION) goto fail_meta; if(!header.dt_count) goto fail_meta; switch(header.key_type) { case 1: ktype = dtype::UINT32; r = load_dividers<int, uint32_t>(config, header.dt_count, ÷rs); break; case 2: ktype = dtype::DOUBLE; r = load_dividers<float, double>(config, header.dt_count, ÷rs); break; case 3: ktype = dtype::STRING; r = load_dividers<istr, istr>(config, header.dt_count, ÷rs); break; case 4: ktype = dtype::BLOB; r = load_dividers<blob, blob>(config, header.dt_count, ÷rs, true); break; default: goto fail_meta; } if(r < 0) goto fail_meta; for(uint32_t i = 0; i < header.dt_count; i++) { char name[32]; dtable * source; sprintf(name, "kdd_data.%u", i); source = base->open(kdd_dfd, name, base_config, sysj); if(!source) goto fail_sub; sub.push_back(source); } if(sub[0]->get_cmp_name()) cmp_name = sub[0]->get_cmp_name(); /* check for abortable transaction support */ atx = sub[0]->create_tx(); if((support_atx = (atx != NO_ABORTABLE_TX))) sub[0]->abort_tx(atx); return 0; fail_sub: for(size_t i = 0; i < sub.size(); i++) sub[i]->destroy(); fail_meta: sub.clear(); dividers.clear(); close(kdd_dfd); return -1; }
int deltaint_dtable::create(int dfd, const char * file, const params & config, dtable::iter * source, const ktable * shadow) { int r, di_dfd, skip; rev_iter_delta * rev; rev_iter_ref * ref; params base_config, ref_config; const dtable_factory * base = dtable_factory::lookup(config, "base"); const dtable_factory * reference = dtable_factory::lookup(config, "ref"); if(!base || !reference) return -ENOENT; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("ref_config", &ref_config, params())) return -EINVAL; if(!config.get("skip", &skip, 0) || skip < 2) return -EINVAL; if(!source_shadow_ok(source, shadow)) return -EINVAL; r = mkdirat(dfd, file, 0755); if(r < 0) return r; di_dfd = openat(dfd, file, O_RDONLY); if(di_dfd < 0) goto fail_open; rev = new rev_iter_delta(source); if(!rev) { r = -ENOMEM; goto fail_iter_1; } r = base->create(di_dfd, "base", base_config, rev, shadow); if(r < 0) goto fail_create_1; if(rev->failed) { r = -ENOSYS; goto fail_iter_2; } ref = new rev_iter_ref(source, skip); if(!ref) { r = -ENOMEM; goto fail_iter_2; } r = reference->create(di_dfd, "ref", ref_config, ref, NULL); if(r < 0) goto fail_create_2; delete ref; delete rev; close(di_dfd); return r; fail_create_2: delete ref; fail_iter_2: util::rm_r(di_dfd, "base"); fail_create_1: delete rev; fail_iter_1: close(di_dfd); fail_open: unlinkat(dfd, file, AT_REMOVEDIR); return (r < 0) ? r : -1; }
int exception_dtable::create(int dfd, const char * file, const params & config, dtable::iter * source, const ktable * shadow) { int excp_dfd, r; memory_dtable alt_mdt; reject_iter * handler; params base_config, alt_config; blob reject_value; const dtable_factory * base = dtable_factory::lookup(config, "base"); const dtable_factory * alt = dtable_factory::lookup(config, "alt"); if(!base || !alt) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("alt_config", &alt_config, params())) return -EINVAL; if(!config.get_blob_or_string("reject_value", &reject_value)) return -EINVAL; /* the reject value must exist, because nonexistent values * can get pruned out if the shadow does not require them */ if(!reject_value.exists()) return -EINVAL; if(!source_shadow_ok(source, shadow)) return -EINVAL; r = mkdirat(dfd, file, 0755); if(r < 0) return r; excp_dfd = openat(dfd, file, O_RDONLY); if(excp_dfd < 0) goto fail_open; /* we should really save the reject_value in a meta file here */ /* we'll always be appending, but it's faster if we say false here */ r = alt_mdt.init(source->key_type(), false, true); if(r < 0) goto fail_mdt; if(source->get_blob_cmp()) alt_mdt.set_blob_cmp(source->get_blob_cmp()); handler = new reject_iter(source, &alt_mdt, reject_value); if(!handler) goto fail_mdt; r = base->create(excp_dfd, "base", base_config, handler, shadow); if(r < 0) goto fail_base; /* no shadow - this only has exceptions */ r = alt->create(excp_dfd, "alt", alt_config, &alt_mdt, NULL); if(r < 0) goto fail_alt; delete handler; close(excp_dfd); return 0; fail_alt: util::rm_r(excp_dfd, "base"); fail_base: delete handler; fail_mdt: close(excp_dfd); fail_open: unlinkat(dfd, file, AT_REMOVEDIR); return -1; }