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

📄 erl_node_tables.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ``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$ */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "global.h"#include "erl_node_tables.h"#include "dist.h"#include "big.h"#include "error.h"Hash erts_dist_table;Hash erts_node_table;erts_smp_mtx_t erts_dist_table_mtx;erts_smp_mtx_t erts_node_table_mtx;DistEntry *erts_hidden_dist_entries;DistEntry *erts_visible_dist_entries;DistEntry *erts_not_connected_dist_entries;Sint erts_no_of_hidden_dist_entries;Sint erts_no_of_visible_dist_entries;Sint erts_no_of_not_connected_dist_entries;DistEntry *erts_this_dist_entry;ErlNode *erts_this_node;static Uint node_entries;static Uint dist_entries;#ifdef ERTS_SMP#define ERTS_NO_OF_DIST_ENTRY_MUTEXES 32static erts_smp_mtx_t dist_entry_mutexes[ERTS_NO_OF_DIST_ENTRY_MUTEXES];#endifstatic int references_atoms_need_init = 1;/* -- The distribution table ---------------------------------------------- */#ifdef DEBUGstatic intis_in_de_list(DistEntry *dep, DistEntry *dep_list){    DistEntry *tdep;    for(tdep = dep_list; tdep; tdep = tdep->next)	if(tdep == dep)	    return 1;    return 0;}#endifstatic HashValuedist_table_hash(void *dep){    return atom_tab(atom_val(((DistEntry *) dep)->sysname))->slot.bucket.hvalue;}static intdist_table_cmp(void *dep1, void *dep2){    return (((DistEntry *) dep1)->sysname == ((DistEntry *) dep2)->sysname	    ? 0 : 1);}static void*dist_table_alloc(void *dep_tmpl){    DistEntry *dep;    if(((DistEntry *) dep_tmpl) == erts_this_dist_entry)	return dep_tmpl;    dep = (DistEntry *) erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));    dist_entries++;    dep->prev       = NULL;    erts_refc_init(&dep->refc, -1);    dep->sysname    = ((DistEntry *) dep_tmpl)->sysname;    dep->cid        = NIL;    dep->nlinks     = NULL;    dep->node_links = NULL;    dep->monitors   = NULL;    dep->status     = 0;    dep->flags      = 0;    dep->cache      = NULL;    dep->version    = 0;#ifdef ERTS_SMP    dep->mtxp       = &dist_entry_mutexes[(atom_val(dep->sysname)					   % ERTS_NO_OF_DIST_ENTRY_MUTEXES)];#endif    /* Link in */    /* All new dist entries are "not connected" */    dep->next = erts_not_connected_dist_entries;    if(erts_not_connected_dist_entries) {	ASSERT(erts_not_connected_dist_entries->prev == NULL);	erts_not_connected_dist_entries->prev = dep;    }    erts_not_connected_dist_entries = dep;    erts_no_of_not_connected_dist_entries++;    return (void *) dep;}static voiddist_table_free(void *vdep){    DistEntry *dep = (DistEntry *) vdep;    if(dep == erts_this_dist_entry)	return;    ASSERT(is_nil(dep->cid));    ASSERT(dep->nlinks == NULL);    ASSERT(dep->node_links == NULL);    ASSERT(dep->monitors == NULL);    /* Link out */    /* All dist entries about to be removed are "not connected" */    if(dep->prev) {	ASSERT(is_in_de_list(dep, erts_not_connected_dist_entries));	dep->prev->next = dep->next;    }    else {	ASSERT(erts_not_connected_dist_entries == dep);	erts_not_connected_dist_entries = dep->next;    }    if(dep->next)	dep->next->prev = dep->prev;    ASSERT(erts_no_of_not_connected_dist_entries > 0);    erts_no_of_not_connected_dist_entries--;    delete_cache((DistEntry *) dep);#ifdef DEBUG    sys_memset(vdep, 0x77, sizeof(DistEntry));#endif    erts_free(ERTS_ALC_T_DIST_ENTRY, (void *) dep);    ASSERT(dist_entries > 1);    dist_entries--;}voiderts_dist_table_info(int to, void *to_arg){    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_smp_mtx_lock(&erts_dist_table_mtx);    hash_info(to, to_arg, &erts_dist_table);    if (lock)	erts_smp_mtx_unlock(&erts_dist_table_mtx);}DistEntry *erts_channel_no_to_dist_entry(Uint cno){/* * For this node (and previous incarnations of this node), * ERST_INTERNAL_CHANNEL_NO (will always be 0 I guess) is used as * channel no. For other nodes, the atom index of the atom corresponding * to the node name is used as channel no. */    if(cno == ERST_INTERNAL_CHANNEL_NO) {	erts_refc_inc(&erts_this_dist_entry->refc, 2);	return erts_this_dist_entry;    }    if((cno > MAX_ATOM_INDEX)       || (cno >= atom_table_size())       ||  (atom_tab(cno) == NULL))	return NULL;            /* cno is a valid atom index; find corresponding dist entry (if there       is one) */    return erts_find_dist_entry(make_atom(cno));}DistEntry *erts_sysname_to_connected_dist_entry(Eterm sysname){    DistEntry de;    DistEntry *res_dep;    de.sysname = sysname;      if(erts_this_dist_entry->sysname == sysname) {	erts_refc_inc(&erts_this_dist_entry->refc, 2);	return erts_this_dist_entry;    }    erts_smp_mtx_lock(&erts_dist_table_mtx);    res_dep = (DistEntry *) hash_get(&erts_dist_table, (void *) &de);    if (res_dep) {	long refc = erts_refc_inctest(&res_dep->refc, 1);	if (refc < 2) /* Pending delete */	    erts_refc_inc(&res_dep->refc, 1);    }    erts_smp_mtx_unlock(&erts_dist_table_mtx);    if (res_dep) {	erts_smp_mtx_t *mtxp;#ifdef ERTS_SMP	mtxp = res_dep->mtxp;#else	mtxp = NULL;#endif	erts_smp_mtx_lock(mtxp);	if (is_nil(res_dep->cid)) {	    erts_deref_dist_entry(res_dep);	    res_dep = NULL;	}	erts_smp_mtx_unlock(mtxp);    }    return res_dep;}DistEntry *erts_find_or_insert_dist_entry(Eterm sysname){    DistEntry *res;    DistEntry de;    long refc;    de.sysname = sysname;    erts_smp_mtx_lock(&erts_dist_table_mtx);    res = hash_put(&erts_dist_table, (void *) &de);    refc = erts_refc_inctest(&res->refc, 0);    if (refc < 2) /* New or pending delete */	erts_refc_inc(&res->refc, 1);    erts_smp_mtx_unlock(&erts_dist_table_mtx);    return res;}DistEntry *erts_find_dist_entry(Eterm sysname){    DistEntry *res;    DistEntry de;    de.sysname = sysname;    erts_smp_mtx_lock(&erts_dist_table_mtx);    res = hash_get(&erts_dist_table, (void *) &de);    if (res) {	long refc = erts_refc_inctest(&res->refc, 1);	if (refc < 2) /* Pending delete */	    erts_refc_inc(&res->refc, 1);    }    erts_smp_mtx_unlock(&erts_dist_table_mtx);    return res;}void erts_delete_dist_entry(DistEntry *dep){    ASSERT(dep != erts_this_dist_entry);    if(dep != erts_this_dist_entry) {	erts_smp_mtx_lock(&erts_dist_table_mtx);	/*	 * Another thread might have looked up this dist entry after	 * we decided to delete it (refc became zero). If so, the other	 * thread incremented refc twice. Once for the new reference	 * and once for this thread. Therefore, delete dist entry if	 * refc is 0 or -1 after a decrement.	 */	if (erts_refc_dectest(&dep->refc, -1) <= 0)	    (void) hash_erase(&erts_dist_table, (void *) dep);	erts_smp_mtx_unlock(&erts_dist_table_mtx);    }}Uinterts_dist_table_size(void){    Uint res;#ifdef DEBUG    HashInfo hi;    DistEntry *dep;    int i;#endif    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_smp_mtx_lock(&erts_dist_table_mtx);#ifdef DEBUG    hash_get_info(&hi, &erts_dist_table);    ASSERT(dist_entries == hi.objs);    i = 0;    for(dep = erts_visible_dist_entries; dep; dep = dep->next)	i++;    ASSERT(i == erts_no_of_visible_dist_entries);    i = 0;    for(dep = erts_hidden_dist_entries; dep; dep = dep->next)	i++;    ASSERT(i == erts_no_of_hidden_dist_entries);    i = 0;    for(dep = erts_not_connected_dist_entries; dep; dep = dep->next)	i++;    ASSERT(i == erts_no_of_not_connected_dist_entries);    ASSERT(dist_entries == (erts_no_of_visible_dist_entries			    + erts_no_of_hidden_dist_entries			    + erts_no_of_not_connected_dist_entries			    + 1 /* erts_this_dist_entry */));#endif    res = (hash_table_sz(&erts_dist_table)	   + dist_entries*sizeof(DistEntry)	   + erts_dist_cache_size());    if (lock)	erts_smp_mtx_unlock(&erts_dist_table_mtx);    return res;}voiderts_set_dist_entry_not_connected(DistEntry *dep){    ERTS_SMP_LC_ASSERT(erts_lc_is_dist_entry_locked(dep));    erts_smp_mtx_lock(&erts_dist_table_mtx);    ASSERT(dep != erts_this_dist_entry);    ASSERT(is_internal_port(dep->cid));    if(dep->flags & DFLAG_PUBLISHED) {	if(dep->prev) {	    ASSERT(is_in_de_list(dep, erts_visible_dist_entries));	    dep->prev->next = dep->next;	}	else {	    ASSERT(erts_visible_dist_entries == dep);	    erts_visible_dist_entries = dep->next;	}	ASSERT(erts_no_of_visible_dist_entries > 0);	erts_no_of_visible_dist_entries--;    }    else {	if(dep->prev) {	    ASSERT(is_in_de_list(dep, erts_hidden_dist_entries));	    dep->prev->next = dep->next;	}	else {	    ASSERT(erts_hidden_dist_entries == dep);	    erts_hidden_dist_entries = dep->next;	}	ASSERT(erts_no_of_hidden_dist_entries > 0);	erts_no_of_hidden_dist_entries--;    }    if(dep->next)	dep->next->prev = dep->prev;    dep->status &= ~ERTS_DE_SFLG_CONNECTED;    dep->flags = 0;    dep->prev = NULL;    dep->cid = NIL;    dep->next = erts_not_connected_dist_entries;    if(erts_not_connected_dist_entries) {	ASSERT(erts_not_connected_dist_entries->prev == NULL);	erts_not_connected_dist_entries->prev = dep;    }    erts_not_connected_dist_entries = dep;    erts_no_of_not_connected_dist_entries++;    erts_smp_mtx_unlock(&erts_dist_table_mtx);}voiderts_set_dist_entry_connected(DistEntry *dep, Eterm cid, Uint flags){    ERTS_SMP_LC_ASSERT(erts_lc_is_dist_entry_locked(dep));    erts_smp_mtx_lock(&erts_dist_table_mtx);    ASSERT(dep != erts_this_dist_entry);    ASSERT(is_nil(dep->cid));    ASSERT(is_internal_port(cid));    if(dep->prev) {	ASSERT(is_in_de_list(dep, erts_not_connected_dist_entries));	dep->prev->next = dep->next;    }    else {	ASSERT(erts_not_connected_dist_entries == dep);	erts_not_connected_dist_entries = dep->next;    }    if(dep->next)	dep->next->prev = dep->prev;    ASSERT(erts_no_of_not_connected_dist_entries > 0);    erts_no_of_not_connected_dist_entries--;    dep->status |= ERTS_DE_SFLG_CONNECTED;    dep->flags = flags;    dep->cid = cid;    dep->prev = NULL;    if(flags & DFLAG_PUBLISHED) {	dep->next = erts_visible_dist_entries;	if(erts_visible_dist_entries) {	    ASSERT(erts_visible_dist_entries->prev == NULL);	    erts_visible_dist_entries->prev = dep;	}	erts_visible_dist_entries = dep;	erts_no_of_visible_dist_entries++;    }    else {	dep->next = erts_hidden_dist_entries;	if(erts_hidden_dist_entries) {	    ASSERT(erts_hidden_dist_entries->prev == NULL);	    erts_hidden_dist_entries->prev = dep;	}	erts_hidden_dist_entries = dep;	erts_no_of_hidden_dist_entries++;    }    erts_smp_mtx_unlock(&erts_dist_table_mtx);}/* -- Node table --------------------------------------------------------- *//* Some large primes */#define PRIME0 ((HashValue) 268438039)#define PRIME1 ((HashValue) 268440479)#define PRIME2 ((HashValue) 268439161)#define PRIME3 ((HashValue) 268437017)static HashValuenode_table_hash(void *venp){    Uint32 cre = ((ErlNode *) venp)->creation;    HashValue h = atom_tab(atom_val(((ErlNode *) venp)->sysname))->slot.bucket.hvalue;    h *= PRIME0;    h += cre & 0xff;#if MAX_CREATION >= (1 << 8)    h *= PRIME1;    h += (cre >> 8) & 0xff;#endif#if MAX_CREATION >= (1 << 16)    h *= PRIME2;    h += (cre >> 16) & 0xff;#endif#if MAX_CREATION >= (1 << 24)    h *= PRIME3;    h += (cre >> 24) & 0xff;#endif#if 0/* XXX Problems in older versions of GCC */ #if MAX_CREATION >= (1UL << 32) #error "MAX_CREATION larger than size of expected creation storage (Uint32)" #endif#endif    return h;}static intnode_table_cmp(void *venp1, void *venp2){    return ((((ErlNode *) venp1)->sysname == ((ErlNode *) venp2)->sysname	     && ((ErlNode *) venp1)->creation == ((ErlNode *) venp2)->creation)	    ? 0	    : 1);}static void*node_table_alloc(void *venp_tmpl){    ErlNode *enp;    if(((ErlNode *) venp_tmpl) == erts_this_node)	return venp_tmpl;    enp = (ErlNode *) erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode));    node_entries++;    erts_refc_init(&enp->refc, -1);    enp->creation = ((ErlNode *) venp_tmpl)->creation;    enp->sysname = ((ErlNode *) venp_tmpl)->sysname;    enp->dist_entry = erts_find_or_insert_dist_entry(((ErlNode *) venp_tmpl)->sysname);    return (void *) enp;}static voidnode_table_free(void *venp){    ErlNode *enp = (ErlNode *) venp;    if(enp == erts_this_node)	return;    erts_deref_dist_entry(enp->dist_entry);#ifdef DEBUG    sys_memset(venp, 0x55, sizeof(ErlNode));#endif    erts_free(ERTS_ALC_T_NODE_ENTRY, venp);    ASSERT(node_entries > 1);    node_entries--;}Uinterts_node_table_size(void){    Uint res;#ifdef DEBUG    HashInfo hi;#endif    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_smp_mtx_lock(&erts_node_table_mtx);#ifdef DEBUG    hash_get_info(&hi, &erts_node_table);    ASSERT(node_entries == hi.objs);

⌨️ 快捷键说明

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