⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_db_hash.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 4 页
字号:
	    mpb =db_make_mp_binary(p,(mpi.mp),&hp);	    if (mpi.all_objects)		(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;	    continuation = TUPLE6(hp, tb->common.id,make_small(chain_pos), 				  make_small(chunk_size),  				  mpb, rest, 				  make_small(rest_size));	    mpi.mp = NULL; /*otherwise the return macro will destroy it */	    hp += 7;	    RET_TO_BIF(TUPLE2(hp, match_list, continuation),DB_ERROR_NONE);	} else { /* All data is exhausted */	    if (match_list != NIL) { /* No more data to search but still a					result to return to the caller */		hp = HAlloc(p, 3);		RET_TO_BIF(TUPLE2(hp, match_list, am_EOT),DB_ERROR_NONE);	    } else { /* Reached the end of the ttable with no data to return */		RET_TO_BIF(am_EOT, DB_ERROR_NONE);	    }	}    }    RET_TO_BIF(match_list,DB_ERROR_NONE);trap:    BUMP_ALL_REDS(p);    if (mpi.all_objects)	(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;    hp = HAlloc(p,7+PROC_BIN_SIZE);    mpb =db_make_mp_binary(p,(mpi.mp),&hp);    continuation = TUPLE6(hp, tb->common.id, make_small(chain_pos), 			  make_small(chunk_size), 			  mpb, match_list, 			  make_small(got));    mpi.mp = NULL; /*otherwise the return macro will destroy it */    RET_TO_BIF(bif_trap1(&ets_select_continue_exp, p, 			 continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}static int db_select_count_hash(Process *p, 				DbTable *tbl, 				Eterm pattern,				Eterm *ret){    DbTableHash *tb = &tbl->hash;    struct mp_info mpi;    Uint chain_pos = 0;    HashDbTerm **current_list = NULL;    unsigned current_list_pos = 0;    Uint32 dummy;    Eterm match_res;    Eterm *hp;    int num_left = 1000;    Uint got = 0;    Eterm continuation;    int errcode;    Eterm egot;    Eterm mpb;#define RET_TO_BIF(Term,RetVal) do {		\	if (mpi.mp != NULL) {			\	    erts_match_set_free(mpi.mp);	\	}					\	if (mpi.lists != mpi.dlists) {		\	    erts_free(ERTS_ALC_T_DB_SEL_LIST,	\		      (void *) mpi.lists);	\	}					\	*ret = (Term);				\	return RetVal;				\    } while(0)    if ((errcode = analyze_pattern(tb, pattern, &mpi)) != DB_ERROR_NONE) {	RET_TO_BIF(NIL,errcode);    }    if (!mpi.something_can_match) {	RET_TO_BIF(make_small(0), DB_ERROR_NONE);	/* can't possibly match anything */    }    if (!mpi.key_given) {    /* Run this code if pattern is variable or GETKEY(pattern)  */    /* is a variable                                            */	for(; chain_pos < tb->nactive; ++chain_pos) {	    if (BUCKET(tb,chain_pos) != NULL) {		current_list = &BUCKET(tb,chain_pos);		break;	    }	}	if (chain_pos == tb->nactive) {	    RET_TO_BIF(make_small(0),DB_ERROR_NONE);	}     } else {	/* We have at least one */	current_list = mpi.lists[current_list_pos++];     }    for(;;) {	if ((*current_list)->hvalue != INVALID_HASH && 	    (match_res = 	     db_prog_match(p,mpi.mp,			   make_tuple((*current_list)->dbterm.tpl),			   0,&dummy)) == am_true) {	    ++got;	}	--num_left;	/* Update the list variable */	current_list = &((*current_list)->next);	for (;;) {	    while ((*current_list) != NULL && 		   (*current_list)->hvalue == INVALID_HASH)		current_list = &((*current_list)->next);	    if ((*current_list) == NULL) {		if (mpi.key_given) {  /* Key is bound */		    if (current_list_pos == mpi.num_lists) {			goto done;		    } else {			current_list = mpi.lists[current_list_pos++];		    }		} else {		    for(++chain_pos; chain_pos < tb->nactive; ++chain_pos) {			if (BUCKET(tb,chain_pos) != NULL) {			    current_list = &BUCKET(tb,chain_pos);			    break;			}		    }		    if (chain_pos == tb->nactive) {			goto done;		    } 		    if (num_left <= 0) {			goto trap;		    }		}		    } else {		break;	    }	}    }done:    BUMP_REDS(p, 1000 - num_left);    if (got && ((tb->common.nitems / tb->nactive) < CHAIN_LEN) &&	((tb->common.status & DB_FIXED) == 0))	shrink(tb);    RET_TO_BIF(erts_make_integer(got,p),DB_ERROR_NONE);trap:    BUMP_ALL_REDS(p);    if (IS_USMALL(0, got)) {	hp = HAlloc(p,  PROC_BIN_SIZE + 5);	egot = make_small(got);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + PROC_BIN_SIZE + 5);	egot = uint_to_big(got, hp);	hp += BIG_UINT_HEAP_SIZE;    }    mpb = db_make_mp_binary(p,mpi.mp,&hp);    continuation = TUPLE4(hp, tb->common.id, make_small(chain_pos), 			  mpb, 			  egot);    mpi.mp = NULL; /*otherwise the return macro will destroy it */    RET_TO_BIF(bif_trap1(&ets_select_count_continue_exp, p, 			 continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}static int db_select_delete_hash(Process *p,				 DbTable *tbl,				 Eterm pattern,				 Eterm *ret){    DbTableHash *tb = &tbl->hash;    struct mp_info mpi;    Uint chain_pos = 0;    HashDbTerm **current_list = NULL;    unsigned current_list_pos = 0;    Uint32 dummy;    Eterm match_res;    Eterm *hp;    int num_left = 1000;    Uint got = 0;    Eterm continuation;    int errcode;    Eterm mpb;    Eterm egot;#define RET_TO_BIF(Term,RetVal) do {		\	if (mpi.mp != NULL) {			\	    erts_match_set_free(mpi.mp);	\	}					\	if (mpi.lists != mpi.dlists) {		\	    erts_free(ERTS_ALC_T_DB_SEL_LIST,	\		      (void *) mpi.lists);	\	}					\	*ret = (Term);				\	return RetVal;				\    } while(0)    if ((errcode = analyze_pattern(tb, pattern, &mpi)) != DB_ERROR_NONE) {	RET_TO_BIF(NIL,errcode);    }    if (!mpi.something_can_match) {	RET_TO_BIF(make_small(0), DB_ERROR_NONE);	/* can't possibly match anything */    }    if (!mpi.key_given) {    /* Run this code if pattern is variable or GETKEY(pattern)  */    /* is a variable                                            */	for(; chain_pos < tb->nactive; ++chain_pos) {	    if (BUCKET(tb,chain_pos) != NULL) {		current_list = &BUCKET(tb,chain_pos);		break;	    }	}	if (chain_pos == tb->nactive) {	    RET_TO_BIF(make_small(0),DB_ERROR_NONE);	}     } else {	/* We have at least one */	current_list = mpi.lists[current_list_pos++];     }    for(;;) {	int did_erase = 0;	if ((*current_list)->hvalue != INVALID_HASH && 	    (match_res = 	     db_prog_match(p,mpi.mp,			   make_tuple((*current_list)->dbterm.tpl),			   0,&dummy)) == am_true) {	    if (tb->common.status & DB_FIXED) {		FixedDeletion *fixd = (FixedDeletion *)		    erts_db_alloc(ERTS_ALC_T_DB_FIX_DEL,				  (DbTable *) tb,				  sizeof(FixedDeletion));		int ix;		HASH(tb, (*current_list)->hvalue, ix);		fixd->slot = ix;		fixd->next = tb->fixdel;		tb->fixdel = fixd;		tb->common.kept_items++;		tb->common.nitems--;		(*current_list)->hvalue = INVALID_HASH;	    } else {		HashDbTerm *del = *current_list;		*current_list = (*current_list)->next;		free_term(tb, del);		tb->common.nitems--;		did_erase = 1;	    }	    ++got;	}	--num_left;	/* Update the list variable */	if (!did_erase) {	    current_list = &((*current_list)->next);	}	for (;;) {	    while ((*current_list) != NULL && 		   (*current_list)->hvalue == INVALID_HASH)		current_list = &((*current_list)->next);	    if ((*current_list) == NULL) {		if (mpi.key_given) {  /* Key is bound */		    if (current_list_pos == mpi.num_lists) {			goto done;		    } else {			current_list = mpi.lists[current_list_pos++];		    }		} else {		    for(++chain_pos; chain_pos < tb->nactive; ++chain_pos) {			if (BUCKET(tb,chain_pos) != NULL) {			    current_list = &BUCKET(tb,chain_pos);			    break;			}		    }		    if (chain_pos == tb->nactive) {			goto done;		    } 		    if (num_left <= 0) {			goto trap;		    }		}		    } else {		break;	    }	}    }done:    BUMP_REDS(p, 1000 - num_left);    if (got && ((tb->common.nitems / tb->nactive) < CHAIN_LEN) &&	((tb->common.status & DB_FIXED) == 0))	shrink(tb);    RET_TO_BIF(erts_make_integer(got,p),DB_ERROR_NONE);trap:    BUMP_ALL_REDS(p);    if (IS_USMALL(0, got)) {	hp = HAlloc(p,  PROC_BIN_SIZE + 5);	egot = make_small(got);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + PROC_BIN_SIZE + 5);	egot = uint_to_big(got, hp);	hp += BIG_UINT_HEAP_SIZE;    }    mpb = db_make_mp_binary(p,mpi.mp,&hp);    continuation = TUPLE4(hp, tb->common.id, make_small(chain_pos), 			  mpb, 			  egot);    mpi.mp = NULL; /*otherwise the return macro will destroy it */    RET_TO_BIF(bif_trap1(&ets_select_delete_continue_exp, p, 			 continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}/*** This is called when select_delete traps*/static int db_select_delete_continue_hash(Process *p, 					  DbTable *tbl,					  Eterm continuation,					  Eterm *ret){    DbTableHash *tb = &tbl->hash;    Uint chain_pos;    HashDbTerm **current_list = NULL;    Uint32 dummy;    Eterm match_res;    Eterm *hp;    int num_left = 1000;    Uint got;    Eterm *tptr;    Binary *mp;    int force_delete;    int do_delete;    DbFixation *fix = tb->common.fixations;    Eterm egot;    force_delete = (tb->common.status & DB_FIXED) && 	!ONLY_READER(p,tb) && SOLE_LOCKER(p,fix);    do_delete = (!(tb->common.status & DB_FIXED) || force_delete);    #define RET_TO_BIF(Term,RetVal) do {		\	*ret = (Term);				\	return RetVal;				\    } while(0)        tptr = tuple_val(continuation);    chain_pos = unsigned_val(tptr[2]);    mp = ((ProcBin *) binary_val(tptr[3]))->val;    if (is_big(tptr[4])) {	got = big_to_uint32(tptr[4]);    } else {	got = unsigned_val(tptr[4]);    }        /* Run this code if pattern is variable or GETKEY(pattern)  */    /* is a variable                                            */    for(; chain_pos < tb->nactive; ++chain_pos) {	if (BUCKET(tb,chain_pos) != NULL) {	    current_list = &BUCKET(tb,chain_pos);	    break;	}    }    if (chain_pos == tb->nactive) {	goto done;    }     for(;;) {	int did_erase = 0;	if ((*current_list)->hvalue != INVALID_HASH && 	    (match_res = 	     db_prog_match(p,mp,			   make_tuple((*current_list)->dbterm.tpl),			   0,&dummy)) == am_true) {	    if (do_delete) {		HashDbTerm *del = *current_list;		*current_list = (*current_list)->next;		free_term(tb, del);		tb->common.nitems--;		did_erase = 1;	    } else {		FixedDeletion *fixd = (FixedDeletion *) 		    erts_db_alloc(ERTS_ALC_T_DB_FIX_DEL,				  (DbTable *) tb,				  sizeof(FixedDeletion));		fixd->slot = chain_pos;		fixd->next = tb->fixdel;		tb->fixdel = fixd;		tb->common.kept_items++;		tb->common.nitems--;		(*current_list)->hvalue = INVALID_HASH;	    }	    ++got;	}	--num_left;	/* Update the list variable */	if (!did_erase) {	    current_list = &((*current_list)->next);	}	for (;;) {	    while ((*current_list) != NULL && 		   (*current_list)->hvalue == INVALID_HASH)		current_list = &((*current_list)->next);	    if ((*current_list) == NULL) {		for(++chain_pos; chain_pos < tb->nactive; ++chain_pos) {		    if (BUCKET(tb,chain_pos) != NULL) {			current_list = &BUCKET(tb,chain_pos);			break;		    }		}		if (chain_pos == tb->nactive) {		    goto done;		} 		if (num_left <= 0) {		    goto trap;		}	    } else {		break;	    }	}    }done:    BUMP_REDS(p, 1000 - num_left);    if (got && ((tb->common.nitems / tb->nactive) < CHAIN_LEN) &&	((tb->common.status & DB_FIXED) == 0))	shrink(tb);    RET_TO_BIF(erts_make_integer(got,p),DB_ERROR_NONE);trap:    BUMP_ALL_REDS(p);    if (IS_USMALL(0, got)) {	hp = HAlloc(p,  5);	egot = make_small(got);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + 5);	egot = uint_to_big(got, hp);	hp += BIG_UINT_HEAP_SIZE;    }    continuation = TUPLE4(hp, tb->common.id, make_small(chain_pos), 			  tptr[3], 			  egot);    RET_TO_BIF(bif_trap1(&ets_select_delete_continue_exp, p, 			 continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}    /*** This is called when select_delete traps*/static int db_select_count_continue_hash(Process *p, 					 DbTable *tbl,					 Eterm continuation,					 Eterm *ret){    DbTableHash *tb = &tbl->hash;    Uint chain_pos;    HashDbTerm **current_list = NULL;    Uint32 dummy;    Eterm match_res;    Eterm *hp;    int num_left = 1000;    Uint got;    Eterm *tptr;    Binary *mp;    Eterm egot;#define RET_TO_BIF(Term,RetVal) do {		\	*ret = (Term);				\	return RetVal;				\    } while(0)        tptr = tuple_val(continuation);    chain_pos = unsigned_val(tptr[2]);    mp = ((ProcBin *) binary_val(tptr[3]))->val;    if (is_big(tptr[4])) {	got = big_to_uint32(tptr[4]);    } else {	got = unsigned_val(tptr[4]);    }        /* Run this code if pattern is variable or GETKEY(pattern)  */    /* is a variable                                            */    for(; chain_pos < tb->nactive; ++chain_pos) {	if (BUCKET(tb,chain_pos) != NULL) {	    current_list = &BUCKET(tb,chain_pos);	    break;	}    }    if (chain_pos == tb->nactive) {	goto done;    }     for(;;) {	if ((*current_list)->hvalue != INVALID_HASH && 	    (match_res = 	     db_prog_match(p,mp,			   make_tuple((*current_list)->dbterm.tpl),			   0,&dummy)) == am_true) {	    ++got;	}	--num_left;	/* Update the list variable */	current_list = &((*current_list)->next);	for (;;) {	    while ((*current_list) != NULL && 		   (*current_list)->hvalue == INVALID_HASH)		current_list = &((*current_list)->next);	    if ((*current_list) == NULL) {		for(++chain_pos; chain_pos < tb->nactive; ++chain_pos) {		    if (BUCKET(tb,chain_pos) != NULL) {			current_list = &BUCKET(tb,chain_pos);			break;		    }		}		if (chain_pos == tb->nactive) {		    goto done;		} 		if (num_left <= 0) {		    goto trap;		}	    } else {		break;	    }	}    }done:    BUMP_REDS(p, 1000 - num_left);    if (got && ((tb->common.nitems / tb->nactive) < CHAIN_LEN) &&	((tb->common.status & DB_FIXED) == 0))	shrink(tb);    RET_TO_BIF(erts_make_integer(got,p),DB_ERROR_NONE);trap:    BUMP_ALL_REDS(p);    if (IS_USMALL(0, got)) {	hp = HAlloc(p, 5);	egot = make_small(got);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + 5);	egot = uint_to_big(got, hp);	hp += BIG_UINT_HEAP_SIZE;    }    continuation = TUPLE4(hp, tb->common.id, make_small(chain_pos), 			  tptr[3], 			  egot);    RET_TO_BIF(bif_trap1(&ets_select_count_continue_exp, p, 			 continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}    /*** Other interface routines (not directly coupled to one bif)*/void db_initialize_hash(void) {};int db_mark_all_deleted_hash(DbTable *tbl){    DbTableHash *tb = &tbl->hash;    HashDbTerm* list;    int i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -