📄 erl_db_hash.c
字号:
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 + -