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

📄 erl_db_tree.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    sc.mp = mpi.mp;    sc.all_objects = mpi.all_objects;    if (!mpi.got_partial && mpi.some_limitation && 	cmp(mpi.least,mpi.most) == 0) {	doit_select(tb,mpi.save_term,&sc,0 /* direction doesn't matter */);	RET_TO_BIF(sc.accum,DB_ERROR_NONE);    }    if (reverse) {	if (mpi.some_limitation) {	    if ((this = find_prev_from_pb_key(tb, mpi.least)) != NULL) {		lastkey = GETKEY(tb, this->dbterm.tpl);	    }	    sc.end_condition = mpi.most;	}		traverse_forward(tb, lastkey, &doit_select, &sc);    } else {	if (mpi.some_limitation) {	    if ((this = find_next_from_pb_key(tb, mpi.most)) != NULL) {		lastkey = GETKEY(tb, this->dbterm.tpl);	    }	    sc.end_condition = mpi.least;	}		traverse_backwards(tb, lastkey, &doit_select, &sc);    }#ifdef HARDDEBUG	erts_fprintf(stderr,"Least: %T\n", mpi.least);	erts_fprintf(stderr,"Most: %T\n", mpi.most);#endif    BUMP_REDS(p, 1000 - sc.max);    if (sc.max > 0) {	RET_TO_BIF(sc.accum,DB_ERROR_NONE);    }    key = GETKEY(tb, sc.lastobj);    sz = size_object(key);    hp = HAlloc(p, 9 + sz + PROC_BIN_SIZE);    key = copy_struct(key, sz, &hp, &MSO(p));    if (mpi.all_objects)	(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;    mpb=db_make_mp_binary(p,mpi.mp,&hp);	        continuation = TUPLE8	(hp,	 tb->common.id,	 key,	 sc.end_condition, /* From the match program, needn't be copied */	 make_small(0), /* Chunk size of zero means not chunked to the			   continuation BIF */	 mpb,	 sc.accum,	 make_small(reverse),	 make_small(sc.got));    /* Don't free mpi.mp, so don't use macro */    *ret = bif_trap1(bif_export[BIF_ets_select_1], p, continuation);     return DB_ERROR_NONE;#undef RET_TO_BIF}    /*** This is called either when the select_count bif traps.*/static int db_select_count_continue_tree(Process *p, 					 DbTable *tbl,					 Eterm continuation,					 Eterm *ret){    DbTableTree *tb = &tbl->tree;    struct select_count_context sc;    unsigned sz;    Eterm *hp;     Eterm lastkey;    Eterm end_condition;     Binary *mp;    Eterm key;    Eterm *tptr;    Eterm egot;#define RET_TO_BIF(Term, State) do { *ret = (Term); return State; } while(0);    /* Decode continuation. We know it's a tuple and everything else as     this is only called by ourselves */    /* continuation:        {Table, Lastkey, EndCondition, MatchProgBin, HowManyGot}*/    tptr = tuple_val(continuation);    if (arityval(*tptr) != 5)	erl_exit(1,"Internal error in ets:select_count/1");        lastkey = tptr[2];    end_condition = tptr[3];    if (!(thing_subtag(*binary_val(tptr[4])) == REFC_BINARY_SUBTAG))	RET_TO_BIF(NIL,DB_ERROR_BADPARAM);    mp = ((ProcBin *) binary_val(tptr[4]))->val;    if (!(mp->flags & BIN_FLAG_MATCH_PROG))	RET_TO_BIF(NIL,DB_ERROR_BADPARAM);    sc.p = p;    sc.mp = mp;    sc.end_condition = NIL;    sc.lastobj = NULL;    sc.max = 1000;    sc.keypos = tb->common.keypos;    if (is_big(tptr[5])) {	sc.got = big_to_uint32(tptr[5]);    } else {	sc.got = unsigned_val(tptr[5]);    }    traverse_backwards(tb, lastkey, &doit_select_count, &sc);    BUMP_REDS(p, 1000 - sc.max);    if (sc.max > 0) {	RET_TO_BIF(erts_make_integer(sc.got,p), DB_ERROR_NONE);    }	    key = GETKEY(tb, sc.lastobj);    if (end_condition != NIL && 	(cmp_partly_bound(end_condition,key) > 0)) { 	/* done anyway */	RET_TO_BIF(make_small(sc.got),DB_ERROR_NONE);    }    /* Not done yet, let's trap. */    sz = size_object(key);    if (IS_USMALL(0, sc.got)) {	hp = HAlloc(p, sz + 6);	egot = make_small(sc.got);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + sz + 6);	egot = uint_to_big(sc.got, hp);	hp += BIG_UINT_HEAP_SIZE;    }    key = copy_struct(key, sz, &hp, &MSO(p));    continuation = TUPLE5	(hp,	 tptr[1],	 key,	 tptr[3], 	 tptr[4],	 egot);    RET_TO_BIF(bif_trap1(&ets_select_count_continue_exp, p, continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}static int db_select_count_tree(Process *p, DbTable *tbl, 				Eterm pattern, Eterm *ret){    DbTableTree *tb = &tbl->tree;    struct select_count_context sc;    struct mp_info mpi;    Eterm lastkey = NIL;    Eterm key;    Eterm continuation;    unsigned sz;    Eterm *hp;     TreeDbTerm *this;    int errcode;    Eterm egot;    Eterm mpb;#define RET_TO_BIF(Term,RetVal) do { 	       	\	if (mpi.mp != NULL) {			\	    erts_match_set_free(mpi.mp);       	\	}					\	*ret = (Term); 				\	return RetVal; 			        \    } while(0)    mpi.mp = NULL;    sc.lastobj = NULL;    sc.p = p;    sc.max = 1000;     sc.end_condition = NIL;    sc.keypos = tb->common.keypos;    sc.got = 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 */    }    sc.mp = mpi.mp;    sc.all_objects = mpi.all_objects;    if (!mpi.got_partial && mpi.some_limitation && 	cmp(mpi.least,mpi.most) == 0) {	doit_select_count(tb,mpi.save_term,&sc,0 /* dummy */);	RET_TO_BIF(erts_make_integer(sc.got,p),DB_ERROR_NONE);    }    if (mpi.some_limitation) {	if ((this = find_next_from_pb_key(tb, mpi.most)) != NULL) {	    lastkey = GETKEY(tb, this->dbterm.tpl);	}	sc.end_condition = mpi.least;    }        traverse_backwards(tb, lastkey, &doit_select_count, &sc);    BUMP_REDS(p, 1000 - sc.max);    if (sc.max > 0) {	RET_TO_BIF(erts_make_integer(sc.got,p),DB_ERROR_NONE);    }    key = GETKEY(tb, sc.lastobj);    sz = size_object(key);    if (IS_USMALL(0, sc.got)) {	hp = HAlloc(p, sz + PROC_BIN_SIZE + 6);	egot = make_small(sc.got);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + sz + PROC_BIN_SIZE + 6);	egot = uint_to_big(sc.got, hp);	hp += BIG_UINT_HEAP_SIZE;    }    key = copy_struct(key, sz, &hp, &MSO(p));    if (mpi.all_objects)	(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;    mpb = db_make_mp_binary(p,mpi.mp,&hp);	        continuation = TUPLE5	(hp,	 tb->common.id,	 key,	 sc.end_condition, /* From the match program, needn't be copied */	 mpb,	 egot);    /* Don't free mpi.mp, so don't use macro */    *ret = bif_trap1(&ets_select_count_continue_exp, p, continuation);     return DB_ERROR_NONE;#undef RET_TO_BIF}static int db_select_chunk_tree(Process *p, DbTable *tbl, 				Eterm pattern, Sint chunk_size,				int reverse,				Eterm *ret){    DbTableTree *tb = &tbl->tree;    struct select_context sc;    struct mp_info mpi;    Eterm lastkey = NIL;    Eterm key;    Eterm continuation;    unsigned sz;    Eterm *hp;     TreeDbTerm *this;    int errcode;    Eterm mpb;#define RET_TO_BIF(Term,RetVal) do { 		\	if (mpi.mp != NULL) {			\	    erts_match_set_free(mpi.mp);	\	}					\	*ret = (Term); 				\	return RetVal; 			        \    } while(0)    mpi.mp = NULL;    sc.accum = NIL;    sc.lastobj = NULL;    sc.p = p;    sc.max = 1000;     sc.end_condition = NIL;    sc.keypos = tb->common.keypos;    sc.got = 0;    sc.chunk_size = chunk_size;    if ((errcode = analyze_pattern(tb, pattern, &mpi)) != DB_ERROR_NONE) {	RET_TO_BIF(NIL,errcode);    }    if (!mpi.something_can_match) {	RET_TO_BIF(am_EOT,DB_ERROR_NONE);	/* can't possibly match anything */    }    sc.mp = mpi.mp;    sc.all_objects = mpi.all_objects;    if (!mpi.got_partial && mpi.some_limitation && 	cmp(mpi.least,mpi.most) == 0) {	doit_select(tb,mpi.save_term,&sc, 0 /* direction doesn't matter */);	if (sc.accum != NIL) {	    hp=HAlloc(p, 3);	    RET_TO_BIF(TUPLE2(hp,sc.accum,am_EOT),DB_ERROR_NONE);	} else {	    RET_TO_BIF(am_EOT,DB_ERROR_NONE);	}    }    if (reverse) {	if (mpi.some_limitation) {	    if ((this = find_next_from_pb_key(tb, mpi.most)) != NULL) {		lastkey = GETKEY(tb, this->dbterm.tpl);	    }	    sc.end_condition = mpi.least;	}	traverse_backwards(tb, lastkey, &doit_select_chunk, &sc);    } else {	if (mpi.some_limitation) {	    if ((this = find_prev_from_pb_key(tb, mpi.least)) != NULL) {		lastkey = GETKEY(tb, this->dbterm.tpl);	    }	    sc.end_condition = mpi.most;	}	traverse_forward(tb, lastkey, &doit_select_chunk, &sc);    }    BUMP_REDS(p, 1000 - sc.max);    if (sc.max > 0) {	Eterm *hp; 	unsigned sz;	if (sc.got < chunk_size ||	    sc.lastobj == NULL) { 	    /* We haven't got all and we haven't trapped 	       which should mean we are at the end of the 	       table, sc.lastobj may be NULL if the table was empty */	    	    if (!sc.got) {		RET_TO_BIF(am_EOT, DB_ERROR_NONE);	    } else {		RET_TO_BIF(bif_trap3(&ets_select_reverse_exp, p,				     sc.accum, NIL, am_EOT), 			   DB_ERROR_NONE);	    }	}	key = GETKEY(tb, sc.lastobj);	sz = size_object(key);	hp = HAlloc(p, 9 + sz + PROC_BIN_SIZE);	key = copy_struct(key, sz, &hp, &MSO(p));	if (mpi.all_objects)	    (mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;	mpb = db_make_mp_binary(p,mpi.mp,&hp);		continuation = TUPLE8	    (hp,	     tb->common.id,	     key,	     sc.end_condition, /* From the match program, 				  needn't be copied */	     make_small(chunk_size),	     mpb,	     NIL,	     make_small(reverse),	     make_small(0));	/* Don't let RET_TO_BIF macro free mpi.mp*/	*ret = bif_trap3(&ets_select_reverse_exp, p,			 sc.accum, NIL, continuation);	return DB_ERROR_NONE;     }    key = GETKEY(tb, sc.lastobj);    sz = size_object(key);    hp = HAlloc(p, 9 + sz + PROC_BIN_SIZE);    key = copy_struct(key, sz, &hp, &MSO(p));    if (mpi.all_objects)	(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;    mpb = db_make_mp_binary(p,mpi.mp,&hp);        continuation = TUPLE8	(hp,	 tb->common.id,	 key,	 sc.end_condition, /* From the match program, needn't be copied */	 make_small(chunk_size),	 mpb,	 sc.accum,	 make_small(reverse),	 make_small(sc.got));    /* Don't let RET_TO_BIF macro free mpi.mp*/    *ret = bif_trap1(bif_export[BIF_ets_select_1], p, continuation);    return DB_ERROR_NONE;#undef RET_TO_BIF}/*** This is called when select_delete traps*/static int db_select_delete_continue_tree(Process *p, 					  DbTable *tbl,					  Eterm continuation,					  Eterm *ret){    DbTableTree *tb = &tbl->tree;    struct select_delete_context sc;    unsigned sz;    Eterm *hp;     Eterm lastkey;    Eterm end_condition;     Binary *mp;    Eterm key;    Eterm *tptr;    Eterm eaccsum;#define RET_TO_BIF(Term, State) do { 		\	if (sc.erase_lastterm) {		\	    free_term(tb, sc.lastterm);		\	}					\	*ret = (Term); 				\	return State; 				\    } while(0);    /* Decode continuation. We know it's correct, this can only be called       by trapping */    tptr = tuple_val(continuation);    lastkey = tptr[2];    end_condition = tptr[3];    sc.erase_lastterm = 0; /* Before first RET_TO_BIF */    sc.lastterm = NULL;    mp = ((ProcBin *) binary_val(tptr[4]))->val;    sc.p = p;    sc.tb = tb;    if (is_big(tptr[5])) {	sc.accum = big_to_uint32(tptr[5]);    } else {	sc.accum = unsigned_val(tptr[5]);    }    sc.mp = mp;    sc.end_condition = NIL;    sc.max = 1000;    sc.keypos = tb->common.keypos;    traverse_backwards(tb, lastkey, &doit_select_delete, &sc);    BUMP_REDS(p, 1000 - sc.max);    if (sc.max > 0) {	RET_TO_BIF(erts_make_integer(sc.accum, p), DB_ERROR_NONE);    }	    key = GETKEY(tb, (sc.lastterm)->dbterm.tpl);    if (end_condition != NIL && 	cmp_partly_bound(end_condition,key) > 0) { /* done anyway */	RET_TO_BIF(erts_make_integer(sc.accum,p),DB_ERROR_NONE);    }    /* Not done yet, let's trap. */    sz = size_object(key);    if (IS_USMALL(0, sc.accum)) {	hp = HAlloc(p, sz + 6);	eaccsum = make_small(sc.accum);    }    else {	hp = HAlloc(p, BIG_UINT_HEAP_SIZE + sz + 6);	eaccsum = uint_to_big(sc.accum, hp);	hp += BIG_UINT_HEAP_SIZE;    }    key = copy_struct(key, sz, &hp, &MSO(p));    continuation = TUPLE5	(hp,	 tptr[1],	 key,	 tptr[3], 	 tptr[4],	 eaccsum);    RET_TO_BIF(bif_trap1(&ets_select_delete_continue_exp, p, continuation), 	       DB_ERROR_NONE);#undef RET_TO_BIF}static int db_select_delete_tree(Process *p, DbTable *tbl, 				 Eterm pattern, Eterm *ret){    DbTableTree *tb = &tbl->tree;    struct select_delete_context sc;    struct mp_info mpi;    Eterm lastkey = NIL;    Eterm key;    Eterm continuation;    unsigned sz;    Eterm *hp;     TreeDbTerm *this;    int errcode;    Eterm mpb;    Eterm eaccsum;#define RET_TO_BIF(Term,RetVal) do { 	       	\	if (mpi.mp != NULL) {			\	    erts_match_set_free(mpi.mp);       	\	}					\	if (sc.erase_lastterm) {                \	    free_term(tb, sc.lastterm);         \	}                                       \	*ret = (Term); 				\	return RetVal; 			        \    } while(0)    mpi.mp = NULL;    sc.accum = 0;    sc.erase_lastterm = 0;    sc.lastterm = NULL;    sc.p = p;    sc.max = 1000;     sc.end_condition = NIL;    sc.keypos = tb->common.keypos;    sc.tb = tb;        if ((errcode = analyze_pattern(tb, pattern, &mpi)) != DB_ERROR_NONE) {	RET_TO_BIF(0,errcode);    }    if (!mpi.something_can_match) {	RET_TO_BIF(make_small(0),DB_ERROR_NONE);  	/* can't possibly match anything */    }    sc.mp = mpi.mp;    if (!mpi.got_partial && mpi.some_limitation && 	cmp(mpi.least,mpi.most) == 0) {	doit_select_delete(tb,mpi.save_term,&sc, 0 /* direction doesn't 						      matter */);

⌨️ 快捷键说明

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