1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2000-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 package com.ericsson.otp.erlang;
21 
22 /**
23  * This class represents local node types. It is used to group the node types
24  * {@link OtpNode OtpNode} and {@link OtpSelf OtpSelf}.
25  */
26 public class OtpLocalNode extends AbstractNode {
27     private int serial = 0;
28     private int pidCount = 1;
29     private int portCount = 1;
30     private int refId[];
31 
32     protected int port;
33     protected OtpTransport epmd;
34 
35     /**
36      * Create a node with the given name and the default cookie.
37      */
OtpLocalNode(final String node)38     protected OtpLocalNode(final String node) {
39         super(node);
40         init();
41     }
42 
43     /**
44      * Create a node with the given name, transport factory and the default
45      * cookie.
46      */
OtpLocalNode(final String node, final OtpTransportFactory transportFactory)47     protected OtpLocalNode(final String node,
48             final OtpTransportFactory transportFactory) {
49         super(node, transportFactory);
50         init();
51     }
52 
53     /**
54      * Create a node with the given name and cookie.
55      */
OtpLocalNode(final String node, final String cookie)56     protected OtpLocalNode(final String node, final String cookie) {
57         super(node, cookie);
58         init();
59     }
60 
61     /**
62      * Create a node with the given name, cookie and transport factory.
63      */
OtpLocalNode(final String node, final String cookie, final OtpTransportFactory transportFactory)64     protected OtpLocalNode(final String node, final String cookie,
65             final OtpTransportFactory transportFactory) {
66         super(node, cookie, transportFactory);
67         init();
68     }
69 
init()70     private void init() {
71         serial = 0;
72         pidCount = 1;
73         portCount = 1;
74         refId = new int[3];
75         refId[0] = 1;
76         refId[1] = 0;
77         refId[2] = 0;
78     }
79 
80     /**
81      * Get the port number used by this node.
82      *
83      * @return the port number this server node is accepting connections on.
84      */
port()85     public int port() {
86         return port;
87     }
88 
89     /**
90      * Set the Epmd socket after publishing this nodes listen port to Epmd.
91      *
92      * @param s
93      *            The socket connecting this node to Epmd.
94      */
setEpmd(final OtpTransport s)95     protected void setEpmd(final OtpTransport s) {
96         epmd = s;
97     }
98 
99     /**
100      * Get the Epmd socket.
101      *
102      * @return The socket connecting this node to Epmd.
103      */
getEpmd()104     protected OtpTransport getEpmd() {
105         return epmd;
106     }
107 
108     /**
109      * Create an Erlang {@link OtpErlangPid pid}. Erlang pids are based upon
110      * some node specific information; this method creates a pid using the
111      * information in this node. Each call to this method produces a unique pid.
112      *
113      * @return an Erlang pid.
114      */
createPid()115     public synchronized OtpErlangPid createPid() {
116         final OtpErlangPid p = new OtpErlangPid(node, pidCount, serial,
117                 creation);
118 
119         pidCount++;
120         if (pidCount > 0x7fff) {
121             pidCount = 0;
122 
123             serial++;
124             if (serial > 0x1fff) { /* 13 bits */
125                 serial = 0;
126             }
127         }
128 
129         return p;
130     }
131 
132     /**
133      * Create an Erlang {@link OtpErlangPort port}. Erlang ports are based upon
134      * some node specific information; this method creates a port using the
135      * information in this node. Each call to this method produces a unique
136      * port. It may not be meaningful to create a port in a non-Erlang
137      * environment, but this method is provided for completeness.
138      *
139      * @return an Erlang port.
140      */
createPort()141     public synchronized OtpErlangPort createPort() {
142         final OtpErlangPort p = new OtpErlangPort(node, portCount, creation);
143 
144         portCount++;
145         if (portCount > 0xfffffff) { /* 28 bits */
146             portCount = 0;
147         }
148 
149         return p;
150     }
151 
152     /**
153      * Create an Erlang {@link OtpErlangRef reference}. Erlang references are
154      * based upon some node specific information; this method creates a
155      * reference using the information in this node. Each call to this method
156      * produces a unique reference.
157      *
158      * @return an Erlang reference.
159      */
createRef()160     public synchronized OtpErlangRef createRef() {
161         final OtpErlangRef r = new OtpErlangRef(node, refId, creation);
162 
163         // increment ref ids (3 ints: 18 + 32 + 32 bits)
164         refId[0]++;
165         if (refId[0] > 0x3ffff) {
166             refId[0] = 0;
167 
168             refId[1]++;
169             if (refId[1] == 0) {
170                 refId[2]++;
171             }
172         }
173 
174         return r;
175     }
176 }
177