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

📄 erl_db_util.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 5 页
字号:
 */Eterm db_make_mp_binary(Process *p, Binary *mp, Eterm **hpp) {    ProcBin *pb;    erts_refc_inc(&mp->refc, 1);    pb = (ProcBin *) *hpp;    *hpp += PROC_BIN_SIZE;    pb->thing_word = HEADER_PROC_BIN;    pb->size = 0;    pb->next = MSO(p).mso;    MSO(p).mso = pb;    pb->val = mp;    pb->bytes = (byte*) mp->orig_bytes;    return make_binary(pb);}DMCErrInfo *db_new_dmc_err_info(void) {    DMCErrInfo *ret = erts_alloc(ERTS_ALC_T_DB_DMC_ERR_INFO,				 sizeof(DMCErrInfo));    ret->var_trans = NULL;    ret->num_trans = 0;    ret->error_added = 0;    ret->first = NULL;    return ret;}Eterm db_format_dmc_err_info(Process *p, DMCErrInfo *ei){    int ll,sl;    int vnum;    DMCError *tmp;    Eterm *lhp, *shp;    Eterm ret = NIL, tpl, sev;    char buff[DMC_ERR_STR_LEN + 20 /* for the number */];    ll = 0;    for (tmp = ei->first; tmp != NULL; tmp = tmp->next)	++ll;    lhp = HAlloc(p, ll * (2 /*cons cell*/ + 3 /*tuple of arity 2*/));    for (tmp = ei->first; tmp != NULL; tmp = tmp->next) {	if (tmp->variable >= 0 && 	    tmp->variable < ei->num_trans &&	    ei->var_trans != NULL) {	    vnum = (int) ei->var_trans[tmp->variable];	} else {	    vnum = tmp->variable;	}	if (vnum >= 0)	    sprintf(buff,tmp->error_string, vnum);	else	    strcpy(buff,tmp->error_string);	sl = strlen(buff);	shp = HAlloc(p, sl * 2);	sev = (tmp->severity == dmcWarning) ? 	    am_atom_put("warning",7) :	    am_error;	tpl = TUPLE2(lhp, sev, buf_to_intlist(&shp, buff, sl, NIL));	lhp += 3;	ret = CONS(lhp, tpl, ret);	lhp += 2;    }    return ret;}void db_free_dmc_err_info(DMCErrInfo *ei){    while (ei->first != NULL) {	DMCError *ll = ei->first->next;	erts_free(ERTS_ALC_T_DB_DMC_ERROR, ei->first);	ei->first = ll;    }    if (ei->var_trans)	erts_free(ERTS_ALC_T_DB_TRANS_TAB, ei->var_trans);    erts_free(ERTS_ALC_T_DB_DMC_ERR_INFO, ei);}#define FIX_BIG_SIZE 16#define MAX_NEED(x,y) (((x)>(y)) ? (x) : (y))static Eterm  big_tmp[2];static Eterm  db_big_buf[FIX_BIG_SIZE];static Eterm add_counter(Eterm counter, Eterm incr){    Eterm res;    Sint ires;    Eterm arg1;    Eterm arg2;    Uint sz1;    Uint sz2;    Uint need;    Eterm *ptr;    int i;    if (is_small(counter) && is_small(incr)) {	ires = signed_val(counter) + signed_val(incr);	if (IS_SSMALL(ires))	    return make_small(ires);	else	    return small_to_big(ires, db_big_buf);    }    else {	switch(i = NUMBER_CODE(counter, incr)) {	case SMALL_BIG:	    arg1 = small_to_big(signed_val(counter), big_tmp);	    arg2 = incr;	    break;	case BIG_SMALL:	    arg1 = counter;	    arg2 = small_to_big(signed_val(incr), big_tmp);	    break;	case BIG_BIG:	    arg1 = incr;	    arg2 = counter;	    break;	default:	    return THE_NON_VALUE;	}	sz1 = big_size(arg1);	sz2 = big_size(arg2);	sz1 = MAX_NEED(sz1,sz2)+1;	need = BIG_NEED_SIZE(sz1);	if (need <= FIX_BIG_SIZE)	    ptr = db_big_buf;	else {	    ptr = (Eterm *) erts_alloc_fnf(ERTS_ALC_T_DB_TMP,					   need*sizeof(Eterm));	    if (!ptr)		return NIL;  /* system limit */	}	res = big_plus(arg1, arg2, ptr);	if (is_small(res) || is_nil(res)) {	    if (ptr != db_big_buf)		erts_free(ERTS_ALC_T_DB_TMP, (void *) ptr);	}	return res;    }}/*** The actual update of a counter, a lot of parameters are needed:** p: The calling process (BIF_P), ** bp: A pointer to the pointer to the object to be updated (extra ** indirection for the reallocation), this pointer is only used to** pass information to the realloc function.** tpl: A pointer to the tuple in the DbTerm.** keypos: The key position in the DbTerm.** realloc_fun: A function that does the reallocation, it takes ** bp, new size, new_value and keypos as parameter. ** ret: pointer to where the result is put.** Returns normal DB error code.*/int db_do_update_counter(Process *p,			 DbTableCommon *tb, void *bp /* XDbTerm **bp */, 			 Eterm *tpl, int counterpos,			 int (*realloc_fun)(DbTableCommon *,					    void *,					    Uint,					    Eterm,					    int),			 Eterm incr,			 int warp,			 Eterm *ret){    Eterm counter;    Eterm *counterp;    Eterm res; /* In register? */    if (arityval(*tpl) < counterpos || !(is_small(tpl[counterpos]) ||					 is_big(tpl[counterpos])))	return DB_ERROR_BADITEM;    counterp = tpl + counterpos;    counter = *counterp;    if (warp) {	if (is_small(incr)) {	    res = incr;	} else {	    /* copy to buffer */	    Eterm *tmp;	    Eterm *p = big_val(incr);	    Uint psz = BIG_ARITY(p)+1;	    if (psz > FIX_BIG_SIZE) {		tmp = db_big_buf;	    } else {		tmp = (Eterm *) erts_alloc_fnf(ERTS_ALC_T_DB_TMP,					       psz*sizeof(Eterm));		if (!tmp)		    return DB_ERROR_SYSRES;	    }	    sys_memcpy(tmp, p, psz*sizeof(Eterm));	    res = make_big(tmp);	}		    } else {	if ((res = add_counter(counter, incr)) == NIL) {	    return DB_ERROR_SYSRES;	} else if (is_non_value(res)) {	    return DB_ERROR_UNSPEC;	}    }    if (is_small(res)) {	if (is_small(counter)) {	    *counterp = res;	} else {	    if ((*realloc_fun)(tb, bp, 0, res, counterpos) < 0) 		return DB_ERROR_SYSRES;	}	*ret = res;	return DB_ERROR_NONE;    } else {	Eterm *ptr = big_val(res);	Uint sz = BIG_ARITY(ptr) + 1;	Eterm *hp;	if ((*realloc_fun)(tb, bp, sz, res, counterpos) < 0) 	    return DB_ERROR_SYSRES;	hp = HAlloc(p, sz);	sys_memcpy(hp, ptr, sz*sizeof(Eterm));	res = make_big(hp);	hp += sz;	if (ptr != db_big_buf)	    erts_free(ERTS_ALC_T_DB_TMP, (void *) ptr);	*ret = res;	return DB_ERROR_NONE;    }}   /*** Copy the object into a possibly new DbTerm, ** offset is the offset of the DbTerm from the start** of the sysAllocaed structure, The possibly realloced and copied** structure is returned. Make sure (((char *) old) - offset) is a ** pointer to a ERTS_ALC_T_DB_TERM allocated data area.*/void* db_get_term(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj){    int size = size_object(obj);    void *structp = ((char*) old) - offset;    DbTerm* p;    Eterm copy;    Eterm *top;    if (old != 0) {	erts_cleanup_offheap(&old->off_heap);	if (size == old->size) {	    p = old;	} else {	    Uint new_sz = offset + sizeof(DbTerm) + sizeof(Eterm)*(size-1);	    Uint old_sz = offset + sizeof(DbTerm) + sizeof(Eterm)*(old->size-1);	    if (erts_ets_realloc_always_moves) {		void *nstructp = erts_db_alloc(ERTS_ALC_T_DB_TERM,					       (DbTable *) tb,					       new_sz);		memcpy(nstructp,structp,offset);		erts_db_free(ERTS_ALC_T_DB_TERM,			     (DbTable *) tb,			     structp,			     old_sz);		structp = nstructp;	    } else {		structp = erts_db_realloc(ERTS_ALC_T_DB_TERM,					  (DbTable *) tb,					  structp,					  old_sz,					  new_sz);	    }	    p = (DbTerm*) ((void *)(((char *) structp) + offset));	}    }    else {	structp = erts_db_alloc(ERTS_ALC_T_DB_TERM,				(DbTable *) tb,				(offset				 + sizeof(DbTerm)				 + sizeof(Eterm)*(size-1)));	p = (DbTerm*) ((void *)(((char *) structp) + offset));    }    p->size = size;    p->off_heap.mso = NULL;    p->off_heap.externals = NULL;#ifndef HYBRID /* FIND ME! */    p->off_heap.funs = NULL;#endif    p->off_heap.overhead = 0;    top = p->v;    copy = copy_struct(obj, size, &top, &p->off_heap);    p->tpl = tuple_val(copy);    return structp;}void db_free_term_data(DbTerm* p){    erts_cleanup_offheap(&p->off_heap);}/*** Copy the new counter value into the DbTerm at ((char *) *bp) + offset,** Allocate new structure of (needed size + offset) if that DbTerm** is to small. When changing size, the old structure is ** freed using ERTS_ALC_T_DB_TERM, make sure this can be done** (((char *) b) - offset is a pointer to a ERTS_ALC_T_DB_TERM area).** bp is a pure out parameter, i e it does not have to** point to (((char *) b) - offset) when calling.*/int db_realloc_counter(DbTableCommon *tb,		       void** bp, DbTerm *b, Uint offset, Uint sz, 		       Eterm new_counter, int counterpos){    DbTerm* new;    void *newbp;    Eterm  old_counter;    Uint  old_sz;    Uint  new_sz;    Uint  basic_sz;    Eterm  copy;    Eterm *top;    Eterm *ptr;    old_counter = b->tpl[counterpos];    if (is_small(old_counter))	old_sz = 0;    else {	top = big_val(old_counter);	old_sz = BIG_ARITY(top) + 1;	if (sz == old_sz) {  /* OK we fit in old space */	    sys_memcpy(top, big_val(new_counter), sz*sizeof(Eterm));	    return 0;	}    }    basic_sz = b->size - old_sz;    new_sz = basic_sz + sz;    newbp = erts_db_alloc(ERTS_ALC_T_DB_TERM,			  (DbTable *) tb,			  sizeof(DbTerm)+sizeof(Eterm)*(new_sz-1)+offset);    if (newbp == NULL)	return -1;    new = (DbTerm*) ((void *)(((char *) newbp) + offset));    memcpy(newbp, ((char *) b) - offset, offset);        new->size = new_sz;    new->off_heap.mso = NULL;    new->off_heap.externals = NULL;#ifndef HYBRID /* FIND ME! */    new->off_heap.funs = NULL;#endif    new->off_heap.overhead = 0;    top = new->v;    b->tpl[counterpos] = SMALL_ZERO;               /* zap, do not copy */    /* copy term (except old counter) */    copy = copy_struct(make_tuple(b->tpl), basic_sz, 		       &top, &new->off_heap);    new->tpl = tuple_val(copy);    db_free_term_data(b);    /* free old term */    erts_db_free(ERTS_ALC_T_DB_TERM,		 (DbTable *) tb,		 (void *) (((char *) b) - offset),		 offset + sizeof(DbTerm) + sizeof(Eterm)*(b->size-1));    *bp = newbp;     /* patch new */    /* copy new counter */    if (sz == 0)	new->tpl[counterpos] = new_counter;  /* must be small !!! */    else {	ptr = big_val(new_counter);	sys_memcpy(top, ptr, sz*sizeof(Eterm));	new->tpl[counterpos] = make_big(top);    }    return 0;}/*** Check if object represents a "match" variable ** i.e and atom $N where N is an integer ***/int db_is_variable(Eterm obj){    byte *b;    int n;    int N;    if (is_not_atom(obj))        return -1;    b = atom_tab(atom_val(obj))->name;    if ((n = atom_tab(atom_val(obj))->len) < 2)        return -1;    if (*b++ != '$')        return -1;    n--;    /* Handle first digit */    if (*b == '0')        return (n == 1) ? 0 : -1;    if (*b >= '1' && *b <= '9')        N = *b++ - '0';    else        return -1;    n--;    while(n--) {        if (*b >= '0' && *b <= '9') {            N = N*10 + (*b - '0');            b++;        }        else            return -1;    }    return N;}/* check if obj is (or contains) a variable *//* return 1 if obj contains a variable or underscore *//* return 0 if obj is fully ground                   */int db_has_variable(Eterm obj){    switch(obj & _TAG_PRIMARY_MASK) {    case TAG_PRIMARY_LIST: {	while (is_list(obj)) {	    if (db_has_variable(CAR(list_val(obj))))		return 1;	    obj = CDR(list_val(obj));	}	return(db_has_variable(obj));  /* Non wellformed list or [] */    }    case TAG_PRIMARY_BOXED: 	if (!BOXED_IS_TUPLE(obj)) {	    return 0;	} else {	    Eterm *tuple = tuple_val(obj);	    int arity = arityval(*tuple++);	    while(arity--) {		if (db_has_variable(*tuple))		    return 1;		tuple++;	    }	    return(0);	}    case TAG_PRIMARY_IMMED1:	if (obj == am_Underscore || db_is_variable(obj) >= 0)	    return 1;    }    return 0;}int erts_db_is_compiled_ms(Eterm term){    return (!is_binary(term) || 	    !(thing_subtag(*binary_val(term)) == REFC_BINARY_SUBTAG) ||	    !((((ProcBin *) binary_val(term))->val)->flags & 	      BIN_FLAG_MATCH_PROG)) ? 0 : 1;}/* ** Local (static) utilities.*//****************************************************************************** Compiled matches ****************************************************************************//*** Utility to add an error*/static void add_dmc_err(DMCErrInfo *err_info, 			char *str,			int variable,			Eterm term,			DMCErrorSeverity severity){    /* Linked in in reverse order, to ease the formatting */    DMCError *e = erts_alloc(ERTS_ALC_T_DB_DMC_ERROR, sizeof(DMCError));    if (term != 0UL) {	erts_snprintf(e->error_string, DMC_ERR_STR_LEN, str, term);    } else {	strncpy(e->error_string, str, DMC_ERR_STR_LEN);	e->error_string[DMC_ERR_STR_LEN] ='\0';    }    e->variable = variable;    e->severity = severity;    e->next = err_info->first;#ifdef HARDDEBUG    erts_fprintf(stderr,"add_dmc_err: %s\n",e->error_string);#endif    err_info->first = e;    if (severity >= dmcError)	err_info->error_added = 1;}    /*** Handle one term in the match expression (not the guard) */static DMCRet dmc_one_term(DMCContext *context, 			   DMCHeap *heap,			   DMC_STACK_TYPE(Eterm) *stack,			   DMC_STACK_TYPE(Uint) *text,			   Eterm c){    Sint n;    Eterm *hp;    ErlHeapFragment *tmp_mb;    Uint sz, sz2, sz3;    Uint i, j;    switch (c & _TAG_PRIMARY_MASK) {    case TAG_PRIMARY_IMMED1:	if ((n = db_is_variable(c)) >= 0) { /* variable */	    if (n >= heap->size) {		/*		** Ouch, big integer in match variable.		*/		Eterm *save_hp;		ASSERT(heap->data == heap->def);		sz = sz2 = sz3 = 0;		for (j = 0; j < context->num_match; ++j) {		    sz += size_object(context->matchexpr[j]);		    sz2 += size_object(context->guardexpr[j]);		    sz3 += size_object(context->bodyexpr[j]);		}		context->copy = 		    new_message_buffer(sz + sz2 + sz3 +				       context->num_match);		save_hp = hp = context->copy->mem;		hp += context->num_match;		for (j = 0; j < context->num_match; ++j) {		    context->matchexpr[j] = 			copy_struct(context->matchexpr[j], 				    size_object(context->matchexpr[j]), &hp, 				    &(context->copy->off_heap));		    context->guardexpr[j] = 			copy_struct(context->guardexpr[j], 				    size_object(context->guardexpr[j]), &hp, 				    &(context->copy->off_heap));		    context->bodyexpr[j] = 			copy_struct(context->bodyexpr[j], 				    size_object(context->bodyexpr[j]), &hp, 				    &(context->copy->off_heap));		}		for (j = 0; j < context->num_match; ++j) {		 

⌨️ 快捷键说明

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