diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/erl_interface/doc/src | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/erl_interface/doc/src')
28 files changed, 7008 insertions, 0 deletions
diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile new file mode 100644 index 0000000000..e05b647cb2 --- /dev/null +++ b/lib/erl_interface/doc/src/Makefile @@ -0,0 +1,129 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1998-2009. All Rights Reserved. +# +# 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 online 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. +# +# %CopyrightEnd% +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(EI_VSN) +APPLICATION=erl_interface + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +XML_REF1_FILES = erl_call.xml +XML_REF3_FILES = erl_connect.xml \ + erl_error.xml \ + erl_eterm.xml \ + erl_format.xml \ + erl_malloc.xml \ + erl_marshal.xml \ + erl_global.xml \ + ei.xml \ + ei_connect.xml \ + registry.xml + +BOOK_FILES = book.xml +XML_APPLICATION_FILES = ref_man.xml +#ref_man_ei.xml ref_man_erl_interface.xml +XML_PART_FILES = \ + part.xml \ + part_notes.xml \ + part_notes_history.xml +XML_CHAPTER_FILES = ei_users_guide.xml notes.xml notes_history.xml + +XML_FILES = $(XML_REF1_FILES) $(XML_REF3_FILES) $(BOOK_FILES) \ + $(XML_APPLICATION_FILES) $(XML_PART_FILES) $(XML_CHAPTER_FILES) +# ---------------------------------------------------- + +HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) + +INFO_FILE = ../../info + +GIF_FILES = + +MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1) +MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) + +HTML_REF_MAN_FILE = $(HTMLDIR)/index.html + +TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +XML_FLAGS += + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +$(HTMLDIR)/%.gif: %.gif + $(INSTALL_DATA) $< $@ + +docs: pdf html man + +$(TOP_PDF_FILE): $(XML_FILES) + +pdf: $(TOP_PDF_FILE) + +html: gifs $(HTML_REF_MAN_FILE) + +man: $(MAN1_FILES) $(MAN3_FILES) + +gifs: $(GIF_FILES:%=$(HTMLDIR)/%) + +debug opt: + +clean clean_docs clean_tex: + rm -rf $(HTMLDIR)/* + rm -f $(MAN1DIR)/* + rm -f $(MAN3DIR)/* + rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f errs core *~ + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_docs_spec: docs + $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf + $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf + $(INSTALL_DIR) $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(HTMLDIR)/* \ + $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR) + $(INSTALL_DIR) $(RELEASE_PATH)/man/man1 + $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1 + $(INSTALL_DIR) $(RELEASE_PATH)/man/man3 + $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3 + + +release_spec: + diff --git a/lib/erl_interface/doc/src/book.xml b/lib/erl_interface/doc/src/book.xml new file mode 100644 index 0000000000..e911b6aa2b --- /dev/null +++ b/lib/erl_interface/doc/src/book.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE book SYSTEM "book.dtd"> + +<book xmlns:xi="http://www.w3.org/2001/XInclude"> + <header titlestyle="normal"> + <copyright> + <year>1998</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erlang Interface</title> + <prepared>Gordon Beaton</prepared> + <docno></docno> + <date>1998-11-30</date> + <rev>1.2</rev> + <file>book.sgml</file> + </header> + <insidecover> + </insidecover> + <pagetext>Erlang Interface</pagetext> + <preamble> + <contents level="2"></contents> + </preamble> + <parts lift="no"> + <xi:include href="part.xml"/> + </parts> + <applications> + <xi:include href="ref_man.xml"/> + </applications> + <releasenotes> + <xi:include href="notes.xml"/> + </releasenotes> + <listofterms></listofterms> + <index></index> +</book> + diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml new file mode 100644 index 0000000000..2f65a8c375 --- /dev/null +++ b/lib/erl_interface/doc/src/ei.xml @@ -0,0 +1,728 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>2001</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>ei</title> + <prepared>Jakob Cederlund</prepared> + <responsible>Kent Boortz</responsible> + <docno>1</docno> + <approved>Kenneth Lundin</approved> + <checked></checked> + <date>2000-11-27</date> + <rev>PA1</rev> + <file>ei.sgml</file> + </header> + <lib>ei</lib> + <libsummary>routines for handling the erlang binary term format</libsummary> + <description> + <p>The library <c><![CDATA[ei]]></c> contains macros and functions to encode + and decode the erlang binary term format.</p> + <p>With <c><![CDATA[ei]]></c>, you can convert atoms, lists, numbers and + binaries to and from the binary format. This is useful when + writing port programs and drivers. <c><![CDATA[ei]]></c> uses a given + buffer, and no dynamic memory (with the exception of + <c><![CDATA[ei_decode_fun()]]></c>), and is often quite fast.</p> + <p>It also handles C-nodes, C-programs that talks erlang + distribution with erlang nodes (or other C-nodes) using the + erlang distribution format. The difference between <c><![CDATA[ei]]></c> and + <c><![CDATA[erl_interface]]></c> is that <c><![CDATA[ei]]></c> uses the binary format + directly when sending and receiving terms. It is also thread + safe, and using threads, one process can handle multiple + C-nodes. The <c><![CDATA[erl_interface]]></c> library is built on top of + <c><![CDATA[ei]]></c>, but of legacy reasons, it doesn't allow for multiple + C-nodes. In general, <c><![CDATA[ei]]></c> is the preferred way of doing + C-nodes.</p> + <p>The decode and encode functions use a buffer an index into the + buffer, which points at the point where to encode and + decode. The index is updated to point right after the term + encoded/decoded. No checking is done whether the term fits in + the buffer or not. If encoding goes outside the buffer, the + program may crash.</p> + <p>All functions takes two parameter, <c><![CDATA[buf]]></c> is a pointer to + the buffer where the binary data is / will be, <c><![CDATA[index]]></c> is a + pointer to an index into the buffer. This parameter will be + incremented with the size of the term decoded / encoded. The + data is thus at <c><![CDATA[buf[*index]]]></c> when an <c><![CDATA[ei]]></c> function is + called.</p> + <p>The encode functions all assumes that the <c><![CDATA[buf]]></c> and + <c><![CDATA[index]]></c> parameters points to a buffer big enough for the + data. To get the size of an encoded term, without encoding it, + pass <c><![CDATA[NULL]]></c> instead of a buffer pointer. The <c><![CDATA[index]]></c> + parameter will be incremented, but nothing will be encoded. This + is the way in <c><![CDATA[ei]]></c> to "preflight" term encoding.</p> + <p>There are also encode-functions that uses a dynamic buffer. It + is often more convenient to use these to encode data. All encode + functions comes in two versions: those starting with <c><![CDATA[ei_x]]></c>, + uses a dynamic buffer.</p> + <p>All functions return <c><![CDATA[0]]></c> if successful, and <c><![CDATA[-1]]></c> if + not. (For instance, if a term is not of the expected type, or + the data to decode is not a valid erlang term.)</p> + <p>Some of the decode-functions needs a preallocated buffer. This + buffer must be allocated big enough, and for non compound types + the <c><![CDATA[ei_get_type()]]></c> + function returns the size required (note that for strings an + extra byte is needed for the 0 string terminator).</p> + </description> + <funcs> + <func> + <name><ret>void</ret><nametext>ei_set_compat_rel(release_number)</nametext></name> + <fsummary>Set the ei library in compatibility mode</fsummary> + <type> + <v>unsigned release_number;</v> + </type> + <desc> + <marker id="ei_set_compat_rel"></marker> + <p>By default, the <c><![CDATA[ei]]></c> library is only guaranteed + to be compatible with other Erlang/OTP components from the same + release as the <c><![CDATA[ei]]></c> library itself. For example, <c><![CDATA[ei]]></c> from + the OTP R10 release is not compatible with an Erlang emulator + from the OTP R9 release by default.</p> + <p>A call to <c><![CDATA[ei_set_compat_rel(release_number)]]></c> sets the + <c><![CDATA[ei]]></c> library in compatibility mode of release + <c><![CDATA[release_number]]></c>. Valid range of <c><![CDATA[release_number]]></c> + is [7, current release]. This makes it possible to + communicate with Erlang/OTP components from earlier releases.</p> + <note> + <p>If this function is called, it may only be called once + and must be called before any other functions in the <c><![CDATA[ei]]></c> + library is called.</p> + </note> + <warning> + <p>You may run into trouble if this feature is used + carelessly. Always make sure that all communicating + components are either from the same Erlang/OTP release, or + from release X and release Y where all components + from release Y are in compatibility mode of release X.</p> + </warning> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_version(char *buf, int *index)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_version(ei_x_buff* x)</nametext></name> + <fsummary>Encode version</fsummary> + <desc> + <p>Encodes a version magic number for the binary format. Must + be the first token in a binary term.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_long(char *buf, int *index, long p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_long(ei_x_buff* x, long p)</nametext></name> + <fsummary>Encode integer</fsummary> + <desc> + <p>Encodes a long integer in the binary format. + Note that if the code is 64 bits the function ei_encode_long() is + exactly the same as ei_encode_longlong().</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_ulong(char *buf, int *index, unsigned long p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_ulong(ei_x_buff* x, unsigned long p)</nametext></name> + <fsummary>Encode unsigned integer</fsummary> + <desc> + <p>Encodes an unsigned long integer in the binary format. + Note that if the code is 64 bits the function ei_encode_ulong() is + exactly the same as ei_encode_ulonglong().</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_longlong(char *buf, int *index, long long p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_longlong(ei_x_buff* x, long long p)</nametext></name> + <fsummary>Encode integer</fsummary> + <desc> + <p>Encodes a GCC <c><![CDATA[long long]]></c> or Visual C++ <c><![CDATA[__int64]]></c> (64 bit) + integer in the binary format. Note that this function is missing + in the VxWorks port.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_ulonglong(char *buf, int *index, unsigned long long p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p)</nametext></name> + <fsummary>Encode unsigned integer</fsummary> + <desc> + <p>Encodes a GCC <c><![CDATA[unsigned long long]]></c> or Visual C++ <c><![CDATA[unsigned __int64]]></c> (64 bit) integer in the binary format. Note that + this function is missing in the VxWorks port.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_bignum(char *buf, int *index, mpz_t obj)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_bignum(ei_x_buff *x, mpz_t obj)</nametext></name> + <fsummary>Encode an arbitrary precision integer</fsummary> + <desc> + <p>Encodes a GMP <c><![CDATA[mpz_t]]></c> integer to binary format. + To use this function the ei library needs to be configured and compiled + to use the GMP library. </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_double(char *buf, int *index, double p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_double(ei_x_buff* x, double p)</nametext></name> + <fsummary>Encode a double float</fsummary> + <desc> + <p>Encodes a double-precision (64 bit) floating point number in + the binary format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_boolean(char *buf, int *index, int p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_boolean(ei_x_buff* x, int p)</nametext></name> + <fsummary>Encode a boolean</fsummary> + <desc> + <p>Encodes a boolean value, as the atom <c><![CDATA[true]]></c> if p is not + zero or <c><![CDATA[false]]></c> if p is zero.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_char(char *buf, int *index, char p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_char(ei_x_buff* x, char p)</nametext></name> + <fsummary>Encode an 8-bit integer between 0-255</fsummary> + <desc> + <p>Encodes a char (8-bit) as an integer between 0-255 in the binary format. + Note that for historical reasons the integer argument is of + type <c><![CDATA[char]]></c>. Your C code should consider the + given argument to be of type <c><![CDATA[unsigned char]]></c> even if + the C compilers and system may define <c><![CDATA[char]]></c> to be + signed.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_string(char *buf, int *index, const char *p)</nametext></name> + <name><ret>int</ret><nametext>ei_encode_string_len(char *buf, int *index, const char *p, int len)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_string(ei_x_buff* x, const char *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)</nametext></name> + <fsummary>Encode a string</fsummary> + <desc> + <p>Encodes a string in the binary format. (A string in erlang + is a list, but is encoded as a character array in the binary + format.) The string should be zero-terminated, except for + the <c><![CDATA[ei_x_encode_string_len()]]></c> function.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_atom(char *buf, int *index, const char *p)</nametext></name> + <name><ret>int</ret><nametext>ei_encode_atom_len(char *buf, int *index, const char *p, int len)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_atom(ei_x_buff* x, const char *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len)</nametext></name> + <fsummary>Encode an atom</fsummary> + <desc> + <p>Encodes an atom in the binary format. The <c><![CDATA[p]]></c> parameter + is the name of the atom. Only upto <c><![CDATA[MAXATOMLEN]]></c> bytes + are encoded. The name should be zero-terminated, except for + the <c><![CDATA[ei_x_encode_atom_len()]]></c> function.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_binary(char *buf, int *index, const void *p, long len)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_binary(ei_x_buff* x, const void *p, long len)</nametext></name> + <fsummary>Encode a binary</fsummary> + <desc> + <p>Encodes a binary in the binary format. The data is at + <c><![CDATA[p]]></c>, of <c><![CDATA[len]]></c> bytes length.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_pid(char *buf, int *index, const erlang_pid *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p)</nametext></name> + <fsummary>Encode a pid</fsummary> + <desc> + <p>Encodes an erlang process identifier, pid, in the binary + format. The <c><![CDATA[p]]></c> parameter points to an + <c><![CDATA[erlang_pid]]></c> structure (which should have been obtained + earlier with <c><![CDATA[ei_decode_pid()]]></c>).</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_fun(char *buf, int *index, const erlang_fun *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)</nametext></name> + <fsummary>Encode a fun</fsummary> + <desc> + <p>Encodes a fun in the binary format. The <c><![CDATA[p]]></c> parameter + points to an <c><![CDATA[erlang_fun]]></c> structure. The + <c><![CDATA[erlang_fun]]></c> is not freed automatically, the + <c><![CDATA[free_fun]]></c> should be called if the fun is not needed + after encoding.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_port(char *buf, int *index, const erlang_port *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_port(ei_x_buff* x, const erlang_port *p)</nametext></name> + <fsummary>Encodes a port</fsummary> + <desc> + <p>Encodes an erlang port in the binary format. The <c><![CDATA[p]]></c> + parameter points to a <c><![CDATA[erlang_port]]></c> structure (which + should have been obtained earlier with + <c><![CDATA[ei_decode_port()]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_ref(char *buf, int *index, const erlang_ref *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p)</nametext></name> + <fsummary>Encodes a ref</fsummary> + <desc> + <p>Encodes an erlang reference in the binary format. The + <c><![CDATA[p]]></c> parameter points to a <c><![CDATA[erlang_ref]]></c> structure + (which should have been obtained earlier with + <c><![CDATA[ei_decode_ref()]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_term(char *buf, int *index, void *t)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_term(ei_x_buff* x, void *t)</nametext></name> + <fsummary>Encode an <c><![CDATA[erl_interface]]></c>term</fsummary> + <desc> + <p>This function encodes an <c><![CDATA[ETERM]]></c>, as obtained from + <c><![CDATA[erl_interface]]></c>. The <c><![CDATA[t]]></c> parameter is actually an + <c><![CDATA[ETERM]]></c> pointer. This function doesn't free the + <c><![CDATA[ETERM]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_trace(char *buf, int *index, const erlang_trace *p)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p)</nametext></name> + <fsummary>Encode a trace token</fsummary> + <desc> + <p>This function encodes an erlang trace token in the binary + format. The <c><![CDATA[p]]></c> parameter points to a + <c><![CDATA[erlang_trace]]></c> structure (which should have been + obtained earlier with <c><![CDATA[ei_decode_trace()]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_tuple_header(char *buf, int *index, int arity)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_tuple_header(ei_x_buff* x, int arity)</nametext></name> + <fsummary>Encode a tuple</fsummary> + <desc> + <p>This function encodes a tuple header, with a specified + arity. The next <c><![CDATA[arity]]></c> terms encoded will be the + elements of the tuple. Tuples and lists are encoded + recursively, so that a tuple may contain another tuple or + list.</p> + <p>E.g. to encode the tuple <c><![CDATA[{a, {b, {}}}]]></c>:</p> + <pre> +ei_encode_tuple_header(buf, &i, 2); +ei_encode_atom(buf, &i, "a"); +ei_encode_tuple_header(buf, &i, 2); +ei_encode_atom(buf, &i, "b"); +ei_encode_tuple_header(buf, &i, 0); + </pre> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_list_header(char *buf, int *index, int arity)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_list_header(ei_x_buff* x, int arity)</nametext></name> + <fsummary>Encode a list</fsummary> + <desc> + <p>This function encodes a list header, with a specified + arity. The next <c><![CDATA[arity+1]]></c> terms are the elements + (actually it's <c><![CDATA[arity]]></c> cons cells) and the tail of the + list. Lists and tuples are encoded recursively, so that a + list may contain another list or tuple.</p> + <p>E.g. to encode the list <c><![CDATA[[c, d, [e | f]]]]></c>:</p> + <pre> +ei_encode_list_header(buf, &i, 3); +ei_encode_atom(buf, &i, "c"); +ei_encode_atom(buf, &i, "d"); +ei_encode_list_header(buf, &i, 1); +ei_encode_atom(buf, &i, "e"); +ei_encode_atom(buf, &i, "f"); +ei_encode_empty_list(buf, &i); + </pre> + <note> + <p>It may seem that there is no way to create a list without + knowing the number of elements in advance. But indeed + there is a way. Note that the list <c><![CDATA[[a, b, c]]]></c> can be + written as <c><![CDATA[[a | [b | [c]]]]]></c>. Using this, a list can + be written as conses.</p> + </note> + <p>To encode a list, without knowing the arity in advance:</p> + <pre> +while (something()) { + ei_x_encode_list_header(&x, 1); + ei_x_encode_ulong(&x, i); /* just an example */ +} +ei_x_encode_empty_list(&x); + </pre> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_encode_empty_list(char* buf, int* index)</nametext></name> + <name><ret>int</ret><nametext>ei_x_encode_empty_list(ei_x_buff* x)</nametext></name> + <fsummary>Encode an empty list (<c><![CDATA[nil]]></c>)</fsummary> + <desc> + <p>This function encodes an empty list. It's often used at the + tail of a list.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_get_type(const char *buf, const int *index, int *type, int *size)</nametext></name> + <fsummary>Fetch the type and size of an encoded term</fsummary> + <desc> + <p>This function returns the type in <c><![CDATA[type]]></c> and size in + <c><![CDATA[size]]></c> of the encoded term. + For strings and atoms, size + is the number of characters <em>not</em> including the + terminating 0. For binaries, <c><![CDATA[size]]></c> is the number of + bytes. For lists and tuples, <c><![CDATA[size]]></c> is the arity of the + object. For other types, <c><![CDATA[size]]></c> is 0. In all cases, + <c><![CDATA[index]]></c> is left unchanged.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_version(const char *buf, int *index, int *version)</nametext></name> + <fsummary>Encode an empty list (<c><![CDATA[nil]]></c>)</fsummary> + <desc> + <p>This function decodes the version magic number for the + erlang binary term format. It must be the first token in a + binary term.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_long(const char *buf, int *index, long *p)</nametext></name> + <fsummary>Decode integer</fsummary> + <desc> + <p>This function decodes a long integer from the binary format. + Note that if the code is 64 bits the function ei_decode_long() is + exactly the same as ei_decode_longlong().</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_ulong(const char *buf, int *index, unsigned long *p)</nametext></name> + <fsummary>Decode unsigned integer</fsummary> + <desc> + <p>This function decodes an unsigned long integer from + the binary format. + Note that if the code is 64 bits the function ei_decode_ulong() is + exactly the same as ei_decode_ulonglong().</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_longlong(const char *buf, int *index, long long *p)</nametext></name> + <fsummary>Decode integer</fsummary> + <desc> + <p>This function decodes a GCC <c><![CDATA[long long]]></c> or Visual C++ <c><![CDATA[__int64]]></c> + (64 bit) integer from the binary format. Note that this + function is missing in the VxWorks port.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p)</nametext></name> + <fsummary>Decode unsigned integer</fsummary> + <desc> + <p>This function decodes a GCC <c><![CDATA[unsigned long long]]></c> or Visual C++ + <c><![CDATA[unsigned __int64]]></c> (64 bit) integer from the binary format. + Note that this function is missing in the VxWorks port.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_bignum(const char *buf, int *index, mpz_t obj)</nametext></name> + <fsummary>Decode a GMP arbitrary precision integer</fsummary> + <desc> + <p>This function decodes an integer in the binary format to a GMP <c><![CDATA[mpz_t]]></c> integer. + To use this function the ei library needs to be configured and compiled + to use the GMP library. </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_double(const char *buf, int *index, double *p)</nametext></name> + <fsummary>Decode a double</fsummary> + <desc> + <p>This function decodes an double-precision (64 bit) floating + point number from the binary format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_boolean(const char *buf, int *index, int *p)</nametext></name> + <fsummary>Decode a boolean</fsummary> + <desc> + <p>This function decodes a boolean value from the binary + format. A boolean is actually an atom, <c><![CDATA[true]]></c> decodes 1 + and <c><![CDATA[false]]></c> decodes 0.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_char(const char *buf, int *index, char *p)</nametext></name> + <fsummary>Decode an 8-bit integer between 0-255</fsummary> + <desc> + <p>This function decodes a char (8-bit) integer between 0-255 + from the binary format. + Note that for historical reasons the returned integer is of + type <c><![CDATA[char]]></c>. Your C code should consider the + returned value to be of type <c><![CDATA[unsigned char]]></c> even if + the C compilers and system may define <c><![CDATA[char]]></c> to be + signed.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_string(const char *buf, int *index, char *p)</nametext></name> + <fsummary>Decode a string</fsummary> + <desc> + <p>This function decodes a string from the binary format. A + string in erlang is a list of integers between 0 and + 255. Note that since the string is just a list, sometimes + lists are encoded as strings by <c><![CDATA[term_to_binary/1]]></c>, + even if it was not intended.</p> + <p>The string is copied to <c><![CDATA[p]]></c>, and enough space must be + allocated. The returned string is null terminated so you + need to add an extra byte to the memory requirement.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_atom(const char *buf, int *index, char *p)</nametext></name> + <fsummary>Decode an atom</fsummary> + <desc> + <p>This function decodes an atom from the binary format. The + name of the atom is placed at <c><![CDATA[p]]></c>. There can be at most + <c><![CDATA[MAXATOMLEN]]></c> bytes placed in the buffer.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_binary(const char *buf, int *index, void *p, long *len)</nametext></name> + <fsummary>Decode a binary</fsummary> + <desc> + <p>This function decodes a binary from the binary format. The + <c><![CDATA[len]]></c> parameter is set to the actual size of the + binary. Note that <c><![CDATA[ei_decode_binary()]]></c> assumes that there + are enough room for the binary. The size required can be + fetched by <c><![CDATA[ei_get_type()]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_fun(const char *buf, int *index, erlang_fun *p)</nametext></name> + <name><ret>void</ret><nametext>free_fun(erlang_fun* f)</nametext></name> + <fsummary>Decode a fun</fsummary> + <desc> + <p>This function decodes a fun from the binary format. The + <c><![CDATA[p]]></c> parameter should be NULL or point to an + <c><![CDATA[erlang_fun]]></c> structure. This is the only decode + function that allocates memory; when the <c><![CDATA[erlang_fun]]></c> + is no longer needed, it should be freed with + <c><![CDATA[free_fun]]></c>. (This has to do with the arbitrary size of + the environment for a fun.)</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_pid(const char *buf, int *index, erlang_pid *p)</nametext></name> + <fsummary>Decode a <c><![CDATA[pid]]></c></fsummary> + <desc> + <p>Decodes a pid, process identifier, from the binary format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_port(const char *buf, int *index, erlang_port *p)</nametext></name> + <fsummary>Decode a port</fsummary> + <desc> + <p>This function decodes a port identifier from the binary + format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_ref(const char *buf, int *index, erlang_ref *p)</nametext></name> + <fsummary>Decode a reference</fsummary> + <desc> + <p>This function decodes a reference from the binary format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_trace(const char *buf, int *index, erlang_trace *p)</nametext></name> + <fsummary>Decode a trace token</fsummary> + <desc> + <p>Decodes an erlang trace token from the binary format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_tuple_header(const char *buf, int *index, int *arity)</nametext></name> + <fsummary>Decode a tuple</fsummary> + <desc> + <p>This function decodes a tuple header, the number of elements + is returned in <c><![CDATA[arity]]></c>. The tuple elements follows in order in + the buffer.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_list_header(const char *buf, int *index, int *arity)</nametext></name> + <fsummary>Decode a list</fsummary> + <desc> + <p>This function decodes a list header from the binary + format. The number of elements is returned in + <c><![CDATA[arity]]></c>. The <c><![CDATA[arity+1]]></c> elements follows (the last + one is the tail of the list, normally an empty list.) If + <c><![CDATA[arity]]></c> is <c><![CDATA[0]]></c>, it's an empty list.</p> + <p>Note that lists are encoded as strings, if they consist + entirely of integers in the range 0..255. This function will + not decode such strings, use <c><![CDATA[ei_decode_string()]]></c> + instead.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_ei_term(const char* buf, int* index, ei_term* term)</nametext></name> + <fsummary>Decode a term, without prior knowledge of type</fsummary> + <desc> + <p>This function decodes any term, or at least tries to. If the + term pointed at by <c><![CDATA[*index]]></c> in <c><![CDATA[buf]]></c> fits in the + <c><![CDATA[term]]></c> union, it is decoded, and the appropriate field + in <c><![CDATA[term->value]]></c> is set, and <c><![CDATA[*index]]></c> is + incremented by the term size.</p> + <p>The function returns 0 on successful encoding, -1 on error, + and 1 if the term seems alright, but does not fit in the + <c><![CDATA[term]]></c> structure. If it returns 0, the <c><![CDATA[index]]></c> + will be incremented, and the <c><![CDATA[term]]></c> contains the + decoded term.</p> + <p>The <c><![CDATA[term]]></c> structure will contain the arity for a tuple + or list, size for a binary, string or atom. It will contains + a term if it's any of the following: integer, float, atom, + pid, port or ref.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_decode_term(const char *buf, int *index, void *t)</nametext></name> + <fsummary>Decode a <c><![CDATA[ETERM]]></c></fsummary> + <desc> + <p>This function decodes a term from the binary format. The + term is return in <c><![CDATA[t]]></c> as a <c><![CDATA[ETERM*]]></c>, so <c><![CDATA[t]]></c> + is actually an <c><![CDATA[ETERM**]]></c> (see + <c><![CDATA[erl_interface(3)]]></c>. The term should later be + deallocated.</p> + <p>Note that this function is located in the erl_interface + library.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_print_term(FILE* fp, const char* buf, int* index)</nametext></name> + <name><ret>int</ret><nametext>ei_s_print_term(char** s, const char* buf, int* index)</nametext></name> + <fsummary>Print a term in clear text</fsummary> + <desc> + <p>This function prints a term, in clear text, to the file + given by <c><![CDATA[fp]]></c>, or the buffer pointed to by <c><![CDATA[s]]></c>. It + tries to resemble the term printing in the erlang shell.</p> + <p>In <c><![CDATA[ei_s_print_term()]]></c>, the parameter <c><![CDATA[s]]></c> should + point to a dynamically (malloc) allocated string of + <c><![CDATA[BUFSIZ]]></c> bytes or a NULL pointer. The string may be + reallocated (and <c><![CDATA[*s]]></c> may be updated) by this function + if the result is more than <c><![CDATA[BUFSIZ]]></c> characters. The + string returned is zero-terminated.</p> + <p>The return value is the number of characters written to the + file or string, or -1 if <c><![CDATA[buf[index]]]></c> doesn't contain a + valid term. Unfortunately, I/O errors on <c><![CDATA[fp]]></c> is not + checked.</p> + <p>The argument <c><![CDATA[index]]></c> is updated, i.e. this function can + be viewed as en decode function that decodes a term into a + human readable format.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_x_format(ei_x_buff* x, const char* fmt, ...)</nametext></name> + <name><ret>int</ret><nametext>ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... )</nametext></name> + <fsummary>Format a term from a format string and parameters.</fsummary> + <desc> + <p>Format a term, given as a string, to a buffer. This + functions works like a sprintf for erlang terms. The + <c><![CDATA[fmt]]></c> contains a format string, with arguments like + <c><![CDATA[~d]]></c>, to insert terms from variables. The following + formats are supported (with the C types given):</p> + <p></p> + <pre> +~a - an atom, char* +~s - a string, char* +~i - an integer, int +~l - a long integer, long int +~u - a unsigned long integer, unsigned long int +~f - a float, float +~d - a double float, double float + </pre> + <p>For instance, to encode a tuple with some stuff:</p> + <pre> +ei_x_format("{~a,~i,~d}", "numbers", 12, 3.14159) +encodes the tuple {numbers,12,3.14159} + </pre> + <p>The <c><![CDATA[ei_x_format_wo_ver()]]></c> formats into a buffer, without + the initial version byte.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_x_new(ei_x_buff* x)</nametext></name> + <name><ret>int</ret><nametext>ei_x_new_with_version(ei_x_buff* x)</nametext></name> + <fsummary>Allocate a new buffer</fsummary> + <desc> + <p>This function allocates a new <c><![CDATA[ei_x_buff]]></c> buffer. The + fields of the structure pointed to by <c><![CDATA[x]]></c> parameter is + filled in, and a default buffer is allocated. The + <c><![CDATA[ei_x_new_with_version()]]></c> also puts an initial version + byte, that is used in the binary format. (So that + <c><![CDATA[ei_x_encode_version()]]></c> won't be needed.)</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_x_free(ei_x_buff* x)</nametext></name> + <fsummary>Frees a buffer</fsummary> + <desc> + <p>This function frees an <c><![CDATA[ei_x_buff]]></c> buffer. The memory + used by the buffer is returned to the OS.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_x_append(ei_x_buff* x, const ei_x_buff* x2)</nametext></name> + <name><ret>int</ret><nametext>ei_x_append_buf(ei_x_buff* x, const char* buf, int len)</nametext></name> + <fsummary>Appends a buffer at the end</fsummary> + <desc> + <p>These functions appends data at the end of the buffer <c><![CDATA[x]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_skip_term(const char* buf, int* index)</nametext></name> + <fsummary>skip a term</fsummary> + <desc> + <p>This function skips a term in the given buffer, it + recursively skips elements of lists and tuples, so that a + full term is skipped. This is a way to get the size of an + erlang term.</p> + <p><c><![CDATA[buf]]></c> is the buffer.</p> + <p><c><![CDATA[index]]></c> is updated to point right after the term in the + buffer.</p> + <note> + <p>This can be useful when you want to hold arbitrary + terms: just skip them and copy the binary term data to some + buffer.</p> + </note> + <p>The function returns <c><![CDATA[0]]></c> on success and <c><![CDATA[-1]]></c> on + failure.</p> + </desc> + </func> + </funcs> + + <section> + <title>Debug Information</title> + <p>Some tips on what to check when the emulator doesn't seem to + receive the terms that you send.</p> + <list type="bulleted"> + <item>be careful with the version header, use + <c><![CDATA[ei_x_new_with_version()]]></c> when appropriate</item> + <item>turn on distribution tracing on the erlang node</item> + <item>check the result codes from ei_decode_-calls</item> + </list> + </section> + + <section> + <title>See Also</title> + <p>erl_interface(3)</p> + </section> +</cref> + diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml new file mode 100644 index 0000000000..08e7b122c6 --- /dev/null +++ b/lib/erl_interface/doc/src/ei_connect.xml @@ -0,0 +1,639 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>2001</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>ei_connect</title> + <prepared>Jakob Cederlund</prepared> + <docno></docno> + <approved>?</approved> + <checked>?</checked> + <date>2001-09-01</date> + <rev>A</rev> + <file>ei_connect.sgml</file> + </header> + <lib>ei_connect</lib> + <libsummary>Communicate with distributed erlang</libsummary> + <description> + <p>This module enables C programs to communicate with erlang nodes, + using the erlang distribution over TCP/IP.</p> + <p>A C node appears to Erlang as a + <em>hidden node</em>. + That is, Erlang processes that know the name of the + C node are able to communicate with it in a normal manner, but + the node name will not appear in the listing provided by the + Erlang function <c><![CDATA[nodes/0]]></c>.</p> + <p>The environment variable <c><![CDATA[ERL_EPMD_PORT]]></c> can be used + to indicate which logical cluster a C node belongs to.</p> + </description> + + <section> + <title>Timeout functions</title> + <p>Most functions appear in a version with the suffix + <c><![CDATA[_tmo]]></c> appended to the function name. Those function take + an additional argument, a timeout in <em>milliseconds</em>. The + semantics is this; for each communication primitive involved in + the operation, if the primitive does not complete within the time + specified, the function will return an error and + <c><![CDATA[erl_errno]]></c> will be set to <c><![CDATA[ETIMEDOUT]]></c>. With + communication primitive is ment an operation on the socket, like + <c><![CDATA[connect]]></c>, <c><![CDATA[accept]]></c>, <c><![CDATA[recv]]></c> or <c><![CDATA[send]]></c>.</p> + <p>Obviously the timeouts are for implementing fault tolerance, + not to keep hard realtime promises. The <c><![CDATA[_tmo]]></c> functions + are for detecting non-responsive peers and to avoid blocking on + socket operations. </p> + <p>A timeout value of <c><![CDATA[0]]></c> (zero), means that timeouts are + disabled. Calling a <c><![CDATA[_tmo]]></c>-function with the last argument as + <c><![CDATA[0]]></c> is therefore exactly the same thing as calling the + function without the <c><![CDATA[_tmo]]></c> suffix.</p> + <p>As with all other ei functions, you are <em>not</em> expected + to put the socket in non blocking mode yourself in the program. Every + use of non blocking mode is embedded inside the timeout + functions. The socket will always be back in blocking mode after + the operations are completed (regardless of the result). To + avoid problems, leave the socket options alone. Ei will handle + any socket options that need modification.</p> + <p>In all other senses, the <c><![CDATA[_tmo]]></c> functions inherit all + the return values and the semantics from the functions without + the <c><![CDATA[_tmo]]></c> suffix.</p> + </section> + <funcs> + <func> + <name><ret>int</ret><nametext>ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation)</nametext></name> + <name><ret>int</ret><nametext>ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation)</nametext></name> + <fsummary>Initialize for a connection.</fsummary> + <desc> + <p>These function initializes the <c><![CDATA[ec]]></c> structure, to + identify the node name and cookie of the server. One of them + has to be called before other functions that works on the + type <c><![CDATA[ei_cnode]]></c> or a file descriptor associated with a + connection to another node are used.</p> + <p><c><![CDATA[ec]]></c> is a structure containing information about the + C-node. It is used in other <c><![CDATA[ei]]></c> functions for + connecting and receiving data.</p> + <p><c><![CDATA[this_node_name]]></c> is the registered name of the process + (the name before '@').</p> + <p><c><![CDATA[cookie]]></c> is the cookie for the node.</p> + <p><c><![CDATA[creation]]></c> identifies a specific instance of a C + node. It can help prevent the node from receiving messages + sent to an earlier process with the same registered name.</p> + <p><c><![CDATA[thishostname]]></c> is the name of the machine we're running + on. If long names are to be used, it should be fully + qualified (i.e. <c><![CDATA[durin.erix.ericsson.se]]></c> instead of + <c><![CDATA[durin]]></c>).</p> + <p><c><![CDATA[thisalivename]]></c> is the registered name of the process.</p> + <p><c><![CDATA[thisnodename]]></c> is the full name of the node, + i.e. <c><![CDATA[einode@durin]]></c>.</p> + <p><c><![CDATA[thispaddr]]></c> if the IP address of the host.</p> + <p>A C node acting as a server will be assigned a creation + number when it calls <c><![CDATA[ei_publish()]]></c>.</p> + <p>A connection is closed by simply closing the socket. Refer + to system documentation to close the socket gracefully (when + there are outgoing packets before close).</p> + <p>This function return a negative value indicating that an error + occurred.</p> + <p>Example 1: + </p> + <code type="none"><![CDATA[ +int n = 0; +struct in_addr addr; +ei_cnode ec; +addr = inet_addr("150.236.14.75"); +if (ei_connect_xinit(&ec, + "chivas", + "madonna", + "[email protected]", + &addr; + "cookie...", + n++) < 0) { + fprintf(stderr,"ERROR when initializing: %d",erl_errno); + exit(-1); +} + ]]></code> + <p>Example 2: + </p> + <code type="none"><![CDATA[ +if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) { + fprintf("ERROR when initializing: %d",erl_errno); + exit(-1); +} + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_connect(ei_cnode* ec, char *nodename)</nametext></name> + <name><ret>int</ret><nametext>ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename)</nametext></name> + <fsummary>Establishe a connection to an Erlang node</fsummary> + <desc> + <p>These functions set up a connection to an Erlang node.</p> + <p><c><![CDATA[ei_xconnect()]]></c> requires the IP address of the remote + host and the alive name of the remote node + to be specified. <c><![CDATA[ei_connect()]]></c> provides an alternative + interface, and determines the information from the node name + provided.</p> + <p><c><![CDATA[addr]]></c> is the 32-bit IP address of the remote host.</p> + <p><c><![CDATA[alive]]></c> is the alivename of the remote node.</p> + <p><c><![CDATA[node]]></c> is the name of the remote node.</p> + <p>These functions return an open file descriptor on success, or + a negative value indicating that an error occurred --- in + which case they will set <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EHOSTUNREACH]]></c></tag> + <item>The remote host <c><![CDATA[node]]></c> is unreachable</item> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + <p>Additionally, <c><![CDATA[errno]]></c> values from + <c><![CDATA[socket]]></c><em>(2)</em> and <c><![CDATA[connect]]></c><em>(2)</em> + system calls may be propagated into <c><![CDATA[erl_errno]]></c>.</p> + <p>Example:</p> + <code type="none"><![CDATA[ +#define NODE "[email protected]" +#define ALIVE "madonna" +#define IP_ADDR "150.236.14.75" + +/*** Variant 1 ***/ +int fd = ei_connect(&ec, NODE); + +/*** Variant 2 ***/ +struct in_addr addr; +addr = inet_addr(IP_ADDR); +fd = ei_xconnect(&ec, &addr, ALIVE); + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned timeout_ms)</nametext></name> + <name><ret>int</ret><nametext>ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned timeout_ms)</nametext></name> + <fsummary>Establish a connection to an Erlang node with optional timeout</fsummary> + <desc> + <p>ei_connect and ei_xconnect with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_receive(int fd, unsigned char* bufp, int bufsize)</nametext></name> + <fsummary>Receive a message</fsummary> + <desc> + <p>This function receives a message consisting of a sequence + of bytes in the Erlang external format.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection. It + is obtained from a previous <c><![CDATA[ei_connect]]></c> or + <c><![CDATA[ei_accept]]></c>.</p> + <p><c><![CDATA[bufp]]></c> is a buffer large enough to hold the expected + message. </p> + <p><c><![CDATA[bufsize]]></c> indicates the size of <c><![CDATA[bufp]]></c>.</p> + <p>If a <em>tick</em> occurs, i.e., the Erlang node on the + other end of the connection has polled this node to see if it + is still alive, the function will return <c><![CDATA[ERL_TICK]]></c> and + no message will be placed in the buffer. Also, + <c><![CDATA[erl_errno]]></c> will be set to <c><![CDATA[EAGAIN]]></c>.</p> + <p>On success, the message is placed in the specified buffer + and the function returns the number of bytes actually read. On + failure, the function returns <c><![CDATA[ERL_ERROR]]></c> and will set + <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EAGAIN]]></c></tag> + <item>Temporary error: Try again.</item> + <tag><c><![CDATA[EMSGSIZE]]></c></tag> + <item>Buffer too small.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_receive_tmo(int fd, unsigned char* bufp, int bufsize, unsigned timeout_ms)</nametext></name> + <fsummary>Receive a message with optional timeout</fsummary> + <desc> + <p>ei_receive with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x)</nametext></name> + <name><ret>int</ret><nametext>ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x)</nametext></name> + <fsummary>Receive a message</fsummary> + <desc> + <p>These functions receives a message to the buffer in + <c><![CDATA[x]]></c>. <c><![CDATA[ei_xreceive_msg]]></c> allows the buffer in + <c><![CDATA[x]]></c> to grow, but <c><![CDATA[ei_receive_msg]]></c> fails if the + message is bigger than the preallocated buffer in <c><![CDATA[x]]></c>.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[msg]]></c> is a pointer to an <c><![CDATA[erlang_msg]]></c> structure + and contains information on the message received.</p> + <p><c><![CDATA[x]]></c> is buffer obtained from <c><![CDATA[ei_x_new]]></c>.</p> + <p>On success, the function returns <c><![CDATA[ERL_MSG]]></c> and the + <c><![CDATA[msg]]></c> struct will be initialized. <c><![CDATA[erlang_msg]]></c> + is defined as follows:</p> + <code type="none"><![CDATA[ +typedef struct { + long msgtype; + erlang_pid from; + erlang_pid to; + char toname[MAXATOMLEN+1]; + char cookie[MAXATOMLEN+1]; + erlang_trace token; +} erlang_msg; + ]]></code> + <p><c><![CDATA[msgtype]]></c> identifies the type of message, and is one of + <c><![CDATA[ERL_SEND]]></c>, <c><![CDATA[ERL_REG_SEND]]></c>, <c><![CDATA[ERL_LINK]]></c>, + <c><![CDATA[ERL_UNLINK]]></c> and <c><![CDATA[ERL_EXIT]]></c>.</p> + <p>If <c><![CDATA[msgtype]]></c> is <c><![CDATA[ERL_SEND]]></c> this indicates that an + ordinary send operation has taken place, and <c><![CDATA[msg->to]]></c> + contains the Pid of the recipient (the C-node). If + <c><![CDATA[type]]></c> is <c><![CDATA[ERL_REG_SEND]]></c> then a registered send + operation took place, and <c><![CDATA[msg->from]]></c> contains the Pid + of the sender.</p> + <p>If <c><![CDATA[msgtype]]></c> is <c><![CDATA[ERL_LINK]]></c> or <c><![CDATA[ERL_UNLINK]]></c>, then + <c><![CDATA[msg->to]]></c> and <c><![CDATA[msg->from]]></c> contain the pids of the + sender and recipient of the link or unlink.</p> + <p>If <c><![CDATA[msgtype]]></c> is <c><![CDATA[ERL_EXIT]]></c>, then this indicates that + a link has been broken. In this case, <c><![CDATA[msg->to]]></c> and + <c><![CDATA[msg->from]]></c> contain the pids of the linked processes.</p> + <p>The return value is the same as for <c><![CDATA[ei_receive]]></c>, see + above.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_receive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned imeout_ms)</nametext></name> + <name><ret>int</ret><nametext>ei_xreceive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned timeout_ms)</nametext></name> + <fsummary>Receive a message with optional timeout</fsummary> + <desc> + <p>ei_receive_msg and ei_xreceive_msg with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_receive_encoded(int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglen)</nametext></name> + <fsummary>Obsolete function for receiving a message</fsummary> + <desc> + <p>This function is retained for compatibility with code + generated by the interface compiler and with code following + examples in the same application.</p> + <p>In essence the function performs the same operation as + <c><![CDATA[ei_xreceive_msg]]></c>, but instead of using an ei_x_buff, the + function expects a pointer to a character pointer + (<c><![CDATA[mbufp]]></c>), where the character pointer should point to a + memory area allocated by <c><![CDATA[malloc]]></c>. The argument + <c><![CDATA[bufsz]]></c> should be a pointer to an integer containing the + exact size (in bytes) of the memory area. The function may + reallocate the memory area and will in such cases put the new + size in <c><![CDATA[*bufsz]]></c> and update <c><![CDATA[*mbufp]]></c>.</p> + <p>Furthermore the function returns either ERL_TICK or the + <c><![CDATA[msgtype]]></c> field of the <c><![CDATA[erlang_msg *msg]]></c>. The actual + length of the message is put in <c><![CDATA[*msglen]]></c>. On error it + will return a value <c><![CDATA[< 0]]></c>.</p> + <p>It is recommended to use ei_xreceive_msg instead when + possible, for the sake of readability. The function will + however be retained in the interface for compatibility and + will <em>not</em> be removed not be removed in future releases + without notice.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_receive_encoded_tmo(int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglen, unsigned timeout_ms)</nametext></name> + <fsummary>Obsolete function for receiving a message with timeout</fsummary> + <desc> + <p>ei_receive_encoded with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_send(int fd, erlang_pid* to, char* buf, int len)</nametext></name> + <fsummary>Send a message</fsummary> + <desc> + <p>This function sends an Erlang term to a process.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[to]]></c> is the Pid of the intended recipient of the + message.</p> + <p><c><![CDATA[buf]]></c> is the buffer containing the term in binary + format.</p> + <p><c><![CDATA[len]]></c> is the length of the message in bytes.</p> + <p>The function returns 0 if successful, otherwise -1, in the + latter case it will set <c><![CDATA[erl_errno]]></c> to <c><![CDATA[EIO]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms)</nametext></name> + <fsummary>Send a message with optional timeout</fsummary> + <desc> + <p>ei_send with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_send_encoded(int fd, erlang_pid* to, char* buf, int len)</nametext></name> + <fsummary>Obsolete function to send a message</fsummary> + <desc> + <p>Works exactly as ei_send, the alternative name retained for + backward compatibility. The function will <em>not</em> be + removed without notice.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_send_encoded_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms)</nametext></name> + <fsummary>Obsolete function to send a message with optional timeout</fsummary> + <desc> + <p>ei_send_encoded with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_send(ei_cnode* ec, int fd, char* server_name, char* buf, int len)</nametext></name> + <fsummary>Send a message to a registered name</fsummary> + <desc> + <p>This function sends an Erlang term to a registered process. + </p> + <p>This function sends an Erlang term to a process.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[server_name]]></c> is the registered name of the intended + recipient.</p> + <p><c><![CDATA[buf]]></c> is the buffer containing the term in binary + format.</p> + <p><c><![CDATA[len]]></c> is the length of the message in bytes.</p> + <p>The function returns 0 if successful, otherwise -1, in the + latter case it will set <c><![CDATA[erl_errno]]></c> to <c><![CDATA[EIO]]></c>.</p> + <p>Example, send the atom "ok" to the process "worker":</p> + <code type="none"><![CDATA[ +ei_x_buff x; +ei_x_new_with_version(&x); +ei_x_encode_atom(&x, "ok"); +if (ei_reg_send(&ec, fd, x.buff, x.index) < 0) + handle_error(); + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_send_tmo(ei_cnode* ec, int fd, char* server_name, char* buf, int len, unsigned timeout_ms)</nametext></name> + <fsummary>Send a message to a registered name with optional timeout</fsummary> + <desc> + <p>ei_reg_send with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name> + <fsummary>Obsolete function to send a message to a registered name</fsummary> + <desc> + <p>This function is retained for compatibility with code + generated by the interface compiler and with code following + examples in the same application.</p> + <p>The function works as <c><![CDATA[ei_reg_send]]></c> with one + exception. Instead of taking the <c><![CDATA[ei_cnode]]></c> as a first + argument, it takes a second argument, an <c><![CDATA[erlang_pid]]></c> + which should be the process identifier of the sending process + (in the erlang distribution protocol). </p> + <p>A suitable <c><![CDATA[erlang_pid]]></c> can be constructed from the + <c><![CDATA[ei_cnode]]></c> structure by the following example code:</p> + <code type="none"><![CDATA[ + ei_cnode ec; + erlang_pid *self; + int fd; /* the connection fd */ + ... + self = ei_self(&ec); + self->num = fd; + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name> + <fsummary>Obsolete function to send a message to a registered name with timeout</fsummary> + <desc> + <p>ei_send_reg_encoded with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_rpc(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf, int argbuflen, ei_x_buff *x)</nametext></name> + <name><ret>int</ret><nametext>ei_rpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf, int argbuflen)</nametext></name> + <name><ret>int</ret><nametext>ei_rpc_from(ei_cnode *ec, int fd, int timeout, erlang_msg *msg, ei_x_buff *x)</nametext></name> + <fsummary>Remote Procedure Call from C to Erlang</fsummary> + <desc> + <p>These functions support calling Erlang functions on remote nodes. + <c><![CDATA[ei_rpc_to()]]></c> sends an rpc request to a remote node and + <c><![CDATA[ei_rpc_from()]]></c> receives the results of such a call. + <c><![CDATA[ei_rpc()]]></c> combines the functionality of these two functions + by sending an rpc request and waiting for the results. See also + <c><![CDATA[rpc:call/4]]></c>. </p> + <p><c><![CDATA[ec]]></c> is the C-node structure previously initiated by a + call to <c><![CDATA[ei_connect_init()]]></c> or + <c><![CDATA[ei_connect_xinit()]]></c></p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[timeout]]></c> is the maximum time (in ms) to wait for + results. Specify <c><![CDATA[ERL_NO_TIMEOUT]]></c> to wait forever. + <c><![CDATA[ei_rpc()]]></c> will wait infinitely for the answer, + i.e. the call will never time out.</p> + <p><c><![CDATA[mod]]></c> is the name of the module containing the function + to be run on the remote node.</p> + <p><c><![CDATA[fun]]></c> is the name of the function to run.</p> + <p><c><![CDATA[argbuf]]></c> is a pointer to a buffer with an encoded + Erlang list, without a version magic number, containing the + arguments to be passed to the function.</p> + <p><c><![CDATA[argbuflen]]></c> is the length of the buffer containing the + encoded Erlang list.</p> + <p><c><![CDATA[msg]]></c> structure of type <c><![CDATA[erlang_msg]]></c> and contains + information on the message received. See <c><![CDATA[ei_receive_msg()]]></c> + for a description of the <c><![CDATA[erlang_msg]]></c> format.</p> + <p><c><![CDATA[x]]></c> points to the dynamic buffer that receives the + result. For for <c><![CDATA[ei_rpc()]]></c> this will be the result + without the version magic number. For <c><![CDATA[ei_rpc_from()]]></c> + the result will return a version magic number and a 2-tuple + <c><![CDATA[{rex,Reply}]]></c>.</p> + <p><c><![CDATA[ei_rpc()]]></c> returns the number of bytes in the result + on success and -1 on failure. <c><![CDATA[ei_rpc_from()]]></c> returns + number of bytes or one of <c><![CDATA[ERL_TICK]]></c>, <c><![CDATA[ERL_TIMEOUT]]></c> + and <c><![CDATA[ERL_ERROR]]></c> otherwise. When failing, + all three functions set <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + <tag><c><![CDATA[ETIMEDOUT]]></c></tag> + <item>Timeout expired.</item> + <tag><c><![CDATA[EAGAIN]]></c></tag> + <item>Temporary error: Try again.</item> + </taglist> + <p>Example, check to see if an erlang process is alive:</p> + <code type="none"><![CDATA[ +int index = 0, is_alive; +ei_x_buff args, result; + +ei_x_new(&result); +ei_x_new(&args); +ei_x_encode_list_header(&args, 1); +ei_x_encode_pid(&args, &check_pid); +ei_x_encode_empty_list(&args); + +if (ei_rpc(&ec, fd, "erlang", "is_process_alive", + args.buff, args.index, &result) < 0) + handle_error(); + +if (ei_decode_version(result.buff, &index) < 0 + || ei_decode_bool(result.buff, &index, &is_alive) < 0) + handle_error(); + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_publish(ei_cnode *ec, int port)</nametext></name> + <fsummary>Publish a node name</fsummary> + <desc> + <p>These functions are used by a server process to register + with the local name server <em>epmd</em>, thereby allowing + other processes to send messages by using the registered name. + Before calling either of these functions, the process should + have called <c><![CDATA[bind()]]></c> and <c><![CDATA[listen()]]></c> on an open socket.</p> + <p><c><![CDATA[ec]]></c> is the C-node structure.</p> + <p><c><![CDATA[port]]></c> is the local name to register, and should be the + same as the port number that was previously bound to the socket.</p> + <p><c><![CDATA[addr]]></c> is the 32-bit IP address of the local host.</p> + <p>To unregister with epmd, simply close the returned + descriptor. See also <c><![CDATA[ei_unpublish()]]></c>.</p> + <p>On success, the functions return a descriptor connecting the + calling process to epmd. On failure, they return -1 and set + <c><![CDATA[erl_errno]]></c> to <c><![CDATA[EIO]]></c>.</p> + <p>Additionally, <c><![CDATA[errno]]></c> values from <c><![CDATA[socket]]></c><em>(2)</em> + and <c><![CDATA[connect]]></c><em>(2)</em> system calls may be propagated + into <c><![CDATA[erl_errno]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_publish_tmo(ei_cnode *ec, int port, unsigned timeout_ms)</nametext></name> + <fsummary>Publish a node name with optional timeout</fsummary> + <desc> + <p>ei_publish with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_accept(ei_cnode *ec, int listensock, ErlConnect *conp)</nametext></name> + <fsummary>Accept a connection from another node</fsummary> + <desc> + <p>This function is used by a server process to accept a + connection from a client process.</p> + <p><c><![CDATA[ec]]></c> is the C-node structure.</p> + <p><c><![CDATA[listensock]]></c> is an open socket descriptor on which + <c><![CDATA[listen()]]></c> has previously been called.</p> + <p><c><![CDATA[conp]]></c> is a pointer to an <c><![CDATA[ErlConnect]]></c> struct, + described as follows:</p> + <code type="none"><![CDATA[ +typedef struct { + char ipadr[4]; + char nodename[MAXNODELEN]; +} ErlConnect; + ]]></code> + <p>On success, <c><![CDATA[conp]]></c> is filled in with the address and + node name of the connecting client and a file descriptor is + returned. On failure, <c><![CDATA[ERL_ERROR]]></c> is returned and + <c><![CDATA[erl_errno]]></c> is set to <c><![CDATA[EIO]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_accept_tmo(ei_cnode *ec, int listensock, ErlConnect *conp, unsigned timeout_ms)</nametext></name> + <fsummary>Accept a connection from another node with optional timeout</fsummary> + <desc> + <p>ei_accept with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_unpublish(ei_cnode *ec)</nametext></name> + <fsummary>Unpublish a node name</fsummary> + <desc> + <p>This function can be called by a process to unregister a + specified node from epmd on the localhost. This may be + useful, for example, when epmd has not detected the failure of a + node, and will not allow the name to be reused. If you use this + function to unregister your own process, be sure to also close + the descriptor that was returned by <c><![CDATA[ei_publish()]]></c>.</p> + <note> + <p>Careless use of this function may have unpredictable + results, if the registered node is in fact still running.</p> + </note> + <p><c><![CDATA[ec]]></c> is the node structure of the node to unregister.</p> + <p>If the node was successfully unregistered from epmd, the + function returns 0. Otherwise, it returns -1 and sets + <c><![CDATA[erl_errno]]></c> is to <c><![CDATA[EIO]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_unpublish_tmo(ei_cnode *ec, unsigned timeout_ms)</nametext></name> + <fsummary>Unpublish a node name with optional timeout</fsummary> + <desc> + <p>ei_unpublish with an optional timeout argument, + see the description at the beginning of this document.</p> + </desc> + </func> + <func> + <name><ret>const char *</ret><nametext>ei_thisnodename(ei_cnode *ec)</nametext></name> + <name><ret>const char *</ret><nametext>ei_thishostname(ei_cnode *ec)</nametext></name> + <name><ret>const char *</ret><nametext>ei_thisalivename(ei_cnode *ec)</nametext></name> + <fsummary>Retrieve some values</fsummary> + <desc> + <p>These functions can be used to retrieve information about + the C Node. These values are initially set with + <c><![CDATA[ei_connect_init()]]></c> or <c><![CDATA[ei_connect_xinit()]]></c>.</p> + <p>They simply fetches the appropriate field from the <c><![CDATA[ec]]></c> + structure. Read the field directly will probably be safe for + a long time, so these functions are not really needed.</p> + </desc> + </func> + <func> + <name><ret>erlang_pid *</ret><nametext>ei_self(ei_cnode *ec)</nametext></name> + <fsummary>Retrieve the Pid of the C-node</fsummary> + <desc> + <p>This function retrieves the Pid of the C-node. Every C-node + has a (pseudo) pid used in <c><![CDATA[ei_send_reg]]></c>, <c><![CDATA[ei_rpc]]></c> + and others. This is contained in a field in the <c><![CDATA[ec]]></c> + structure. It will be safe for a long time to fetch this + field directly from the <c><![CDATA[ei_cnode]]></c> structure.</p> + </desc> + </func> + <func> + <name><ret>struct hostent</ret><nametext>*ei_gethostbyname(const char *name)</nametext></name> + <name><ret>struct hostent</ret><nametext>*ei_gethostbyaddr(const char *addr, int len, int type)</nametext></name> + <name><ret>struct hostent</ret><nametext>*ei_gethostbyname_r(const char *name, struct hostent *hostp, char *buffer, int buflen, int *h_errnop)</nametext></name> + <name><ret>struct hostent</ret><nametext>*ei_gethostbyaddr_r(const char *addr, int length, int type, struct hostent *hostp, char *buffer, int buflen, int *h_errnop)</nametext></name> + <fsummary>Name lookup functions</fsummary> + <desc> + <p>These are convenience functions for some common name lookup functions.</p> + </desc> + </func> + </funcs> + + <section> + <title>Debug Information</title> + <p>If a connection attempt fails, the following can be checked:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_errno]]></c></item> + <item>that the right cookie was used</item> + <item>that <em>epmd</em> is running</item> + <item>the remote Erlang node on the other side is running the + same version of Erlang as the <c><![CDATA[ei]]></c> + library.</item> + <item>the environment variable <c><![CDATA[ERL_EPMD_PORT]]></c> + is set correctly.</item> + </list> + </section> +</cref> + diff --git a/lib/erl_interface/doc/src/ei_users_guide.xml b/lib/erl_interface/doc/src/ei_users_guide.xml new file mode 100644 index 0000000000..5d18e356cb --- /dev/null +++ b/lib/erl_interface/doc/src/ei_users_guide.xml @@ -0,0 +1,612 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>The El Library User's Guide</title> + <prepared>Kent Boortz</prepared> + <responsible>Kent Boortz</responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date></date> + <rev></rev> + <file>ei_users_guide.xml</file> + </header> + <p>The Erl_Interface library contains functions. which help you + integrate programs written in C and Erlang. The functions in + Erl_Interface support the following:</p> + <list type="bulleted"> + <item>manipulation of data represented as Erlang data types</item> + <item>conversion of data between C and Erlang formats</item> + <item>encoding and decoding of Erlang data types for transmission or storage</item> + <item>communication between C nodes and Erlang processes</item> + <item>backup and restore of C node state to and from Mnesia</item> + </list> + <p>In the following sections, these topics are described:</p> + <list type="bulleted"> + <item>compiling your code for use with Erl_Interface</item> + <item>initializing Erl_Interface</item> + <item>encoding, decoding, and sending Erlang terms</item> + <item>building terms and patterns</item> + <item>pattern matching</item> + <item>connecting to a distributed Erlang node</item> + <item>using EPMD</item> + <item>sending and receiving Erlang messages</item> + <item>remote procedure calls</item> + <item>global names</item> + <item>the registry</item> + </list> + + <section> + <title>Compiling and Linking Your Code</title> + <p>In order to use any of the Erl_Interface functions, include the + following lines in your code:</p> + <code type="none"><![CDATA[ +#include "erl_interface.h" +#include "ei.h" ]]></code> + <p>Determine where the top directory of your OTP installation is. You + can find this out by starting Erlang and entering the following + command at the Eshell prompt:</p> + <code type="none"><![CDATA[ +Eshell V4.7.4 (abort with ^G) +1> code:root_dir(). +/usr/local/otp ]]></code> + <p>To compile your code, make sure that your C compiler knows where + to find <c><![CDATA[erl_interface.h]]></c> by specifying an appropriate <c><![CDATA[-I]]></c> + argument on the command line, or by adding it to the <c><![CDATA[CFLAGS]]></c> + definition in your <c><![CDATA[Makefile]]></c>. The correct value for this path is + <c><![CDATA[$OTPROOT/lib/erl_interface]]></c><em>Vsn</em><c><![CDATA[/include]]></c>, where <c><![CDATA[$OTPROOT]]></c> is the path + reported by <c><![CDATA[code:root_dir/0]]></c> in the above example, and <em>Vsn</em> is + the version of the Erl_interface application, for example + <c><![CDATA[erl_interface-3.2.3]]></c></p> + <code type="none"><![CDATA[ +$ cc -c -I/usr/local/otp/lib/erl_interface-3.2.3/include myprog.c ]]></code> + <p>When linking, you will need to specify the path to + <c><![CDATA[liberl_interface.a]]></c> and <c><![CDATA[libei.a]]></c> with + <c><![CDATA[-L$OTPROOT/lib/erl_interface-3.2.3/lib]]></c>, and you will need to specify the + name of the libraries with <c><![CDATA[-lerl_interface -lei]]></c>. You can do + this on the command line or by adding the flags to the <c><![CDATA[LDFLAGS]]></c> + definition in your <c><![CDATA[Makefile]]></c>.</p> + <code type="none"><![CDATA[ +$ ld -L/usr/local/otp/lib/erl_interface-3.2.3/ + lib myprog.o -lerl_interface -lei -o myprog ]]></code> + <p>Also, on some systems it may be necessary to link with some + additional libraries (e.g. <c><![CDATA[libnsl.a]]></c> and <c><![CDATA[libsocket.a]]></c> on + Solaris, or <c><![CDATA[wsock32.lib]]></c> on Windows) in order to use the + communication facilities of Erl_Interface.</p> + <p>If you are using Erl_Interface functions in a threaded + application based on POSIX threads or Solaris threads, then + Erl_Interface needs access to some of the synchronization + facilities in your threads package, and you will need to specify + additional compiler flags in order to indicate which of the packages + you are using. Define <c><![CDATA[_REENTRANT]]></c> and either <c><![CDATA[STHREADS]]></c> or + <c><![CDATA[PTHREADS]]></c>. The default is to use POSIX threads if + <c><![CDATA[_REENTRANT]]></c> is specified.</p> + </section> + + <section> + <title>Initializing the erl_interface Library</title> + <p>Before calling any of the other Erl_Interface functions, you + must call <c><![CDATA[erl_init()]]></c> exactly once to initialize the library. + <c><![CDATA[erl_init()]]></c> takes two arguments, however the arguments are no + longer used by Erl_Interface, and should therefore be specified + as <c><![CDATA[erl_init(NULL,0)]]></c>.</p> + </section> + + <section> + <title>Encoding, Decoding and Sending Erlang Terms</title> + <p>Data sent between distributed Erlang nodes is encoded in the + Erlang external format. Consequently, you have to encode and decode + Erlang terms into byte streams if you want to use the distribution + protocol to communicate between a C program and Erlang. </p> + <p>The Erl_Interface library supports this activity. It has a + number of C functions which create and manipulate Erlang data + structures. The library also contains an encode and a decode function. + The example below shows how to create and encode an Erlang tuple + <c><![CDATA[{tobbe,3928}]]></c>:</p> + <code type="none"><![CDATA[ + +ETERM *arr[2], *tuple; +char buf[BUFSIZ]; +int i; + +arr[0] = erl_mk_atom("tobbe"); +arr[1] = erl_mk_integer(3928); +tuple = erl_mk_tuple(arr, 2); +i = erl_encode(tuple, buf); ]]></code> + <p>Alternatively, you can use <c><![CDATA[erl_send()]]></c> and + <c><![CDATA[erl_receive_msg]]></c>, which handle the encoding and decoding of + messages transparently.</p> + <p>Refer to the Reference Manual for a complete description of the + following modules:</p> + <list type="bulleted"> + <item>the <c><![CDATA[erl_eterm]]></c> module for creating Erlang terms</item> + <item>the <c><![CDATA[erl_marshal]]></c> module for encoding and decoding routines.</item> + </list> + </section> + + <section> + <title>Building Terms and Patterns</title> + <p>The previous example can be simplified by using + <c><![CDATA[erl_format()]]></c> to create an Erlang term.</p> + <code type="none"><![CDATA[ + +ETERM *ep; +ep = erl_format("{~a,~i}", "tobbe", 3928); ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_format]]></c> module, for a + full description of the different format directives. The following + example is more complex:</p> + <code type="none"><![CDATA[ + +ETERM *ep; +ep = erl_format("[{name,~a},{age,~i},{data,~w}]", + "madonna", + 21, + erl_format("[{adr,~s,~i}]", "E-street", 42)); +erl_free_compound(ep); ]]></code> + <p>As in previous examples, it is your responsibility to free the + memory allocated for Erlang terms. In this example, + <c><![CDATA[erl_free_compound()]]></c> ensures that the complete term pointed to + by <c><![CDATA[ep]]></c> is released. This is necessary, because the pointer from + the second call to <c><![CDATA[erl_format()]]></c> is lost. </p> + <p>The following + example shows a slightly different solution:</p> + <code type="none"><![CDATA[ + +ETERM *ep,*ep2; +ep2 = erl_format("[{adr,~s,~i}]","E-street",42); +ep = erl_format("[{name,~a},{age,~i},{data,~w}]", + "madonna", 21, ep2); +erl_free_term(ep); +erl_free_term(ep2); ]]></code> + <p>In this case, you free the two terms independently. The order in + which you free the terms <c><![CDATA[ep]]></c> and <c><![CDATA[ep2]]></c> is not important, + because the Erl_Interface library uses reference counting to + determine when it is safe to actually remove objects. </p> + <p>If you are not sure whether you have freed the terms properly, you + can use the following function to see the status of the fixed term + allocator:</p> + <code type="none"><![CDATA[ +long allocated, freed; + +erl_eterm_statistics(&allocated,&freed); +printf("currently allocated blocks: %ld\n",allocated); +printf("length of freelist: %ld\n",freed); + +/* really free the freelist */ +erl_eterm_release(); + ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_malloc]]></c> module for more + information.</p> + </section> + + <section> + <title>Pattern Matching</title> + <p>An Erlang pattern is a term that may contain unbound variables or + <c><![CDATA["do not care"]]></c> symbols. Such a pattern can be matched against a + term and, if the match is successful, any unbound variables in the + pattern will be bound as a side effect. The content of a bound + variable can then be retrieved.</p> + <code type="none"><![CDATA[ + +ETERM *pattern; +pattern = erl_format("{madonna,Age,_}"); ]]></code> + <p><c><![CDATA[erl_match()]]></c> is used to perform pattern matching. It takes a + pattern and a term and tries to match them. As a side effect any unbound + variables in the pattern will be bound. In the following example, we + create a pattern with a variable <em>Age</em> which appears at two + positions in the tuple. The pattern match is performed as follows:</p> + <list type="ordered"> + <item><c><![CDATA[erl_match()]]></c> will bind the contents of + <em>Age</em> to <em>21</em> the first time it reaches the variable</item> + <item>the second occurrence of <em>Age</em> will cause a test for + equality between the terms since <em>Age</em> is already bound to + <em>21</em>. Since <em>Age</em> is bound to 21, the equality test will + succeed and the match continues until the end of the pattern.</item> + <item>if the end of the pattern is reached, the match succeeds and you + can retrieve the contents of the variable</item> + </list> + <code type="none"><![CDATA[ +ETERM *pattern,*term; +pattern = erl_format("{madonna,Age,Age}"); +term = erl_format("{madonna,21,21}"); +if (erl_match(pattern, term)) { + fprintf(stderr, "Yes, they matched: Age = "); + ep = erl_var_content(pattern, "Age"); + erl_print_term(stderr, ep); + fprintf(stderr,"\n"); + erl_free_term(ep); +} +erl_free_term(pattern); +erl_free_term(term); ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_match()]]></c> function for + more information.</p> + </section> + + <section> + <title>Connecting to a Distributed Erlang Node</title> + <p>In order to connect to a distributed Erlang node you need to first + initialize the connection routine with <c><![CDATA[erl_connect_init()]]></c>, + which stores information such as the host name, node name, and IP + address for later use:</p> + <code type="none"><![CDATA[ +int identification_number = 99; +int creation=1; +char *cookie="a secret cookie string"; /* An example */ +erl_connect_init(identification_number, cookie, creation); ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_connect]]></c> module for more information.</p> + <p>After initialization, you set up the connection to the Erlang node. + Use <c><![CDATA[erl_connect()]]></c> to specify the Erlang node you want to + connect to. The following example sets up the connection and should + result in a valid socket file descriptor:</p> + <code type="none"><![CDATA[ +int sockfd; +char *nodename="[email protected]"; /* An example */ +if ((sockfd = erl_connect(nodename)) < 0) + erl_err_quit("ERROR: erl_connect failed"); ]]></code> + <p><c><![CDATA[erl_err_quit()]]></c> prints the specified string and terminates + the program. Refer to the Reference Manual, the <c><![CDATA[erl_error()]]></c> + function for more information.</p> + </section> + + <section> + <title>Using EPMD</title> + <p><c><![CDATA[Epmd]]></c> is the Erlang Port Mapper Daemon. Distributed Erlang nodes + register with <c><![CDATA[epmd]]></c> on the localhost to indicate to other nodes that + they exist and can accept connections. <c><![CDATA[Epmd]]></c> maintains a register of + node and port number information, and when a node wishes to connect to + another node, it first contacts <c><![CDATA[epmd]]></c> in order to find out the correct + port number to connect to.</p> + <p>When you use <c><![CDATA[erl_connect()]]></c> to connect to an Erlang node, a + connection is first made to <c><![CDATA[epmd]]></c> and, if the node is known, a + connection is then made to the Erlang node.</p> + <p>C nodes can also register themselves with <c><![CDATA[epmd]]></c> if they want other + nodes in the system to be able to find and connect to them.</p> + <p>Before registering with <c><![CDATA[epmd]]></c>, you need to first create a listen socket + and bind it to a port. Then:</p> + <code type="none"><![CDATA[ +int pub; + +pub = erl_publish(port); ]]></code> + <p><c><![CDATA[pub]]></c> is a file descriptor now connected to <c><![CDATA[epmd]]></c>. <c><![CDATA[Epmd]]></c> + monitors the other end of the connection, and if it detects that the + connection has been closed, the node will be unregistered. So, if you + explicitly close the descriptor or if your node fails, it will be + unregistered from <c><![CDATA[epmd]]></c>.</p> + <p>Be aware that on some systems (such as VxWorks), a failed node will + not be detected by this mechanism since the operating system does not + automatically close descriptors that were left open when the node + failed. If a node has failed in this way, <c><![CDATA[epmd]]></c> will prevent you from + registering a new node with the old name, since it thinks that the old + name is still in use. In this case, you must unregister the name + explicitly:</p> + <code type="none"><![CDATA[ +erl_unpublish(node); ]]></code> + <p>This will cause <c><![CDATA[epmd]]></c> to close the connection from the far end. Note + that if the name was in fact still in use by a node, the results of + this operation are unpredictable. Also, doing this does not cause the + local end of the connection to close, so resources may be consumed.</p> + </section> + + <section> + <title>Sending and Receiving Erlang Messages</title> + <p>Use one of the following two functions to send messages:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_send()]]></c></item> + <item><c><![CDATA[erl_reg_send()]]></c></item> + </list> + <p>As in Erlang, it is possible to send messages to a + <em>Pid</em> or to a registered name. It is easier to send a + message to a registered name because it avoids the problem of finding + a suitable <em>Pid</em>.</p> + <p>Use one of the following two functions to receive messages:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_receive()]]></c></item> + <item><c><![CDATA[erl_receive_msg()]]></c></item> + </list> + <p><c><![CDATA[erl_receive()]]></c> receives the message into a buffer, while + <c><![CDATA[erl_receive_msg()]]></c> decodes the message into an Erlang term. </p> + + <section> + <title>Example of Sending Messages</title> + <p>In the following example, <c><![CDATA[{Pid, hello_world}]]></c> is + sent to a registered process <c><![CDATA[my_server]]></c>. The message is encoded + by <c><![CDATA[erl_send()]]></c>:</p> + <code type="none"><![CDATA[ +extern const char *erl_thisnodename(void); +extern short erl_thiscreation(void); +#define SELF(fd) erl_mk_pid(erl_thisnodename(),fd,0,erl_thiscreation()) +ETERM *arr[2], *emsg; +int sockfd, creation=1; + +arr[0] = SELF(sockfd); +arr[1] = erl_mk_atom("Hello world"); +emsg = erl_mk_tuple(arr, 2); + +erl_reg_send(sockfd, "my_server", emsg); +erl_free_term(emsg); ]]></code> + <p>The first element of the tuple that is sent is your own + <em>Pid</em>. This enables <c><![CDATA[my_server]]></c> to reply. Refer to the + Reference Manual, the <c><![CDATA[erl_connect]]></c> module for more information + about send primitives.</p> + </section> + + <section> + <title>Example of Receiving Messages</title> + <p>In this example <c><![CDATA[{Pid, Something}]]></c> is received. The + received Pid is then used to return <c><![CDATA[{goodbye,Pid}]]></c></p> + <code type="none"><![CDATA[ +ETERM *arr[2], *answer; +int sockfd,rc; +char buf[BUFSIZE]; +ErlMessage emsg; + +if ((rc = erl_receive_msg(sockfd , buf, BUFSIZE, &emsg)) == ERL_MSG) { + arr[0] = erl_mk_atom("goodbye"); + arr[1] = erl_element(1, emsg.msg); + answer = erl_mk_tuple(arr, 2); + erl_send(sockfd, arr[1], answer); + erl_free_term(answer); + erl_free_term(emsg.msg); + erl_free_term(emsg.to); +} ]]></code> + <p>In order to provide robustness, a distributed Erlang node + occasionally polls all its connected neighbours in an attempt to + detect failed nodes or communication links. A node which receives such + a message is expected to respond immediately with an <c><![CDATA[ERL_TICK]]></c> message. + This is done automatically by <c><![CDATA[erl_receive()]]></c>, however when this + has occurred <c><![CDATA[erl_receive]]></c> returns <c><![CDATA[ERL_TICK]]></c> to the caller + without storing a message into the <c><![CDATA[ErlMessage]]></c> structure.</p> + <p>When a message has been received, it is the caller's responsibility + to free the received message <c><![CDATA[emsg.msg]]></c> as well as <c><![CDATA[emsg.to]]></c> + or <c><![CDATA[emsg.from]]></c>, depending on the type of message received.</p> + <p>Refer to the Reference Manual for additional information about the + following modules:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_connect]]></c></item> + <item><c><![CDATA[erl_eterm]]></c>.</item> + </list> + </section> + </section> + + <section> + <title>Remote Procedure Calls</title> + <p>An Erlang node acting as a client to another Erlang node + typically sends a request and waits for a reply. Such a request is + included in a function call at a remote node and is called a remote + procedure call. The following example shows how the + Erl_Interface library supports remote procedure calls:</p> + <code type="none"><![CDATA[ + +char modname[]=THE_MODNAME; +ETERM *reply,*ep; +ep = erl_format("[~a,[]]", modname); +if (!(reply = erl_rpc(fd, "c", "c", ep))) + erl_err_msg("<ERROR> when compiling file: %s.erl !\n", modname); +erl_free_term(ep); +ep = erl_format("{ok,_}"); +if (!erl_match(ep, reply)) + erl_err_msg("<ERROR> compiler errors !\n"); +erl_free_term(ep); +erl_free_term(reply); ]]></code> + <p><c><![CDATA[c:c/1]]></c> is called to compile the specified module on the + remote node. <c><![CDATA[erl_match()]]></c> checks that the compilation was + successful by testing for the expected <c><![CDATA[ok]]></c>.</p> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_connect]]></c> module for + more information about <c><![CDATA[erl_rpc()]]></c>, and its companions + <c><![CDATA[erl_rpc_to()]]></c> and <c><![CDATA[erl_rpc_from()]]></c>.</p> + </section> + + <section> + <title>Using Global Names</title> + <p>A C node has access to names registered through the Erlang Global + module. Names can be looked up, allowing the C node to send messages + to named Erlang services. C nodes can also register global names, + allowing them to provide named services to Erlang processes or other C + nodes. </p> + <p>Erl_Interface does not provide a native implementation of the global + service. Instead it uses the global services provided by a "nearby" + Erlang node. In order to use the services described in this section, + it is necessary to first open a connection to an Erlang node.</p> + <p>To see what names there are:</p> + <code type="none"><![CDATA[ +char **names; +int count; +int i; + +names = erl_global_names(fd,&count); + +if (names) + for (i=0; i<count; i++) + printf("%s\n",names[i]); + +free(names); ]]></code> + <p><c><![CDATA[erl_global_names()]]></c> allocates and returns a buffer containing + all the names known to global. <c><![CDATA[count]]></c> will be initialized to + indicate how many names are in the array. The array of strings in + names is terminated by a NULL pointer, so it is not necessary to use + <c><![CDATA[count]]></c> to determine when the last name is reached.</p> + <p>It is the caller's responsibility to free the array. + <c><![CDATA[erl_global_names()]]></c> allocates the array and all of the strings + using a single call to <c><![CDATA[malloc()]]></c>, so <c><![CDATA[free(names)]]></c> is all + that is necessary.</p> + <p>To look up one of the names:</p> + <code type="none"><![CDATA[ +ETERM *pid; +char node[256]; + +pid = erl_global_whereis(fd,"schedule",node); ]]></code> + <p>If <c><![CDATA["schedule"]]></c> is known to global, an Erlang pid is returned + that can be used to send messages to the schedule service. + Additionally, <c><![CDATA[node]]></c> will be initialized to contain the name of + the node where the service is registered, so that you can make a + connection to it by simply passing the variable to <c><![CDATA[erl_connect()]]></c>.</p> + <p>Before registering a name, you should already have registered your + port number with <c><![CDATA[epmd]]></c>. This is not strictly necessary, but if you + neglect to do so, then other nodes wishing to communicate with your + service will be unable to find or connect to your process.</p> + <p>Create a pid that Erlang processes can use to communicate with your + service:</p> + <code type="none"><![CDATA[ +ETERM *pid; + +pid = erl_mk_pid(thisnode,14,0,0); +erl_global_register(fd,servicename,pid); ]]></code> + <p>After registering the name, you should use <c><![CDATA[erl_accept()]]></c> to wait for + incoming connections.</p> + <p>Do not forget to free <c><![CDATA[pid]]></c> later with <c><![CDATA[erl_free_term()]]></c>!</p> + <p>To unregister a name:</p> + <code type="none"><![CDATA[ +erl_global_unregister(fd,servicename); ]]></code> + </section> + + <section> + <title>The Registry</title> + <p>This section describes the use of the registry, a simple mechanism + for storing key-value pairs in a C-node, as well as backing them up or + restoring them from a Mnesia table on an Erlang node. More detailed + information about the individual API functions can be found in the + Reference Manual.</p> + <p>Keys are strings, i.e. 0-terminated arrays of characters, and values + are arbitrary objects. Although integers and floating point numbers + are treated specially by the registry, you can store strings or binary + objects of any type as pointers.</p> + <p>To start, you need to open a registry:</p> + <code type="none"><![CDATA[ +ei_reg *reg; + +reg = ei_reg_open(45); ]]></code> + <p>The number 45 in the example indicates the approximate number of + objects that you expect to store in the registry. Internally the + registry uses hash tables with collision chaining, so there is no + absolute upper limit on the number of objects that the registry can + contain, but if performance or memory usage are important, then you + should choose a number accordingly. The registry can be resized later.</p> + <p>You can open as many registries as you like (if memory permits).</p> + <p>Objects are stored and retrieved through set and get functions. In + the following examples you see how to store integers, floats, strings + and arbitrary binary objects:</p> + <code type="none"><![CDATA[ +struct bonk *b = malloc(sizeof(*b)); +char *name = malloc(7); + +ei_reg_setival(reg,"age",29); +ei_reg_setfval(reg,"height",1.85); + +strcpy(name,"Martin"); +ei_reg_setsval(reg,"name",name); + +b->l = 42; +b->m = 12; +ei_reg_setpval(reg,"jox",b,sizeof(*b)); ]]></code> + <p>If you attempt to store an object in the registry and there is an + existing object with the same key, the new value will replace the old + one. This is done regardless of whether the new object and the old one + have the same type, so you can, for example, replace a string with an + integer. If the existing value is a string or binary, it will be freed + before the new value is assigned.</p> + <p>Stored values are retrieved from the registry as follows:</p> + <code type="none"><![CDATA[ +long i; +double f; +char *s; +struct bonk *b; +int size; + +i = ei_reg_getival(reg,"age"); +f = ei_reg_getfval(reg,"height"); +s = ei_reg_getsval(reg,"name"); +b = ei_reg_getpval(reg,"jox",&size); ]]></code> + <p>In all of the above examples, the object must exist and it must be of + the right type for the specified operation. If you do not know the + type of a given object, you can ask:</p> + <code type="none"><![CDATA[ +struct ei_reg_stat buf; + +ei_reg_stat(reg,"name",&buf); ]]></code> + <p>Buf will be initialized to contain object attributes.</p> + <p>Objects can be removed from the registry:</p> + <code type="none"><![CDATA[ +ei_reg_delete(reg,"name"); ]]></code> + <p>When you are finished with a registry, close it to remove all the + objects and free the memory back to the system:</p> + <code type="none"><![CDATA[ +ei_reg_close(reg); ]]></code> + + <section> + <title>Backing Up the Registry to Mnesia</title> + <p>The contents of a registry can be backed up to Mnesia on a "nearby" + Erlang node. You need to provide an open connection to the Erlang node + (see <c><![CDATA[erl_connect()]]></c>). Also, Mnesia 3.0 or later must be running + on the Erlang node before the backup is initiated:</p> + <code type="none"><![CDATA[ +ei_reg_dump(fd, reg, "mtab", dumpflags); ]]></code> + <p>The example above will backup the contents of the registry to the + specified Mnesia table <c><![CDATA["mtab"]]></c>. Once a registry has been backed + up to Mnesia in this manner, additional backups will only affect + objects that have been modified since the most recent backup, i.e. + objects that have been created, changed or deleted. The backup + operation is done as a single atomic transaction, so that the entire + backup will be performed or none of it will.</p> + <p>In the same manner, a registry can be restored from a Mnesia table:</p> + <code type="none"><![CDATA[ +ei_reg_restore(fd, reg, "mtab"); ]]></code> + <p>This will read the entire contents of <c><![CDATA["mtab"]]></c> into the specified + registry. After the restore, all of the objects in the registry will + be marked as unmodified, so a subsequent backup will only affect + objects that you have modified since the restore.</p> + <p>Note that if you restore to a non-empty registry, objects in the + table will overwrite objects in the registry with the same keys. Also, + the <em>entire</em> contents of the registry is marked as unmodified + after the restore, including any modified objects that were not + overwritten by the restore operation. This may not be your intention.</p> + </section> + + <section> + <title>Storing Strings and Binaries</title> + <p>When string or binary objects are stored in the registry it is + important that a number of simple guidelines are followed. </p> + <p>Most importantly, the object must have been created with a single call + to <c><![CDATA[malloc()]]></c> (or similar), so that it can later be removed by a + single call to <c><![CDATA[free()]]></c>. Objects will be freed by the registry + when it is closed, or when you assign a new value to an object that + previously contained a string or binary.</p> + <p>You should also be aware that if you store binary objects that are + context-dependent (e.g. containing pointers or open file descriptors), + they will lose their meaning if they are backed up to a Mnesia table + and subsequently restored in a different context.</p> + <p>When you retrieve a stored string or binary value from the registry, + the registry maintains a pointer to the object and you are passed a + copy of that pointer. You should never free an object retrieved in + this manner because when the registry later attempts to free it, a + runtime error will occur that will likely cause the C-node to crash.</p> + <p>You are free to modify the contents of an object retrieved this way. + However when you do so, the registry will not be aware of the changes + you make, possibly causing it to be missed the next time you make a + Mnesia backup of the registry contents. This can be avoided if you + mark the object as dirty after any such changes with + <c><![CDATA[ei_reg_markdirty()]]></c>, or pass appropriate flags to + <c><![CDATA[ei_reg_dump()]]></c>.</p> + </section> + </section> +</chapter> + diff --git a/lib/erl_interface/doc/src/erl_call.xml b/lib/erl_interface/doc/src/erl_call.xml new file mode 100644 index 0000000000..2d88e7616a --- /dev/null +++ b/lib/erl_interface/doc/src/erl_call.xml @@ -0,0 +1,240 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_call</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>97-05-16</date> + <rev>B</rev> + <file>erl_call.sgml</file> + </header> + <com>erl_call</com> + <comsummary>Call/Start a Distributed Erlang Node</comsummary> + <description> + <p><c><![CDATA[erl_call]]></c> makes it possible to start and/or communicate with + a distributed Erlang node. It is built upon the <c><![CDATA[erl_interface]]></c> + library as an example application. Its purpose is to use an Unix shell script to interact with a distributed Erlang node. It performs all + communication with the Erlang <em>rex server</em>, using the standard Erlang RPC facility. It does not require any special + software to be run at the Erlang target node.</p> + <p>The main use is to either start a distributed Erlang node + or to make an ordinary function call. However, it is also + possible to pipe an Erlang module to <c><![CDATA[erl_call]]></c> and have it + compiled, or to pipe a sequence of Erlang expressions to be evaluated + (similar to the Erlang shell).</p> + <p>Options, which cause <c><![CDATA[stdin]]></c> to be read, can be used with + advantage + as scripts from within (Unix) shell scripts. Another + nice use of <c><![CDATA[erl_call]]></c> could be from (http) CGI-bin scripts.</p> + </description> + <funcs> + <func> + <name>erl_call <options></name> + <fsummary>Start/Call Erlang</fsummary> + <desc> + <p>Each option flag is described below with its name, type and + meaning. </p> + <taglist> + <tag>-a [Mod [Fun [Args]]]]</tag> + <item> + <p>(<em>optional</em>): Applies the specified function + and returns the result. <c><![CDATA[Mod]]></c> must be specified, however + <em>[]</em> is assumed for unspecified <c><![CDATA[Fun]]></c> and <c><![CDATA[Args]]></c>. <c><![CDATA[Args]]></c> should + be in the same format as for <c><![CDATA[erlang:apply/3]]></c>. Note + that this flag takes exactly one argument, so quoting + may be necessary in order to group <c><![CDATA[Mod]]></c>, <c><![CDATA[Fun]]></c> + and <c><![CDATA[Args]]></c>, in a manner dependent on the behavior + of your command shell.</p> + <p></p> + </item> + <tag>-c Cookie</tag> + <item> + <p>(<em>optional</em>): Use this option to specify a certain cookie. If no cookie is specified, the <c><![CDATA[~/.erlang.cookie]]></c> file is read and its content are used as cookie. The Erlang node we want to communicate with must have the same cookie.</p> + </item> + <tag>-d</tag> + <item> + <p>(<em>optional</em>): Debug mode. This causes all IO to be output + to the file <c><![CDATA[~/.erl_call.out.Nodename]]></c>, where <c><![CDATA[Nodename]]></c> + is the node name of the Erlang node in question.</p> + <p></p> + </item> + <tag>-e</tag> + <item> + <p>(<em>optional</em>): Reads a sequence of Erlang expressions, separated + by '<em>,</em>' and ended with a '<em>.</em>', from <c><![CDATA[stdin]]></c> until + EOF (Control-D). Evaluates the expressions and returns the result from + the last expression. Returns <c><![CDATA[{ok,Result}]]></c> if successful.</p> + <p></p> + </item> + <tag>-h HiddenName</tag> + <item> + <p>(<em>optional</em>): Specifies the name of the hidden node + that <c><![CDATA[erl_call]]></c> represents.</p> + <p></p> + </item> + <tag>-m</tag> + <item> + <p>(<em>optional</em>): Reads an Erlang module from <c><![CDATA[stdin]]></c> and + compiles it.</p> + <p></p> + </item> + <tag>-n Node</tag> + <item> + <p>(one of <c><![CDATA[-n, -name, -sname]]></c> is required): + Has the same meaning as <c><![CDATA[-name]]></c> and can still be used for + backwards compatibility reasons.</p> + <p></p> + </item> + <tag>-name Node</tag> + <item> + <p>(one of <c><![CDATA[-n, -name, -sname]]></c> is required): <c><![CDATA[Node]]></c> is the name of the node to be + started or communicated with. It is assumed that + <c><![CDATA[Node]]></c> is started with <c><![CDATA[erl -name]]></c>, which means that fully + qualified long node names are used. + If the <c><![CDATA[-s]]></c> option is given, an Erlang node will (if necessary) + be started with <c><![CDATA[erl -name]]></c>.</p> + <p></p> + </item> + <tag>-q</tag> + <item> + <p>(<em>optional</em>): Halts the Erlang node specified + with the -n switch. This switch overrides the -s switch.</p> + <p></p> + </item> + <tag>-r</tag> + <item> + <p>(<em>optional</em>): Generates a random name of the hidden node + that <c><![CDATA[erl_call]]></c> represents.</p> + <p></p> + </item> + <tag>-s</tag> + <item> + <p>(<em>optional</em>): Starts a distributed Erlang node if necessary. + This means that in a sequence of calls, where the '<c><![CDATA[-s]]></c>' + and '<c><![CDATA[-n Node]]></c>' are constant, only the first call will start + the Erlang node. This makes the rest of the communication + very fast. This flag is currently only available on the Unix platform.</p> + <p></p> + </item> + <tag>-sname Node</tag> + <item> + <p>(one of <c><![CDATA[-n, -name, -sname]]></c> is required): <c><![CDATA[Node]]></c> is the name of the node to + be started or communicated with. It is assumed that <c><![CDATA[Node]]></c> is started with <c><![CDATA[erl -sname]]></c> which means that short node names are used. + If <c><![CDATA[-s]]></c> option is given, an Erlang node will be started (if necessary) with <c><![CDATA[erl -sname]]></c>.</p> + <p></p> + </item> + <tag>-v</tag> + <item> + <p>(<em>optional</em>): Prints a lot of <c><![CDATA[verbose]]></c> information. + This is only useful for the developer and maintainer of <c><![CDATA[erl_call]]></c>.</p> + <p></p> + </item> + <tag>-x ErlScript</tag> + <item> + <p>(<em>optional</em>): Specifies another name of the Erlang start-up script + to be used. If not specified, the standard <c><![CDATA[erl]]></c> start-up script + is used.</p> + </item> + </taglist> + </desc> + </func> + </funcs> + + <section> + <title>Examples</title> + <p>Starts an Erlang node and calls <c><![CDATA[erlang:time/0]]></c>.</p> + <code type="none"><![CDATA[ +erl_call -s -a 'erlang time' -n madonna +{18,27,34} + ]]></code> + <p>Terminates an Erlang node by calling <c><![CDATA[erlang:halt/0]]></c>.</p> + <code type="none"><![CDATA[ +erl_call -s -a 'erlang halt' -n madonna + ]]></code> + <p>An apply with several arguments.</p> + <code type="none"><![CDATA[ +erl_call -s -a 'lists map [{math,sqrt},[1,4,9,16,25]]' -n madonna + ]]></code> + <p>Evaluates a couple of expressions. <b>The input ends with EOF (Control-D)</b>.</p> + <code type="none"><![CDATA[ +erl_call -s -e -n madonna +statistics(runtime), +X=1, +Y=2, +{_,T}=statistics(runtime), +{X+Y,T}. +^D +{ok,{3,0}} + ]]></code> + <p>Compiles a module and runs it. <b>Again, the input ends with EOF (Control-D)</b>. (In the example shown, the output has been formatted afterwards).</p> + <code type="none"><![CDATA[ +erl_call -s -m -a lolita -n madonna +-module(lolita). +-compile(export_all). +start() -> + P = processes(), + F = fun(X) -> {X,process_info(X,registered_name)} end, + lists:map(F,[],P). +^D +[{<[email protected],0,0>, + {registered_name,init}}, + {<[email protected],2,0>, + {registered_name,erl_prim_loader}}, + {<[email protected],4,0>, + {registered_name,error_logger}}, + {<[email protected],5,0>, + {registered_name,application_controller}}, + {<[email protected],6,0>, + {registered_name,kernel}}, + {<[email protected],7,0>, + []}, + {<[email protected],8,0>, + {registered_name,kernel_sup}}, + {<[email protected],9,0>, + {registered_name,net_sup}}, + {<[email protected],10,0>, + {registered_name,net_kernel}}, + {<[email protected],11,0>, + []}, + {<[email protected],12,0>, + {registered_name,global_name_server}}, + {<[email protected],13,0>, + {registered_name,auth}}, + {<[email protected],14,0>, + {registered_name,rex}}, + {<[email protected],15,0>, + []}, + {<[email protected],16,0>, + {registered_name,file_server}}, + {<[email protected],17,0>, + {registered_name,code_server}}, + {<[email protected],20,0>, + {registered_name,user}}, + {<[email protected],38,0>, + []}] + ]]></code> + </section> +</comref> + diff --git a/lib/erl_interface/doc/src/erl_connect.xml b/lib/erl_interface/doc/src/erl_connect.xml new file mode 100644 index 0000000000..b2235925b2 --- /dev/null +++ b/lib/erl_interface/doc/src/erl_connect.xml @@ -0,0 +1,566 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_connect</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>980703</date> + <rev>A</rev> + <file>erl_connect.sgml</file> + </header> + <lib>erl_connect</lib> + <libsummary>Communicate with Distributed Erlang</libsummary> + <description> + <p>This module provides support for communication between distributed + Erlang nodes and C nodes, in a manner that is transparent to Erlang + processes.</p> + <p>A C node appears to Erlang as a + <em>hidden node</em>. + That is, Erlang processes that know the name of the + C node are able to communicate with it in a normal manner, but + the node name will not appear in the listing provided by the + Erlang function <c><![CDATA[nodes/0]]></c>.</p> + </description> + <funcs> + <func> + <name><ret>int</ret><nametext>erl_connect_init(number, cookie, creation)</nametext></name> + <name><ret>int</ret><nametext>erl_connect_xinit(host, alive, node, addr, cookie, creation)</nametext></name> + <fsummary>Initialize communication</fsummary> + <type> + <v>int number;</v> + <v>char *cookie;</v> + <v>short creation;</v> + <v>char *host,*alive,*node;</v> + <v>struct in_addr *addr;</v> + </type> + <desc> + <p>These functions initialize the <c><![CDATA[erl_connect]]></c> + module. In particular, they are used to identify the name of the + C-node from which they are called. One of these functions must + be called before any of the other functions in the erl_connect + module are used.</p> + <p><c><![CDATA[erl_connect_xinit()]]></c> stores for later use information about + the node's host name <c><![CDATA[host]]></c>, alive name <c><![CDATA[alive]]></c>, node + name <c><![CDATA[node]]></c>, IP address <c><![CDATA[addr]]></c>, cookie <c><![CDATA[cookie]]></c>, + and creation number <c><![CDATA[creation]]></c>. <c><![CDATA[erl_connect_init()]]></c> + provides an alternative interface which does not require as much + information from the caller. Instead, <c><![CDATA[erl_connect_init()]]></c> + uses <c><![CDATA[gethostbyname()]]></c> to obtain default values. + </p> + <p>If you use <c><![CDATA[erl_connect_init()]]></c> your node will have a + short name, i.e., it will not be fully qualified. If you need to + use fully qualified (a.k.a. long) names, use + <c><![CDATA[erl_connect_xinit()]]></c> instead. + </p> + <p><c><![CDATA[host]]></c> is the name of the host on which the node is running.</p> + <p><c><![CDATA[alive]]></c> is the alivename of the node.</p> + <p><c><![CDATA[node]]></c> is the name of the node. The nodename should + be of the form <em>alivename@hostname</em>.</p> + <p><c><![CDATA[addr]]></c> is the 32-bit IP address of <c><![CDATA[host]]></c>.</p> + <p><c><![CDATA[cookie]]></c> is the authorization string required for access + to the remote node. If NULL the user HOME directory is + searched for a cookie file <c><![CDATA[.erlang.cookie]]></c>. The path to + the home directory is retrieved from the environment variable + <c><![CDATA[HOME]]></c> on Unix and from the <c><![CDATA[HOMEDRIVE]]></c> and + <c><![CDATA[HOMEPATH]]></c> variables on Windows. Refer to the <c><![CDATA[auth]]></c> + module for more details.</p> + <p><c><![CDATA[creation]]></c> helps identify a particular instance of a C + node. In particular, it can help prevent us from receiving + messages sent to an earlier process with the same registered + name.</p> + <p>A C node acting as a server will be assigned a creation number + when it calls <c><![CDATA[erl_publish()]]></c>.</p> + <p><c><![CDATA[number]]></c> is used by <c><![CDATA[erl_connect_init()]]></c> to + construct the actual node name. In the second example shown + below, <em>"[email protected]"</em> will be the resulting node + name.</p> + <p>Example 1:</p> + <code type="none"><![CDATA[ +struct in_addr addr; +addr = inet_addr("150.236.14.75"); +if (!erl_connect_xinit("chivas", + "madonna", + "[email protected]", + &addr; + "samplecookiestring..."), + 0) + erl_err_quit("<ERROR> when initializing !"); + ]]></code> + <p>Example 2:</p> + <code type="none"><![CDATA[ +if (!erl_connect_init(17, "samplecookiestring...", 0)) + erl_err_quit("<ERROR> when initializing !"); + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_connect(node)</nametext></name> + <name><ret>int</ret><nametext>erl_xconnect(addr, alive)</nametext></name> + <fsummary>Establishe a connection to an Erlang node</fsummary> + <type> + <v>char *node, *alive;</v> + <v>struct in_addr *addr;</v> + </type> + <desc> + <p>These functions set up a connection to an Erlang node.</p> + <p><c><![CDATA[erl_xconnect()]]></c> requires the IP address of the remote + host and the alive name of the remote node + to be specified. <c><![CDATA[erl_connect()]]></c> provides an alternative + interface, and determines the information from the node name + provided.</p> + <p><c><![CDATA[addr]]></c> is the 32-bit IP address of the remote host.</p> + <p><c><![CDATA[alive]]></c> is the alivename of the remote node.</p> + <p><c><![CDATA[node]]></c> is the name of the remote node.</p> + <p>These functions return an open file descriptor on success, or + a negative value indicating that an error occurred --- in + which case they will set <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EHOSTUNREACH]]></c></tag> + <item>The remote host <c><![CDATA[node]]></c> is unreachable</item> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + <p>Additionally, <c><![CDATA[errno]]></c> values from + <c><![CDATA[socket]]></c><em>(2)</em> and <c><![CDATA[connect]]></c><em>(2)</em> + system calls may be propagated into <c><![CDATA[erl_errno]]></c>.</p> + <code type="none"><![CDATA[ +#define NODE "[email protected]" +#define ALIVE "madonna" +#define IP_ADDR "150.236.14.75" + +/*** Variant 1 ***/ +erl_connect( NODE ); + +/*** Variant 2 ***/ +struct in_addr addr; +addr = inet_addr(IP_ADDR); +erl_xconnect( &addr , ALIVE ); + ]]></code> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_close_connection(fd)</nametext></name> + <fsummary>Close a connection to an Erlang node</fsummary> + <type> + <v>int fd;</v> + </type> + <desc> + <p>This function closes an open connection to an Erlang node.</p> + <p><c><![CDATA[Fd]]></c> is a file descriptor obtained from + <c><![CDATA[erl_connect()]]></c> or <c><![CDATA[erl_xconnect()]]></c>.</p> + <p>On success, 0 is returned. If the call fails, a non-zero value + is returned, and the reason for + the error can be obtained with the appropriate platform-dependent + call.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_receive(fd, bufp, bufsize)</nametext></name> + <fsummary>Receive a message</fsummary> + <type> + <v>int fd;</v> + <v>char *bufp;</v> + <v>int bufsize;</v> + </type> + <desc> + <p>This function receives a message consisting of a sequence + of bytes in the Erlang external format.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[bufp]]></c> is a buffer large enough to hold the expected + message. </p> + <p><c><![CDATA[bufsize]]></c> indicates the size of <c><![CDATA[bufp]]></c>.</p> + <p>If a <em>tick</em> occurs, i.e., the Erlang node on the + other end of the connection has polled this node to see if it + is still alive, the function will return <c><![CDATA[ERL_TICK]]></c> and + no message will be placed in the buffer. Also, + <c><![CDATA[erl_errno]]></c> will be set to <c><![CDATA[EAGAIN]]></c>.</p> + <p>On success, the message is placed in the specified buffer + and the function returns the number of bytes actually read. On + failure, the function returns a negative value and will set + <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EAGAIN]]></c></tag> + <item>Temporary error: Try again.</item> + <tag><c><![CDATA[EMSGSIZE]]></c></tag> + <item>Buffer too small.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_receive_msg(fd, bufp, bufsize, emsg)</nametext></name> + <fsummary>Receive and decodes a message</fsummary> + <type> + <v>int fd;</v> + <v>unsigned char *bufp;</v> + <v>int bufsize;</v> + <v>ErlMessage *emsg;</v> + </type> + <desc> + <p>This function receives the message into the specified buffer, + and decodes into the <c><![CDATA[(ErlMessage *) emsg]]></c>.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[bufp]]></c> is a buffer large enough to hold the expected message.</p> + <p><c><![CDATA[bufsize]]></c> indicates the size of <c><![CDATA[bufp]]></c>.</p> + <p><c><![CDATA[emsg]]></c> is a pointer to an <c><![CDATA[ErlMessage]]></c> structure, + into which the message will be decoded. <c><![CDATA[ErlMessage]]></c> is + defined as follows:</p> + <code type="none"><![CDATA[ +typedef struct { + int type; + ETERM *msg; + ETERM *to; + ETERM *from; + char to_name[MAXREGLEN]; +} ErlMessage; + ]]></code> + <note> + <p>The definition of <c><![CDATA[ErlMessage]]></c> has changed since + earlier versions of Erl_Interface.</p> + </note> + <p><c><![CDATA[type]]></c> identifies the type of message, one of + <c><![CDATA[ERL_SEND]]></c>, <c><![CDATA[ERL_REG_SEND]]></c>, <c><![CDATA[ERL_LINK]]></c>, + <c><![CDATA[ERL_UNLINK]]></c> and <c><![CDATA[ERL_EXIT]]></c>. + </p> + <p>If <c><![CDATA[type]]></c> contains <c><![CDATA[ERL_SEND]]></c> + this indicates that an ordinary send operation has taken + place, and <c><![CDATA[emsg->to]]></c> contains the Pid of the + recipient. If <c><![CDATA[type]]></c> contains <c><![CDATA[ERL_REG_SEND]]></c> then a + registered send operation took place, and <c><![CDATA[emsg->from]]></c> + contains the Pid of the sender. In both cases, the actual + message will be in <c><![CDATA[emsg->msg]]></c>. + </p> + <p>If <c><![CDATA[type]]></c> contains one of <c><![CDATA[ERL_LINK]]></c> or + <c><![CDATA[ERL_UNLINK]]></c>, then <c><![CDATA[emsg->to]]></c> and <c><![CDATA[emsg->from]]></c> + contain the pids of the sender and recipient of the link or unlink. + <c><![CDATA[emsg->msg]]></c> is not used in these cases. + </p> + <p>If <c><![CDATA[type]]></c> contains <c><![CDATA[ERL_EXIT]]></c>, then this + indicates that a link has been broken. In this case, + <c><![CDATA[emsg->to]]></c> and <c><![CDATA[emsg->from]]></c> contain the pids of the + linked processes, and <c><![CDATA[emsg->msg]]></c> contains the reason for + the exit. + </p> + <note> + <p>It is the caller's responsibility to release the + memory pointed to by <c><![CDATA[emsg->msg]]></c>, <c><![CDATA[emsg->to]]></c> and + <c><![CDATA[emsg->from]]></c>.</p> + </note> + <p>If a <em>tick</em> occurs, i.e., the Erlang node on the + other end of the connection has polled this node to see if it + is still alive, the function will return <c><![CDATA[ERL_TICK]]></c> + indicating that the tick has been received and responded to, + but no message will be placed in the buffer. In this case you + should call <c><![CDATA[erl_receive_msg()]]></c> again.</p> + <p>On success, the function returns <c><![CDATA[ERL_MSG]]></c> and the + <c><![CDATA[Emsg]]></c> struct will be initialized as described above, or + <c><![CDATA[ERL_TICK]]></c>, in which case no message is returned. On + failure, the function returns <c><![CDATA[ERL_ERROR]]></c> and will set + <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EMSGSIZE]]></c></tag> + <item>Buffer too small.</item> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_xreceive_msg(fd, bufpp, bufsizep, emsg)</nametext></name> + <fsummary>Receive and decodes a message</fsummary> + <type> + <v>int fd;</v> + <v>unsigned char **bufpp;</v> + <v>int *bufsizep;</v> + <v>ErlMessage *emsg;</v> + </type> + <desc> + <p>This function is similar to <c><![CDATA[erl_receive_msg]]></c>. The + difference is that <c><![CDATA[erl_xreceive_msg]]></c> expects the buffer to + have been allocated by <c><![CDATA[malloc]]></c>, and reallocates it if the received + message does not fit into the original buffer. For that reason, + both buffer and buffer length are given as pointers - their values + may change by the call. + </p> + <p>On success, the function returns <c><![CDATA[ERL_MSG]]></c> and the + <c><![CDATA[Emsg]]></c> struct will be initialized as described above, or + <c><![CDATA[ERL_TICK]]></c>, in which case no message is returned. On + failure, the function returns <c><![CDATA[ERL_ERROR]]></c> and will set + <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EMSGSIZE]]></c></tag> + <item>Buffer too small.</item> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_send(fd, to, msg)</nametext></name> + <fsummary>Send a message</fsummary> + <type> + <v>int fd;</v> + <v>ETERM *to, *msg;</v> + </type> + <desc> + <p>This function sends an Erlang term to a process.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[to]]></c> is an Erlang term containing the Pid of the + intended recipient of the message.</p> + <p><c><![CDATA[msg]]></c> is the Erlang term to be sent.</p> + <p>The function returns 1 if successful, otherwise 0 --- in + which case it will set <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[EINVAL]]></c></tag> + <item>Invalid argument: <c><![CDATA[to]]></c> is not a valid Erlang pid.</item> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_reg_send(fd, to, msg)</nametext></name> + <fsummary>Send a message to a registered name</fsummary> + <type> + <v>int fd;</v> + <v>char *to;</v> + <v>ETERM *msg;</v> + </type> + <desc> + <p>This function sends an Erlang term to a registered process.</p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[to]]></c> is a string containing the registered name of + the intended recipient of the message.</p> + <p><c><![CDATA[msg]]></c> is the Erlang term to be sent.</p> + <p>The function returns 1 if successful, otherwise 0 --- in + which case it will set <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_rpc(fd, mod, fun, args)</nametext></name> + <name><ret>int</ret><nametext>erl_rpc_to(fd, mod, fun, args)</nametext></name> + <name><ret>int</ret><nametext>erl_rpc_from(fd, timeout, emsg)</nametext></name> + <fsummary>Remote Procedure Call</fsummary> + <type> + <v>int fd, timeout;</v> + <v>char *mod, *fun;</v> + <v>ETERM *args;</v> + <v>ErlMessage *emsg;</v> + </type> + <desc> + <p>These functions support calling Erlang functions on remote nodes. + <c><![CDATA[erl_rpc_to()]]></c> sends an rpc request to a remote node and + <c><![CDATA[erl_rpc_from()]]></c> receives the results of such a call. + <c><![CDATA[erl_rpc()]]></c> combines the functionality of these two functions + by sending an rpc request and waiting for the results. See also + <c><![CDATA[rpc:call/4]]></c>. </p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection.</p> + <p><c><![CDATA[timeout]]></c> is the maximum time (in ms) to wait for + results. Specify <c><![CDATA[ERL_NO_TIMEOUT]]></c> to wait forever. + When erl_rpc() calls erl_rpc_from(), the call will never + timeout.</p> + <p><c><![CDATA[mod]]></c> is the name of the module containing the function + to be run on the remote node.</p> + <p><c><![CDATA[fun]]></c> is the name of the function to run.</p> + <p><c><![CDATA[args]]></c> is an Erlang list, containing the arguments to be + passed to the function. </p> + <p><c><![CDATA[emsg]]></c> is a message containing the result of the + function call.</p> + <p>The actual message returned by the rpc server + is a 2-tuple <c><![CDATA[{rex,Reply}]]></c>. If you are using + <c><![CDATA[erl_rpc_from()]]></c> in your code then this is the message you + will need to parse. If you are using <c><![CDATA[erl_rpc()]]></c> then the + tuple itself is parsed for you, and the message returned to your + program is the erlang term containing <c><![CDATA[Reply]]></c> only. Replies + to rpc requests are always ERL_SEND messages. + </p> + <note> + <p>It is the caller's responsibility to free the returned + <c><![CDATA[ETERM]]></c> structure as well as the memory pointed to by + <c><![CDATA[emsg->msg]]></c> and <c><![CDATA[emsg->to]]></c>. </p> + </note> + <p><c><![CDATA[erl_rpc()]]></c> returns the remote function's return value (or + <c><![CDATA[NULL]]></c> if it failed). <c><![CDATA[erl_rpc_to()]]></c> returns 0 on + success, and a negative number on failure. <c><![CDATA[erl_rcp_from()]]></c> + returns <c><![CDATA[ERL_MSG]]></c> when successful (with <c><![CDATA[Emsg]]></c> now + containing the reply tuple), and one of <c><![CDATA[ERL_TICK]]></c>, + <c><![CDATA[ERL_TIMEOUT]]></c> and <c><![CDATA[ERL_ERROR]]></c> otherwise. When failing, + all three functions set <c><![CDATA[erl_errno]]></c> to one of:</p> + <taglist> + <tag><c><![CDATA[ENOMEM]]></c></tag> + <item>No more memory available.</item> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error.</item> + <tag><c><![CDATA[ETIMEDOUT]]></c></tag> + <item>Timeout expired.</item> + <tag><c><![CDATA[EAGAIN]]></c></tag> + <item>Temporary error: Try again.</item> + </taglist> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_publish(port)</nametext></name> + <fsummary>Publish a node name</fsummary> + <type> + <v>int port;</v> + </type> + <desc> + <p>These functions are used by a server process to register + with the local name server <em>epmd</em>, thereby allowing + other processes to send messages by using the registered name. + Before calling either of these functions, the process should + have called <c><![CDATA[bind()]]></c> and <c><![CDATA[listen()]]></c> on an open socket.</p> + <p><c><![CDATA[port]]></c> is the local name to register, and should be the + same as the port number that was previously bound to the socket.</p> + <p>To unregister with epmd, simply close the returned + descriptor. See also <c><![CDATA[erl_unpublish()]]></c>. + </p> + <p>On success, the functions return a descriptor connecting the + calling process to epmd. On failure, they return -1 and set + <c><![CDATA[erl_errno]]></c> to:</p> + <taglist> + <tag><c><![CDATA[EIO]]></c></tag> + <item>I/O error</item> + </taglist> + <p>Additionally, <c><![CDATA[errno]]></c> values from <c><![CDATA[socket]]></c><em>(2)</em> + and <c><![CDATA[connect]]></c><em>(2)</em> system calls may be propagated + into <c><![CDATA[erl_errno]]></c>. + </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_accept(listensock, conp)</nametext></name> + <fsummary>Accept a connection</fsummary> + <type> + <v>int listensock;</v> + <v>ErlConnect *conp;</v> + </type> + <desc> + <p>This function is used by a server process to accept a + connection from a client process.</p> + <p><c><![CDATA[listensock]]></c> is an open socket descriptor on which + <c><![CDATA[listen()]]></c> has previously been called.</p> + <p><c><![CDATA[conp]]></c> is a pointer to an <c><![CDATA[ErlConnect]]></c> struct, + described as follows:</p> + <code type="none"><![CDATA[ +typedef struct { + char ipadr[4]; + char nodename[MAXNODELEN]; +} ErlConnect; + ]]></code> + <p>On success, <c><![CDATA[conp]]></c> is filled in with the address and + node name of the connecting client and a file descriptor is + returned. On failure, <c><![CDATA[ERL_ERROR]]></c> is returned and + <c><![CDATA[erl_errno]]></c> is set to <c><![CDATA[EIO]]></c>.</p> + </desc> + </func> + <func> + <name><ret>const char *</ret><nametext>erl_thiscookie()</nametext></name> + <name><ret>const char *</ret><nametext>erl_thisnodename()</nametext></name> + <name><ret>const char *</ret><nametext>erl_thishostname()</nametext></name> + <name><ret>const char *</ret><nametext>erl_thisalivename()</nametext></name> + <name><ret>short</ret><nametext>erl_thiscreation()</nametext></name> + <fsummary>Retrieve some values</fsummary> + <desc> + <p>These functions can be used to retrieve information about + the C Node. These values are initially set with + <c><![CDATA[erl_connect_init()]]></c> or <c><![CDATA[erl_connect_xinit()]]></c>.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_unpublish(alive)</nametext></name> + <fsummary>Unpublish a node name</fsummary> + <type> + <v>char *alive;</v> + </type> + <desc> + <p>This function can be called by a process to unregister a + specified node name from epmd on the localhost. This may be + useful, for example, when epmd has not detected the failure of a + node, and will not allow the name to be reused. If you use this + function to unregister your own process, be sure to also close + the descriptor that was returned by <c><![CDATA[erl_publish()]]></c>.</p> + <note> + <p>Careless use of this function may have unpredictable + results, if the registered node is in fact still running.</p> + </note> + <p><c><![CDATA[alive]]></c> is the name of the node to unregister, i.e., the + first component of the nodename, without the <c><![CDATA[@hostname]]></c>.</p> + <p>If the node was successfully unregistered from epmd, the + function returns 0. Otherwise, it returns -1 and sets + <c><![CDATA[erl_errno]]></c> is to <c><![CDATA[EIO]]></c>.</p> + </desc> + </func> + <func> + <name><ret>struct hostent</ret><nametext>*erl_gethostbyname(name)</nametext></name> + <name><ret>struct hostent</ret><nametext>*erl_gethostbyaddr(addr, length, type)</nametext></name> + <name><ret>struct hostent</ret><nametext>*erl_gethostbyname_r(name, hostp, buffer, buflen, h_errnop)</nametext></name> + <name><ret>struct hostent</ret><nametext>*erl_gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, h_errnop)</nametext></name> + <fsummary>Name lookup functions</fsummary> + <type> + <v>const char *name;</v> + <v>const char *addr;</v> + <v>int length;</v> + <v>int type;</v> + <v>struct hostent *hostp;</v> + <v>char *buffer;</v> + <v>int buflen;</v> + <v>int *h_errnop;</v> + </type> + <desc> + <p>These are convenience functions for some common name lookup functions.</p> + </desc> + </func> + </funcs> + + <section> + <title>Debug Information</title> + <p>If a connection attempt fails, the following can be checked:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_errno]]></c></item> + <item>that the right cookie was used</item> + <item>that <em>epmd</em> is running</item> + <item>the remote Erlang node on the other side is running the same + version of Erlang as the <c><![CDATA[erl_interface]]></c> library.</item> + </list> + </section> +</cref> + diff --git a/lib/erl_interface/doc/src/erl_error.xml b/lib/erl_interface/doc/src/erl_error.xml new file mode 100644 index 0000000000..4a3f34fac7 --- /dev/null +++ b/lib/erl_interface/doc/src/erl_error.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_error</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>961014</date> + <rev>A</rev> + <file>erl_error.sgml</file> + </header> + <lib>erl_error</lib> + <libsummary>Error Print Routines</libsummary> + <description> + <p>This module contains some error printing routines taken + from <em>Advanced Programming in the UNIX Environment</em> + by W. Richard Stevens. </p> + <p>These functions are all called in the same manner as + <c><![CDATA[printf()]]></c>, i.e. with a string containing format specifiers + followed by a list of corresponding arguments. All output from + these functions is to <c><![CDATA[stderr]]></c>.</p> + </description> + <funcs> + <func> + <name><ret>void</ret><nametext>erl_err_msg(FormatStr, ... )</nametext></name> + <fsummary>Non-fatal error, and not system call error</fsummary> + <type> + <v>const char *FormatStr;</v> + </type> + <desc> + <p>The message provided by the caller is printed. This + function is simply a wrapper for <c><![CDATA[fprintf()]]></c>.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_err_quit(FormatStr, ... )</nametext></name> + <fsummary>Fatal error, but not system call error</fsummary> + <type> + <v>const char *FormatStr;</v> + </type> + <desc> + <p>Use this function when a fatal error has occurred that + is not due to a system call. The message provided by the + caller is printed and the process terminates with an exit + value of 1. The function does not return.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_err_ret(FormatStr, ... )</nametext></name> + <fsummary>Non-fatal system call error</fsummary> + <type> + <v>const char *FormatStr;</v> + </type> + <desc> + <p>Use this function after a failed system call. The message + provided by the caller is printed followed by a string + describing the reason for failure. </p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_err_sys(FormatStr, ... )</nametext></name> + <fsummary>Fatal system call error</fsummary> + <type> + <v>const char *FormatStr;</v> + </type> + <desc> + <p>Use this function after a failed system call. The message + provided by the caller is printed followed by a string + describing the reason for failure, and the process + terminates with an exit value of 1. The function does not + return.</p> + </desc> + </func> + </funcs> + + <section> + <title>Error Reporting</title> + <p>Most functions in erl_interface report failures to the caller by + returning some otherwise meaningless value (typically <c><![CDATA[NULL]]></c> + or a negative number). As this only tells you that things did not + go well, you will have to examine the error code in + <c><![CDATA[erl_errno]]></c> if you want to find out more about the failure.</p> + </section> + <funcs> + <func> + <name><ret>volatile int</ret><nametext>erl_errno</nametext></name> + <fsummary>The variable <c><![CDATA[erl_errno]]></c>contains the erl_interface error number. You can change the value if you wish. </fsummary> + <desc> + <p><c><![CDATA[erl_errno]]></c> is initially (at program startup) zero and + is then set by many erl_interface functions on failure to a + non-zero error code to indicate what kind of error it + encountered. A successful function call might change + <c><![CDATA[erl_errno]]></c> (by calling some other function that + fails), but no function will ever set it to zero. This means + that you cannot use <c><![CDATA[erl_errno]]></c> to see <em>if</em> a + function call failed. Instead, each function reports failure + in its own way (usually by returning a negative number or + <c><![CDATA[NULL]]></c>), in which case you can examine <c><![CDATA[erl_errno]]></c> + for details.</p> + <p><c><![CDATA[erl_errno]]></c> uses the error codes defined in your + system's <c><![CDATA[<errno.h>]]></c>.</p> + <note> + <p>Actually, <c><![CDATA[erl_errno]]></c> is a "modifiable lvalue" (just + like ISO C defines <c><![CDATA[errno]]></c> to be) rather than a + variable. This means it might be implemented as a macro + (expanding to, e.g., <c><![CDATA[*_erl_errno()]]></c>). For reasons of + thread- (or task-)safety, this is exactly what we do on most + platforms.</p> + </note> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/erl_eterm.xml b/lib/erl_interface/doc/src/erl_eterm.xml new file mode 100644 index 0000000000..ce14549672 --- /dev/null +++ b/lib/erl_interface/doc/src/erl_eterm.xml @@ -0,0 +1,675 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_eterm</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>980703</date> + <rev>A</rev> + <file>erl_eterm.sgml</file> + </header> + <lib>erl_eterm</lib> + <libsummary>Functions for Erlang Term Construction</libsummary> + <description> + <p>This module contains functions for creating and manipulating + Erlang terms. </p> + <p>An Erlang term is represented by a C structure of type + <c><![CDATA[ETERM]]></c>. Applications should not reference any fields in this + structure directly, because it may be changed in future releases + to provide faster and more compact term storage. Instead, + applications should us the macros and functions provided. </p> + <p>The following macros each take a single ETERM pointer as an + argument. They return a non-zero value if the test is true, and 0 + otherwise:</p> + <taglist> + <tag><c><![CDATA[ERL_IS_INTEGER(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is an integer.</item> + <tag><c><![CDATA[ERL_IS_UNSIGNED_INTEGER(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is an integer.</item> + <tag><c><![CDATA[ERL_IS_FLOAT(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a floating point number.</item> + <tag><c><![CDATA[ERL_IS_ATOM(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is an atom.</item> + <tag><c><![CDATA[ERL_IS_PID(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a Pid (process identifier).</item> + <tag><c><![CDATA[ERL_IS_PORT(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a port.</item> + <tag><c><![CDATA[ERL_IS_REF(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a reference.</item> + <tag><c><![CDATA[ERL_IS_TUPLE(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a tuple.</item> + <tag><c><![CDATA[ERL_IS_BINARY(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a binary.</item> + <tag><c><![CDATA[ERL_IS_LIST(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a list with zero or more elements.</item> + <tag><c><![CDATA[ERL_IS_EMPTY_LIST(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is an empty list.</item> + <tag><c><![CDATA[ERL_IS_CONS(t)]]></c></tag> + <item>True if <c><![CDATA[t]]></c> is a list with at least one element.</item> + </taglist> + <p>The following macros can be used for retrieving parts of Erlang + terms. None of these do any type checking; results are undefined + if you pass an ETERM* containing the wrong type. For example, + passing a tuple to ERL_ATOM_PTR() will likely result in garbage. + </p> + <taglist> + <tag><c><![CDATA[char *ERL_ATOM_PTR(t)]]></c></tag> + <item>A string representing atom <c><![CDATA[t]]></c>. + </item> + <tag><c><![CDATA[int ERL_ATOM_SIZE(t)]]></c></tag> + <item>The length (in characters) of atom t.</item> + <tag><c><![CDATA[void *ERL_BIN_PTR(t)]]></c></tag> + <item>A pointer to the contents of <c><![CDATA[t]]></c></item> + <tag><c><![CDATA[int ERL_BIN_SIZE(t)]]></c></tag> + <item>The length (in bytes) of binary object <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_INT_VALUE(t)]]></c></tag> + <item>The integer of <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[unsigned int ERL_INT_UVALUE(t)]]></c></tag> + <item>The unsigned integer value of <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[double ERL_FLOAT_VALUE(t)]]></c></tag> + <item>The floating point value of <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[ETERM *ERL_PID_NODE(t)]]></c></tag> + <item>The Node in pid <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_PID_NUMBER(t)]]></c></tag> + <item>The sequence number in pid <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_PID_SERIAL(t)]]></c></tag> + <item>The serial number in pid <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_PID_CREATION(t)]]></c></tag> + <item>The creation number in pid <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_PORT_NUMBER(t)]]></c></tag> + <item>The sequence number in port <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_PORT_CREATION(t)]]></c></tag> + <item>The creation number in port <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[ETERM *ERL_PORT_NODE(t)]]></c></tag> + <item>The node in port <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_REF_NUMBER(t)]]></c></tag> + <item>The first part of the reference number in ref <c><![CDATA[t]]></c>. Use + only for compatibility.</item> + <tag><c><![CDATA[int ERL_REF_NUMBERS(t)]]></c></tag> + <item>Pointer to the array of reference numbers in ref <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_REF_LEN(t)]]></c></tag> + <item>The number of used reference numbers in ref <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_REF_CREATION(t)]]></c></tag> + <item>The creation number in ref <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[int ERL_TUPLE_SIZE(t)]]></c></tag> + <item>The number of elements in tuple <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[ETERM *ERL_CONS_HEAD(t)]]></c></tag> + <item>The head element of list <c><![CDATA[t]]></c>.</item> + <tag><c><![CDATA[ETERM *ERL_CONS_TAIL(t)]]></c></tag> + <item>A List representing the tail elements of list <c><![CDATA[t]]></c>.</item> + </taglist> + </description> + <funcs> + <func> + <name><ret>ETERM *</ret><nametext>erl_cons(head, tail)</nametext></name> + <fsummary>Prepends a term to the head of a list.</fsummary> + <type> + <v>ETERM *head;</v> + <v>ETERM *tail;</v> + </type> + <desc> + <p>This function concatenates two Erlang terms, prepending + <c><![CDATA[head]]></c> onto <c><![CDATA[tail]]></c> and thereby creating a <c><![CDATA[cons]]></c> cell. + To make a proper list, <c><![CDATA[tail]]></c> should always be a + list or an empty list. Note that NULL is not a valid list.</p> + <p><c><![CDATA[head]]></c> is the new term to be added.</p> + <p><c><![CDATA[tail]]></c> is the existing list to which <c><![CDATA[head]]></c> will + be concatenated.</p> + <p>The function returns a new list.</p> + <p><c><![CDATA[ERL_CONS_HEAD(list)]]></c> and <c><![CDATA[ERL_CONS_TAIL(list)]]></c> + can be used to retrieve the head and tail components + from the list. <c><![CDATA[erl_hd(list)]]></c> and <c><![CDATA[erl_tl(list)]]></c> will do + the same thing, but check that the argument really is a list.</p> + <p>For example:</p> + <code type="none"><![CDATA[ +ETERM *list,*anAtom,*anInt; +anAtom = erl_mk_atom("madonna"); +anInt = erl_mk_int(21); +list = erl_mk_empty_list(); +list = erl_cons(anAtom, list); +list = erl_cons(anInt, list); + ... /* do some work */ +erl_free_compound(list); + ]]></code> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_copy_term(term)</nametext></name> + <fsummary>Creates a copy of an Erlang term</fsummary> + <type> + <v>ETERM *term;</v> + </type> + <desc> + <p>This function creates and returns a copy of the Erlang term + <c><![CDATA[term]]></c>.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_element(position, tuple)</nametext></name> + <fsummary>Extracts an element from an Erlang tuple</fsummary> + <type> + <v>int position;</v> + <v>ETERM *tuple;</v> + </type> + <desc> + <p>This function extracts a specified element from an Erlang + tuple. </p> + <p><c><![CDATA[position]]></c> specifies which element to retrieve from + <c><![CDATA[tuple]]></c>. The elements are numbered starting from 1.</p> + <p><c><![CDATA[tuple]]></c> is an Erlang term containing at least + <c><![CDATA[position]]></c> elements.</p> + <p>The function returns a new Erlang term corresponding to the + requested element, or NULL if <c><![CDATA[position]]></c> was greater than + the arity of <c><![CDATA[tuple]]></c>.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_init(NULL, 0)</nametext></name> + <fsummary>Initialization routine</fsummary> + <type> + <v>void *NULL;</v> + <v>int 0;</v> + </type> + <desc> + <marker id="erl_init"></marker> + <p>This function must be called before any of the others in + the <c><![CDATA[erl_interface]]></c> library in order to initialize the + library functions. The arguments must be specified as + <c><![CDATA[erl_init(NULL,0)]]></c>.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_hd(list)</nametext></name> + <fsummary>Extracts the first element from a list</fsummary> + <type> + <v>ETERM *list;</v> + </type> + <desc> + <p>Extracts the first element from a list.</p> + <p><c><![CDATA[list]]></c> is an Erlang term containing a list.</p> + <p>The function returns an Erlang term corresponding to the + head element in the list, or a NULL pointer if <c><![CDATA[list]]></c> was + not a list.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_iolist_to_binary(term)</nametext></name> + <fsummary>Converts an IO list to a binary</fsummary> + <type> + <v>ETERM *list;</v> + </type> + <desc> + <p>This function converts an IO list to a binary term.</p> + <p><c><![CDATA[list]]></c> is an Erlang term containing a list.</p> + <p>This function an Erlang binary term, or NULL if <c><![CDATA[list]]></c> + was not an IO list. </p> + <p>Informally, an IO list is a deep list of characters and + binaries which can be sent to an Erlang port. In BNF, an IO + list is formally defined as follows: </p> + <code type="none"><![CDATA[ +iolist ::= [] + | Binary + | [iohead | iolist] + ; +iohead ::= Binary + | Byte (integer in the range [0..255]) + | iolist + ; + ]]></code> + </desc> + </func> + <func> + <name><ret>char *</ret><nametext>erl_iolist_to_string(list)</nametext></name> + <fsummary>Converts an IO list to a zero terminated string</fsummary> + <type> + <v>ETERM *list;</v> + </type> + <desc> + <p>This function converts an IO list to a '\\0' terminated C + string. </p> + <p><c><![CDATA[list]]></c> is an Erlang term containing an IO list. The IO + list must not contain the integer 0, since C strings may not + contain this value except as a terminating marker.</p> + <p>This function returns a pointer to a dynamically allocated + buffer containing a string. If <c><![CDATA[list]]></c> is not an IO list, + or if <c><![CDATA[list]]></c> contains the integer 0, NULL is returned. It + is the caller's responsibility free the allocated buffer + with <c><![CDATA[erl_free()]]></c>. </p> + <p>Refer to <c><![CDATA[erl_iolist_to_binary()]]></c> for the definition of an + IO list. </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_iolist_length(list)</nametext></name> + <fsummary>Return the length of an IO list</fsummary> + <type> + <v>ETERM *list;</v> + </type> + <desc> + <p>Returns the length of an IO list. + </p> + <p><c><![CDATA[list]]></c> is an Erlang term containing an IO list. </p> + <p>The function returns the length of <c><![CDATA[list]]></c>, or -1 if + <c><![CDATA[list]]></c> is not an IO list.</p> + <p>Refer to <c><![CDATA[erl_iolist_to_binary()]]></c> for the definition of + an IO list. </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_length(list)</nametext></name> + <fsummary>Determines the length of a list</fsummary> + <type> + <v>ETERM *list;</v> + </type> + <desc> + <p>Determines the length of a proper list.</p> + <p><c><![CDATA[list]]></c> is an Erlang term containing proper list. In a + proper list, all tails except the last point to another list + cell, and the last tail points to an empty list.</p> + <p>Returns -1 if <c><![CDATA[list]]></c> is not a proper list.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_atom(string)</nametext></name> + <fsummary>Creates an atom</fsummary> + <type> + <v>char *string;</v> + </type> + <desc> + <p>Creates an atom.</p> + <p><c><![CDATA[string]]></c> is the sequence of characters that will be + used to create the atom.</p> + <p>Returns an Erlang term containing an atom. Note that it is + the callers responsibility to make sure that <c><![CDATA[string]]></c> + contains a valid name for an atom.</p> + <p><c><![CDATA[ERL_ATOM_PTR(atom)]]></c> can be used to retrieve the + atom name (as a string). Note that the string is not + 0-terminated in the atom. <c><![CDATA[ERL_ATOM_SIZE(atom)]]></c>returns + the length of the atom name.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_binary(bptr, size)</nametext></name> + <fsummary>Creates a binary object</fsummary> + <type> + <v>char *bptr;</v> + <v>int size;</v> + </type> + <desc> + <p>This function produces an Erlang binary object from a + buffer containing a sequence of bytes.</p> + <p><c><![CDATA[bptr]]></c> is a pointer to a buffer containing data to be converted.</p> + <p><c><![CDATA[size]]></c> indicates the length of <c><![CDATA[bptr]]></c>.</p> + <p>The function returns an Erlang binary object.</p> + <p><c><![CDATA[ERL_BIN_PTR(bin)]]></c> retrieves a pointer to + the binary data. <c><![CDATA[ERL_BIN_SIZE(bin)]]></c> retrieves the + size. </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_empty_list()</nametext></name> + <fsummary>Creates an empty Erlang list</fsummary> + <desc> + <p>This function creates and returns an empty Erlang list. + Note that NULL is not used to represent an empty list; + Use this function instead.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_estring(string, len)</nametext></name> + <fsummary>Creates an Erlang string</fsummary> + <type> + <v>char *string;</v> + <v>int len;</v> + </type> + <desc> + <p>This function creates a list from a sequence of bytes.</p> + <p><c><![CDATA[string]]></c> is a buffer containing a sequence of + bytes. The buffer does not need to be zero-terminated.</p> + <p><c><![CDATA[len]]></c> is the length of <c><![CDATA[string]]></c>.</p> + <p>The function returns an Erlang list object corresponding to + the character sequence in <c><![CDATA[string]]></c>.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_float(f)</nametext></name> + <fsummary>Creates an Erlang float</fsummary> + <type> + <v>double f;</v> + </type> + <desc> + <p>Creates an Erlang float.</p> + <p><c><![CDATA[f]]></c> is a value to be converted to an Erlang float.</p> + <p></p> + <p>The function returns an Erlang float object with the value + specified in <c><![CDATA[f]]></c>.</p> + <p><c><![CDATA[ERL_FLOAT_VALUE(t)]]></c> can be used to retrieve the + value from an Erlang float.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_int(n)</nametext></name> + <fsummary>Creates an Erlang integer</fsummary> + <type> + <v>int n;</v> + </type> + <desc> + <p>Creates an Erlang integer.</p> + <p><c><![CDATA[n]]></c> is a value to be converted to an Erlang integer.</p> + <p></p> + <p>The function returns an Erlang integer object with the + value specified in <c><![CDATA[n]]></c>.</p> + <p><c><![CDATA[ERL_INT_VALUE(t)]]></c> can be used to retrieve the value + value from an Erlang integer.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_list(array, arrsize)</nametext></name> + <fsummary>Creates a list from an array</fsummary> + <type> + <v>ETERM **array;</v> + <v>int arrsize;</v> + </type> + <desc> + <p>Creates an Erlang list from an array of Erlang terms, such + that each element in the list corresponds to one element in + the array. </p> + <p><c><![CDATA[array]]></c> is an array of Erlang terms.</p> + <p><c><![CDATA[arrsize]]></c> is the number of elements in <c><![CDATA[array]]></c>.</p> + <p>The function creates an Erlang list object, whose length + <c><![CDATA[arrsize]]></c> and whose elements are taken from the terms in + <c><![CDATA[array]]></c>.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_pid(node, number, serial, creation)</nametext></name> + <fsummary>Creates a process identifier</fsummary> + <type> + <v>const char *node;</v> + <v>unsigned int number;</v> + <v>unsigned int serial;</v> + <v>unsigned int creation;</v> + </type> + <desc> + <p>This function creates an Erlang process identifier. The + resulting pid can be used by Erlang processes wishing to + communicate with the C node.</p> + <p><c><![CDATA[node]]></c> is the name of the C node.</p> + <p><c><![CDATA[number]]></c>, <c><![CDATA[serial]]></c> and <c><![CDATA[creation]]></c> are + arbitrary numbers. Note though, that these are limited in + precision, so only the low 15, 3 and 2 bits of these numbers + are actually used.</p> + <p>The function returns an Erlang pid object.</p> + <p><c><![CDATA[ERL_PID_NODE(pid)]]></c>, <c><![CDATA[ERL_PID_NUMBER(pid)]]></c>, + <c><![CDATA[ERL_PID_SERIAL(pid)]]></c> and <c><![CDATA[ERL_PID_CREATION(pid)]]></c> + can be used to retrieve the four values used to create the pid.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_port(node, number, creation)</nametext></name> + <fsummary>Creates a port identifier</fsummary> + <type> + <v>const char *node;</v> + <v>unsigned int number;</v> + <v>unsigned int creation;</v> + </type> + <desc> + <p>This function creates an Erlang port identifier. </p> + <p><c><![CDATA[node]]></c> is the name of the C node.</p> + <p><c><![CDATA[number]]></c> and <c><![CDATA[creation]]></c> are arbitrary numbers. + Note though, that these are limited in + precision, so only the low 18 and 2 bits of these numbers + are actually used.</p> + <p>The function returns an Erlang port object.</p> + <p><c><![CDATA[ERL_PORT_NODE(port)]]></c>, <c><![CDATA[ERL_PORT_NUMBER(port)]]></c> + and <c><![CDATA[ERL_PORT_CREATION]]></c> can be used to retrieve the three + values used to create the port. </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_ref(node, number, creation)</nametext></name> + <fsummary>Creates an old Erlang reference</fsummary> + <type> + <v>const char *node;</v> + <v>unsigned int number;</v> + <v>unsigned int creation;</v> + </type> + <desc> + <p>This function creates an old Erlang reference, with + only 18 bits - use <c><![CDATA[erl_mk_long_ref]]></c> instead.</p> + <p><c><![CDATA[node]]></c> is the name of the C node.</p> + <p><c><![CDATA[number]]></c> should be chosen uniquely for each reference + created for a given C node.</p> + <p><c><![CDATA[creation]]></c> is an arbitrary number.</p> + <p>Note that <c><![CDATA[number]]></c> and <c><![CDATA[creation]]></c> are limited in + precision, so only the low 18 and 2 bits of these numbers + are actually used. + </p> + <p>The function returns an Erlang reference object.</p> + <p><c><![CDATA[ERL_REF_NODE(ref)]]></c>, <c><![CDATA[ERL_REF_NUMBER(ref)]]></c>, and + <c><![CDATA[ERL_REF_CREATION(ref)]]></c> to retrieve the three values used + to create the reference. </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_long_ref(node, n1, n2, n3, creation)</nametext></name> + <fsummary>Creates an Erlang reference</fsummary> + <type> + <v>const char *node;</v> + <v>unsigned int n1, n2, n3;</v> + <v>unsigned int creation;</v> + </type> + <desc> + <p>This function creates an Erlang reference, with 82 bits.</p> + <p><c><![CDATA[node]]></c> is the name of the C node.</p> + <p><c><![CDATA[n1]]></c>, <c><![CDATA[n2]]></c> and <c><![CDATA[n3]]></c> can be seen as one big number + <c><![CDATA[n1*2^64+n2*2^32+n3]]></c> which should be chosen uniquely for + each reference + created for a given C node.</p> + <p><c><![CDATA[creation]]></c> is an arbitrary number.</p> + <p>Note that <c><![CDATA[n3]]></c> and <c><![CDATA[creation]]></c> are limited in + precision, so only the low 18 and 2 bits of these numbers + are actually used. + </p> + <p>The function returns an Erlang reference object.</p> + <p><c><![CDATA[ERL_REF_NODE(ref)]]></c>, <c><![CDATA[ERL_REF_NUMBERS(ref)]]></c>, + <c><![CDATA[ERL_REF_LEN(ref)]]></c> and + <c><![CDATA[ERL_REF_CREATION(ref)]]></c> to retrieve the values used + to create the reference. </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_string(string)</nametext></name> + <fsummary>Creates a string</fsummary> + <type> + <v>char *string;</v> + </type> + <desc> + <p>This function creates a list from a zero terminated string.</p> + <p><c><![CDATA[string]]></c> is the zero-terminated sequence of characters + (i.e. a C string) from which the list will be created.</p> + <p>The function returns an Erlang list.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_tuple(array, arrsize)</nametext></name> + <fsummary>Creates an Erlang tuple from an array</fsummary> + <type> + <v>ETERM **array;</v> + <v>int arrsize;</v> + </type> + <desc> + <p>Creates an Erlang tuple from an array of Erlang terms.</p> + <p><c><![CDATA[array]]></c> is an array of Erlang terms.</p> + <p><c><![CDATA[arrsize]]></c> is the number of elements in <c><![CDATA[array]]></c>.</p> + <p>The function creates an Erlang tuple, whose arity is + <c><![CDATA[size]]></c> and whose elements are taken from the terms in + <c><![CDATA[array]]></c>.</p> + <p>To retrieve the size of a tuple, either use the + <c><![CDATA[erl_size]]></c> function (which checks the type of the checked + term and works for a binary as well as for a tuple), or the + <c><![CDATA[ERL_TUPLE_SIZE(tuple)]]></c> returns the arity of a tuple. + <c><![CDATA[erl_size()]]></c> will do the same thing, but it checks that + the argument really is a tuple. + <c><![CDATA[erl_element(index,tuple)]]></c> returns the element + corresponding to a given position in the tuple. </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_uint(n)</nametext></name> + <fsummary>Creates an unsigned integer</fsummary> + <type> + <v>unsigned int n;</v> + </type> + <desc> + <p>Creates an Erlang unsigned integer.</p> + <p><c><![CDATA[n]]></c> is a value to be converted to an Erlang + unsigned integer.</p> + <p></p> + <p>The function returns an Erlang unsigned integer object with + the value specified in <c><![CDATA[n]]></c>.</p> + <p><c><![CDATA[ERL_INT_UVALUE(t)]]></c> can be used to retrieve the + value from an Erlang unsigned integer.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_mk_var(name)</nametext></name> + <fsummary>Creates an Erlang variable</fsummary> + <type> + <v>char *name;</v> + </type> + <desc> + <p>This function creates an unbound Erlang variable. The + variable can later be bound through pattern matching or assignment.</p> + <p><c><![CDATA[name]]></c> specifies a name for the variable.</p> + <p>The function returns an Erlang variable object with the + name <c><![CDATA[name]]></c>. </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_print_term(stream, term)</nametext></name> + <fsummary>Prints an Erlang term</fsummary> + <type> + <v>FILE *stream;</v> + <v>ETERM *term;</v> + </type> + <desc> + <p>This function prints the specified Erlang term to the given + output stream.</p> + <p><c><![CDATA[stream]]></c> indicates where the function should send its + output.</p> + <p><c><![CDATA[term]]></c> is the Erlang term to print.</p> + <p>The function returns the number of characters written, or a + negative value if there was an error.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_set_compat_rel(release_number)</nametext></name> + <fsummary>Set the erl_interface library in compatibility mode</fsummary> + <type> + <v>unsigned release_number;</v> + </type> + <desc> + <marker id="erl_set_compat_rel"></marker> + <p>By default, the <c><![CDATA[erl_interface]]></c> library is only guaranteed + to be compatible with other Erlang/OTP components from the same + release as the <c><![CDATA[erl_interface]]></c> library itself. For example, + <c><![CDATA[erl_interface]]></c> from the OTP R10 release is not compatible + with an Erlang emulator from the OTP R9 release by default.</p> + <p>A call to <c><![CDATA[erl_set_compat_rel(release_number)]]></c> sets the + <c><![CDATA[erl_interface]]></c> library in compatibility mode of release + <c><![CDATA[release_number]]></c>. Valid range of <c><![CDATA[release_number]]></c> + is [7, current release]. This makes it possible to + communicate with Erlang/OTP components from earlier releases.</p> + <note> + <p>If this function is called, it may only be called once + directly after the call to the + <seealso marker="#erl_init">erl_init()</seealso> function.</p> + </note> + <warning> + <p>You may run into trouble if this feature is used + carelessly. Always make sure that all communicating + components are either from the same Erlang/OTP release, or + from release X and release Y where all components + from release Y are in compatibility mode of release X.</p> + </warning> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_size(term)</nametext></name> + <fsummary>Return the arity of a tuple or binary</fsummary> + <type> + <v>ETERM *term;</v> + </type> + <desc> + <p>Returns the arity of an Erlang tuple, or the + number of bytes in an Erlang binary object. </p> + <p><c><![CDATA[term]]></c> is an Erlang tuple or an Erlang binary object.</p> + <p>The function returns the size of <c><![CDATA[term]]></c> as described + above, or -1 if <c><![CDATA[term]]></c> is not one of the two supported + types. </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_tl(list)</nametext></name> + <fsummary>Extracts the tail from a list</fsummary> + <type> + <v>ETERM *list;</v> + </type> + <desc> + <p>Extracts the tail from a list.</p> + <p><c><![CDATA[list]]></c> is an Erlang term containing a list.</p> + <p>The function returns an Erlang list corresponding to the + original list minus the first element, or NULL pointer if + <c><![CDATA[list]]></c> was not a list.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_var_content(term, name)</nametext></name> + <fsummary>Extracts the content of a variable</fsummary> + <type> + <v>ETERM *term;</v> + <v>char *name;</v> + </type> + <desc> + <p>This function returns the contents of the specified + variable in an Erlang term. + </p> + <p><c><![CDATA[term]]></c> is an Erlang term. In order for this function + to succeed, <c><![CDATA[term]]></c> must be an Erlang variable with the + specified name, or it must be an Erlang list or tuple + containing a variable with the specified name. Other Erlang + types cannot contain variables.</p> + <p><c><![CDATA[name]]></c> is the name of an Erlang variable.</p> + <p>Returns the Erlang object corresponding to the value of + <c><![CDATA[name]]></c> in <c><![CDATA[term]]></c>. If no variable with the name + <c><![CDATA[name]]></c> was found in <c><![CDATA[term]]></c>, or if <c><![CDATA[term]]></c> is + not a valid Erlang term, NULL is returned.</p> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/erl_format.xml b/lib/erl_interface/doc/src/erl_format.xml new file mode 100644 index 0000000000..5699485845 --- /dev/null +++ b/lib/erl_interface/doc/src/erl_format.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_format</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>961016</date> + <rev>A</rev> + <file>erl_format.sgml</file> + </header> + <lib>erl_format</lib> + <libsummary>Create and Match Erlang Terms</libsummary> + <description> + <p>This module contains two routines - one general function for + creating Erlang terms and one for pattern matching Erlang terms.</p> + </description> + <funcs> + <func> + <name><ret>ETERM *</ret><nametext>erl_format(FormatStr, ... )</nametext></name> + <fsummary>Creates an Erlang term</fsummary> + <type> + <v>char *FormatStr;</v> + </type> + <desc> + <p>This is a general function for creating Erlang terms using + a format specifier and a corresponding set of arguments, much + in the way <c><![CDATA[printf()]]></c> works.</p> + <p><c><![CDATA[FormatStr]]></c> is a format specification string. The set + of valid format specifiers is as follows:</p> + <list type="bulleted"> + <item> + <p>~i - Integer</p> + </item> + <item> + <p>~f - Floating point</p> + </item> + <item> + <p>~a - Atom</p> + </item> + <item> + <p>~s - String</p> + </item> + <item> + <p>~w - Arbitrary Erlang term</p> + </item> + </list> + <p>For each format specifier that appears in <c><![CDATA[FormatStr]]></c>, + there must be a corresponding argument following + <c><![CDATA[FormatStr]]></c>. An Erlang term is built according to the + <c><![CDATA[FormatStr]]></c> with values and Erlang terms substituted from + the corresponding arguments and according to the individual + format specifiers. For example:</p> + <code type="none"><![CDATA[ +erl_format("[{name,~a},{age,~i},{data,~w}]", + "madonna", + 21, + erl_format("[{adr,~s,~i}]","E-street",42)); + ]]></code> + <p>This will create an <c><![CDATA[(ETERM *)]]></c> structure corresponding + to the Erlang term: + <c><![CDATA[[{name,madonna},{age,21},{data,[{adr,"E-street",42}]}]]]></c></p> + <p>The function returns an Erlang term, or NULL if + <c><![CDATA[FormatStr]]></c> does not describe a valid Erlang term.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_match(Pattern, Term)</nametext></name> + <fsummary>Performs pattern matching</fsummary> + <type> + <v>ETERM *Pattern,*Term;</v> + </type> + <desc> + <p>This function is used to perform pattern matching similar + to that done in Erlang. Refer to an Erlang manual for matching + rules and more examples.</p> + <p><c><![CDATA[Pattern]]></c> is an Erlang term, possibly containing unbound + variables. </p> + <p><c><![CDATA[Term]]></c> is an Erlang term that we wish to match against + <c><![CDATA[Pattern]]></c>.</p> + <p><c><![CDATA[Term]]></c> and <c><![CDATA[Pattern]]></c> are compared, and any + unbound variables in <c><![CDATA[Pattern]]></c> are bound to corresponding + values in <c><![CDATA[Term]]></c>. </p> + <p>If <c><![CDATA[Term]]></c> and <c><![CDATA[Pattern]]></c> can be matched, the + function returns a non-zero value and binds any unbound + variables in <c><![CDATA[Pattern]]></c>. If <c><![CDATA[Term]]></c><c><![CDATA[Pattern]]></c> do + not match, the function returns 0. For example:</p> + <code type="none"><![CDATA[ +ETERM *term, *pattern, *pattern2; +term1 = erl_format("{14,21}"); +term2 = erl_format("{19,19}"); +pattern1 = erl_format("{A,B}"); +pattern2 = erl_format("{F,F}"); +if (erl_match(pattern1, term1)) { + /* match succeeds: + * A gets bound to 14, + * B gets bound to 21 + */ + ... +} +if (erl_match(pattern2, term1)) { + /* match fails because F cannot be + * bound to two separate values, 14 and 21 + */ + ... +} +if (erl_match(pattern2, term2)) { + /* match succeeds and F gets bound to 19 */ + ... +} + ]]></code> + <p><c><![CDATA[erl_var_content()]]></c> can be used to retrieve the + content of any variables bound as a result of a call to + <c><![CDATA[erl_match()]]></c>.</p> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/erl_global.xml b/lib/erl_interface/doc/src/erl_global.xml new file mode 100644 index 0000000000..8f9a354b4f --- /dev/null +++ b/lib/erl_interface/doc/src/erl_global.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1998</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_global</title> + <prepared>Gordon Beaton</prepared> + <responsible>Gordon Beaton</responsible> + <docno></docno> + <approved>Gordon Beaton</approved> + <checked>Gordon Beaton</checked> + <date>980703</date> + <rev>A</rev> + <file>erl_global.sgml</file> + </header> + <lib>erl_global</lib> + <libsummary>Access globally registered names</libsummary> + <description> + <p>This module provides support for registering, looking + up and unregistering names in the Erlang Global module. For more + information, see the description of Global in the reference manual.</p> + <p>Note that the functions below perform an RPC using an open file + descriptor provided by the caller. This file descriptor must + not be used for other traffic during the global operation or the + function may receive unexpected data and fail.</p> + </description> + <funcs> + <func> + <name><ret>char **</ret><nametext>erl_global_names(fd,count)</nametext></name> + <fsummary>Obtain list of Global names</fsummary> + <type> + <v>int fd;</v> + <v>int *count;</v> + </type> + <desc> + <p>Retrieve a list of all known global names. + </p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection. + </p> + <p><c><![CDATA[count]]></c> is the address of an integer, or NULL. If + <c><![CDATA[count]]></c> is not NULL, it will be set by the function to + the number of names found. + </p> + <p>On success, the function returns an array of strings, each + containing a single registered name, and sets <c><![CDATA[count]]></c> to + the number of names found. The array is terminated + by a single NULL pointer. On failure, the function returns + NULL and <c><![CDATA[count]]></c> is not modified. + </p> + <note> + <p>It is the caller's responsibility to free the array + afterwards. It has been allocated by the function with a + single call to <c><![CDATA[malloc()]]></c>, so a single <c><![CDATA[free()]]></c> is + all that is necessary.</p> + </note> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_global_register(fd,name,pid)</nametext></name> + <fsummary>Register a name in Global</fsummary> + <type> + <v>int fd;</v> + <v>const char *name;</v> + <v>ETERM *pid;</v> + </type> + <desc> + <p>This function registers a name in Global. + </p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection. + </p> + <p><c><![CDATA[name]]></c> is the name to register in Global. + </p> + <p><c><![CDATA[pid]]></c> is the pid that should be associated with + <c><![CDATA[name]]></c>. This is the value that Global will return when + processes request the location of <c><![CDATA[name]]></c>. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_global_unregister(fd,name)</nametext></name> + <fsummary>Unregister a name in Global</fsummary> + <type> + <v>int fd;</v> + <v>const char *name;</v> + </type> + <desc> + <p>This function unregisters a name from Global. + </p> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection. + </p> + <p><c><![CDATA[name]]></c> is the name to unregister from Global. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_global_whereis(fd,name,node)</nametext></name> + <fsummary>Look up a name in global</fsummary> + <type> + <v>int fd;</v> + <v>const char *name;</v> + <v>char *node;</v> + </type> + <desc> + <p><c><![CDATA[fd]]></c> is an open descriptor to an Erlang connection. + </p> + <p><c><![CDATA[name]]></c> is the name that is to be looked up in Global. + </p> + <p>If <c><![CDATA[node]]></c> is not NULL, it is a pointer to a buffer + where the function can fill in the name of the node where + <c><![CDATA[name]]></c> is found. <c><![CDATA[node]]></c> can be passed directly to + <c><![CDATA[erl_connect()]]></c> if necessary. + </p> + <p>On success, the function returns an Erlang Pid containing the address + of the given name, and node will be initialized to + the nodename where <c><![CDATA[name]]></c> is found. On failure NULL will be + returned and <c><![CDATA[node]]></c> will not be modified.</p> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/erl_interface.xml b/lib/erl_interface/doc/src/erl_interface.xml new file mode 100644 index 0000000000..850a4127f4 --- /dev/null +++ b/lib/erl_interface/doc/src/erl_interface.xml @@ -0,0 +1,625 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>The Erl_Interface Library</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>K.Lundin</checked> + <date>990113</date> + <rev>A</rev> + <file>erl_interface.sgml</file> + </header> + <p>The Erl_Interface library contains functions. which help you + integrate programs written in C and Erlang. The functions in + Erl_Interface support the following:</p> + <list type="bulleted"> + <item>manipulation of data represented as Erlang data types</item> + <item>conversion of data between C and Erlang formats</item> + <item>encoding and decoding of Erlang data types for transmission or storage</item> + <item>communication between C nodes and Erlang processes</item> + <item>backup and restore of C node state to and from Mnesia</item> + </list> + <p>In the following sections, these topics are described:</p> + <list type="bulleted"> + <item>compiling your code for use with Erl_Interface</item> + <item>initializing Erl_Interface</item> + <item>encoding, decoding, and sending Erlang terms</item> + <item>building terms and patterns</item> + <item>pattern matching</item> + <item>connecting to a distributed Erlang node</item> + <item>using EPMD</item> + <item>sending and receiving Erlang messages</item> + <item>remote procedure calls</item> + <item>global names</item> + <item>the registry</item> + </list> + + <section> + <title>Compiling and Linking Your Code</title> + <p>In order to use any of the Erl_Interface functions, include the + following lines in your code:</p> + <code type="none"><![CDATA[ +#include "erl_interface.h" +#include "ei.h" ]]></code> + <p>Determine where the top directory of your OTP installation is. You + can find this out by starting Erlang and entering the following + command at the Eshell prompt:</p> + <code type="none"><![CDATA[ +Eshell V4.7.4 (abort with ^G) +1> code:root_dir(). +/usr/local/otp ]]></code> + <p>To compile your code, make sure that your C compiler knows where + to find <c><![CDATA[erl_interface.h]]></c> by specifying an appropriate <c><![CDATA[-I]]></c> + argument on the command line, or by adding it to the <c><![CDATA[CFLAGS]]></c> + definition in your <c><![CDATA[Makefile]]></c>. The correct value for this path is + <c><![CDATA[$OTPROOT/lib/erl_interface]]></c><em>Vsn</em><c><![CDATA[/include]]></c>, where <c><![CDATA[$OTPROOT]]></c> is the path + reported by <c><![CDATA[code:root_dir/0]]></c> in the above example, and <em>Vsn</em> is + the version of the Erl_interface application, for example + <c><![CDATA[erl_interface-3.2.3]]></c></p> + <code type="none"><![CDATA[ +$ cc -c -I/usr/local/otp/lib/erl_interface-3.2.3/include myprog.c ]]></code> + <p>When linking, you will need to specify the path to + <c><![CDATA[liberl_interface.a]]></c> and <c><![CDATA[libei.a]]></c> with + <c><![CDATA[-L$OTPROOT/lib/erl_interface-3.2.3/lib]]></c>, and you will need to specify the + name of the libraries with <c><![CDATA[-lerl_interface -lei]]></c>. You can do + this on the command line or by adding the flags to the <c><![CDATA[LDFLAGS]]></c> + definition in your <c><![CDATA[Makefile]]></c>.</p> + <code type="none"><![CDATA[ +$ ld -L/usr/local/otp/lib/erl_interface-3.2.3/ + lib myprog.o -lerl_interface -lei -o myprog ]]></code> + <p>Also, on some systems it may be necessary to link with some + additional libraries (e.g. <c><![CDATA[libnsl.a]]></c> and <c><![CDATA[libsocket.a]]></c> on + Solaris, or <c><![CDATA[wsock32.lib]]></c> on Windows) in order to use the + communication facilities of Erl_Interface.</p> + <p>If you are using Erl_Interface functions in a threaded + application based on POSIX threads or Solaris threads, then + Erl_Interface needs access to some of the synchronization + facilities in your threads package, and you will need to specify + additional compiler flags in order to indicate which of the packages + you are using. Define <c><![CDATA[_REENTRANT]]></c> and either <c><![CDATA[STHREADS]]></c> or + <c><![CDATA[PTHREADS]]></c>. The default is to use POSIX threads if + <c><![CDATA[_REENTRANT]]></c> is specified.</p> + <p>Note that both single threaded and default versions of the Erl_interface + and Ei libraries are provided. (The single threaded versions are named + <c><![CDATA[liberl_interface_st]]></c> and <c><![CDATA[libei_st]]></c>). Whether the default + versions of the libraries have support for threads or not is determined by if + the platform in question has support for POSIX or Solaris threads. To check this, + have a look in the <c><![CDATA[eidefs.mk]]></c> file in the erl_interface src directory.</p> + </section> + + <section> + <title>Initializing the erl_interface Library</title> + <p>Before calling any of the other Erl_Interface functions, you + must call <c><![CDATA[erl_init()]]></c> exactly once to initialize the library. + <c><![CDATA[erl_init()]]></c> takes two arguments, however the arguments are no + longer used by Erl_Interface, and should therefore be specified + as <c><![CDATA[erl_init(NULL,0)]]></c>.</p> + </section> + + <section> + <title>Encoding, Decoding and Sending Erlang Terms</title> + <p>Data sent between distributed Erlang nodes is encoded in the + Erlang external format. Consequently, you have to encode and decode + Erlang terms into byte streams if you want to use the distribution + protocol to communicate between a C program and Erlang. </p> + <p>The Erl_Interface library supports this activity. It has a + number of C functions which create and manipulate Erlang data + structures. The library also contains an encode and a decode function. + The example below shows how to create and encode an Erlang tuple + <c><![CDATA[{tobbe,3928}]]></c>:</p> + <code type="none"><![CDATA[ + +ETERM *arr[2], *tuple; +char buf[BUFSIZ]; +int i; + +arr[0] = erl_mk_atom("tobbe"); +arr[1] = erl_mk_integer(3928); +tuple = erl_mk_tuple(arr, 2); +i = erl_encode(tuple, buf); ]]></code> + <p>Alternatively, you can use <c><![CDATA[erl_send()]]></c> and + <c><![CDATA[erl_receive_msg]]></c>, which handle the encoding and decoding of + messages transparently.</p> + <p>Refer to the Reference Manual for a complete description of the + following modules:</p> + <list type="bulleted"> + <item>the <c><![CDATA[erl_eterm]]></c> module for creating Erlang terms</item> + <item>the <c><![CDATA[erl_marshal]]></c> module for encoding and decoding routines.</item> + </list> + </section> + + <section> + <title>Building Terms and Patterns</title> + <p>The previous example can be simplified by using + <c><![CDATA[erl_format()]]></c> to create an Erlang term.</p> + <code type="none"><![CDATA[ + +ETERM *ep; +ep = erl_format("{~a,~i}", "tobbe", 3928); ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_format]]></c> module, for a + full description of the different format directives. The following + example is more complex:</p> + <code type="none"><![CDATA[ + +ETERM *ep; +ep = erl_format("[{name,~a},{age,~i},{data,~w}]", + "madonna", + 21, + erl_format("[{adr,~s,~i}]", "E-street", 42)); +erl_free_compound(ep); ]]></code> + <p>As in previous examples, it is your responsibility to free the + memory allocated for Erlang terms. In this example, + <c><![CDATA[erl_free_compound()]]></c> ensures that the complete term pointed to + by <c><![CDATA[ep]]></c> is released. This is necessary, because the pointer from + the second call to <c><![CDATA[erl_format()]]></c> is lost. </p> + <p>The following + example shows a slightly different solution:</p> + <code type="none"><![CDATA[ + +ETERM *ep,*ep2; +ep2 = erl_format("[{adr,~s,~i}]","E-street",42); +ep = erl_format("[{name,~a},{age,~i},{data,~w}]", + "madonna", 21, ep2); +erl_free_term(ep); +erl_free_term(ep2); ]]></code> + <p>In this case, you free the two terms independently. The order in + which you free the terms <c><![CDATA[ep]]></c> and <c><![CDATA[ep2]]></c> is not important, + because the Erl_Interface library uses reference counting to + determine when it is safe to actually remove objects. </p> + <p>If you are not sure whether you have freed the terms properly, you + can use the following function to see the status of the fixed term + allocator:</p> + <code type="none"><![CDATA[ +long allocated, freed; + +erl_eterm_statistics(&allocated,&freed); +printf("currently allocated blocks: %ld\ +",allocated); +printf("length of freelist: %ld\ +",freed); + +/* really free the freelist */ +erl_eterm_release(); + ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_malloc]]></c> module for more + information.</p> + </section> + + <section> + <title>Pattern Matching</title> + <p>An Erlang pattern is a term that may contain unbound variables or + <c><![CDATA["do not care"]]></c> symbols. Such a pattern can be matched against a + term and, if the match is successful, any unbound variables in the + pattern will be bound as a side effect. The content of a bound + variable can then be retrieved.</p> + <code type="none"><![CDATA[ + +ETERM *pattern; +pattern = erl_format("{madonna,Age,_}"); ]]></code> + <p><c><![CDATA[erl_match()]]></c> is used to perform pattern matching. It takes a + pattern and a term and tries to match them. As a side effect any unbound + variables in the pattern will be bound. In the following example, we + create a pattern with a variable <em>Age</em> which appears at two + positions in the tuple. The pattern match is performed as follows:</p> + <list type="ordered"> + <item><c><![CDATA[erl_match()]]></c> will bind the contents of + <em>Age</em> to <em>21</em> the first time it reaches the variable</item> + <item>the second occurrence of <em>Age</em> will cause a test for + equality between the terms since <em>Age</em> is already bound to + <em>21</em>. Since <em>Age</em> is bound to 21, the equality test will + succeed and the match continues until the end of the pattern.</item> + <item>if the end of the pattern is reached, the match succeeds and you + can retrieve the contents of the variable</item> + </list> + <code type="none"><![CDATA[ +ETERM *pattern,*term; +pattern = erl_format("{madonna,Age,Age}"); +term = erl_format("{madonna,21,21}"); +if (erl_match(pattern, term)) { + fprintf(stderr, "Yes, they matched: Age = "); + ep = erl_var_content(pattern, "Age"); + erl_print_term(stderr, ep); + fprintf(stderr,"\ +"); + erl_free_term(ep); +} +erl_free_term(pattern); +erl_free_term(term); ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_match()]]></c> function for + more information.</p> + </section> + + <section> + <title>Connecting to a Distributed Erlang Node</title> + <p>In order to connect to a distributed Erlang node you need to first + initialize the connection routine with <c><![CDATA[erl_connect_init()]]></c>, + which stores information such as the host name, node name, and IP + address for later use:</p> + <code type="none"><![CDATA[ +int identification_number = 99; +int creation=1; +char *cookie="a secret cookie string"; /* An example */ +erl_connect_init(identification_number, cookie, creation); ]]></code> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_connect]]></c> module for more information.</p> + <p>After initialization, you set up the connection to the Erlang node. + Use <c><![CDATA[erl_connect()]]></c> to specify the Erlang node you want to + connect to. The following example sets up the connection and should + result in a valid socket file descriptor:</p> + <code type="none"><![CDATA[ +int sockfd; +char *nodename="[email protected]"; /* An example */ +if ((sockfd = erl_connect(nodename)) < 0) + erl_err_quit("ERROR: erl_connect failed"); ]]></code> + <p><c><![CDATA[erl_err_quit()]]></c> prints the specified string and terminates + the program. Refer to the Reference Manual, the <c><![CDATA[erl_error()]]></c> + function for more information.</p> + </section> + + <section> + <title>Using EPMD</title> + <p><c><![CDATA[Epmd]]></c> is the Erlang Port Mapper Daemon. Distributed Erlang nodes + register with <c><![CDATA[epmd]]></c> on the localhost to indicate to other nodes that + they exist and can accept connections. <c><![CDATA[Epmd]]></c> maintains a register of + node and port number information, and when a node wishes to connect to + another node, it first contacts <c><![CDATA[epmd]]></c> in order to find out the correct + port number to connect to.</p> + <p>When you use <c><![CDATA[erl_connect()]]></c> to connect to an Erlang node, a + connection is first made to <c><![CDATA[epmd]]></c> and, if the node is known, a + connection is then made to the Erlang node.</p> + <p>C nodes can also register themselves with <c><![CDATA[epmd]]></c> if they want other + nodes in the system to be able to find and connect to them.</p> + <p>Before registering with <c><![CDATA[epmd]]></c>, you need to first create a listen socket + and bind it to a port. Then:</p> + <code type="none"><![CDATA[ +int pub; + +pub = erl_publish(port); ]]></code> + <p><c><![CDATA[pub]]></c> is a file descriptor now connected to <c><![CDATA[epmd]]></c>. <c><![CDATA[Epmd]]></c> + monitors the other end of the connection, and if it detects that the + connection has been closed, the node will be unregistered. So, if you + explicitly close the descriptor or if your node fails, it will be + unregistered from <c><![CDATA[epmd]]></c>.</p> + <p>Be aware that on some systems (such as VxWorks), a failed node will + not be detected by this mechanism since the operating system does not + automatically close descriptors that were left open when the node + failed. If a node has failed in this way, <c><![CDATA[epmd]]></c> will prevent you from + registering a new node with the old name, since it thinks that the old + name is still in use. In this case, you must unregister the name + explicitly:</p> + <code type="none"><![CDATA[ +erl_unpublish(node); ]]></code> + <p>This will cause <c><![CDATA[epmd]]></c> to close the connection from the far end. Note + that if the name was in fact still in use by a node, the results of + this operation are unpredictable. Also, doing this does not cause the + local end of the connection to close, so resources may be consumed.</p> + </section> + + <section> + <title>Sending and Receiving Erlang Messages</title> + <p>Use one of the following two functions to send messages:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_send()]]></c></item> + <item><c><![CDATA[erl_reg_send()]]></c></item> + </list> + <p>As in Erlang, it is possible to send messages to a + <em>Pid</em> or to a registered name. It is easier to send a + message to a registered name because it avoids the problem of finding + a suitable <em>Pid</em>.</p> + <p>Use one of the following two functions to receive messages:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_receive()]]></c></item> + <item><c><![CDATA[erl_receive_msg()]]></c></item> + </list> + <p><c><![CDATA[erl_receive()]]></c> receives the message into a buffer, while + <c><![CDATA[erl_receive_msg()]]></c> decodes the message into an Erlang term. </p> + + <section> + <title>Example of Sending Messages</title> + <p>In the following example, <c><![CDATA[{Pid, hello_world}]]></c> is + sent to a registered process <c><![CDATA[my_server]]></c>. The message is encoded + by <c><![CDATA[erl_send()]]></c>:</p> + <code type="none"><![CDATA[ +extern const char *erl_thisnodename(void); +extern short erl_thiscreation(void); +#define SELF(fd) erl_mk_pid(erl_thisnodename(),fd,0,erl_thiscreation()) +ETERM *arr[2], *emsg; +int sockfd, creation=1; + +arr[0] = SELF(sockfd); +arr[1] = erl_mk_atom("Hello world"); +emsg = erl_mk_tuple(arr, 2); + +erl_reg_send(sockfd, "my_server", emsg); +erl_free_term(emsg); ]]></code> + <p>The first element of the tuple that is sent is your own + <em>Pid</em>. This enables <c><![CDATA[my_server]]></c> to reply. Refer to the + Reference Manual, the <c><![CDATA[erl_connect]]></c> module for more information + about send primitives.</p> + </section> + + <section> + <title>Example of Receiving Messages</title> + <p>In this example <c><![CDATA[{Pid, Something}]]></c> is received. The + received Pid is then used to return <c><![CDATA[{goodbye,Pid}]]></c></p> + <code type="none"><![CDATA[ +ETERM *arr[2], *answer; +int sockfd,rc; +char buf[BUFSIZE]; +ErlMessage emsg; + +if ((rc = erl_receive_msg(sockfd , buf, BUFSIZE, &emsg)) == ERL_MSG) { + arr[0] = erl_mk_atom("goodbye"); + arr[1] = erl_element(1, emsg.msg); + answer = erl_mk_tuple(arr, 2); + erl_send(sockfd, arr[1], answer); + erl_free_term(answer); + erl_free_term(emsg.msg); + erl_free_term(emsg.to); +} +} ]]></code> + <p>In order to provide robustness, a distributed Erlang node + occasionally polls all its connected neighbours in an attempt to + detect failed nodes or communication links. A node which receives such + a message is expected to respond immediately with an <c><![CDATA[ERL_TICK]]></c> message. + This is done automatically by <c><![CDATA[erl_receive()]]></c>, however when this + has occurred <c><![CDATA[erl_receive]]></c> returns <c><![CDATA[ERL_TICK]]></c> to the caller + without storing a message into the <c><![CDATA[ErlMessage]]></c> structure.</p> + <p>When a message has been received, it is the caller's responsibility + to free the received message <c><![CDATA[emsg.msg]]></c> as well as <c><![CDATA[emsg.to]]></c> + or <c><![CDATA[emsg.from]]></c>, depending on the type of message received.</p> + <p>Refer to the Reference Manual for additional information about the + following modules:</p> + <list type="bulleted"> + <item><c><![CDATA[erl_connect]]></c></item> + <item><c><![CDATA[erl_eterm]]></c>.</item> + </list> + </section> + </section> + + <section> + <title>Remote Procedure Calls</title> + <p>An Erlang node acting as a client to another Erlang node + typically sends a request and waits for a reply. Such a request is + included in a function call at a remote node and is called a remote + procedure call. The following example shows how the + Erl_Interface library supports remote procedure calls:</p> + <code type="none"><![CDATA[ + +char modname[]=THE_MODNAME; +ETERM *reply,*ep; +ep = erl_format("[~a,[]]", modname); +if (!(reply = erl_rpc(fd, "c", "c", ep))) + erl_err_msg("<ERROR> when compiling file: %s.erl !\ +", modname); +erl_free_term(ep); +ep = erl_format("{ok,_}"); +if (!erl_match(ep, reply)) + erl_err_msg("<ERROR> compiler errors !\ +"); +erl_free_term(ep); +erl_free_term(reply); ]]></code> + <p><c><![CDATA[c:c/1]]></c> is called to compile the specified module on the + remote node. <c><![CDATA[erl_match()]]></c> checks that the compilation was + successful by testing for the expected <c><![CDATA[ok]]></c>.</p> + <p>Refer to the Reference Manual, the <c><![CDATA[erl_connect]]></c> module for + more information about <c><![CDATA[erl_rpc()]]></c>, and its companions + <c><![CDATA[erl_rpc_to()]]></c> and <c><![CDATA[erl_rpc_from()]]></c>.</p> + </section> + + <section> + <title>Using Global Names</title> + <p>A C node has access to names registered through the Erlang Global + module. Names can be looked up, allowing the C node to send messages + to named Erlang services. C nodes can also register global names, + allowing them to provide named services to Erlang processes or other C + nodes. </p> + <p>Erl_Interface does not provide a native implementation of the global + service. Instead it uses the global services provided by a "nearby" + Erlang node. In order to use the services described in this section, + it is necessary to first open a connection to an Erlang node.</p> + <p>To see what names there are:</p> + <code type="none"><![CDATA[ +char **names; +int count; +int i; + +names = erl_global_names(fd,&count); + +if (names) + for (i=0; i<count; i++) + printf("%s\ +",names[i]); + +free(names); ]]></code> + <p><c><![CDATA[erl_global_names()]]></c> allocates and returns a buffer containing + all the names known to global. <c><![CDATA[count]]></c> will be initialized to + indicate how many names are in the array. The array of strings in + names is terminated by a NULL pointer, so it is not necessary to use + <c><![CDATA[count]]></c> to determine when the last name is reached.</p> + <p>It is the caller's responsibility to free the array. + <c><![CDATA[erl_global_names()]]></c> allocates the array and all of the strings + using a single call to <c><![CDATA[malloc()]]></c>, so <c><![CDATA[free(names)]]></c> is all + that is necessary.</p> + <p>To look up one of the names:</p> + <code type="none"><![CDATA[ +ETERM *pid; +char node[256]; + +pid = erl_global_whereis(fd,"schedule",node); ]]></code> + <p>If <c><![CDATA["schedule"]]></c> is known to global, an Erlang pid is returned + that can be used to send messages to the schedule service. + Additionally, <c><![CDATA[node]]></c> will be initialized to contain the name of + the node where the service is registered, so that you can make a + connection to it by simply passing the variable to <c><![CDATA[erl_connect()]]></c>.</p> + <p>Before registering a name, you should already have registered your + port number with <c><![CDATA[epmd]]></c>. This is not strictly necessary, but if you + neglect to do so, then other nodes wishing to communicate with your + service will be unable to find or connect to your process.</p> + <p>Create a pid that Erlang processes can use to communicate with your + service:</p> + <code type="none"><![CDATA[ +ETERM *pid; + +pid = erl_mk_pid(thisnode,14,0,0); +erl_global_register(fd,servicename,pid); ]]></code> + <p>After registering the name, you should use <c><![CDATA[erl_accept()]]></c> to wait for + incoming connections.</p> + <p>Do not forget to free <c><![CDATA[pid]]></c> later with <c><![CDATA[erl_free_term()]]></c>!</p> + <p>To unregister a name:</p> + <code type="none"><![CDATA[ +erl_global_unregister(fd,servicename); ]]></code> + </section> + + <section> + <title>The Registry</title> + <p>This section describes the use of the registry, a simple mechanism + for storing key-value pairs in a C-node, as well as backing them up or + restoring them from a Mnesia table on an Erlang node. More detailed + information about the individual API functions can be found in the + Reference Manual.</p> + <p>Keys are strings, i.e. 0-terminated arrays of characters, and values + are arbitrary objects. Although integers and floating point numbers + are treated specially by the registry, you can store strings or binary + objects of any type as pointers.</p> + <p>To start, you need to open a registry:</p> + <code type="none"><![CDATA[ +ei_reg *reg; + +reg = ei_reg_open(45); ]]></code> + <p>The number 45 in the example indicates the approximate number of + objects that you expect to store in the registry. Internally the + registry uses hash tables with collision chaining, so there is no + absolute upper limit on the number of objects that the registry can + contain, but if performance or memory usage are important, then you + should choose a number accordingly. The registry can be resized later.</p> + <p>You can open as many registries as you like (if memory permits).</p> + <p>Objects are stored and retrieved through set and get functions. In + the following examples you see how to store integers, floats, strings + and arbitrary binary objects:</p> + <code type="none"><![CDATA[ +struct bonk *b = malloc(sizeof(*b)); +char *name = malloc(7); + +ei_reg_setival(reg,"age",29); +ei_reg_setfval(reg,"height",1.85); + +strcpy(name,"Martin"); +ei_reg_setsval(reg,"name",name); + +b->l = 42; +b->m = 12; +ei_reg_setpval(reg,"jox",b,sizeof(*b)); ]]></code> + <p>If you attempt to store an object in the registry and there is an + existing object with the same key, the new value will replace the old + one. This is done regardless of whether the new object and the old one + have the same type, so you can, for example, replace a string with an + integer. If the existing value is a string or binary, it will be freed + before the new value is assigned.</p> + <p>Stored values are retrieved from the registry as follows:</p> + <code type="none"><![CDATA[ +long i; +double f; +char *s; +struct bonk *b; +int size; + +i = ei_reg_getival(reg,"age"); +f = ei_reg_getfval(reg,"height"); +s = ei_reg_getsval(reg,"name"); +b = ei_reg_getpval(reg,"jox",&size); ]]></code> + <p>In all of the above examples, the object must exist and it must be of + the right type for the specified operation. If you do not know the + type of a given object, you can ask:</p> + <code type="none"><![CDATA[ +struct ei_reg_stat buf; + +ei_reg_stat(reg,"name",&buf); ]]></code> + <p>Buf will be initialized to contain object attributes.</p> + <p>Objects can be removed from the registry:</p> + <code type="none"><![CDATA[ +ei_reg_delete(reg,"name"); ]]></code> + <p>When you are finished with a registry, close it to remove all the + objects and free the memory back to the system:</p> + <code type="none"><![CDATA[ +ei_reg_close(reg); ]]></code> + + <section> + <title>Backing Up the Registry to Mnesia</title> + <p>The contents of a registry can be backed up to Mnesia on a "nearby" + Erlang node. You need to provide an open connection to the Erlang node + (see <c><![CDATA[erl_connect()]]></c>). Also, Mnesia 3.0 or later must be running + on the Erlang node before the backup is initiated:</p> + <code type="none"><![CDATA[ +ei_reg_dump(fd, reg, "mtab", dumpflags); ]]></code> + <p>The example above will backup the contents of the registry to the + specified Mnesia table <c><![CDATA["mtab"]]></c>. Once a registry has been backed + up to Mnesia in this manner, additional backups will only affect + objects that have been modified since the most recent backup, i.e. + objects that have been created, changed or deleted. The backup + operation is done as a single atomic transaction, so that the entire + backup will be performed or none of it will.</p> + <p>In the same manner, a registry can be restored from a Mnesia table:</p> + <code type="none"><![CDATA[ +ei_reg_restore(fd, reg, "mtab"); ]]></code> + <p>This will read the entire contents of <c><![CDATA["mtab"]]></c> into the specified + registry. After the restore, all of the objects in the registry will + be marked as unmodified, so a subsequent backup will only affect + objects that you have modified since the restore.</p> + <p>Note that if you restore to a non-empty registry, objects in the + table will overwrite objects in the registry with the same keys. Also, + the <em>entire</em> contents of the registry is marked as unmodified + after the restore, including any modified objects that were not + overwritten by the restore operation. This may not be your intention.</p> + </section> + + <section> + <title>Storing Strings and Binaries</title> + <p>When string or binary objects are stored in the registry it is + important that a number of simple guidelines are followed. </p> + <p>Most importantly, the object must have been created with a single call + to <c><![CDATA[malloc()]]></c> (or similar), so that it can later be removed by a + single call to <c><![CDATA[free()]]></c>. Objects will be freed by the registry + when it is closed, or when you assign a new value to an object that + previously contained a string or binary.</p> + <p>You should also be aware that if you store binary objects that are + context-dependent (e.g. containing pointers or open file descriptors), + they will lose their meaning if they are backed up to a Mnesia table + and subsequently restored in a different context.</p> + <p>When you retrieve a stored string or binary value from the registry, + the registry maintains a pointer to the object and you are passed a + copy of that pointer. You should never free an object retrieved in + this manner because when the registry later attempts to free it, a + runtime error will occur that will likely cause the C-node to crash.</p> + <p>You are free to modify the contents of an object retrieved this way. + However when you do so, the registry will not be aware of the changes + you make, possibly causing it to be missed the next time you make a + Mnesia backup of the registry contents. This can be avoided if you + mark the object as dirty after any such changes with + <c><![CDATA[ei_reg_markdirty()]]></c>, or pass appropriate flags to + <c><![CDATA[ei_reg_dump()]]></c>.</p> + </section> + </section> +</chapter> + diff --git a/lib/erl_interface/doc/src/erl_malloc.xml b/lib/erl_interface/doc/src/erl_malloc.xml new file mode 100644 index 0000000000..8c8750d62a --- /dev/null +++ b/lib/erl_interface/doc/src/erl_malloc.xml @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_malloc</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>980703</date> + <rev>A</rev> + <file>erl_malloc.sgml</file> + </header> + <lib>erl_malloc</lib> + <libsummary>Memory Allocation Functions</libsummary> + <description> + <p>This module provides functions for allocating and deallocating + memory.</p> + </description> + <funcs> + <func> + <name><ret>ETERM *</ret><nametext>erl_alloc_eterm(etype)</nametext></name> + <fsummary>Allocates an ETERM structure</fsummary> + <type> + <v>unsigned char etype;</v> + </type> + <desc> + <p>This function allocates an <c><![CDATA[(ETERM)]]></c> structure. + Specify <c><![CDATA[etype]]></c> as one of the following constants:</p> + <list type="bulleted"> + <item> + <p>ERL_INTEGER</p> + </item> + <item> + <p>ERL_U_INTEGER <c><![CDATA[/* unsigned integer */]]></c></p> + </item> + <item> + <p>ERL_ATOM</p> + </item> + <item> + <p>ERL_PID <c><![CDATA[/* Erlang process identifier */]]></c></p> + </item> + <item> + <p>ERL_PORT</p> + </item> + <item> + <p>ERL_REF <c><![CDATA[/* Erlang reference */]]></c></p> + </item> + <item> + <p>ERL_LIST</p> + </item> + <item> + <p>ERL_EMPTY_LIST</p> + </item> + <item> + <p>ERL_TUPLE</p> + </item> + <item> + <p>ERL_BINARY</p> + </item> + <item> + <p>ERL_FLOAT</p> + </item> + <item> + <p>ERL_VARIABLE</p> + </item> + <item> + <p>ERL_SMALL_BIG <c><![CDATA[/* bignum */]]></c></p> + </item> + <item> + <p>ERL_U_SMALL_BIG <c><![CDATA[/* bignum */]]></c></p> + </item> + </list> + <p><c><![CDATA[ERL_SMALL_BIG]]></c> and <c><![CDATA[ERL_U_SMALL_BIG]]></c> are for + creating Erlang <c><![CDATA[bignums]]></c>, which can contain integers of + arbitrary size. The size of an integer in Erlang is machine + dependent, but in general any integer larger than 2^28 + requires a bignum.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_eterm_release(void)</nametext></name> + <fsummary>Clears the ETERM freelist</fsummary> + <desc> + <p>Clears the + freelist, where blocks are placed when they are + released by <c><![CDATA[erl_free_term()]]></c> and + <c><![CDATA[erl_free_compound()]]></c>. </p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_eterm_statistics(allocated, freed)</nametext></name> + <fsummary>Reports term allocation statistics</fsummary> + <type> + <v>long *allocated;</v> + <v>long *freed;</v> + </type> + <desc> + <p><c><![CDATA[allocated]]></c> and <c><![CDATA[freed]]></c> are initialized to + contain information about the fix-allocator used to allocate + ETERM components. <c><![CDATA[allocated]]></c> is the number of blocks + currently allocated to ETERM objects. <c><![CDATA[freed]]></c> is the + length of the freelist, where blocks are placed when they are + released by <c><![CDATA[erl_free_term()]]></c> and + <c><![CDATA[erl_free_compound()]]></c>. </p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_free_array(array, size)</nametext></name> + <fsummary>Frees an array of ETERM structures</fsummary> + <type> + <v>ETERM **array;</v> + <v>int size;</v> + </type> + <desc> + <p>This function frees an array of Erlang terms.</p> + <p><c><![CDATA[array]]></c> is an array of ETERM* objects. + </p> + <p><c><![CDATA[size]]></c> is the number of terms in the array.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_free_term(t)</nametext></name> + <fsummary>Frees an ETERM structure</fsummary> + <type> + <v>ETERM *t;</v> + </type> + <desc> + <p>Use this function to free an Erlang term.</p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_free_compound(t)</nametext></name> + <fsummary>Frees an array of ETERM structures</fsummary> + <type> + <v>ETERM *t;</v> + </type> + <desc> + <p>Normally it is the programmer's responsibility to free each + Erlang term that has been returned from any of the + <c><![CDATA[erl_interface]]></c> functions. However since many of the + functions that build new Erlang terms in fact share objects + with other existing terms, it may be difficult for the + programmer to maintain pointers to all such terms in order to + free them individually. + </p> + <p><c><![CDATA[erl_free_compound()]]></c> will recursively free all of the + sub-terms associated with a given Erlang term, regardless of + whether we are still holding pointers to the sub-terms. + </p> + <p>There is an example in the User Manual under "Building + Terms and Patterns" + </p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_malloc(size)</nametext></name> + <fsummary>Allocates some memory</fsummary> + <type> + <v>long size;</v> + </type> + <desc> + <p>This function calls the standard + <c><![CDATA[malloc()]]></c> function. </p> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>erl_free(ptr)</nametext></name> + <fsummary>Frees some memory</fsummary> + <type> + <v>void *ptr;</v> + </type> + <desc> + <p>This function calls the standard + <c><![CDATA[free()]]></c> function. </p> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/erl_marshal.xml b/lib/erl_interface/doc/src/erl_marshal.xml new file mode 100644 index 0000000000..a7eaf78f35 --- /dev/null +++ b/lib/erl_interface/doc/src/erl_marshal.xml @@ -0,0 +1,272 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>erl_marshal</title> + <prepared>Torbjörn Törnkvist</prepared> + <responsible>Torbjörn Törnkvist</responsible> + <docno></docno> + <approved>Bjarne Däcker</approved> + <checked>Torbjörn Törnkvist</checked> + <date>980703</date> + <rev>A</rev> + <file>erl_marshal.sgml</file> + </header> + <lib>erl_marshal</lib> + <libsummary>Encoding and Decoding of Erlang terms</libsummary> + <description> + <p>This module contains functions for encoding Erlang terms into + a sequence of bytes, and for decoding Erlang terms from a + sequence of bytes.</p> + </description> + <funcs> + <func> + <name><ret>int</ret><nametext>erl_compare_ext(bufp1, bufp2)</nametext></name> + <fsummary>Compares encoded byte sequences</fsummary> + <type> + <v>unsigned char *bufp1,*bufp2;</v> + </type> + <desc> + <p>This function compares two encoded terms. + </p> + <p><c><![CDATA[bufp1]]></c> is a buffer containing an encoded Erlang + term term1. + </p> + <p><c><![CDATA[bufp2]]></c> is a buffer containing an encoded Erlang + term term2. + </p> + <p>The function returns 0 if the terms are equal, -1 if term1 + is less than term2, or 1 if term2 is less than term1. + </p> + </desc> + </func> + <func> + <name><ret>ETERM *</ret><nametext>erl_decode(bufp)</nametext></name> + <name><ret>ETERM *</ret><nametext>erl_decode_buf(bufpp)</nametext></name> + <fsummary>Converts a term from Erlang external format</fsummary> + <type> + <v>unsigned char *bufp;</v> + <v>unsigned char **bufpp;</v> + </type> + <desc> + <p><c><![CDATA[erl_decode()]]></c> and <c><![CDATA[erl_decode_buf()]]></c> decode + the contents of a buffer and return the corresponding + Erlang term. <c><![CDATA[erl_decode_buf()]]></c> provides a simple + mechanism for dealing with several encoded terms stored + consecutively in the buffer.</p> + <p><c><![CDATA[bufp]]></c> is a pointer to a buffer containing one or + more encoded Erlang terms. + </p> + <p><c><![CDATA[bufpp]]></c> is the address of a buffer pointer. The buffer + contains one or more consecutively encoded Erlang terms. + Following a successful call to <c><![CDATA[erl_decode_buf()]]></c>, + <c><![CDATA[bufpp]]></c> will be updated so that it points to the next + encoded term. + </p> + <p><c><![CDATA[erl_decode()]]></c> returns an Erlang term + corresponding to the contents of <c><![CDATA[bufp]]></c> on success, or + NULL on failure. <c><![CDATA[erl_decode_buf()]]></c> returns an Erlang + term corresponding to the first of the consecutive terms in + <c><![CDATA[bufpp]]></c> and moves <c><![CDATA[bufpp]]></c> forward to point to the + next term in the buffer. On failure, each of the functions + returns NULL. + </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_encode(term, bufp)</nametext></name> + <name><ret>int</ret><nametext>erl_encode_buf(term, bufpp)</nametext></name> + <fsummary>Converts a term into Erlang external format</fsummary> + <type> + <v>ETERM *term;</v> + <v>unsigned char *bufp;</v> + <v>unsigned char **bufpp;</v> + </type> + <desc> + <p><c><![CDATA[erl_encode()]]></c> and <c><![CDATA[erl_encode_buf()]]></c> encode + Erlang terms into external format for storage or transmission. + <c><![CDATA[erl_encode_buf()]]></c> provides a simple mechanism for + encoding several terms consecutively in the same + buffer. + </p> + <p><c>term</c> is an Erlang term to be encoded. + </p> + <p><c>bufp</c> is a pointer to a buffer containing one or + more encoded Erlang terms. + </p> + <p><c>bufpp</c> is a pointer to a pointer to a buffer + containing one or more consecutively encoded Erlang terms. + Following a successful call to <c><![CDATA[erl_encode_buf()]]></c>, + <c>bufpp</c> will be updated so that it points to the + position for the next encoded term. + </p> + <p> + These functions returns the number of bytes written to buffer + if successful, otherwise returns 0. + </p> + <p>Note that no bounds checking is done on the buffer. It is + the caller's responsibility to make sure that the buffer is + large enough to hold the encoded terms. You can either use a + static buffer that is large enough to hold the terms you + expect to need in your program, or use <c><![CDATA[erl_term_len()]]></c> + to determine the exact requirements for a given term. + </p> + <p>The following can help you estimate the buffer + requirements for a term. Note that this information is + implementation specific, and may change in future versions. + If you are unsure, use <c><![CDATA[erl_term_len()]]></c>. + </p> + <p>Erlang terms are encoded with a 1 byte tag that + identifies the type of object, a 2- or 4-byte length field, + and then the data itself. Specifically: + </p> + <taglist> + <tag><c><![CDATA[Tuples]]></c></tag> + <item>need 5 bytes, plus the space for each element.</item> + <tag><c><![CDATA[Lists]]></c></tag> + <item>need 5 bytes, plus the space for each element, and 1 + additional byte for the empty list at the end.</item> + <tag><c><![CDATA[Strings and atoms]]></c></tag> + <item>need 3 bytes, plus 1 byte for each character (the + terminating 0 is not encoded). Really long strings (more + than 64k characters) are encoded as lists. Atoms cannot + contain more than 256 characters.</item> + <tag><c><![CDATA[Integers]]></c></tag> + <item>need 5 bytes.</item> + <tag><c><![CDATA[Characters]]></c></tag> + <item>(integers < 256) need 2 bytes.</item> + <tag><c><![CDATA[Floating point numbers]]></c></tag> + <item>need 32 bytes.</item> + <tag><c><![CDATA[Pids]]></c></tag> + <item>need 10 bytes, plus the space for the node name, which + is an atom.</item> + <tag><c><![CDATA[Ports and Refs]]></c></tag> + <item>need 6 bytes, plus the space for the node name, which + is an atom.</item> + </taglist> + <p>The total space required will be the result calculated + from the information above, plus 1 additional byte for a + version identifier. + </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_ext_size(bufp)</nametext></name> + <fsummary>Counts elements in encoded term</fsummary> + <type> + <v>unsigned char *bufp;</v> + </type> + <desc> + <p>This function returns the number of elements in an + encoded term.</p> + </desc> + </func> + <func> + <name><ret>unsigned char</ret><nametext>erl_ext_type(bufp)</nametext></name> + <fsummary>Determines type of an encoded byte sequence</fsummary> + <type> + <v>unsigned char *bufp;</v> + </type> + <desc> + <p>This function identifies and returns the type of Erlang term encoded + in a buffer. It will skip a trailing <em>magic</em> identifier. + Returns <c><![CDATA[0]]></c> if the type can't be determined or one of</p> + <list type="bulleted"> + <item> + <p>ERL_INTEGER</p> + </item> + <item> + <p>ERL_ATOM</p> + </item> + <item> + <p>ERL_PID <c><![CDATA[/* Erlang process identifier */]]></c></p> + </item> + <item> + <p>ERL_PORT</p> + </item> + <item> + <p>ERL_REF <c><![CDATA[/* Erlang reference */]]></c></p> + </item> + <item> + <p>ERL_EMPTY_LIST</p> + </item> + <item> + <p>ERL_LIST</p> + </item> + <item> + <p>ERL_TUPLE</p> + </item> + <item> + <p>ERL_FLOAT</p> + </item> + <item> + <p>ERL_BINARY</p> + </item> + <item> + <p>ERL_FUNCTION</p> + </item> + </list> + </desc> + </func> + <func> + <name><ret>unsigned char *</ret><nametext>erl_peek_ext(bufp, pos)</nametext></name> + <fsummary>Steps over encoded term</fsummary> + <type> + <v>unsigned char *bufp;</v> + <v>int pos;</v> + </type> + <desc> + <p>This function is used for stepping over one or more + encoded terms in a buffer, in order to directly access a + later term. + </p> + <p><c><![CDATA[bufp]]></c> is a pointer to a buffer containing one or + more encoded Erlang terms. + </p> + <p><c><![CDATA[pos]]></c> indicates how many terms to step over in the + buffer. + </p> + <p>The function returns a pointer to a sub-term that can be + used in a subsequent call to <c><![CDATA[erl_decode()]]></c> in order to retrieve + the term at that position. If there is no term, or <c><![CDATA[pos]]></c> + would exceed the size of the terms in the buffer, NULL is returned. + </p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_term_len(t)</nametext></name> + <fsummary>Determines encoded size of term</fsummary> + <type> + <v>ETERM *t;</v> + </type> + <desc> + <p>This function determines the buffer space that would be + needed by <c><![CDATA[t]]></c> if it were encoded into Erlang external + format by <c><![CDATA[erl_encode()]]></c>. + </p> + <p>The size in bytes is returned. + </p> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/fascicules.xml b/lib/erl_interface/doc/src/fascicules.xml new file mode 100644 index 0000000000..3d6219a2bd --- /dev/null +++ b/lib/erl_interface/doc/src/fascicules.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE fascicules SYSTEM "fascicules.dtd"> + +<fascicules> + <fascicule file="part_ei" href="part_ei_frame.html" entry="no"> + EI User's Guide + </fascicule> + <fascicule file="ref_man_ei" href="ref_man_ei_frame.html" entry="yes"> + EI Library Reference + </fascicule> + <fascicule file="ref_man_erl_interface" href="ref_man_erl_interface_frame.html" entry="no"> + Erl_interface Library Reference + </fascicule> + <fascicule file="ref_man" href="ref_man_frame.html" entry="no"> + Command Reference + </fascicule> + <fascicule file="part_notes" href="part_notes_frame.html" entry="no"> + Release Notes + </fascicule> + <fascicule file="" href="../../../../doc/print.html" entry="no"> + Off-Print + </fascicule> +</fascicules> + diff --git a/lib/erl_interface/doc/src/make.dep b/lib/erl_interface/doc/src/make.dep new file mode 100644 index 0000000000..3f43cf64fe --- /dev/null +++ b/lib/erl_interface/doc/src/make.dep @@ -0,0 +1,24 @@ +# ---------------------------------------------------- +# >>>> Do not edit this file <<<< +# This file was automaticly generated by +# /home/otp/bin//docdepend +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# TeX files that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: book.tex ei.tex ei_connect.tex ei_users_guide.tex \ + erl_call.tex erl_connect.tex erl_error.tex \ + erl_eterm.tex erl_format.tex erl_global.tex \ + erl_malloc.tex erl_marshal.tex part_ei.tex \ + ref_man.tex ref_man_ei.tex ref_man_erl_interface.tex \ + registry.tex + +# ---------------------------------------------------- +# Source inlined when transforming from source to LaTeX +# ---------------------------------------------------- + +book.tex: ref_man.xml ref_man_ei.xml ref_man_erl_interface.xml + diff --git a/lib/erl_interface/doc/src/note.gif b/lib/erl_interface/doc/src/note.gif Binary files differnew file mode 100644 index 0000000000..6fffe30419 --- /dev/null +++ b/lib/erl_interface/doc/src/note.gif diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml new file mode 100644 index 0000000000..f2519fda0b --- /dev/null +++ b/lib/erl_interface/doc/src/notes.xml @@ -0,0 +1,535 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2004</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erl_interface Release Notes</title> + <prepared>otp_appnotes</prepared> + <docno>nil</docno> + <date>nil</date> + <rev>nil</rev> + <file>notes.xml</file> + </header> + <p>This document describes the changes made to the Erl_interface application.</p> + +<section><title>Erl_Interface 3.6.4</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The documentation is now built with open source tools + (xsltproc and fop) that exists on most platforms. One + visible change is that the frames are removed.</p> + <p> + Own Id: OTP-8201</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.6.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The manual states that erl_receive() return the reason in + the <c>ErlMessage</c> struct. This was not the case and + the function is now corrected.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-4969</p> + </item> + <item> + <p> + In <c>send_exit.c</c> an errorneous size of memory + allocation could occur when reallocating a buffer.</p> + <p> + In <c>ei_decode_trace.c</c> the index could be updated + when the decoding failed.</p> + <p> + In <c>ei_printterm.c</c> the index could be updated when + the decoding failed in lists and tuples.</p> + <p> + In <c>ei_decode_term.c</c> when decoding a double + (ERL_FLOAT_EXT) no check was done to ensure that the last + of the 31 bytes was null terminated.</p> + <p> + In <c>ei_decode_term.c</c> when decoding references, only + the first 3 bytes are read, but the index did not + increment by the total size.</p> + <p> + In <c>ei_decode_fun.c</c> no check of correct buffer + allocation or data length was done.</p> + <p> + In <c>ei_decode_string.c</c> the integer list string case + did not decode the NIL tail correctly.</p> + <p> + These errors has now been fixed. (Thanks to Romain + Lenglet, Paul Mineiro and Paul Guyot).</p> + <p> + Own Id: OTP-6117</p> + </item> + <item> + <p> + <c>ei_decode_big</c> could be decoded with a garbage + byte.</p> + <p> + <c>ei_encode_big</c> and <c>ei_x_encode_big</c> is now + available.</p> + <p> + Own Id: OTP-7554</p> + </item> + <item> + <p> + The function <c>erl_init_resolve()</c> did not conform to + C99 standard which caused a build error on some + platforms. This has now been fixed.</p> + <p> + Own Id: OTP-8093</p> + </item> + <item> + <p> + <c>Makefile.in</c> has been updated to use the LDFLAGS + environment variable (if set). (Thanks to Davide + Pesavento.)</p> + <p> + Own Id: OTP-8157</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Added support for 64-bit integers in encoding/decoding.</p> + <p> + Added support for better printouts of binaries.</p> + <p> + Own Id: OTP-6091</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.6.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A problem with <c>gethostbyname</c> in <c>erl_start.c</c> + could cause a buffer overflow. This has now been fixed.</p> + <p> + Clean up of code and removed compiler warnings.</p> + <p> + Own Id: OTP-7978</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.6.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>A faulty validation in <c>ei_reg_getpval</c> caused it + to never return the key-value. This has now been fixed. + (Thanks to Matt Stancliff)</p> + <p> + Own Id: OTP-7960</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Minor update to the <c>configure</c> script.</p> + <p> + Own Id: OTP-7959</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.6.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Minor update to the <c>configure</c> script.</p> + <p> + Own Id: OTP-7959</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.6</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Nodes belonging to different independent clusters can now + co-exist on the same host with the help of a new + environment variable setting ERL_EPMD_PORT.</p> + <p> + Own Id: OTP-7826</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.5.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A type-casting bug in ei_skip_term and ei_printterm on + 64bit platforms rendering undefined results is now + corrected.</p> + <p> + Own Id: OTP-7577</p> + </item> + <item> + <p> + A bug in the hostent copying code of erl_interface on + MacOS X/Darwin is now corrected.</p> + <p> + Own Id: OTP-7593</p> + </item> + <item> + <p>A problem with building <c>erl_interface</c> on + FreeBSD has been fixed (Thanks to Akira Kitada).</p> + <p> + Own Id: OTP-7611</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.5.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug in erl_interface when decoding broken data</p> + <p> + Own Id: OTP-7448</p> + </item> + </list> + </section> + +</section> + + +<section><title>Erl_Interface 3.5.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + An erroneous freeing of memory could occur when using + <c>ei_x_format_wo_ver</c> in erl_interface, resulting in + a segmentation fault.</p> + <p> + Own Id: OTP-6795</p> + </item> + <item> + <p> + A faulty compare in <c>erl_marshal</c> has now been + fixed. (Thanks to Simon Cornish and Paul Mineiro)</p> + <p> + Own Id: OTP-7368</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.5.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Minor documentation fixes.</p> + <p> + Own Id: OTP-7183 Aux Id: OTP-7118 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.5.5.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The symbol __erl_errno was undefined in the single thread + version of the ei library, but is now defined.</p> + <p> + Own Id: OTP-6887</p> + </item> + <item> + <p> + Corrected FreeBSD build error.</p> + <p> + Own Id: OTP-7093</p> + </item> + </list> + </section> + +</section> + + <section> + <title>Erl_Interface 3.5.5.3</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Calls to alloca in erl_marshal.c have been removed. A + static buffer is now used instead to store node names + temporarily.</p> + <p>Own Id: OTP-6331 Aux Id: seq10468 </p> + </item> + <item> + <p>ei_print_term interprets a list of integers with values + from 0 to 255 as a string. If the original list contains + the integer 0, this is considered terminator of the + string. This is incorrect. The function has now been + modified to not look for '\\0' in a string, but always + print all characters.</p> + <p>Own Id: OTP-6339 Aux Id: seq10492 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.5.5.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The combination of xeon processors with 64bit x86 + extensions and a 32bit linux could cause ei_decode_long + and ei_decode_longlong to fail for the value LONG_MIN and + LONGLONG_MIN. The conversion is now made more portable.</p> + <p>Own Id: OTP-6216</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.5.5.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Portability enhancements.</p> + <p>Own Id: OTP-6132</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.5.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Different (and old) <c><![CDATA[config.guess]]></c> files in the + <c><![CDATA[erts]]></c> and <c><![CDATA[erl_interface]]></c> applications would + cause build problems on the new Intel-based iMacs. + (Thanks to Sebastion Strollo.)</p> + <p>Own Id: OTP-5967</p> + </item> + <item> + <p>pthread header and library mismatch on linux systems (at + least some SuSE and Debian) with both NPTL and + Linuxthreads libraries installed.</p> + <p>Own Id: OTP-5981</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Support for a C node to connect to an Erlang node on a + standalone host has been added.</p> + <p>Own Id: OTP-5883 Aux Id: seq10170 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.5.2</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>A configuration test error caused erl_interface to be + built without support for threads. This has been + corrected.</p> + <p>Own Id: OTP-5456</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.5.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Changes and improvements have been made to the build and + test environment to solve problems with failing + erl_interface test cases.</p> + <p>Own Id: OTP-5295 Aux Id: OTP-5387 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.5</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Process identifiers and port identifiers have been + made more unique. Previously 18 bits were used as id in + the internal representation of process and port + identifiers. Now 28 bits are used. </p> + <p>The maximum + limit on the number of concurrently existing processes + due to the representation of pids has been increased to + 268435456 processes. The same is true for ports. This + limit will at least on a 32-bit architecture be + impossible to reach due to memory shortage. </p> + <p><em>NOTE:</em> By default, the <c><![CDATA[ERTS]]></c>, and the + <c><![CDATA[erl_interface]]></c>, <c><![CDATA[ei]]></c>, and <c><![CDATA[jinterface]]></c> + libraries are now only guaranteed to be compatible with + other Erlang/OTP components from the same release. It is + possible to set each component in compatibility mode of + an earlier release, though. See the documentation for + respective component on how to set it in compatibility + mode. </p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-4968 Aux Id: OTP-4196 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.4.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Corrections for mistakes done for patch erl_605/OTP-4874.</p> + <p>Own Id: OTP-4995 Aux Id: OTP-4874 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.4.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>A small optimization in ei_rpc*() was added and a bug in + ei_decode_longlong() was corrected.</p> + <p>Own Id: OTP-4784</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.4.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Strings longer than 65535 bytes were encoded wrong in + ei/erl_interface.</p> + <p>Own Id: OTP-4865 Aux Id: EABln07451 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_interface 3.4.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>erl_call -a parsed erlang terms incorrectly due to a bug + in ei_format, which is now corrected.</p> + <p>Own Id: OTP-4777 Aux Id: seq8099 </p> + </item> + </list> + </section> + </section> +</chapter> + diff --git a/lib/erl_interface/doc/src/notes_history.xml b/lib/erl_interface/doc/src/notes_history.xml new file mode 100644 index 0000000000..f484f3c04e --- /dev/null +++ b/lib/erl_interface/doc/src/notes_history.xml @@ -0,0 +1,367 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2006</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erl_Interface Release Notes History</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + + <section> + <title>Erl_Interface 3.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[erl_print_term()]]></c> and <c><![CDATA[erl_copy_term()]]></c> could not + previously handle uints. This bug has now been fixed.</p> + <p>Own Id: OTP-4061 Aux Id: seq7079</p> + </item> + <item> + <p><c><![CDATA[ei_x_format()]]></c> was not working correctly for floating + point arguments on some platforms. This is now corrected.</p> + <p>Own Id: OTP-4379</p> + </item> + <item> + <p><c><![CDATA[erl_compare_ext()]]></c> did not compare the node parts of + pids, ports, and references. This has now been fixed. + Comparison between two pids, ports, or references does now + conform to the Erlang specification.</p> + <p>Own Id: OTP-4512 Aux Id: OTP-4511</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Erl_Interface and EI now supports 64 bit architectures.</p> + <p>Own Id: OTP-4772</p> + </item> + <item> + <p>There are new functions that support the GCC and Visual + C++ 64 bit extended integer types.</p> + <code type="none"><![CDATA[ +int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p); +int ei_decode_ulonglong(const char *buf, int *index, EI_ULONGLONG *p); +int ei_encode_longlong(char *buf, int *index, EI_LONGLONG p); +int ei_encode_ulonglong(char *buf, int *index, EI_ULONGLONG p); +int ei_x_encode_longlong(ei_x_buff* x, EI_LONGLONG n); +int ei_x_encode_ulonglong(ei_x_buff* x, EI_ULONGLONG n); + ]]></code> + <p>Own Id: OTP-4772</p> + </item> + <item> + <p>If you compile the library from source you can use the ei + library together with GMP, the GNU multi precision + library, to convert integers larger than 64 bits from and + to the external format.</p> + <code type="none"><![CDATA[ +int ei_decode_bignum(const char *buf, int *index, mpz_t obj); +int ei_encode_bignum(char *buf, int *index, mpz_t obj); +int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj); + ]]></code> + <p>Own Id: OTP-4772</p> + </item> + <item> + <p>Some general code improvements where done like correcting + buffer sizes, added more error checking etc.</p> + <p>Own Id: OTP-4772</p> + </item> + <item> + <p>In order to conform to the Erlang specification, + comparison between two pids was changed in the R9B + release. This change did however break a deadlock + prevention algorithm used by Mnesia during release + upgrade. Therefore, comparison between two pids has been + changed back so that R9B nodes are compatible with Erlang + nodes running pre-R9 releases.</p> + <p>Pre-R9 comparison between two pids which now is used + again: If t1 and t2 are both pids, t1 will precede t2 if + and only if either</p> + <list type="bulleted"> + <item>the node local id of t1 precedes the node local id + of t2, or</item> + <item>the node local ids of t1 and t2 are equal, and + node(t1) precedes node(t2), or</item> + <item>the node local ids of t1 and t2 are equal, and also + node(t1) and node(t2) are equal, and node(t1) was + created before node(t2).</item> + </list> + <p>The node local id consist of two integers; serial which + is most significant, and number.</p> + <p>The Erlang specification states: If t1 and t2 are both + refs, both PIDs, or both ports, then t1 precedes t2 if + and only if either</p> + <list type="bulleted"> + <item>node(t1) precedes node(t2), or</item> + <item>node(t1) equals node(t2) and t1 was created before + t2.</item> + </list> + <p>Note that comparisons between two refs, or two ports will + still conform to the Erlang specification.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-4715 Aux Id: OTP-4511, OTP-4512</p> + </item> + </list> + </section> + </section> + + <section> + <title>ErlInterface 3.3</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Erl_Interface has been rewritten extensively. The library + <c><![CDATA[ei]]></c> is now documented and supported. The old + <c><![CDATA[erl_interface]]></c> is considered obsolete, and provided + only for backward compatibility.</p> + </item> + <item> + <p>Erl_Interface is now thread-safe, and multiple C-nodes may + run from the same process.</p> + </item> + <item> + <p>New functions are added for connecting and accepting + connections from <c><![CDATA[ei]]></c>; these are documented in + <c><![CDATA[ei_connect]]></c>.</p> + </item> + <item> + <p>New functions are added for converting to and from Erlang + binary format; these are documented in <c><![CDATA[ei]]></c>.</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.2.9</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Changed back the return values from <c><![CDATA[erl_send()]]></c> and + <c><![CDATA[erl_reg_send()]]></c> to 1 (as they used to be). + Incompatible with plain R7, compatible with previous + versions.</p> + <p>*** INCOMPATIBILITY with R7B ***</p> + <p>Own Id: OTP-3772</p> + </item> + <item> + <p>A race-condition bug in the term allocation routines was + corrected.</p> + <p>Own Id: OTP-3809</p> + </item> + <item> + <p>Erl_Interface could not be linked with pthreads.</p> + <p>Own Id: OTP-3810 Aux Id: Seq 5032</p> + </item> + <item> + <p>The TCB of VxWorks processes no longer grows when + <c><![CDATA[erl_errno]]></c> is accessed. On Pthreads platforms + the use of <c><![CDATA[erl_errno]]></c> no longer crashes programs + using multithreading.</p> + <p>Own Id: OTP-3820</p> + </item> + <item> + <p>Name clashes between Erlang emulator and Erl_Interface + on VxWorks removed.</p> + <p>Own Id: OTP-3824</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.2.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Memory lossage affecting pids, ports and refs fixed.</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.2.2</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>An error reporting facility <c><![CDATA[erl_errno]]></c> has been + introduced.</p> + <p>Own Id: OTP-3641</p> + </item> + <item> + <p>ETERMs are now shrunk to a more reasonable size.</p> + <p>Own Id: OTP-3648</p> + <p></p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.2.1</title> + + <section> + <title>Fixed Errors and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Lists containing negative numbers were incorrectly + encoded by <c><![CDATA[erl_encode()]]></c>. This has been corrected.</p> + <p>Own Id: OTP-3535</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.2</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The reference type has been extended from 18 bits to + 82 bits. For compatibility with older nodes, an R6 node + can send a ref to an older node; if the older node sends + it back, it has lost all but its 18 least significant + bits, but still compares equal to the original ref. + The external format has been extended to represent the new + longer refs; that means for example that binaries with + refs, produced on an R6 node, cannot be converted to a + term on an older node. + In <c><![CDATA[erl_interface]]></c>, a function <c><![CDATA[erl_mk_long_ref]]></c> + has been added, and macros <c><![CDATA[ERL_REF_NUMBERS]]></c> and + <c><![CDATA[ERL_REF_LEN]]></c>.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-3140 Aux Id: OTP-3139</p> + </item> + <item> + <p>The function <c><![CDATA[erl_receive_msg]]></c> has the problem that + a fixed buffer must be given - a larger message than + expected is simply discarded. A function + <c><![CDATA[erl_xreceive_msg]]></c> has been introduced, which + dynamically resizes the buffer given to it, if needed.</p> + <p>Own Id: OTP-3313 Aux Id: OTP-2927</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.1.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[#ifdef __cplusplus extern C {]]></c> is added to all the + <c><![CDATA[erl*.h]]></c> and <c><![CDATA[ei*.h]]></c> files in order to support + use from C++.</p> + <p>On Unix the object files are now produced with + the <c><![CDATA[-fPIC]]></c> option to make it possible to include + them in a shared library.</p> + <p>Own Id: OTP-3138 Aux Id: Seq 1722</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erl_Interface 3.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>A buffer overflow in <c><![CDATA[erl_connect()]]></c> was causing + C-node crashes on Linux.</p> + <p>Own Id: OTP-2743</p> + </item> + <item> + <p>When decoding very long strings (more than 65535 + characters) the terminating 0 was left out.</p> + <p>Own Id: OTP-2744</p> + </item> + <item> + <p><c><![CDATA[erl_accept()]]></c> was not handshaking properly with + Erlang, causing incoming connection attempts to fail.</p> + <p>Own Id: OTP-2862</p> + </item> + <item> + <p>Very large negative numbers are no longer encoded + incorrectly.</p> + <p>Own Id: OTP-2897</p> + </item> + <item> + <p>Atoms could sometimes contain an unterminated string. + This is fixed.</p> + <p>Own Id: OTP-2956</p> + </item> + <item> + <p>Erl_Interface now uses the SENS resolver functions if + they are available at runtime. This primarily concerns + use on the VxWorks platform.</p> + <p>Own Id: OTP-3034 Aux Id: Seq 1559</p> + </item> + <item> + <p>The documentation for <c><![CDATA[erl_connect_init()]]></c> no longer + makes erroneous reference to the remote node.</p> + <p>Own Id: OTP-3102 Aux Id: Seq 1671</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Erl_Interface has been moved out of the Erlang runtime + system (ERTS) and is now a separate application. This has + implications for all users of Erl_Interface, who will + need to make changes to the Makefiles used to build + applications based on Erl_Interface. In particular, + header and library files are no longer in + <c><![CDATA[$(OTPROOT)/usr/]]></c>. The <c><![CDATA[include]]></c> and <c><![CDATA[lib]]></c> + directories are now located in the directory + <c><![CDATA[$(OTPROOT)/lib/erl_interface-3.1]]></c> (i.e. + the directory name is now version specific).</p> + <p>Own Id: OTP-3082</p> + </item> + </list> + </section> + </section> +</chapter> + diff --git a/lib/erl_interface/doc/src/part.xml b/lib/erl_interface/doc/src/part.xml new file mode 100644 index 0000000000..e38b9164b8 --- /dev/null +++ b/lib/erl_interface/doc/src/part.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>EI User's Guide</title> + <prepared>Gordon Beaton</prepared> + <docno></docno> + <date>1998-11-30</date> + <rev>1.2</rev> + <file>part.xml</file> + </header> + <xi:include href="ei_users_guide.xml"/> +</part> + diff --git a/lib/erl_interface/doc/src/part_erl_interface.xml b/lib/erl_interface/doc/src/part_erl_interface.xml new file mode 100644 index 0000000000..c69cc85c63 --- /dev/null +++ b/lib/erl_interface/doc/src/part_erl_interface.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erl_Interface User's Guide</title> + <prepared>Gordon Beaton</prepared> + <docno></docno> + <date>1998-11-30</date> + <rev>1.2</rev> + <file>part_erl_interface.sgml</file> + </header> + <xi:include href="erl_interface.xml"/> +</part> + diff --git a/lib/erl_interface/doc/src/part_notes.xml b/lib/erl_interface/doc/src/part_notes.xml new file mode 100644 index 0000000000..14c1de1d6e --- /dev/null +++ b/lib/erl_interface/doc/src/part_notes.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2004</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erl_Interface Release Notes</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <description> + <p><em>Erl_Interface</em> is a C interface library for communication + with Erlang.</p> + <p>For information about older versions, see + <url href="part_notes_history_frame.html">Release Notes History</url>.</p> + </description> + <xi:include href="notes.xml"/> +</part> + diff --git a/lib/erl_interface/doc/src/part_notes_history.xml b/lib/erl_interface/doc/src/part_notes_history.xml new file mode 100644 index 0000000000..612b4a9e1e --- /dev/null +++ b/lib/erl_interface/doc/src/part_notes_history.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2006</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erl_Interface Release Notes History</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <description> + <p><em>Erl_Interface</em> is a C interface library for communication + with Erlang.</p> + </description> + <xi:include href="notes_history.xml"/> +</part> + diff --git a/lib/erl_interface/doc/src/ref_man.xml b/lib/erl_interface/doc/src/ref_man.xml new file mode 100644 index 0000000000..9ae4cf27f5 --- /dev/null +++ b/lib/erl_interface/doc/src/ref_man.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE application SYSTEM "application.dtd"> + +<application xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1998</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + <title>Erl_Interface Command Reference</title> + <prepared>Gordon Beaton</prepared> + <docno></docno> + <date>1998-11.30</date> + <rev>1.2</rev> + <file>ref_man.xml</file> + </header> + <description> + <p>The <c>ei</c> and <c>erl_interface</c> are <c>C</c> interface libraries for + communication with <c>Erlang</c>.</p> + <note> + <p>By default, the <c>ei</c> and <c>erl_interface</c> libraries are only guaranteed + to be compatible with other Erlang/OTP components from the same + release as the libraries themself. See the documentation of the + <seealso marker="ei#ei_set_compat_rel">ei_set_compat_rel()</seealso> and + <seealso marker="erl_eterm#erl_set_compat_rel">erl_set_compat_rel()</seealso> + functions on how to communicate with Erlang/OTP components from earlier + releases.</p> + </note> + </description> + <xi:include href="ei.xml"/> + <xi:include href="ei_connect.xml"/> + <xi:include href="registry.xml"/> + <xi:include href="erl_connect.xml"/> + <xi:include href="erl_error.xml"/> + <xi:include href="erl_eterm.xml"/> + <xi:include href="erl_format.xml"/> + <xi:include href="erl_global.xml"/> + <xi:include href="erl_malloc.xml"/> + <xi:include href="erl_marshal.xml"/> + <xi:include href="erl_call.xml"/> +</application> + diff --git a/lib/erl_interface/doc/src/ref_man_ei.xml b/lib/erl_interface/doc/src/ref_man_ei.xml new file mode 100644 index 0000000000..ff161f9e7f --- /dev/null +++ b/lib/erl_interface/doc/src/ref_man_ei.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE application SYSTEM "application.dtd"> + +<application xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>EI Library Reference</title> + <prepared>Gordon Beaton</prepared> + <docno></docno> + <date>1998-11-30</date> + <rev>1.2</rev> + <file>ref_man_ei.xml</file> + </header> + <description> + <p>The <c><![CDATA[ei]]></c> library is a <c><![CDATA[C]]></c> interface library for + communication with <c><![CDATA[Erlang]]></c>.</p> + <note> + <p>By default, the <c><![CDATA[ei]]></c> library is only guaranteed + to be compatible with other Erlang/OTP components from the same + release as the <c><![CDATA[ei]]></c> library itself. See the documentation of the + <seealso marker="ei#ei_set_compat_rel">ei_set_compat_rel()</seealso> + function on how to communicate with Erlang/OTP components from earlier + releases.</p> + </note> + </description> + <xi:include href="ei.xml"/> + <xi:include href="ei_connect.xml"/> + <xi:include href="registry.xml"/> +</application> + diff --git a/lib/erl_interface/doc/src/ref_man_erl_interface.xml b/lib/erl_interface/doc/src/ref_man_erl_interface.xml new file mode 100644 index 0000000000..7ffa0cfb23 --- /dev/null +++ b/lib/erl_interface/doc/src/ref_man_erl_interface.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE application SYSTEM "application.dtd"> + +<application xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>Erl_Interface Library Reference</title> + <prepared>Gordon Beaton</prepared> + <docno></docno> + <date>1998-11-30</date> + <rev>1.2</rev> + <file>ref_man_erl_interface.xml</file> + </header> + <description> + <p>The <c>erl_interface</c> library is a <c>C</c> interface library + for communication with <c>Erlang</c>.</p> + <note> + <p>By default, the <c>erl_interface</c> library is only guaranteed + to be compatible with other Erlang/OTP components from the same + release as the <c>erl_interface</c> library. See the documentation + of the + <seealso marker="erl_eterm#erl_set_compat_rel">erl_set_compat_rel()</seealso> + function on how to communicate with Erlang/OTP components from earlier + releases.</p> + </note> + </description> + <xi:include href="erl_connect.xml"/> + <xi:include href="erl_error.xml"/> + <xi:include href="erl_eterm.xml"/> + <xi:include href="erl_format.xml"/> + <xi:include href="erl_global.xml"/> + <xi:include href="erl_malloc.xml"/> + <xi:include href="erl_marshal.xml"/> +</application> + diff --git a/lib/erl_interface/doc/src/registry.xml b/lib/erl_interface/doc/src/registry.xml new file mode 100644 index 0000000000..8aeb378d95 --- /dev/null +++ b/lib/erl_interface/doc/src/registry.xml @@ -0,0 +1,611 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1998</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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 online 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. + + </legalnotice> + + <title>registry</title> + <prepared>Gordon Beaton</prepared> + <responsible>Gordon Beaton</responsible> + <docno></docno> + <approved>Gordon Beaton</approved> + <checked>Gordon Beaton</checked> + <date>980707</date> + <rev>A</rev> + <file>registry.sgml</file> + </header> + <lib>registry</lib> + <libsummary>Store and backup key-value pairs</libsummary> + <description> + <p>This module provides support for storing key-value + pairs in a table known as a registry, backing up registries to + Mnesia in an atomic manner, and later restoring the contents of a + registry from Mnesia.</p> + </description> + <funcs> + <func> + <name><ret>ei_reg *</ret><nametext>ei_reg_open(size)</nametext></name> + <fsummary>Create and open a registry</fsummary> + <type> + <v>int size;</v> + </type> + <desc> + <p>Open (create) a registry. The registry will be + initially empty. Use <c><![CDATA[ei_reg_close()]]></c> to close the registry + later. + </p> + <p><c><![CDATA[size]]></c> is the approximate number of objects you intend + to store in the registry. Since the registry uses a hash table + with collision chaining, there is no absolute upper limit on the + number of objects that can be stored in it. However for reasons + of efficiency, it is a good idea to choose a number that is + appropriate for your needs. It is possible to use + <c><![CDATA[ei_reg_resize()]]></c> to change the size later. Note that the + number you provide will be increased to the nearest larger prime + number. + </p> + <p>On success, an empty registry will be returned. On failure, NULL + will be returned.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_resize(reg,newsize)</nametext></name> + <fsummary>Resize a registry</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>int newsize;</v> + </type> + <desc> + <p>Change the size of a registry. + </p> + <p><c><![CDATA[newsize]]></c> is the new size to make the registry. The + number will be increased to the nearest larger prime number. + </p> + <p>On success, the registry will be resized, all contents + rehashed, and the function will return 0. On failure, the + registry will be left unchanged and the function will return -1.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_close(reg)</nametext></name> + <fsummary>Close a registry </fsummary> + <type> + <v>ei_reg *reg;</v> + </type> + <desc> + <p>A registry that has previously been created with + <c><![CDATA[ei_reg_open()]]></c> is closed, and all the objects it contains + are freed. + </p> + <p><c><![CDATA[reg]]></c> is the registry to close. + </p> + <p>The function returns 0.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_setival(reg,key,i)</nametext></name> + <fsummary>Assign an integer object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>int i;</v> + </type> + <desc> + <p>Create a key-value pair with the specified <c><![CDATA[key]]></c> and integer + value <c><![CDATA[i]]></c>. If an object already existed with the same + <c><![CDATA[key]]></c>, the new value replaces the old one. If the previous + value was a binary or string, it is freed with <c><![CDATA[free()]]></c>. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object should be placed. + </p> + <p><c><![CDATA[key]]></c> is the name of the object. + </p> + <p><c><![CDATA[i]]></c> is the integer value to assign. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_setfval(reg,key,f)</nametext></name> + <fsummary>Assign a floating point object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>double f;</v> + </type> + <desc> + <p>Create a key-value pair with the specified <c><![CDATA[key]]></c> and + floating point value <c><![CDATA[f]]></c>. If an object already existed with + the same <c><![CDATA[key]]></c>, the new value replaces the old one. If the + previous value was a binary or string, it is freed with <c><![CDATA[free()]]></c>. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object should be placed. + </p> + <p><c><![CDATA[key]]></c> is the name of the object. + </p> + <p><c><![CDATA[f]]></c> is the floating point value to assign. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_setsval(reg,key,s)</nametext></name> + <fsummary>Assign a string object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>const char *s;</v> + </type> + <desc> + <p>Create a key-value pair with the specified <c><![CDATA[key]]></c> whose + "value" is the specified string <c><![CDATA[s]]></c>. If an object already + existed with the same <c><![CDATA[key]]></c>, the new value replaces the old + one. If the previous value was a binary or string, it is freed + with <c><![CDATA[free()]]></c>. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object should be placed. + </p> + <p><c><![CDATA[key]]></c> is the name of the object. + </p> + <p><c><![CDATA[s]]></c> is the string to assign. The string itself + must have been created through a single call to <c><![CDATA[malloc()]]></c> or + similar function, so that the registry can later delete it if + necessary by calling <c><![CDATA[free()]]></c>. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_setpval(reg,key,p,size)</nametext></name> + <fsummary>Assign a binary object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>const void *p;</v> + <v>int size;</v> + </type> + <desc> + <p>Create a key-value pair with the specified <c><![CDATA[key]]></c> whose + "value" is the binary object pointed to by <c><![CDATA[p]]></c>. If an + object already existed with the same <c><![CDATA[key]]></c>, the new value + replaces the old one. If the previous value was a binary or + string, it is freed with <c><![CDATA[free()]]></c>. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object should be placed. + </p> + <p><c><![CDATA[key]]></c> is the name of the object. + </p> + <p><c><![CDATA[p]]></c> is a pointer to the binary object. The object itself + must have been created through a single call to <c><![CDATA[malloc()]]></c> or + similar function, so that the registry can later delete it if + necessary by calling <c><![CDATA[free()]]></c>. + </p> + <p><c><![CDATA[size]]></c> is the length in bytes of the binary object. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_setval(reg,key,flags,v,...)</nametext></name> + <fsummary>Assign a value to any object type</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>int flags;</v> + <v>v (see below)</v> + </type> + <desc> + <p>Create a key-value pair with the specified <c><![CDATA[key]]></c> whose + value is specified by <c><![CDATA[v]]></c>. If an object already + existed with the same <c><![CDATA[key]]></c>, the new value replaces the old + one. If the previous value was a binary or string, it is freed + with <c><![CDATA[free()]]></c>. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object should be placed. + </p> + <p><c><![CDATA[key]]></c> is the name of the object. + </p> + <p><c><![CDATA[flags]]></c> indicates the type of the object specified by + <c><![CDATA[v]]></c>. Flags must be one of EI_INT, EI_FLT, EI_STR and + EI_BIN, indicating whether <c><![CDATA[v]]></c> is <c><![CDATA[int]]></c>, <c><![CDATA[double]]></c>, + <c><![CDATA[char*]]></c> or <c><![CDATA[void*]]></c>. If <c><![CDATA[flags]]></c> is EI_BIN, then a + fifth argument <c><![CDATA[size]]></c> is required, indicating the size + in bytes of the object pointed to by <c><![CDATA[v]]></c>. + </p> + <p>If you wish to store an arbitrary pointer in the registry, + specify a <c><![CDATA[size]]></c> of 0. In this case, the object itself will + not be transferred by an <c><![CDATA[ei_reg_dump()]]></c> operation, just + the pointer value. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_getival(reg,key)</nametext></name> + <fsummary>Get an integer object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + </type> + <desc> + <p>Get the value associated with <c><![CDATA[key]]></c> in the + registry. The value must be an integer. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object will be looked + up. + </p> + <p><c><![CDATA[key]]></c> is the name of the object to look up. + </p> + <p>On success, the function returns the value associated with <c><![CDATA[key]]></c>. + If the object was not found or it was not an integer + object, -1 is returned. To avoid problems with in-band error + reporting (i.e. if you cannot distinguish between -1 and a + valid result) use the more general function <c><![CDATA[ei_reg_getval()]]></c> + instead.</p> + </desc> + </func> + <func> + <name><ret>double</ret><nametext>ei_reg_getfval(reg,key)</nametext></name> + <fsummary>Get a floating point object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + </type> + <desc> + <p>Get the value associated with <c><![CDATA[key]]></c> in the + registry. The value must be a floating point type. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object will be looked + up. + </p> + <p><c><![CDATA[key]]></c> is the name of the object to look up. + </p> + <p>On success, the function returns the value associated with <c><![CDATA[key]]></c>. + If the object was not found or it was not a floating point + object, -1.0 is returned. To avoid problems with in-band error + reporting (i.e. if you cannot distinguish between -1.0 and a + valid result) use the more general function <c><![CDATA[ei_reg_getval()]]></c> + instead.</p> + </desc> + </func> + <func> + <name><ret>const char *</ret><nametext>ei_reg_getsval(reg,key)</nametext></name> + <fsummary>Get a string object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + </type> + <desc> + <p>Get the value associated with <c><![CDATA[key]]></c> in the + registry. The value must be a string. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object will be looked + up. + </p> + <p><c><![CDATA[key]]></c> is the name of the object to look up. + </p> + <p>On success, the function returns the value associated with + <c><![CDATA[key]]></c>. If the object was not found or it was not a string, + NULL is returned. To avoid problems with in-band error + reporting (i.e. if you cannot distinguish between NULL and a + valid result) use the more general function <c><![CDATA[ei_reg_getval()]]></c> + instead.</p> + </desc> + </func> + <func> + <name><ret>const void *</ret><nametext>ei_reg_getpval(reg,key,size)</nametext></name> + <fsummary>Get a binary object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>int size;</v> + </type> + <desc> + <p>Get the value associated with <c><![CDATA[key]]></c> in the + registry. The value must be a binary (pointer) type. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object will be looked + up. + </p> + <p><c><![CDATA[key]]></c> is the name of the object to look up. + </p> + <p><c><![CDATA[size]]></c> will be initialized to contain the length in + bytes of the object, if it is found. + </p> + <p>On success, the function returns the value associated with + <c><![CDATA[key]]></c> and indicates its length in <c><![CDATA[size]]></c>. + If the object was not found or it was not a binary object, + NULL is returned. To avoid problems with in-band error + reporting (i.e. if you cannot distinguish between NULL and a + valid result) use the more general function <c><![CDATA[ei_reg_getval()]]></c> + instead.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_getval(reg,key,flags,v,...)</nametext></name> + <fsummary>Get any object</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>int flags;</v> + <v>void *v (see below)</v> + </type> + <desc> + <p>This is a general function for retrieving any kind of + object from the registry. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the object will be looked + up. + </p> + <p><c><![CDATA[key]]></c> is the name of the object to look up. + </p> + <p><c><![CDATA[flags]]></c> indicates the type of object that you are + looking for. If <c><![CDATA[flags]]></c> is 0, then any kind of object will + be returned. If <c><![CDATA[flags]]></c> is one of EI_INT, EI_FLT, EI_STR or + EI_BIN, then only values of that kind will be returned. The + buffer pointed to by <c><![CDATA[v]]></c> must be large enough to hold the return + data, i.e. it must be a pointer to one of <c><![CDATA[int]]></c>, + <c><![CDATA[double]]></c>, <c><![CDATA[char*]]></c> or <c><![CDATA[void*]]></c>, respectively. Also, + if <c><![CDATA[flags]]></c> is EI_BIN, then a fifth argument <c><![CDATA[int *size]]></c> is required, so that the size of the object can be + returned. + </p> + <p>If the function succeeds, <c><![CDATA[v]]></c> (and <c><![CDATA[size]]></c> if the + object is binary) will be initialized with the value associated + with <c><![CDATA[key]]></c>, and the function will return one of EI_INT, + EI_FLT, EI_STR or EI_BIN, indicating the type of object. On failure the + function will return -1 and the arguments will not be updated.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_markdirty(reg,key)</nametext></name> + <fsummary>Mark an object as dirty </fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + </type> + <desc> + <p>Mark a registry object as dirty. This will ensure that + it is included in the next backup to Mnesia. Normally this + operation will not be necessary since all of the normal registry + 'set' functions do this automatically. However if you have + retrieved the value of a string or binary object from the + registry and modified the contents, then the change will be + invisible to the registry and the object will be assumed to be + unmodified. This function allows you to make such modifications + and then let the registry know about them. + </p> + <p><c><![CDATA[reg]]></c> is the registry containing the object. + </p> + <p><c><![CDATA[key]]></c> is the name of the object to mark. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_delete(reg,key)</nametext></name> + <fsummary>Delete an object from the registry</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + </type> + <desc> + <p>Delete an object from the registry. The object is not + actually removed from the registry, it is only marked for later + removal so that on subsequent backups to Mnesia, the + corresponding object can be removed from the Mnesia table as + well. If another object is later created with the same key, the + object will be reused. + </p> + <p>The object will be removed from the registry after a call to + <c><![CDATA[ei_reg_dump()]]></c> or <c><![CDATA[ei_reg_purge()]]></c>. + </p> + <p><c><![CDATA[reg]]></c> is the registry containing <c><![CDATA[key]]></c>. + </p> + <p><c><![CDATA[key]]></c> is the object to remove. + </p> + <p>If the object was found, the function returns 0 indicating + success. Otherwise the function returns -1.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_stat(reg,key,obuf)</nametext></name> + <fsummary>Get object information</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>const char *key;</v> + <v>struct ei_reg_stat *obuf;</v> + </type> + <desc> + <p>Return information about an object. + </p> + <p><c><![CDATA[reg]]></c> is the registry containing the object. + </p> + <p><c><![CDATA[key]]></c> is the name of the object. + </p> + <p><c><![CDATA[obuf]]></c> is a pointer to an <c><![CDATA[ei_reg_stat]]></c> structure, + defined below: + </p> + <code type="none"><![CDATA[ +struct ei_reg_stat { + int attr; + int size; +}; + ]]></code> + <p>In <c><![CDATA[attr]]></c> the object's attributes are stored as the logical + OR of its type (one of EI_INT, EI_FLT, EI_BIN and EI_STR), + whether it is marked for deletion (EI_DELET) and whether it has + been modified since the last backup to Mnesia (EI_DIRTY). + </p> + <p>The <c><![CDATA[size]]></c> field indicates the size in bytes required to store + EI_STR (including the terminating 0) and EI_BIN objects, or 0 + for EI_INT and EI_FLT. + </p> + <p>The function returns 0 and initializes <c><![CDATA[obuf]]></c> on + success, or returns -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_tabstat(reg,obuf)</nametext></name> + <fsummary>Get registry information</fsummary> + <type> + <v>ei_reg *reg;</v> + <v>struct ei_reg_tabstat *obuf;</v> + </type> + <desc> + <p>Return information about a registry. Using information + returned by this function, you can see whether the size of the + registry is suitable for the amount of data it contains. + </p> + <p><c><![CDATA[reg]]></c> is the registry to return information about. + </p> + <p><c><![CDATA[obuf]]></c> is a pointer to an <c><![CDATA[ei_reg_tabstat]]></c> structure, + defined below: + </p> + <code type="none"><![CDATA[ +struct ei_reg_tabstat { + int size; + int nelem; + int npos; + int collisions; +}; + ]]></code> + <p>The <c><![CDATA[size]]></c> field indicates the number of hash positions + in the registry. This is the number you provided when you + created or last resized the registry, rounded up to the nearest + prime. + </p> + <p><c><![CDATA[nelem]]></c> indicates the number of elements stored in the + registry. It includes objects that are deleted but not purged. + </p> + <p><c><![CDATA[npos]]></c> indicates the number of unique positions that are + occupied in the registry. + </p> + <p><c><![CDATA[collisions]]></c> indicates how many elements are sharing + positions in the registry. + </p> + <p>On success, the function returns 0 and <c><![CDATA[obuf]]></c> is + initialized to contain table statistics. On failure, the function + returns -1.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_dump(fd,reg,mntab,flags)</nametext></name> + <fsummary>Back up a registry to Mnesia</fsummary> + <type> + <v>int fd;</v> + <v>ei_reg *reg;</v> + <v>const char *mntab;</v> + <v>int flags;</v> + </type> + <desc> + <p>Dump the contents of a registry to a Mnesia table in an + atomic manner, i.e. either all data will be updated, or none of + it will. If any errors are encountered while backing up + the data, the entire operation is aborted. + </p> + <p><c><![CDATA[fd]]></c> is an open connection to Erlang. + Mnesia 3.0 or later must be running on the Erlang node. + </p> + <p><c><![CDATA[reg]]></c> is the registry to back up. + </p> + <p><c><![CDATA[mntab]]></c> is the name of the Mnesia table where the backed + up data should be placed. If the table does not exist, it will + be created automatically using configurable defaults. See your + Mnesia documentation for information about configuring this + behaviour. + </p> + <p>If <c><![CDATA[flags]]></c> is 0, the backup will include only those + objects which have been created, modified or deleted since the + last backup or restore (i.e. an incremental backup). After the + backup, any objects that were marked dirty are now clean, and any + objects that had been marked for deletion are deleted. + </p> + <p>Alternatively, setting flags to EI_FORCE will cause a full + backup to be done, and EI_NOPURGE will cause the deleted objects + to be left in the registry afterwards. These can be bitwise ORed + together if both behaviours are desired. If EI_NOPURGE was + specified, you can use <c><![CDATA[ei_reg_purge()]]></c> to explicitly remove + the deleted items from the registry later. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_restore(fd,reg,mntab)</nametext></name> + <fsummary>Restore a registry from Mnesia</fsummary> + <type> + <v>int fd;</v> + <v>ei_reg *reg;</v> + <v>const char *mntab;</v> + </type> + <desc> + <p>The contents of a Mnesia table are read into the + registry. + </p> + <p><c><![CDATA[fd]]></c> is an open connection to Erlang. + Mnesia 3.0 or later must be running on the Erlang node. + </p> + <p><c><![CDATA[reg]]></c> is the registry where the data should be placed. + </p> + <p><c><![CDATA[mntab]]></c> is the name of the Mnesia table to read data + from. + </p> + <p>Note that only tables of a certain format can be + restored, i.e. those that have been created and backed up to + with <c><![CDATA[ei_reg_dump()]]></c>. If the registry was not empty before + the operation, then the contents of the table are added to the + contents of the registry. If the table contains objects with the + same keys as those already in the registry, the registry objects + will be overwritten with the new values. If the registry + contains objects that were not in the table, they will be + unchanged by this operation. + </p> + <p>After the restore operation, the entire contents of the + registry is marked as unmodified. Note that this includes any + objects that were modified before the restore and not + overwritten by the restore. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>ei_reg_purge(reg)</nametext></name> + <fsummary>Remove deleted objects</fsummary> + <type> + <v>ei_reg *reg;</v> + </type> + <desc> + <p>Remove all objects marked for deletion. When objects + are deleted with <c><![CDATA[ei_reg_delete()]]></c> they are not actually + removed from the registry, only marked for later removal. This + is so that on a subsequent backup to Mnesia, the + objects can also be removed from the Mnesia table. If you are + not backing up to Mnesia then you may wish to remove the objects + manually with this function. + </p> + <p><c><![CDATA[reg]]></c> is a registry containing objects marked for + deletion. + </p> + <p>The function returns 0 on success, or -1 on failure.</p> + </desc> + </func> + </funcs> +</cref> + diff --git a/lib/erl_interface/doc/src/warning.gif b/lib/erl_interface/doc/src/warning.gif Binary files differnew file mode 100644 index 0000000000..96af52360e --- /dev/null +++ b/lib/erl_interface/doc/src/warning.gif |