diff options
Diffstat (limited to 'erts/emulator/beam/dist.c')
-rw-r--r-- | erts/emulator/beam/dist.c | 92 |
1 files changed, 68 insertions, 24 deletions
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index c16579037c..3e8c4c65b5 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -120,6 +120,7 @@ static void clear_dist_entry(DistEntry*); static int dsig_send_ctl(ErtsDSigData* dsdp, Eterm ctl, int force_busy); static void send_nodes_mon_msgs(Process *, Eterm, Eterm, Eterm, Eterm); static void init_nodes_monitors(void); +static Sint abort_pending_connection(DistEntry* dep, Uint32 conn_id); static erts_atomic_t no_caches; static erts_atomic_t no_nodes; @@ -3457,30 +3458,16 @@ BIF_RETTYPE new_connection_id_1(BIF_ALIST_1) BIF_RET(TUPLE2(hp, make_small(conn_id), dhandle)); } -BIF_RETTYPE abort_connection_id_2(BIF_ALIST_2) +static Sint abort_pending_connection(DistEntry* dep, Uint32 conn_id) { - DistEntry* dep; - Eterm* tp; - - if (is_not_atom(BIF_ARG_1) || is_not_tuple_arity(BIF_ARG_2, 2)) { - BIF_ERROR(BIF_P, BADARG); - } - tp = tuple_val(BIF_ARG_2); - dep = erts_dhandle_to_dist_entry(tp[2]); - if (is_not_small(tp[1]) || dep != erts_find_dist_entry(BIF_ARG_1)) { - BIF_ERROR(BIF_P, BADARG); - } - ASSERT(dep != erts_this_dist_entry); /* SVERK: What to do? */ - - if (!dep) { - BIF_RET(am_false); - } + Sint reds = 0; erts_de_rwlock(dep); - if (dep->status == ERTS_DE_SFLG_PENDING - && dep->connection_id == unsigned_val(tp[1])) { - + if (dep->status != ERTS_DE_SFLG_PENDING || dep->connection_id != conn_id) { + erts_de_rwunlock(dep); + } + else { NetExitsContext nec = {dep}; ErtsLink *nlinks; ErtsLink *node_links; @@ -3488,7 +3475,6 @@ BIF_RETTYPE abort_connection_id_2(BIF_ALIST_2) ErtsAtomCache *cache; ErtsDistOutputBuf *obuf; ErtsProcList *resume_procs; - Sint reds = 0; ASSERT(is_nil(dep->cid)); @@ -3529,13 +3515,71 @@ BIF_RETTYPE abort_connection_id_2(BIF_ALIST_2) delete_cache(cache); free_de_out_queues(dep, obuf); + } + return reds; +} - BIF_RET2(am_true, reds); +BIF_RETTYPE abort_connection_id_2(BIF_ALIST_2) +{ + DistEntry* dep; + Eterm* tp; + + if (is_not_atom(BIF_ARG_1) || is_not_tuple_arity(BIF_ARG_2, 2)) { + BIF_ERROR(BIF_P, BADARG); + } + tp = tuple_val(BIF_ARG_2); + dep = erts_dhandle_to_dist_entry(tp[2]); + if (is_not_small(tp[1]) || dep != erts_find_dist_entry(BIF_ARG_1)) { + BIF_ERROR(BIF_P, BADARG); } + ASSERT(dep != erts_this_dist_entry); /* SVERK: What to do? */ - erts_de_rwunlock(dep); + if (dep) { + Sint reds = abort_pending_connection(dep, unsigned_val(tp[1])); + BUMP_REDS(BIF_P, reds); + } + BIF_RET(am_true); +} - BIF_RET(am_false); +int erts_auto_connect(DistEntry* dep, Process *proc, ErtsProcLocks proc_locks) +{ + erts_de_rwlock(dep); + if (dep->status != 0) { + erts_de_rwunlock(dep); + } + else { + Process* net_kernel; + ErtsProcLocks nk_locks = ERTS_PROC_LOCK_MSGQ; + Eterm *hp; + ErlOffHeap *ohp; + ErtsMessage *mp; + Eterm msg, dhandle; + Uint32 conn_id; + + dep->status = ERTS_DE_SFLG_PENDING; + dep->flags = (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY); + dep->connection_id = (dep->connection_id + 1) & ERTS_DIST_CON_ID_MASK; + conn_id = dep->connection_id; + erts_de_rwunlock(dep); + + net_kernel = erts_whereis_process(proc, proc_locks, + am_net_kernel, nk_locks, 0); + if (!net_kernel) { + return 0; + } + + /* Send {auto_connect, Node, ConnId, DHandle} to net_kernel */ + mp = erts_alloc_message_heap(net_kernel, &nk_locks, + 5 + ERTS_MAGIC_REF_THING_SIZE, + &hp, &ohp); + dhandle = erts_build_dhandle(&hp, ohp, dep); + msg = TUPLE4(hp, am_auto_connect, dep->sysname, make_small(conn_id), + dhandle); + erts_queue_message(net_kernel, nk_locks, mp, msg, proc->common.id); + erts_proc_unlock(net_kernel, nk_locks); + } + + return 1; } /**********************************************************************/ |