void clear_skipset(skipset* ss ) { /*clear skiplists */ skipnode* s = ss->header->next[0]; while(s != NULL) { skipnode* tmp = s; s = s->next[0]; release_node(tmp); } release_node(ss->header); clear_skipset_item(ss); free(ss); }
void release_node(std::shared_ptr<struct binomial_node<T>> &n) { if (n.use_count() == 0) return; auto &sibling = n->mRight; while(sibling) { auto &s = sibling->mRight; release_node(sibling); sibling = s; } release_node(n->mChild); n.reset(); }
void list_del(PLIST head,PLIST node) { if(head == node) { release_node(head); head = NULL; } while(head) { if(head->next == node) { head->next = node->next; release_node(node); } } }
static void btree_destroy_impl(struct bnode_s *r) { if (!r->leaf) { int i; for (i = 0; i < r->nkeys+1; i++) { btree_destroy_impl(r->child[LEFT_CHILD_OF_KEY(i)]); } } release_node(r); }
void release_list(PLIST head) { PLIST nxt = NULL; while(head) { nxt = head->next; release_node(head); head = nxt; } head = NULL; }
static SCHED_EVENT *sweep_cancellations(SCHED_EVENT *list) { SCHED_EVENT *event; event = list; while (event != NULL) { if (event->state == STATE_CANCELED) { list = event->link; release_node(event); event = list; } else event = event->link; } return list; }
bool HashIdx::deleteobj(const char *key, int length) { struct HashIdx::VElt *finger; struct HashIdx::VElt *result; struct HashElt *hashEltptr; short done; if (key == NULL || length == 0) return false; done = FALSE; result = NULL; if(bernsteinHash==true) hashEltptr = &(hashtable[TCUtility::bernsteinHash(key,length,MAXRES)]); else hashEltptr = &(hashtable[h_hash(key, length)]); EnterCriticalSection(hashEltptr->concurrent); finger = hashEltptr->ptr; for ( ; (finger != NULL && (done != TRUE)); finger = finger -> flink) { if (finger -> length == length && memcmp(finger->key, key, length)==0) { result = finger; done = TRUE; } } if (result != NULL){ finger = result; if (finger->blink != NULL) finger -> blink -> flink = finger -> flink; if (finger->flink != NULL) finger -> flink -> blink = finger -> blink; if (hashEltptr->ptr == finger) hashEltptr-> ptr = finger -> flink; release_node(finger); } LeaveCriticalSection(hashEltptr->concurrent); #ifdef VALIDATE if (result == NULL){ printf("HashIdx:deleteobj: deleteobj did not find the referenced object %d to delete\n", (int) *key); return false; } #endif return true; }
void free_unmarked(node **allocated) { node *cpy, **ptr = allocated; while (*ptr isnt NULL) { cpy = *ptr; if (cpy->marked is 0) { *ptr = next(cpy); release_node(cpy); } else { ptr = &next(cpy); if (cpy->marked is 1) { cpy->marked = 0; } } } }
static SCM sched_thread(void *data) { SCHED_EVENT *event; utime_t next_wake; utime_t now, early, late; time_t tnow; scheduling = 1; next_wake = 0; pthread_mutex_lock(&qmutex); while (scheduling) { pthread_cond_timedwait(&qcondvar, &qmutex, sleep_till(next_wake)); now = now_usec(); late = now - DISPATCH_WINDOW / 2; early = now + DISPATCH_WINDOW / 2; event = queue; while (event != NULL) { if (event->clock < late) { log_msg("would drop %1.3f < %1.3f\n", event->clock / (double)TIME_RES, late / (double)TIME_RES); // queue = event->link; // release_node(event); // event = queue; // continue; } if (event->clock > early) break; queue = event->link; if (event->state == STATE_PENDING) { scm_spawn_thread(dispatch_event, (void *)&(event->action), NULL, NULL); } release_node(event); event = queue; } queue = sweep_cancellations(queue); if (queue != NULL) next_wake = queue->clock; else next_wake = 0; if (((tnow = time(NULL)) - gc_hit) > GC_HIT_INTERVAL) { gc_hit = tnow; scm_gc(); } } pthread_mutex_unlock(&qmutex); return SCM_BOOL_T; }
static void delete_node(skipset* ss, skipnode* s) { int i; for(i = s->level; i >= 0; i--) { /*repoint adjacent nodes*/ if(s->next[i] != NULL) s->next[i]->prev[i] = s->prev[i]; if(s->prev[i] != NULL) s->prev[i]->next[i] = s->next[i]; } /*delete node*/ release_node(s); /*reduce skipset level if higher levels are now empty*/ for(i = ss->level; i >= 0; i--) if(ss->header->next[i] == NULL && ss->level > 0) ss->level--; }
void merge_child(struct btree_s *tree, struct bnode_s *r, int key_pos) { UNUSED(tree); struct bnode_s *left_node = r->child[LEFT_CHILD_OF_KEY(key_pos)]; struct bnode_s *right_node = r->child[RIGHT_CHILD_OF_KEY(key_pos)]; /* 整理key */ int key_beg = left_node->nkeys; left_node->key[key_beg] = r->key[key_pos]; key_beg++; int i; for (i = 0; i < right_node->nkeys; i++) { left_node->key[key_beg+i] = right_node->key[i]; } /* 整理child */ int child_beg = left_node->nkeys+1; for (i = 0; i < right_node->nkeys+1; i++) { left_node->child[child_beg+i] = right_node->child[i]; } left_node->nkeys += 1 + right_node->nkeys; /* 整理父节点key */ for (i = key_pos; i < r->nkeys-1; i++) { r->key[i] = r->key[i+1]; } /* 整理父节点child */ for (i = RIGHT_CHILD_OF_KEY(key_pos); i < r->nkeys; i++) { r->child[i] = r->child[i+1]; } r->nkeys--; release_node(right_node); }
void btree_remove_impl(struct btree_s *tree, struct bnode_s *r, int k) { int i = r->nkeys - 1; while (i >= 0 && k < r->key[i]) i--; if (i >= 0 && k == r->key[i]) { /* 要删除的节点在本节点 */ if (r->leaf) { /* 叶子节点,直接删除 */ for (; i < r->nkeys; i++) { r->key[i] = r->key[i+1]; } r->nkeys--; } else { /* 非叶子节点 */ assert(i >= 0 && "error"); int left = LEFT_CHILD_OF_KEY(i); int right = RIGHT_CHILD_OF_KEY(i); if (r->child[left]->nkeys >= tree->min_key_nr+1) { /* 左边的孩子的key足够t个 */ r->key[i] = btree_delete_max(tree, r->child[left]); } else if (r->child[right]->nkeys >= tree->min_key_nr+1) { /* 右边的孩子的key足够t个 */ r->key[i] = btree_delete_min(tree, r->child[right]); } else { /* 都不够,需要合并 */ merge_child(tree, r, i); if (r->nkeys == 0) { tree->root = r->child[0]; release_node(r); btree_remove_impl(tree, tree->root, k); } else { btree_remove_impl(tree, r->child[i], k); } } } } else { if (i >= 0 && r->leaf) { printf("%d, %d, \n", i, k); void btree_dump(struct btree_s *); btree_dump(tree); assert(0 && "not in tree"); } /* 要删除的节点不在本节点 */ int remove_child_pos = RIGHT_CHILD_OF_KEY(i); if (r->child[remove_child_pos]->nkeys >= tree->min_key_nr+1) { /* 子节点的key个数足够t */ btree_remove_impl(tree, r->child[remove_child_pos], k); } else { /* key个数不够 */ if (remove_child_pos-1 >=0 && r->child[remove_child_pos-1]->nkeys >= tree->min_child_nr+1) { /* 有左兄弟且左兄弟够 */ right_rotate(tree, r, LEFT_KEY_OF_CHILD(remove_child_pos)); btree_remove_impl(tree, r->child[remove_child_pos], k); } else if (remove_child_pos+1 <= r->nkeys && r->child[remove_child_pos+1]->nkeys >= tree->min_child_nr+1) { /* 有右兄弟且有兄弟够 */ left_rotate(tree, r, RIGHT_KEY_OF_CHILD(remove_child_pos)); btree_remove_impl(tree, r->child[remove_child_pos], k); } else { /* 都不够 */ int merge_pos = -1; if (remove_child_pos-1 >= 0) { merge_pos = LEFT_KEY_OF_CHILD(remove_child_pos); } else if (remove_child_pos+1 <= r->nkeys) { merge_pos = RIGHT_KEY_OF_CHILD(remove_child_pos); } else { assert(0 && "damn"); } merge_child(tree, r, merge_pos); if (r->nkeys == 0) { tree->root = r->child[0]; release_node(r); btree_remove_impl(tree, tree->root, k); } else { btree_remove_impl(tree, r->child[merge_pos], k); } } } } }
/*===========================================================================* * fs_unlink * *===========================================================================*/ PUBLIC int fs_unlink() { /* Perform the unlink(name) or rmdir(name) system call. The code for these two * is almost the same. They differ only in some condition testing. Unlink() * may be used by the superuser to do dangerous things; rmdir() may not. */ int r; struct puffs_node *pn, *pn_dir; time_t cur_time; struct puffs_kcn pkcnp; struct puffs_cn pcn = {&pkcnp, 0, {0,0,0}}; PUFFS_KCREDTOCRED(pcn.pcn_cred, &global_kcred); int len; /* Copy the last component */ len = fs_m_in.REQ_PATH_LEN; pcn.pcn_namelen = len - 1; if (pcn.pcn_namelen > NAME_MAX) return(ENAMETOOLONG); r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT, (vir_bytes) 0, (vir_bytes) pcn.pcn_name, (size_t) len, D); if (r != OK) return (r); NUL(pcn.pcn_name, len, sizeof(pcn.pcn_name)); if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) return(EINVAL); /* The last directory exists. Does the file also exist? */ pn = advance(pn_dir, pcn.pcn_name, IGN_PERM); r = err_code; /* If error, return pnode. */ if (r != OK) { /* Mount point? */ if (r == EENTERMOUNT || r == ELEAVEMOUNT) { r = EBUSY; } return(r); } /* Now test if the call is allowed, separately for unlink() and rmdir(). */ if (fs_m_in.m_type == REQ_UNLINK) { /* Only the su may unlink directories, but the su can unlink any dir */ if ((pn->pn_va.va_mode & I_TYPE) == I_DIRECTORY) r = EPERM; if (r == OK) r = unlink_file(pn_dir, pn, &pcn); } else { r = remove_dir(pn_dir, pn, &pcn); /* call is RMDIR */ } if (pn->pn_va.va_nlink != 0) { cur_time = clock_time(); update_times(pn, CTIME, cur_time); update_times(pn_dir, MTIME | CTIME, cur_time); } /* XXX Ideally, we should check pn->pn_flags & PUFFS_NODE_REMOVED, but * librefuse doesn't set it (neither manually or via puffs_pn_remove() ). * Thus we just check that "pn_count == 0". Otherwise release_node() * will be called in fs_put(). */ if (pn->pn_count == 0) release_node(global_pu, pn); return(r); }
/*===========================================================================* * fs_rename * *===========================================================================*/ PUBLIC int fs_rename() { /* Perform the rename(name1, name2) system call. */ struct puffs_node *old_dirp, *old_ip; /* ptrs to old dir, file pnodes */ struct puffs_node *new_dirp, *new_ip; /* ptrs to new dir, file pnodes */ struct puffs_kcn pkcnp_src; PUFFS_MAKECRED(pcr_src, &global_kcred); struct puffs_cn pcn_src = {&pkcnp_src, (struct puffs_cred *) __UNCONST(pcr_src), {0,0,0}}; struct puffs_kcn pkcnp_dest; PUFFS_MAKECRED(pcr_dest, &global_kcred); struct puffs_cn pcn_targ = {&pkcnp_dest, (struct puffs_cred *) __UNCONST(pcr_dest), {0,0,0}}; int r = OK; /* error flag; initially no error */ int odir, ndir; /* TRUE iff {old|new} file is dir */ int same_pdir; /* TRUE iff parent dirs are the same */ phys_bytes len; time_t cur_time; if (global_pu->pu_ops.puffs_node_rename == NULL) return(EINVAL); /* Copy the last component of the old name */ len = fs_m_in.REQ_REN_LEN_OLD; /* including trailing '\0' */ if (len > NAME_MAX + 1) return(ENAMETOOLONG); r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_REN_GRANT_OLD, (vir_bytes) 0, (vir_bytes) pcn_src.pcn_name, (size_t) len, D); if (r != OK) return(r); NUL(pcn_src.pcn_name, len, sizeof(pcn_src.pcn_name)); pcn_src.pcn_namelen = len - 1; /* Copy the last component of the new name */ len = fs_m_in.REQ_REN_LEN_NEW; /* including trailing '\0' */ if (len > NAME_MAX + 1) return(ENAMETOOLONG); r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_REN_GRANT_NEW, (vir_bytes) 0, (vir_bytes) pcn_targ.pcn_name, (size_t) len, D); if (r != OK) return(r); NUL(pcn_targ.pcn_name, len, sizeof(pcn_targ.pcn_name)); pcn_targ.pcn_namelen = len - 1; /* Get old dir pnode */ if ((old_dirp = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_REN_OLD_DIR)) == NULL) return(ENOENT); old_ip = advance(old_dirp, pcn_src.pcn_name, IGN_PERM); if (!old_ip) { return(ENOENT); } r = err_code; if (r == EENTERMOUNT || r == ELEAVEMOUNT) { old_ip = NULL; if (r == EENTERMOUNT) r = EXDEV; /* should this fail at all? */ else if (r == ELEAVEMOUNT) r = EINVAL; /* rename on dot-dot */ } /* Get new dir pnode */ if ((new_dirp = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_REN_NEW_DIR)) == NULL) { r = ENOENT; } else { if (new_dirp->pn_va.va_nlink == NO_LINK) { /* Dir does not actually exist */ return(ENOENT); } } /* not required to exist */ new_ip = advance(new_dirp, pcn_targ.pcn_name, IGN_PERM); /* However, if the check failed because the file does exist, don't continue. * Note that ELEAVEMOUNT is covered by the dot-dot check later. */ if (err_code == EENTERMOUNT) { new_ip = NULL; r = EBUSY; } if (old_ip != NULL) { /* TRUE iff dir */ odir = ((old_ip->pn_va.va_mode & I_TYPE) == I_DIRECTORY); } else { odir = FALSE; } if (r != OK) return(r); /* Check for a variety of possible errors. */ same_pdir = (old_dirp == new_dirp); /* The old or new name must not be . or .. */ if (strcmp(pcn_src.pcn_name, ".") == 0 || strcmp(pcn_src.pcn_name, "..") == 0 || strcmp(pcn_targ.pcn_name, ".") == 0 || strcmp(pcn_targ.pcn_name, "..") == 0) { r = EINVAL; } /* Some tests apply only if the new path exists. */ if (new_ip == NULL) { if (odir && (new_dirp->pn_va.va_nlink >= SHRT_MAX || new_dirp->pn_va.va_nlink >= LINK_MAX) && !same_pdir && r == OK) { r = EMLINK; } } else { if (old_ip == new_ip) r = SAME; /* old=new */ /* dir ? */ ndir = ((new_ip->pn_va.va_mode & I_TYPE) == I_DIRECTORY); if (odir == TRUE && ndir == FALSE) r = ENOTDIR; if (odir == FALSE && ndir == TRUE) r = EISDIR; } if (r == SAME) { r = OK; goto rename_out; } if (r != OK) return(r); /* If a process has another root directory than the system root, we might * "accidently" be moving it's working directory to a place where it's * root directory isn't a super directory of it anymore. This can make * the function chroot useless. If chroot will be used often we should * probably check for it here. */ /* The rename will probably work. Only two things can go wrong now: * 1. being unable to remove the new file. (when new file already exists) * 2. being unable to make the new directory entry. (new file doesn't exists) * [directory has to grow by one block and cannot because the disk * is completely full]. * 3. Something (doubtfully) else depending on the FS. */ if (buildpath) { pcn_src.pcn_po_full = old_ip->pn_po; if (puffs_path_pcnbuild(global_pu, &pcn_targ, new_dirp) != 0) return(EINVAL); } r = global_pu->pu_ops.puffs_node_rename(global_pu, old_dirp, old_ip, &pcn_src, new_dirp, new_ip, &pcn_targ); if (r > 0) r = -r; if (buildpath) { if (r) { global_pu->pu_pathfree(global_pu, &pcn_targ.pcn_po_full); } else { struct puffs_pathinfo pi; struct puffs_pathobj po_old; /* handle this node */ po_old = old_ip->pn_po; old_ip->pn_po = pcn_targ.pcn_po_full; if (old_ip->pn_va.va_type != VDIR) { global_pu->pu_pathfree(global_pu, &po_old); return(OK); } /* handle all child nodes for DIRs */ pi.pi_old = &pcn_src.pcn_po_full; pi.pi_new = &pcn_targ.pcn_po_full; PU_LOCK(); if (puffs_pn_nodewalk(global_pu, puffs_path_prefixadj, &pi) != NULL) { /* Actually nomem */ return(EINVAL); } PU_UNLOCK(); global_pu->pu_pathfree(global_pu, &po_old); } } rename_out: cur_time = clock_time(); update_times(old_dirp, MTIME | CTIME, cur_time); update_times(new_dirp, MTIME | CTIME, cur_time); /* XXX see release_node comment in fs_unlink */ if (new_ip && new_ip->pn_count == 0) { release_node(global_pu, new_ip); } return(r); }