/* * NAME: hfs->rmdir() * DESCRIPTION: delete an empty directory */ int hfs_rmdir(hfsvol *vol, char *path) { CatKeyRec key; CatDataRec data; long parid; char name[HFS_MAX_FLEN + 1]; unsigned char pkey[HFS_CATKEYLEN]; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &data, &parid, name, 0) <= 0) return -1; if (data.cdrType != cdrDirRec) { ERROR(ENOTDIR, 0); return -1; } if (data.u.dir.dirVal != 0) { ERROR(ENOTEMPTY, 0); return -1; } if (parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* delete directory record */ r_makecatkey(&key, parid, name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0) return -1; /* delete thread record */ r_makecatkey(&key, data.u.dir.dirDirID, (char *)""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0 || v_adjvalence(vol, parid, 1, -1) < 0) return -1; return 0; }
void bt_delete(TreeNode * root) { if (NULL == root) { // Nothing to delete. return; } // Delete the left subtree. bt_delete(root->left); // Delete the right subtree. bt_delete(root->right); // Delete the root node. delete root; }
/* * A sample driver */ int DoData(Btree *bt, char *buffer, int mode) { UR ur; char *s; s = strchr(buffer, ';'); if (!s) { if (mode == 0) s = ""; /* don't need address for deletes */ else return TREE_FAIL; /* trying to add partial data */ } else *s++ = '\0'; strncpy(ur.key, buffer, 10); /* key is first 10 characters */ ur.key[10] = '\0'; strncpy(ur.name, buffer, 24); ur.name[24] = '\0'; strncpy(ur.addr, s, 24); ur.addr[24] = '\0'; if (mode == 0) return bt_delete(bt, ur.key); else return bt_add(bt, &ur, ur.key); }
/* * NAME: hfs->rmdir() * DESCRIPTION: delete an empty directory */ int hfs_rmdir(hfsvol *vol, const char *path) { CatKeyRec key; CatDataRec data; unsigned long parid; char name[HFS_MAX_FLEN + 1]; byte pkey[HFS_CATKEYLEN]; if (getvol(&vol) == -1 || v_resolve(&vol, path, &data, &parid, name, 0) <= 0) goto fail; if (data.cdrType != cdrDirRec) ERROR(ENOTDIR, 0); if (data.u.dir.dirVal != 0) ERROR(ENOTEMPTY, 0); if (parid == HFS_CNID_ROOTPAR) ERROR(EINVAL, 0); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* delete directory record */ r_makecatkey(&key, parid, name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1) goto fail; /* delete thread record */ r_makecatkey(&key, data.u.dir.dirDirID, ""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1 || v_adjvalence(vol, parid, 1, -1) == -1) goto fail; return 0; fail: return -1; }
// ----------------------------------------------------------------------------- //virtual bool Solution::Test() { bool pass = true; { int nodes[] = { }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); root = invertTree(root); std::vector<int> v; bt_traverse(root, BT_TRAV_IN, v); pass = pass && v.empty(); bt_delete(root); } { int nodes[] = { '1' }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); root = invertTree(root); std::vector<int> v; bt_traverse(root, BT_TRAV_IN, v); pass = pass && (v.size() == 1) && (v[0] == '1'); bt_delete(root); } { int nodes[] = { '1', '2' }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); root = invertTree(root); std::vector<int> v; bt_traverse(root, BT_TRAV_IN, v); pass = pass && (v.size() == 2) && (v[0] == '1') && (v[1] == '2'); bt_delete(root); } { int nodes[] = { '1', '2', '3' }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); root = invertTree(root); std::vector<int> v; bt_traverse(root, BT_TRAV_IN, v); pass = pass && (v.size() == 3) && (v[0] == '3') && (v[1] == '1') && (v[2] == '2'); bt_delete(root); } return pass; }
/* Moves P around in BT to compensate for its key having changed. Returns a null pointer if successful. If P's new value is equal to that of some other node in BT, returns the other node after removing P from BT. This function is an optimization only if it is likely that P can actually retain its relative position in BT, e.g. its key has only been adjusted slightly. Otherwise, it is more efficient to simply remove P from BT, change its key, and re-insert P. It is not safe to update more than one node's key, then to call this function for each node. Instead, update a single node's key, call this function, update another node's key, and so on. Alternatively, remove all affected nodes from the tree, update their keys, then re-insert all of them. */ struct bt_node * bt_changed (struct bt *bt, struct bt_node *p) { struct bt_node *prev = bt_prev (bt, p); struct bt_node *next = bt_next (bt, p); if ((prev != NULL && bt->compare (prev, p, bt->aux) >= 0) || (next != NULL && bt->compare (p, next, bt->aux) >= 0)) { bt_delete (bt, p); return bt_insert (bt, p); } return NULL; }
// ----------------------------------------------------------------------------- //virtual bool Solution::Test() { bool pass = true; { int nodes[] = { }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); std::vector< std::vector<int> > result = levelOrderBottom(root); pass = pass && result.empty(); bt_delete(root); } { int nodes[] = { 1 }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); std::vector< std::vector<int> > result = levelOrderBottom(root); pass = pass && (result.size() == 1) && (result[0].size() == 1) && (result[0][0] == 1) ; bt_delete(root); } { int nodes[] = { 3, 9, 20, '#', '#', 15, 7 }; BTNode<int> * root = bt_create(nodes, sizeof(nodes) / sizeof(int)); std::vector< std::vector<int> > v = levelOrderBottom(root); pass = pass && (v.size() == 3) && (v[0].size() == 2) && (v[0][0] == 15) && (v[0][1] == 7) && (v[1].size() == 2) && (v[1][0] == 9) && (v[1][1] == 20) && (v[2].size() == 1) && (v[2][0] == 3) ; bt_delete(root); } return pass; }
int main(int argc, char * argv[]) { bool pass = true; { const int N = 15; int nodes[] = { 15, 6, 18, 3, 7, 17, 20, 2, 4, '#', 13, '#', '#', '#', '#' }; TreeNode * root = bt_create(nodes, N, 0, '#'); TreeNode * node15 = root; pass = pass && (bst_find_successor(node15)->value == 17); TreeNode * node13 = root->left->right->right; pass = pass && (bst_find_successor(node13)->value == 15); TreeNode * node20 = root->right->right; pass = pass && (bst_find_successor(node20) == NULL); bt_delete(root); } return (pass ? 0 : -1); }
int main(int argc, char** argv) { if (argc < (INPUT_ARG + 1)) { printf("***Missing input argument\n"); return EXIT_FAILURE; } FILE* file = fopen(argv[INPUT_ARG], FILE_READ_ONLY); if (!file) { printf("***File \"%s\" could not be found\n", argv[INPUT_ARG]); fclose(file); return EXIT_FAILURE; } linked_list* in_order_list = build_list_from_file(file, false); linked_list* post_order_list = build_list_from_file(file, true); if (in_order_list->size != post_order_list->size || in_order_list->size == 0 || post_order_list->size == 0) { ll_delete(in_order_list); ll_delete(post_order_list); fclose(file); printf("***the length of the inorder and post order traversal" " in the input must be nonzero and equal."); return EXIT_FAILURE; } printf("inorder: "); ll_print(in_order_list); printf("postorder: "); ll_print(post_order_list); binary_tree* btree = new_binary_tree(in_order_list, post_order_list); bt_print(btree); fclose(file); ll_delete(in_order_list); free(in_order_list); ll_delete(post_order_list); free(post_order_list); bt_delete(btree); free(btree); return EXIT_SUCCESS; }
/* * NAME: file->trunc() * DESCRIPTION: release allocation blocks unneeded by a file */ int f_trunc(hfsfile *file) { hfsvol *vol = file->vol; ExtDataRec *extrec; ULongInt *lglen, *pylen, alblksz, newpylen; unsigned int dlen, start, end; node n; int i; if (vol->flags & HFS_VOL_READONLY) goto done; f_getptrs(file, &extrec, &lglen, &pylen); alblksz = vol->mdb.drAlBlkSiz; newpylen = (*lglen / alblksz + (*lglen % alblksz != 0)) * alblksz; if (newpylen > *pylen) ERROR(EIO, "file size exceeds physical length"); else if (newpylen == *pylen) goto done; dlen = (*pylen - newpylen) / alblksz; start = file->fabn; end = newpylen / alblksz; if (start >= end) { start = file->fabn = 0; memcpy(&file->ext, extrec, sizeof(ExtDataRec)); } n.nnum = 0; i = -1; while (start < end) { for (i = 0; i < 3; ++i) { unsigned int num; num = file->ext[i].xdrNumABlks; start += num; if (start >= end) break; else if (num == 0) ERROR(EIO, "empty file extent"); } if (start >= end) break; if (v_extsearch(file, start, &file->ext, &n) <= 0) goto fail; file->fabn = start; } if (start > end) { ExtDescriptor blocks; file->ext[i].xdrNumABlks -= start - end; dlen -= start - end; blocks.xdrStABN = file->ext[i].xdrStABN + file->ext[i].xdrNumABlks; blocks.xdrNumABlks = start - end; if (v_freeblocks(vol, &blocks) == -1) goto fail; } *pylen = newpylen; file->flags |= HFS_FILE_UPDATE_CATREC; do { while (dlen && ++i < 3) { unsigned int num; num = file->ext[i].xdrNumABlks; start += num; if (num == 0) ERROR(EIO, "empty file extent"); else if (num > dlen) ERROR(EIO, "file extents exceed physical size"); dlen -= num; if (v_freeblocks(vol, &file->ext[i]) == -1) goto fail; file->ext[i].xdrStABN = 0; file->ext[i].xdrNumABlks = 0; } if (file->fabn) { if (n.nnum == 0 && v_extsearch(file, file->fabn, 0, &n) <= 0) goto fail; if (file->ext[0].xdrNumABlks) { if (v_putextrec(&file->ext, &n) == -1) goto fail; } else { if (bt_delete(&vol->ext, HFS_NODEREC(n, n.rnum)) == -1) goto fail; n.nnum = 0; } } else memcpy(extrec, &file->ext, sizeof(ExtDataRec)); if (dlen) { if (v_extsearch(file, start, &file->ext, &n) <= 0) goto fail; file->fabn = start; i = -1; } } while (dlen); done: return 0; fail: return -1; }
int ark_create_verbose(char *path, ARK **arkret, uint64_t size, uint64_t bsize, uint64_t hcount, int nthrds, int nqueue, int basyncs, uint64_t flags) { int rc = 0; int p_rc = 0; uint64_t bcount = 0; uint64_t x = 0; int i = 0; int tnum = 0; int rnum = 0; scb_t *scbp = NULL; KV_TRC_OPEN(pAT, "arkdb"); if (NULL == arkret) { KV_TRC_FFDC(pAT, "Incorrect value for ARK control block: rc=EINVAL"); rc = EINVAL; goto ark_create_ark_err; } if ( (flags & (ARK_KV_PERSIST_LOAD|ARK_KV_PERSIST_STORE)) && (flags & ARK_KV_VIRTUAL_LUN) ) { KV_TRC_FFDC(pAT, "Invalid persistence combination with ARK flags: %016lx", flags); rc = EINVAL; goto ark_create_ark_err; } if (nthrds <= 0) { KV_TRC_FFDC(pAT, "invalid nthrds:%d", nthrds); rc = EINVAL; goto ark_create_ark_err; } _ARK *ark = am_malloc(sizeof(_ARK)); if (ark == NULL) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocating ARK control structure for %ld", sizeof(_ARK)); goto ark_create_ark_err; } KV_TRC(pAT, "%p path(%s) size %ld bsize %ld hcount %ld " "nthrds %d nqueue %d basyncs %d flags:%08lx", ark, path, size, bsize, hcount, nthrds, nqueue, basyncs, flags); ark->bsize = bsize; ark->rthread = 0; ark->persload = 0; ark->nasyncs = ((nqueue <= 0) ? ARK_MAX_ASYNC_OPS : nqueue); ark->basyncs = basyncs; ark->ntasks = ARK_MAX_TASK_OPS; ark->nthrds = ARK_VERBOSE_NTHRDS_DEF; // hardcode, perf requirement // Create the KV storage, whether that will be memory based // or flash ark->ea = ea_new(path, ark->bsize, basyncs, &size, &bcount, (flags & ARK_KV_VIRTUAL_LUN)); if (ark->ea == NULL) { if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;} rc = errno; KV_TRC_FFDC(pAT, "KV storage initialization failed: rc/errno:%d", rc); goto ark_create_ea_err; } // Now that the "connection" to the store has been established // we need to check to see if data was persisted from a previous // instantiation of the KV store. p_rc = ark_check_persistence(ark, flags); if (p_rc > 0) { // We ran into an error while trying to read from // the store. rc = p_rc; KV_TRC_FFDC(pAT, "Persistence check failed: %d", rc); goto ark_create_persist_err; } else if (p_rc == -1) { KV_TRC(pAT, "NO PERSIST LOAD FLAG"); // There was no persistence data, so we just build off // of what was passed into the API. ark->size = size; ark->bcount = bcount; ark->hcount = hcount; ark->vlimit = ARK_VERBOSE_VLIMIT_DEF; ark->blkbits = ARK_VERBOSE_BLKBITS_DEF; ark->grow = ARK_VERBOSE_GROW_DEF; ark->rthread = 0; ark->flags = flags; ark->astart = 0; ark->blkused = 1; ark->ark_exit = 0; ark->nactive = 0; ark->pers_stats.kv_cnt = 0; ark->pers_stats.blk_cnt = 0; ark->pers_stats.byte_cnt = 0; ark->pcmd = PT_IDLE; // Create the requests and tag control blocks and queues. x = ark->hcount / ark->nthrds; ark->npart = x + (ark->hcount % ark->nthrds ? 1 : 0); // Create the hash table ark->ht = hash_new(ark->hcount); if (ark->ht == NULL) { if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;} rc = errno; KV_TRC_FFDC(pAT, "Hash initialization failed: %d", rc); goto ark_create_ht_err; } // Create the block list ark->bl = bl_new(ark->bcount, ark->blkbits); if (ark->bl == NULL) { if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;} rc = errno; KV_TRC_FFDC(pAT, "Block list initialization failed: %d", rc); goto ark_create_bl_err; } if (flags & ARK_KV_PERSIST_STORE) { ark_persistence_calc(ark); if (bl_reserve(ark->bl, ark->pers_max_blocks)) {goto ark_create_bl_err;} } } else { KV_TRC(pAT, "PERSIST: %p path(%s) size %ld bsize %ld hcount %ld " "nthrds %d nqueue %ld basyncs %d bcount %ld blkbits %ld", ark, path, ark->size, ark->bsize, ark->hcount, ark->nthrds, ark->nasyncs, ark->basyncs, ark->bcount, ark->blkbits); } rc = pthread_mutex_init(&ark->mainmutex,NULL); if (rc != 0) { KV_TRC_FFDC(pAT, "pthread_mutex_init for main mutex failed: %d", rc); goto ark_create_pth_mutex_err; } ark->rtags = tag_new(ark->nasyncs); if ( NULL == ark->rtags ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Tag initialization for requests failed: %d", rc); goto ark_create_rtag_err; } ark->ttags = tag_new(ark->ntasks); if ( NULL == ark->ttags ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Tag initialization for tasks failed: %d", rc); goto ark_create_ttag_err; } ark->rcbs = am_malloc(ark->nasyncs * sizeof(rcb_t)); if ( NULL == ark->rcbs ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for request control blocks", (ark->nasyncs * sizeof(rcb_t))); goto ark_create_rcbs_err; } ark->tcbs = am_malloc(ark->ntasks * sizeof(tcb_t)); if ( NULL == ark->tcbs ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for task control blocks", (ark->ntasks * sizeof(rcb_t))); goto ark_create_tcbs_err; } ark->iocbs = am_malloc(ark->ntasks * sizeof(iocb_t)); if ( NULL == ark->iocbs ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for io control blocks", (ark->ntasks * sizeof(iocb_t))); goto ark_create_iocbs_err; } ark->poolthreads = am_malloc(ark->nthrds * sizeof(scb_t)); if ( NULL == ark->poolthreads ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for server thread control blocks", (ark->nthrds * sizeof(scb_t))); goto ark_create_poolthreads_err; } for ( rnum = 0; rnum < ark->nasyncs ; rnum++ ) { ark->rcbs[rnum].stat = A_NULL; pthread_cond_init(&(ark->rcbs[rnum].acond), NULL); pthread_mutex_init(&(ark->rcbs[rnum].alock), NULL); } for ( tnum = 0; tnum < ark->ntasks; tnum++ ) { ark->tcbs[tnum].inb = bt_new(0, ark->vlimit, sizeof(uint64_t), &(ark->tcbs[tnum].inblen), &(ark->tcbs[tnum].inb_orig)); if (ark->tcbs[tnum].inb == NULL) { if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;} rc = errno; KV_TRC_FFDC(pAT, "Bucket allocation for inbuffer failed: %d", rc); goto ark_create_taskloop_err; } ark->tcbs[tnum].oub = bt_new(0, ark->vlimit, sizeof(uint64_t), &(ark->tcbs[tnum].oublen), &(ark->tcbs[tnum].oub_orig)); if (ark->tcbs[tnum].oub == NULL) { if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;} rc = errno; KV_TRC_FFDC(pAT, "Bucket allocation for outbuffer failed: %d", rc); goto ark_create_taskloop_err; } //ark->tcbs[tnum].vbsize = bsize * 1024; ark->tcbs[tnum].vbsize = bsize * 256; ark->tcbs[tnum].vb_orig = am_malloc(ark->tcbs[tnum].vbsize); if (ark->tcbs[tnum].vb_orig == NULL) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocation for %"PRIu64" bytes for variable size buffer", (bsize * 1024)); goto ark_create_taskloop_err; } ark->tcbs[tnum].vb = ptr_align(ark->tcbs[tnum].vb_orig); } *arkret = (void *)ark; ark->pts = (PT *)am_malloc(sizeof(PT) * ark->nthrds); if ( ark->pts == NULL ) { rc = ENOMEM; KV_TRC_FFDC(pAT, "Out of memory allocation for %"PRIu64" bytes for server thread data", (sizeof(PT) * ark->nthrds)); goto ark_create_taskloop_err; } for (i = 0; i < ark->nthrds; i++) { PT *pt = &(ark->pts[i]); scbp = &(ark->poolthreads[i]); memset(scbp, 0, sizeof(scb_t)); // Start off the random start point for this thread // at -1, to show that it has not been part of a // ark_random call. scbp->rlast = -1; scbp->holds = 0; scbp->poolstate = PT_RUN; scbp->poolstats.io_cnt = 0; scbp->poolstats.ops_cnt = 0; scbp->poolstats.kv_cnt = 0; scbp->poolstats.blk_cnt = 0; scbp->poolstats.byte_cnt = 0; pthread_mutex_init(&(scbp->poolmutex), NULL); pthread_cond_init(&(scbp->poolcond), NULL); scbp->rqueue = queue_new(ark->nasyncs); scbp->tqueue = queue_new(ark->ntasks); scbp->ioqueue = queue_new(ark->ntasks); pt->id = i; pt->ark = ark; rc = pthread_create(&(scbp->pooltid), NULL, pool_function, pt); if (rc != 0) { KV_TRC_FFDC(pAT, "pthread_create of server thread failed: %d", rc); goto ark_create_poolloop_err; } } #if 0 while (ark->nactive < ark->nthrds) { usleep(1); //printf("Create waiting %d/%d\n", ark->nactive, ark->nthrds); } #endif ark->pcmd = PT_RUN; goto ark_create_return; ark_create_poolloop_err: for (; i >= 0; i--) { scbp = &(ark->poolthreads[i]); if (scbp->pooltid != 0) { queue_lock(scbp->rqueue); queue_wakeup(scbp->rqueue); queue_unlock(scbp->rqueue); pthread_join(scbp->pooltid, NULL); pthread_mutex_destroy(&(scbp->poolmutex)); pthread_cond_destroy(&(scbp->poolcond)); if ( scbp->rqueue != NULL ) { queue_free(scbp->rqueue); } if ( scbp->tqueue != NULL ) { queue_free(scbp->tqueue); } if ( scbp->ioqueue != NULL ) { queue_free(scbp->ioqueue); } } } if ( ark->pts != NULL ) { am_free(ark->pts); } ark_create_taskloop_err: for ( tnum = 0; tnum < ark->ntasks; tnum++ ) { if (ark->tcbs[tnum].inb) { bt_delete(ark->tcbs[tnum].inb); } if (ark->tcbs[tnum].oub) { bt_delete(ark->tcbs[tnum].oub); } if (ark->tcbs[tnum].vb_orig) { am_free(ark->tcbs[tnum].vb_orig); } } for (rnum = 0; rnum < ark->nasyncs; rnum++) { pthread_cond_destroy(&(ark->rcbs[rnum].acond)); pthread_mutex_destroy(&(ark->rcbs[rnum].alock)); } if ( ark->poolthreads != NULL ) { am_free(ark->poolthreads); } ark_create_poolthreads_err: if (ark->iocbs) { am_free(ark->iocbs); } ark_create_iocbs_err: if (ark->tcbs) { am_free(ark->tcbs); } ark_create_tcbs_err: if (ark->rcbs) { am_free(ark->rcbs); } ark_create_rcbs_err: if (ark->ttags) { tag_free(ark->ttags); } ark_create_ttag_err: if (ark->rtags) { tag_free(ark->rtags); } ark_create_rtag_err: pthread_mutex_destroy(&ark->mainmutex); ark_create_pth_mutex_err: bl_delete(ark->bl); ark_create_bl_err: hash_free(ark->ht); ark_create_ht_err: ark_create_persist_err: ea_delete(ark->ea); ark_create_ea_err: am_free(ark); *arkret = NULL; ark_create_ark_err: KV_TRC_CLOSE(pAT); ark_create_return: return rc; }
// ----------------------------------------------------------------------------- //virtual bool Solution::Test() { bool pass = true; { int nodes[] = {}; BTNode<int> * p = bt_create(nodes, sizeof(nodes) / sizeof(int)); BTNode<int> * q = bt_create(nodes, sizeof(nodes) / sizeof(int)); pass = pass && isSameTree(p, q); bt_delete(p); bt_delete(q); } { int nodes[] = {1}; BTNode<int> * p = bt_create(nodes, sizeof(nodes) / sizeof(int)); BTNode<int> * q = bt_create(nodes, sizeof(nodes) / sizeof(int)); pass = pass && isSameTree(p, q); bt_delete(p); bt_delete(q); } { int nodes[] = {1, 2, 3}; BTNode<int> * p = bt_create(nodes, sizeof(nodes) / sizeof(int)); BTNode<int> * q = bt_create(nodes, sizeof(nodes) / sizeof(int)); pass = pass && isSameTree(p, q); bt_delete(p); bt_delete(q); } { int nodes[] = { '1', '2', '3', '#', '#', '4', '#', '#', '#', '#', '#', '#', '5' }; BTNode<int> * p = bt_create(nodes, sizeof(nodes) / sizeof(int)); BTNode<int> * q = bt_create(nodes, sizeof(nodes) / sizeof(int)); pass = pass && isSameTree(p, q); bt_delete(p); bt_delete(q); } { int nodes[] = { '1', '2', '3', '#', '#', '4', '#', '#', '#', '#', '#', '#', '5' }; BTNode<int> * p = bt_create(nodes, sizeof(nodes) / sizeof(int)); BTNode<int> * q = p; pass = pass && isSameTree(p, q); bt_delete(p); } { int nodes1[] = { '1', '2', '3', '#', '#', '4', '#', '#', '#', '#', '#', '#', '5' }; int nodes2[] = { '1', '2', '3', '#', '#', '4', '#', '#', '#', '#', '#', '5', '#' }; BTNode<int> * p = bt_create(nodes1, sizeof(nodes1) / sizeof(int)); BTNode<int> * q = bt_create(nodes2, sizeof(nodes2) / sizeof(int)); pass = pass && !isSameTree(p, q); bt_delete(p); bt_delete(q); } { int nodes1[] = { '1', '2', '3', '#', '#', '4', '#', '#', '#', '#', '#', '#', '5' }; int nodes2[] = { '1', '2', '3', '#', '#', '4', '#', '#', '#', '#', '#', '#', '6' }; BTNode<int> * p = bt_create(nodes1, sizeof(nodes1) / sizeof(int)); BTNode<int> * q = bt_create(nodes2, sizeof(nodes2) / sizeof(int)); pass = pass && !isSameTree(p, q); bt_delete(p); bt_delete(q); } return pass; }
void catalog_before_commit(bool is_commit) { /* * Final journal commit. Done by single transaction at a time */ if (!is_commit) { return; } try { catalog_journal_record *r; xptr *tree; bt_key name; char * htname; catalog_validate_objects(); catalog_lock_metadata(); cs_initp(); r = local_catalog->catalog_journal; while (r != NULL) { switch (r->type) { case catalog_journal_record::add_name: tree = &(CATALOG_NAME_TREE(r->nor.object_type)); name.setnew(r->nor.name_to_save->name); if (*tree == XNULL) { *tree = bt_create(xs_string); } bt_insert(*tree, name, r->nor.name_to_save->obj->p); break; case catalog_journal_record::del_name: tree = &(CATALOG_NAME_TREE(r->nor.object_type)); name.setnew(r->nor.name_to_save->name); bt_delete(*tree, name, r->nor.name_to_save->obj->p); htname = catalog_ht_fullname_string(r->nor.object_type, r->nor.name_to_save->name, NULL); local_catalog->masterdata.htable = sbtrie_delete_str(local_catalog->masterdata.htable, htname); free(htname); break; case catalog_journal_record::add_htable_record: local_catalog->masterdata.htable = sbtrie_insert_str(local_catalog->masterdata.htable, r->htr.name, r->htr.data, strlen(r->htr.data) + 2, true); break; } r = r->next; local_catalog->masterdata_updated = true; } local_catalog->catalog_journal = NULL; if (local_catalog->masterdata_updated) { WRITEP(catalog_masterblock); memcpy( &(((catalog_master_record *) XADDR(catalog_masterblock))->masterdata), &(local_catalog->masterdata), sizeof(catalog_name_trees)); local_catalog->masterdata_updated = false; } if (!tr_globals::is_ro_mode) { WRITEP(catalog_masterblock); memcpy( &(((catalog_master_record *) XADDR(catalog_masterblock))->last_nid_size), &last_nid_size, sizeof(int)); memcpy( ((catalog_master_record *) XADDR(catalog_masterblock))->last_nid, last_nid, last_nid_size); } } catch (ANY_SE_EXCEPTION) { catalog_unlock_metadata(); throw; } }
/* * NAME: hfs->delete() * DESCRIPTION: remove both forks of a file */ int hfs_delete(hfsvol *vol, char *path) { hfsfile file; CatKeyRec key; unsigned char pkey[HFS_CATKEYLEN]; int found; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0) return -1; if (file.cat.cdrType != cdrFilRec) { ERROR(EISDIR, 0); return -1; } if (file.parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* free disk blocks */ file.vol = vol; file.flags = 0; file.cat.u.fil.filLgLen = 0; file.cat.u.fil.filRLgLen = 0; f_selectfork(&file, 0); if (f_trunc(&file) < 0) return -1; f_selectfork(&file, 1); if (f_trunc(&file) < 0) return -1; /* delete file record */ r_makecatkey(&key, file.parid, file.name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0 || v_adjvalence(vol, file.parid, 0, -1) < 0) return -1; /* delete file thread, if any */ found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0); if (found < 0) return -1; if (found) { r_makecatkey(&key, file.cat.u.fil.filFlNum, (char *)""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0) return -1; } return 0; }
int ark_delete(ARK *ark) { int rc = 0; int i = 0; _ARK *_arkp = (_ARK *)ark; scb_t *scbp = NULL; if (NULL == ark) { rc = EINVAL; KV_TRC_FFDC(pAT, "Invalid ARK control block parameter: %d", rc); goto ark_delete_ark_err; } // Wait for all active threads to exit for (i = 0; i < _arkp->nthrds; i++) { scbp = &(_arkp->poolthreads[i]); scbp->poolstate = PT_EXIT; queue_lock(scbp->rqueue); queue_wakeup(scbp->rqueue); queue_unlock(scbp->rqueue); pthread_join(scbp->pooltid, NULL); queue_free(scbp->rqueue); queue_free(scbp->tqueue); queue_free(scbp->ioqueue); pthread_mutex_destroy(&(scbp->poolmutex)); pthread_cond_destroy(&(scbp->poolcond)); KV_TRC(pAT, "thread %d joined", i); } if (_arkp->poolthreads) am_free(_arkp->poolthreads); if (_arkp->pts) am_free(_arkp->pts); for ( i = 0; i < _arkp->nasyncs ; i++ ) { pthread_cond_destroy(&(_arkp->rcbs[i].acond)); pthread_mutex_destroy(&(_arkp->rcbs[i].alock)); } for ( i = 0; i < _arkp->ntasks; i++ ) { bt_delete(_arkp->tcbs[i].inb); bt_delete(_arkp->tcbs[i].oub); am_free(_arkp->tcbs[i].vb_orig); } if (_arkp->iocbs) { am_free(_arkp->iocbs); } if (_arkp->tcbs) { am_free(_arkp->tcbs); } if (_arkp->rcbs) { am_free(_arkp->rcbs); } if (_arkp->ttags) { tag_free(_arkp->ttags); } if (_arkp->rtags) { tag_free(_arkp->rtags); } if (!(_arkp->flags & ARK_KV_VIRTUAL_LUN)) { rc = ark_persist(_arkp); if ( rc != 0 ) { KV_TRC_FFDC(pAT, "FFDC: ark_persist failed: %d", rc); } } pthread_mutex_destroy(&_arkp->mainmutex); (void)ea_delete(_arkp->ea); hash_free(_arkp->ht); bl_delete(_arkp->bl); KV_TRC(pAT, "ark_delete done %p", _arkp); am_free(_arkp); ark_delete_ark_err: KV_TRC_CLOSE(pAT); return rc; }
/* * NAME: hfs->rename() * DESCRIPTION: change the name of and/or move a file or directory */ int hfs_rename(hfsvol *vol, const char *srcpath, const char *dstpath) { hfsvol *srcvol; CatDataRec src, dst; unsigned long srcid, dstid; CatKeyRec key; char srcname[HFS_MAX_FLEN + 1], dstname[HFS_MAX_FLEN + 1]; byte record[HFS_MAX_CATRECLEN]; unsigned int reclen; int found, isdir, moving; node n; if (getvol(&vol) == -1 || v_resolve(&vol, srcpath, &src, &srcid, srcname, 0) <= 0) goto fail; isdir = (src.cdrType == cdrDirRec); srcvol = vol; found = v_resolve(&vol, dstpath, &dst, &dstid, dstname, 0); if (found == -1) goto fail; if (vol != srcvol) ERROR(EINVAL, "can't move across volumes"); if (dstid == 0) ERROR(ENOENT, "bad destination path"); if (found && dst.cdrType == cdrDirRec && dst.u.dir.dirDirID != src.u.dir.dirDirID) { dstid = dst.u.dir.dirDirID; strcpy(dstname, srcname); found = v_catsearch(vol, dstid, dstname, 0, 0, 0); if (found == -1) goto fail; } moving = (srcid != dstid); if (found) { const char *ptr; ptr = strrchr(dstpath, ':'); if (ptr == 0) ptr = dstpath; else ++ptr; if (*ptr) strcpy(dstname, ptr); if (! moving && strcmp(srcname, dstname) == 0) goto done; /* source and destination are identical */ if (moving || d_relstring(srcname, dstname)) ERROR(EEXIST, "can't use destination name"); } /* can't move anything into the root directory's parent */ if (moving && dstid == HFS_CNID_ROOTPAR) ERROR(EINVAL, "can't move above root directory"); if (moving && isdir) { unsigned long id; /* can't move root directory anywhere */ if (src.u.dir.dirDirID == HFS_CNID_ROOTDIR) ERROR(EINVAL, "can't move root directory"); /* make sure we aren't trying to move a directory inside itself */ for (id = dstid; id != HFS_CNID_ROOTDIR; id = dst.u.dthd.thdParID) { if (id == src.u.dir.dirDirID) ERROR(EINVAL, "can't move directory inside itself"); if (v_getdthread(vol, id, &dst, 0) <= 0) goto fail; } } if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* change volume name */ if (dstid == HFS_CNID_ROOTPAR) { if (! validvname(dstname)) goto fail; strcpy(vol->mdb.drVN, dstname); vol->flags |= HFS_VOL_UPDATE_MDB; } /* remove source record */ r_makecatkey(&key, srcid, srcname); r_packcatkey(&key, record, 0); if (bt_delete(&vol->cat, record) == -1) goto fail; /* insert destination record */ r_makecatkey(&key, dstid, dstname); r_packcatrec(&key, &src, record, &reclen); if (bt_insert(&vol->cat, record, reclen) == -1) goto fail; /* update thread record */ if (isdir) { if (v_getdthread(vol, src.u.dir.dirDirID, &dst, &n) <= 0) goto fail; dst.u.dthd.thdParID = dstid; strcpy(dst.u.dthd.thdCName, dstname); if (v_putcatrec(&dst, &n) == -1) goto fail; } else { found = v_getfthread(vol, src.u.fil.filFlNum, &dst, &n); if (found == -1) goto fail; if (found) { dst.u.fthd.fthdParID = dstid; strcpy(dst.u.fthd.fthdCName, dstname); if (v_putcatrec(&dst, &n) == -1) goto fail; } } /* update directory valences */ if (moving) { if (v_adjvalence(vol, srcid, isdir, -1) == -1 || v_adjvalence(vol, dstid, isdir, 1) == -1) goto fail; } done: return 0; fail: return -1; }
/* * NAME: hfs->delete() * DESCRIPTION: remove both forks of a file */ int hfs_delete(hfsvol *vol, const char *path) { hfsfile file; CatKeyRec key; byte pkey[HFS_CATKEYLEN]; int found; if (getvol(&vol) == -1 || v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0) goto fail; if (file.cat.cdrType != cdrFilRec) ERROR(EISDIR, 0); if (file.parid == HFS_CNID_ROOTPAR) ERROR(EINVAL, 0); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* free allocation blocks */ file.vol = vol; file.flags = 0; file.cat.u.fil.filLgLen = 0; file.cat.u.fil.filRLgLen = 0; f_selectfork(&file, fkData); if (f_trunc(&file) == -1) goto fail; f_selectfork(&file, fkRsrc); if (f_trunc(&file) == -1) goto fail; /* delete file record */ r_makecatkey(&key, file.parid, file.name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1 || v_adjvalence(vol, file.parid, 0, -1) == -1) goto fail; /* delete file thread, if any */ found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0); if (found == -1) goto fail; if (found) { r_makecatkey(&key, file.cat.u.fil.filFlNum, ""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1) goto fail; } return 0; fail: return -1; }