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

📄 erl_db_util.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//* * Common utilities for the different types of db tables. * Mostly matching etc. */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "sys.h"#include "erl_vm.h"#include "global.h"#include "erl_process.h"#include "error.h"#define ERTS_WANT_DB_INTERNAL__#include "erl_db.h"#include "bif.h"#include "big.h"#include "erl_binary.h"#include "erl_db_util.h"/*** Flags for the guard bif's*//* These are offsets from the DCOMP_* value */#define DBIF_GUARD 1#define DBIF_BODY  0/* These are the DBIF flag bits corresponding to the DCOMP_* value. * If a bit is set, the BIF is allowed in that context. */#define DBIF_TABLE_GUARD (1 << (DCOMP_TABLE + DBIF_GUARD))#define DBIF_TABLE_BODY  (1 << (DCOMP_TABLE + DBIF_BODY))#define DBIF_TRACE_GUARD (1 << (DCOMP_TRACE + DBIF_GUARD))#define DBIF_TRACE_BODY  (1 << (DCOMP_TRACE + DBIF_BODY))#define DBIF_ALL \DBIF_TABLE_GUARD | DBIF_TABLE_BODY | DBIF_TRACE_GUARD | DBIF_TRACE_BODY/*** Some convenience macros for stacks (DMC == db_match_compile)*/#define DMC_DEFAULT_SIZE 25#define DMC_STACK_TYPE(Type) DMC_##Type##_stack#define DMC_DECLARE_STACK_TYPE(Type)            \typedef struct DMC_STACK_TYPE(Type) {		\    int pos;					\    int siz;					\    Type def[DMC_DEFAULT_SIZE];		        \    Type *data;					\} DMC_STACK_TYPE(Type)    #define DMC_INIT_STACK(Name) \     (Name).pos = 0; (Name).siz = DMC_DEFAULT_SIZE; (Name).data = (Name).def#define DMC_STACK_DATA(Name) (Name).data#define DMC_STACK_NUM(Name) (Name).pos#define DMC_PUSH(On, What)						\do {									\    if ((On).pos >= (On).siz) {						\	(On).siz *= 2;							\	(On).data							\	    = (((On).def == (On).data)					\	       ? memcpy(erts_alloc(ERTS_ALC_T_DB_MC_STK,		\				   (On).siz*sizeof(*((On).data))),	\			(On).def,					\			DMC_DEFAULT_SIZE*sizeof(*((On).data)))		\	       : erts_realloc(ERTS_ALC_T_DB_MC_STK,			\			      (void *) (On).data,			\			      (On).siz*sizeof(*((On).data))));		\    }									\    (On).data[(On).pos++] = What;					\} while (0)#define DMC_POP(From) (From).data[--(From).pos]#define DMC_TOP(From) (From).data[(From).pos - 1]#define DMC_EMPTY(Name) ((Name).pos == 0)#define DMC_PEEK(On, At) (On).data[At]     #define DMC_POKE(On, At, Value) ((On).data[At] = (Value))#define DMC_CLEAR(Name) (Name).pos = 0#define DMC_FREE(Name)							\do {									\    if ((Name).def != (Name).data)					\	erts_free(ERTS_ALC_T_DB_MC_STK, (Name).data);			\} while (0)static ERTS_INLINE Process *get_proc(Process *cp, Uint32 cp_locks, Eterm id, Uint32 id_locks){    Process *proc = erts_pid2proc(cp, cp_locks, id, id_locks);    if (!proc && is_atom(id))	proc = erts_whereis_process(cp, cp_locks, id, id_locks, 0);    return proc;}static Etermset_tracee_flags(Process *tracee_p, Eterm tracer, Uint d_flags, Uint e_flags) {    Eterm ret;    Uint flags;    if (tracer == NIL) {	flags = tracee_p->trace_flags & ~TRACEE_FLAGS;    }  else {	flags = ((tracee_p->trace_flags & ~d_flags) | e_flags);	if (! flags) tracer = NIL;    }    ret = tracee_p->tracer_proc != tracer || tracee_p->trace_flags != flags	? am_true : am_false;    tracee_p->tracer_proc = tracer;    tracee_p->trace_flags = flags;    return ret;}/*** Assuming all locks on tracee_p on entry**** Changes tracee_p->trace_flags and tracee_p->tracer_proc** according to input disable/enable flags and tracer.**** Returns am_true|am_false on success, am_true if value changed,** returns fail_term on failure. Fails if tracer pid or port is invalid.*/static Eterm set_match_trace(Process *tracee_p, Eterm fail_term, Eterm tracer,		Uint d_flags, Uint e_flags) {    Eterm ret = fail_term;    Process *tracer_p;        ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCKS_ALL == 		       erts_proc_lc_my_proc_locks(tracee_p));    if (is_internal_pid(tracer)	&& (tracer_p = 	    erts_pid2proc(tracee_p, ERTS_PROC_LOCKS_ALL,			  tracer, ERTS_PROC_LOCKS_ALL))) {	if (tracee_p != tracer_p) {	    ret = set_tracee_flags(tracee_p, tracer, d_flags, e_flags);	    tracer_p->trace_flags |= tracee_p->trace_flags ? F_TRACER : 0;	    erts_smp_proc_unlock(tracer_p, ERTS_PROC_LOCKS_ALL);	}    } else if (is_internal_port(tracer)) {	Port *tracer_port = 	    erts_id2port(tracer, tracee_p, ERTS_PROC_LOCKS_ALL);	if (tracer_port) {	    if (! INVALID_TRACER_PORT(tracer_port, tracer)) {		ret = set_tracee_flags(tracee_p, tracer, d_flags, e_flags);	    }	    erts_smp_port_unlock(tracer_port);	}    } else {	ASSERT(is_nil(tracer));	ret = set_tracee_flags(tracee_p, tracer, d_flags, e_flags);    }    return ret;}/* Type checking... */#define BOXED_IS_TUPLE(Boxed) is_arity_value(*boxed_val((Boxed)))/***** Types and enum's (compiled matches)***//*** match VM instructions*/typedef enum {    matchArray, /* Only when parameter is an array (DCOMP_TRACE) */    matchArrayBind, /* ------------- " ------------ */    matchTuple,    matchPushT,    matchPushL,    matchPop,    matchBind,    matchCmp,    matchEqBin,    matchEqFloat,    matchEqBig,    matchEqRef,    matchEq,    matchList,    matchSkip,    matchPushC,    matchConsA, /* Car is below Cdr */    matchConsB, /* Cdr is below Car (unusual) */    matchMkTuple,    matchCall0,    matchCall1,    matchCall2,    matchCall3,    matchPushV,    matchPushExpr, /* Push the whole expression we're matching ('$_') */    matchPushArrayAsList, /* Only when parameter is an Array and 			     not an erlang term  (DCOMP_TRACE) */    matchPushArrayAsListU, /* As above but unknown size */    matchTrue,    matchOr,    matchAnd,    matchOrElse,    matchAndThen,    matchSelf,    matchWaste,    matchReturn,    matchProcessDump,    matchDisplay,    matchIsSeqTrace,    matchSetSeqToken,    matchGetSeqToken,    matchSetReturnTrace,    matchSetExceptionTrace,    matchCatch,    matchEnableTrace,    matchDisableTrace,    matchEnableTrace2,    matchDisableTrace2,    matchTryMeElse,    matchCaller,    matchHalt,    matchSilent,    matchSetSeqTokenFake,    matchTrace2,    matchTrace3} MatchOps;/*** Guard bif's*/typedef struct dmc_guard_bif {    Eterm name; /* atom */    void *biff;    /*    BIF_RETTYPE (*biff)(); */    int arity;    Uint32 flags;} DMCGuardBif; /*** Error information (for lint)*//*** Type declarations for stacks*/DMC_DECLARE_STACK_TYPE(Eterm);DMC_DECLARE_STACK_TYPE(Uint);DMC_DECLARE_STACK_TYPE(unsigned);/*** Data about the heap during compilation*/typedef struct DMCHeap {    int size;    unsigned def[DMC_DEFAULT_SIZE];    unsigned *data;    int used;} DMCHeap;/*** Return values from sub compilation steps (guard compilation)*/typedef enum dmc_ret {     retOk,     retFail,     retRestart } DMCRet; /*** Diverse context information*/typedef struct dmc_context {    int stack_need;    int stack_used;    ErlHeapFragment *save;    ErlHeapFragment *copy;    Eterm *matchexpr;    Eterm *guardexpr;    Eterm *bodyexpr;    int num_match;    int current_match;    int eheap_need;    Uint cflags;    DMC_STACK_TYPE(Uint) *labels;    int is_guard; /* 1 if in guard, 0 if in body */    int special; /* 1 if the head in the match was a single expression */     DMCErrInfo *err_info;} DMCContext;/***** Global variables ***//*** Internal*//* ** The pseudo process used by the VM (pam).*/#define ERTS_DEFAULT_MS_HEAP_SIZE 128typedef struct {    Process process;    Eterm *heap;    Eterm default_heap[ERTS_DEFAULT_MS_HEAP_SIZE];} ErtsMatchPseudoProcess;#ifdef ERTS_SMPstatic erts_smp_tsd_key_t match_pseudo_process_key;#elsestatic ErtsMatchPseudoProcess *match_pseudo_process;#endifstatic ERTS_INLINE voidcleanup_match_pseudo_process(ErtsMatchPseudoProcess *mpsp, int keep_heap){    if (mpsp->process.mbuf	|| mpsp->process.off_heap.mso#ifndef HYBRID /* FIND ME! */	|| mpsp->process.off_heap.funs#endif	|| mpsp->process.off_heap.externals) {	erts_cleanup_empty_process(&mpsp->process);    }#ifdef DEBUG    else {	erts_debug_verify_clean_empty_process(&mpsp->process);    }#endif    if (!keep_heap) {	if (mpsp->heap != &mpsp->default_heap[0]) {	    /* Have to be done *after* call to erts_cleanup_empty_process() */	    erts_free(ERTS_ALC_T_DB_MS_RUN_HEAP, (void *) mpsp->heap);	    mpsp->heap = &mpsp->default_heap[0];	}#ifdef DEBUG	else {	    int i;	    for (i = 0; i < ERTS_DEFAULT_MS_HEAP_SIZE; i++) {#ifdef ARCH_64		mpsp->default_heap[i] = (Eterm) 0xdeadbeefdeadbeef;#else		mpsp->default_heap[i] = (Eterm) 0xdeadbeef;#endif	    }	}#endif    }}static ErtsMatchPseudoProcess *create_match_pseudo_process(void){    ErtsMatchPseudoProcess *mpsp;    mpsp = (ErtsMatchPseudoProcess *)erts_alloc(ERTS_ALC_T_DB_MS_PSDO_PROC,						sizeof(ErtsMatchPseudoProcess));    erts_init_empty_process(&mpsp->process);    mpsp->heap = &mpsp->default_heap[0];    return mpsp;}static ERTS_INLINE ErtsMatchPseudoProcess *get_match_pseudo_process(Process *c_p, Uint heap_size){    ErtsMatchPseudoProcess *mpsp;#ifdef ERTS_SMP    mpsp = (ErtsMatchPseudoProcess *) c_p->scheduler_data->match_pseudo_process;    if (mpsp)	cleanup_match_pseudo_process(mpsp, 0);    else {	ASSERT(erts_smp_tsd_get(match_pseudo_process_key) == NULL);	mpsp = create_match_pseudo_process();	c_p->scheduler_data->match_pseudo_process = (void *) mpsp;	erts_smp_tsd_set(match_pseudo_process_key, (void *) mpsp);    }    ASSERT(mpsp == erts_smp_tsd_get(match_pseudo_process_key));    mpsp->process.scheduler_data = c_p->scheduler_data;#else    mpsp = match_pseudo_process;    cleanup_match_pseudo_process(mpsp, 0);#endif    if (heap_size > ERTS_DEFAULT_MS_HEAP_SIZE)	mpsp->heap = (Eterm *) erts_alloc(ERTS_ALC_T_DB_MS_RUN_HEAP,					  heap_size*sizeof(Uint));    else {	ASSERT(mpsp->heap == &mpsp->default_heap[0]);    }    return mpsp;}#ifdef ERTS_SMPstatic voiddestroy_match_pseudo_process(void){    ErtsMatchPseudoProcess *mpsp;    mpsp = (ErtsMatchPseudoProcess *)erts_smp_tsd_get(match_pseudo_process_key);    if (mpsp) {	cleanup_match_pseudo_process(mpsp, 0);	erts_free(ERTS_ALC_T_DB_MS_PSDO_PROC, (void *) mpsp);	erts_smp_tsd_set(match_pseudo_process_key, (void *) NULL);    }}#endifstaticvoidmatch_pseudo_process_init(void){#ifdef ERTS_SMP    erts_smp_tsd_key_create(&match_pseudo_process_key);    erts_smp_install_exit_handler(destroy_match_pseudo_process);#else    match_pseudo_process = create_match_pseudo_process();#endif}voiderts_match_set_release_result(Process* c_p){    (void) get_match_pseudo_process(c_p, 0); /* Clean it up */}/* The trace control word. */static erts_smp_atomic_t trace_control_word;Etermerts_ets_copy_object(Eterm obj, Process* to){    Uint size = size_object(obj);    Eterm* hp = HAlloc(to, size);    Eterm res;    res = copy_struct(obj, size, &hp, &MSO(to));#ifdef DEBUG    if (eq(obj, res) == 0) {	erl_exit(1, "copy not equal to source\n");    }#endif    return res;}/* This needs to be here, before the bif table... */static Eterm db_set_trace_control_word_fake_1(Process *p, Eterm val);/*** The table of callable bif's, i e guard bif's and ** some special animals that can provide us with trace** information. This array is sorted on init.*/static DMCGuardBif guard_tab[] ={    {	am_is_atom,	&is_atom_1,	1,	DBIF_ALL    },    {	am_is_constant,	&is_constant_1,	1,	DBIF_ALL    },        {	am_is_float,	&is_float_1,	1,	DBIF_ALL    },    {	am_is_integer,	&is_integer_1,	1,	DBIF_ALL    },    {	am_is_list,	&is_list_1,	1,	DBIF_ALL    },    {	am_is_number,	&is_number_1,	1,	DBIF_ALL    },    {	am_is_pid,	&is_pid_1,	1,	DBIF_ALL    },    {	am_is_port,	&is_port_1,	1,	DBIF_ALL    },    {	am_is_reference,	&is_reference_1,	1,	DBIF_ALL    },    {	am_is_tuple,	&is_tuple_1,	1,	DBIF_ALL    },    {	am_is_binary,	&is_binary_1,	1,	DBIF_ALL

⌨️ 快捷键说明

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