diff options
Diffstat (limited to 'lib/kernel')
63 files changed, 3749 insertions, 3150 deletions
diff --git a/lib/kernel/doc/specs/.gitignore b/lib/kernel/doc/specs/.gitignore new file mode 100644 index 0000000000..322eebcb06 --- /dev/null +++ b/lib/kernel/doc/specs/.gitignore @@ -0,0 +1 @@ +specs_*.xml diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile index f8c1cac8b3..de10e31d36 100644 --- a/lib/kernel/doc/src/Makefile +++ b/lib/kernel/doc/src/Makefile @@ -1,19 +1,20 @@ -# ``The contents of this file are subject to the Erlang Public License, +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2011. 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 via the world wide web at http://www.erlang.org/. -# +# 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. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ +# +# %CopyrightEnd% # include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk @@ -94,19 +95,24 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf +SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml) + +TOP_SPECS_FILE = specs.xml # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- XML_FLAGS += +SPECS_FLAGS = -I../../include + # ---------------------------------------------------- # Targets # ---------------------------------------------------- $(HTMLDIR)/%.gif: %.gif $(INSTALL_DATA) $< $@ -docs: pdf html man +docs: man pdf html $(TOP_PDF_FILE): $(XML_FILES) @@ -125,8 +131,22 @@ clean clean_docs: rm -f $(MAN4DIR)/* rm -f $(MAN6DIR)/* rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f $(SPECDIR)/* rm -f errs core *~ +$(SPECDIR)/specs_erl_prim_loader_stub.xml: + escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ + -o$(dir $@) -module erl_prim_loader_stub +$(SPECDIR)/specs_erlang_stub.xml: + escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ + -o$(dir $@) -module erlang_stub +$(SPECDIR)/specs_init_stub.xml: + escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ + -o$(dir $@) -module init_stub +$(SPECDIR)/specs_zlib_stub.xml: + escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ + -o$(dir $@) -module zlib_stub + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml index 47d578a339..51a3311ec2 100644 --- a/lib/kernel/doc/src/application.xml +++ b/lib/kernel/doc/src/application.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -50,20 +50,27 @@ <p>Refer to <seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso> for more information about applications and behaviours.</p> </description> + <datatypes> + <datatype> + <name name="start_type"/> + </datatype> + <datatype> + <name name="restart_type"/> + </datatype> + <datatype> + <!-- Parameterized opaque types are NYI: --> + <name><marker id="type-tuple_of">tuple_of(T)</marker></name> + <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>get_all_env() -> Env</name> - <name>get_all_env(Application) -> Env</name> + <name name="get_all_env" arity="0"/> + <name name="get_all_env" arity="1"/> <fsummary>Get the configuration parameters for an application</fsummary> - <type> - <v>Application = atom()</v> - <v>Env = [{Par,Val}]</v> - <v> Par = atom()</v> - <v> Val = term()</v> - </type> <desc> <p>Returns the configuration parameters and their values for - <c>Application</c>. If the argument is omitted, it defaults to + <c><anno>Application</anno></c>. If the argument is omitted, it defaults to the application of the calling process.</p> <p>If the specified application is not loaded, or if the process executing the call does not belong to any application, @@ -71,18 +78,12 @@ </desc> </func> <func> - <name>get_all_key() -> {ok, Keys} | []</name> - <name>get_all_key(Application) -> {ok, Keys} | undefined </name> + <name name="get_all_key" arity="0"/> + <name name="get_all_key" arity="1"/> <fsummary>Get the application specification keys</fsummary> - <type> - <v>Application = atom()</v> - <v>Keys = [{Key,Val}]</v> - <v> Key = atom()</v> - <v> Val = term()</v> - </type> <desc> <p>Returns the application specification keys and their values - for <c>Application</c>. If the argument is omitted, it + for <c><anno>Application</anno></c>. If the argument is omitted, it defaults to the application of the calling process.</p> <p>If the specified application is not loaded, the function returns <c>undefined</c>. If the process executing the call @@ -91,17 +92,12 @@ </desc> </func> <func> - <name>get_application() -> {ok, Application} | undefined</name> - <name>get_application(Pid | Module) -> {ok, Application} | undefined</name> + <name name="get_application" arity="0"/> + <name name="get_application" arity="1"/> <fsummary>Get the name of an application containing a certain process or module</fsummary> - <type> - <v>Pid = pid()</v> - <v>Module = atom()</v> - <v>Application = atom()</v> - </type> <desc> <p>Returns the name of the application to which the process - <c>Pid</c> or the module <c>Module</c> belongs. Providing no + <c><anno>Pid</anno></c> or the module <c><anno>Module</anno></c> belongs. Providing no argument is the same as calling <c>get_application(self())</c>.</p> <p>If the specified process does not belong to any application, @@ -110,17 +106,12 @@ </desc> </func> <func> - <name>get_env(Par) -> {ok, Val} | undefined</name> - <name>get_env(Application, Par) -> {ok, Val} | undefined</name> + <name name="get_env" arity="1"/> + <name name="get_env" arity="2"/> <fsummary>Get the value of a configuration parameter</fsummary> - <type> - <v>Application = atom()</v> - <v>Par = atom()</v> - <v>Val = term()</v> - </type> <desc> - <p>Returns the value of the configuration parameter <c>Par</c> - for <c>Application</c>. If the application argument is + <p>Returns the value of the configuration parameter <c><anno>Par</anno></c> + for <c><anno>Application</anno></c>. If the application argument is omitted, it defaults to the application of the calling process.</p> <p>If the specified application is not loaded, or @@ -130,17 +121,12 @@ </desc> </func> <func> - <name>get_key(Key) -> {ok, Val} | undefined</name> - <name>get_key(Application, Key) -> {ok, Val} | undefined</name> + <name name="get_key" arity="1"/> + <name name="get_key" arity="2"/> <fsummary>Get the value of an application specification key</fsummary> - <type> - <v>Application = atom()</v> - <v>Key = atom()</v> - <v>Val = term()</v> - </type> <desc> <p>Returns the value of the application specification key - <c>Key</c> for <c>Application</c>. If the application + <c><anno>Key</anno></c> for <c><anno>Application</anno></c>. If the application argument is omitted, it defaults to the application of the calling process.</p> <p>If the specified application is not loaded, or @@ -150,45 +136,35 @@ </desc> </func> <func> - <name>load(AppDescr) -> ok | {error, Reason}</name> - <name>load(AppDescr, Distributed) -> ok | {error, Reason}</name> + <name name="load" arity="1"/> + <name name="load" arity="2"/> <fsummary>Load an application</fsummary> - <type> - <v>AppDescr = Application | AppSpec</v> - <v> Application = atom()</v> - <v> AppSpec = {application,Application,AppSpecKeys}</v> - <v> AppSpec = [{Key,Val}]</v> - <v> Key = atom()</v> - <v> Val = term()</v> - <v>Distributed = {Application,Nodes} | {Application,Time,Nodes} | default</v> - <v> Nodes = [node() | {node(),..,node()}]</v> - <v> Time = integer() > 0</v> - <v>Reason = term()</v> - </type> + <type name="application_spec"/> + <type name="application_opt"/> <desc> <p>Loads the application specification for an application into the application controller. It will also load the application specifications for any included applications. Note that the function does not load the actual Erlang object code.</p> - <p>The application can be given by its name <c>Application</c>. + <p>The application can be given by its name <c><anno>Application</anno></c>. In this case the application controller will search the code - path for the application resource file <c>Application.app</c> + path for the application resource file <c><anno>Application</anno>.app</c> and load the specification it contains.</p> <p>The application specification can also be given directly as a - tuple <c>AppSpec</c>. This tuple should have the format and + tuple <c><anno>AppSpec</anno></c>. This tuple should have the format and contents as described in <c>app(4)</c>.</p> - <p>If <c>Distributed == {Application,[Time,]Nodes}</c>, + <p>If <c><anno>Distributed</anno> == {<anno>Application</anno>,[<anno>Time</anno>,]<anno>Nodes</anno>}</c>, the application will be distributed. The argument overrides the value for the application in the Kernel configuration - parameter <c>distributed</c>. <c>Application</c> must be + parameter <c>distributed</c>. <c><anno>Application</anno></c> must be the name of the application (same as in the first argument). - If a node crashes and <c>Time</c> has been specified, then - the application controller will wait for <c>Time</c> + If a node crashes and <c><anno>Time</anno></c> has been specified, then + the application controller will wait for <c><anno>Time</anno></c> milliseconds before attempting to restart the application on - another node. If <c>Time</c> is not specified, it will + another node. If <c><anno>Time</anno></c> is not specified, it will default to 0 and the application will be restarted immediately.</p> - <p><c>Nodes</c> is a list of node names where the application + <p><c><anno>Nodes</anno></c> is a list of node names where the application may run, in priority from left to right. Node names can be grouped using tuples to indicate that they have the same priority. Example:</p> @@ -204,32 +180,22 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>loaded_applications() -> [{Application, Description, Vsn}]</name> + <name name="loaded_applications" arity="0"/> <fsummary>Get the currently loaded applications</fsummary> - <type> - <v>Application = atom()</v> - <v>Description = string()</v> - <v>Vsn = string()</v> - </type> <desc> <p>Returns a list with information about the applications which have been loaded using <c>load/1,2</c>, also included - applications. <c>Application</c> is the application name. - <c>Description</c> and <c>Vsn</c> are the values of its + applications. <c><anno>Application</anno></c> is the application name. + <c><anno>Description</anno></c> and <c><anno>Vsn</anno></c> are the values of its <c>description</c> and <c>vsn</c> application specification keys, respectively.</p> </desc> </func> <func> - <name>permit(Application, Bool) -> ok | {error, Reason}</name> + <name name="permit" arity="2"/> <fsummary>Change an application's permission to run on a node.</fsummary> - <type> - <v>Application = atom()</v> - <v>Bool = bool()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Changes the permission for <c>Application</c> to run at + <p>Changes the permission for <c><anno>Application</anno></c> to run at the current node. The application must have been loaded using <c>load/1,2</c> for the function to have effect.</p> <p>If the permission of a loaded, but not started, application @@ -258,20 +224,14 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>set_env(Application, Par, Val) -> ok</name> - <name>set_env(Application, Par, Val, Timeout) -> ok</name> + <name name="set_env" arity="3"/> + <name name="set_env" arity="4"/> <fsummary>Set the value of a configuration parameter</fsummary> - <type> - <v>Application = atom()</v> - <v>Par = atom()</v> - <v>Val = term()</v> - <v>Timeout = int() | infinity</v> - </type> <desc> - <p>Sets the value of the configuration parameter <c>Par</c> for - <c>Application</c>.</p> + <p>Sets the value of the configuration parameter <c><anno>Par</anno></c> for + <c><anno>Application</anno></c>.</p> <p><c>set_env/3</c> uses the standard <c>gen_server</c> timeout - value (5000 ms). A <c>Timeout</c> argument can be provided + value (5000 ms). A <c><anno>Timeout</anno></c> argument can be provided if another timeout value is useful, for example, in situations where the application controller is heavily loaded.</p> <warning> @@ -285,20 +245,15 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>start(Application) -> ok | {error, Reason}</name> - <name>start(Application, Type) -> ok | {error, Reason}</name> + <name name="start" arity="1"/> + <name name="start" arity="2"/> <fsummary>Load and start an application</fsummary> - <type> - <v>Application = atom()</v> - <v>Type = permanent | transient | temporary</v> - <v>Reason = term()</v> - </type> <desc> - <p>Starts <c>Application</c>. If it is not loaded, + <p>Starts <c><anno>Application</anno></c>. If it is not loaded, the application controller will first load it using <c>load/1</c>. It will make sure any included applications are loaded, but will not start them. That is assumed to be - taken care of in the code for <c>Application</c>.</p> + taken care of in the code for <c><anno>Application</anno></c>.</p> <p>The application controller checks the value of the application specification key <c>applications</c>, to ensure that all applications that should be started before @@ -310,7 +265,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> The application master starts the application by calling the application callback function <c>Module:start/2</c> as defined by the application specification key <c>mod</c>.</p> - <p>The <c>Type</c> argument specifies the type of + <p>The <c><anno>Type</anno></c> argument specifies the type of the application. If omitted, it defaults to <c>temporary</c>.</p> <list type="bulleted"> <item>If a permanent application terminates, all other @@ -331,19 +286,15 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>start_type() -> StartType | local | undefined</name> + <name name="start_type" arity="0"/> <fsummary>Get the start type of an ongoing application startup.</fsummary> - <type> - <v>StartType = normal | {takeover,Node} | {failover,Node}</v> - <v> Node = node()</v> - </type> <desc> <p>This function is intended to be called by a process belonging to an application, when the application is being started, to - determine the start type which is either <c>StartType</c> or + determine the start type which is either <c><anno>StartType</anno></c> or <c>local</c>.</p> - <p>See <c>Module:start/2</c> for a description of - <c>StartType</c>.</p> + <p>See <seealso marker="#start_type"><c>Module:start/2</c></seealso> for a description of + <c><anno>StartType</anno></c>.</p> <p><c>local</c> is returned if only parts of the application is being restarted (by a supervisor), or if the function is called outside a startup.</p> @@ -352,14 +303,10 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>stop(Application) -> ok | {error, Reason}</name> + <name name="stop" arity="1"/> <fsummary>Stop an application</fsummary> - <type> - <v>Application = atom()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Stops <c>Application</c>. The application master calls + <p>Stops <c><anno>Application</anno></c>. The application master calls <c>Module:prep_stop/1</c>, if such a function is defined, and then tells the top supervisor of the application to shutdown (see <c>supervisor(3)</c>). This means that the entire @@ -384,16 +331,11 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>takeover(Application, Type) -> ok | {error, Reason}</name> + <name name="takeover" arity="2"/> <fsummary>Take over a distributed application</fsummary> - <type> - <v>Application = atom()</v> - <v>Type = permanent | transient | temporary</v> - <v>Reason = term()</v> - </type> <desc> <p>Performs a takeover of the distributed application - <c>Application</c>, which executes at another node + <c><anno>Application</anno></c>, which executes at another node <c>Node</c>. At the current node, the application is restarted by calling <c>Module:start({takeover,Node},StartArgs)</c>. <c>Module</c> @@ -413,14 +355,10 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>unload(Application) -> ok | {error, Reason}</name> + <name name="unload" arity="1"/> <fsummary>Unload an application</fsummary> - <type> - <v>Application = atom()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Unloads the application specification for <c>Application</c> + <p>Unloads the application specification for <c><anno>Application</anno></c> from the application controller. It will also unload the application specifications for any included applications. Note that the function does not purge the actual Erlang @@ -428,19 +366,14 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>unset_env(Application, Par) -> ok</name> - <name>unset_env(Application, Par, Timeout) -> ok</name> + <name name="unset_env" arity="2"/> + <name name="unset_env" arity="3"/> <fsummary>Unset the value of a configuration parameter</fsummary> - <type> - <v>Application = atom()</v> - <v>Par = atom()</v> - <v>Timeout = int() | infinity</v> - </type> <desc> - <p>Removes the configuration parameter <c>Par</c> and its value - for <c>Application</c>.</p> + <p>Removes the configuration parameter <c><anno>Par</anno></c> and its value + for <c><anno>Application</anno></c>.</p> <p><c>unset_env/2</c> uses the standard <c>gen_server</c> - timeout value (5000 ms). A <c>Timeout</c> argument can be + timeout value (5000 ms). A <c><anno>Timeout</anno></c> argument can be provided if another timeout value is useful, for example, in situations where the application controller is heavily loaded.</p> <warning> @@ -454,23 +387,17 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> </desc> </func> <func> - <name>which_applications() -> [{Application, Description, Vsn}]</name> - <name>which_applications(Timeout) -> [{Application, Description, Vsn}]</name> + <name name="which_applications" arity="0"/> + <name name="which_applications" arity="1"/> <fsummary>Get the currently running applications</fsummary> - <type> - <v>Application = atom()</v> - <v>Description = string()</v> - <v>Vsn = string()</v> - <v>Timeout = int() | infinity</v> - </type> <desc> <p>Returns a list with information about the applications which - are currently running. <c>Application</c> is the application - name. <c>Description</c> and <c>Vsn</c> are the values of its + are currently running. <c><anno>Application</anno></c> is the application + name. <c><anno>Description</anno></c> and <c><anno>Vsn</anno></c> are the values of its <c>description</c> and <c>vsn</c> application specification keys, respectively.</p> <p><c>which_applications/0</c> uses the standard - <c>gen_server</c> timeout value (5000 ms). A <c>Timeout</c> + <c>gen_server</c> timeout value (5000 ms). A <c><anno>Timeout</anno></c> argument can be provided if another timeout value is useful, for example, in situations where the application controller is heavily loaded.</p> @@ -501,7 +428,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> structured according to the OTP design principles as a supervision tree, this means starting the top supervisor of the tree.</p> - <p><c>StartType</c> defines the type of start:</p> + <p><marker id="start_type"/><c>StartType</c> defines the type of start:</p> <list type="bulleted"> <item><c>normal</c> if it's a normal startup.</item> <item><c>normal</c> also if the application is distributed and @@ -532,8 +459,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code> <fsummary>Extended start of an application</fsummary> <type> <v>Phase = atom()</v> - <v>StartType = normal | {takeover,Node} | {failover,Node}</v> - <v> Node = node()</v> + <v>StartType = <seealso marker="#type-start_type">start_type()</seealso></v> <v>PhaseArgs = term()</v> <v>Pid = pid()</v> <v>State = state()</v> diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml index f53fc8b29a..15d9ef0fe4 100644 --- a/lib/kernel/doc/src/auth.xml +++ b/lib/kernel/doc/src/auth.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -34,29 +34,28 @@ Cookie system, refer to <seealso marker="doc/reference_manual:distributed">Distributed Erlang</seealso> in the Erlang Reference Manual.</p> </description> + <datatypes> + <datatype> + <name name="cookie"/> + </datatype> + </datatypes> <funcs> <func> - <name>is_auth(Node) -> yes | no</name> + <name name="is_auth" arity="1"/> <fsummary>Status of communication authorization (deprecated)</fsummary> - <type> - <v>Node = node()</v> - </type> <desc> - <p>Returns <c>yes</c> if communication with <c>Node</c> is - authorized. Note that a connection to <c>Node</c> will - be established in this case. Returns <c>no</c> if <c>Node</c> + <p>Returns <c>yes</c> if communication with <c><anno>Node</anno></c> is + authorized. Note that a connection to <c><anno>Node</anno></c> will + be established in this case. Returns <c>no</c> if <c><anno>Node</anno></c> does not exist or communication is not authorized (it has another cookie than <c>auth</c> thinks it has).</p> - <p>Use <seealso marker="net_adm#ping/1">net_adm:ping(Node)</seealso> + <p>Use <seealso marker="net_adm#ping/1">net_adm:ping(<anno>Node</anno>)</seealso> instead.</p> </desc> </func> <func> - <name>cookie() -> Cookie</name> + <name name="cookie" arity="0"/> <fsummary>Magic cookie for local node (deprecated)</fsummary> - <type> - <v>Cookie = atom()</v> - </type> <desc> <p>Use <seealso marker="erts:erlang#erlang:get_cookie/0">erlang:get_cookie()</seealso> @@ -64,16 +63,14 @@ </desc> </func> <func> - <name>cookie(TheCookie) -> true</name> + <name name="cookie" arity="1"/> <fsummary>Set the magic for the local node (deprecated)</fsummary> - <type> - <v>TheCookie = Cookie | [Cookie]</v> - <d>The cookie may also be given as a list with a single atom element</d> - <v> Cookie = atom()</v> - </type> + <type_desc variable="TheCookie"> + The cookie may also be given as a list with a single atom element. + </type_desc> <desc> <p>Use - <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(node(), Cookie)</seealso> + <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(node(), <anno>Cookie</anno>)</seealso> instead.</p> </desc> </func> @@ -82,7 +79,7 @@ <fsummary>Set the magic cookie for a node and verify authorization (deprecated)</fsummary> <type> <v>Node = node()</v> - <v>Cookie = atom()</v> + <v>Cookie = <seealso marker="#type-cookie">cookie()</seealso></v> </type> <desc> <p>Equivalent to @@ -90,18 +87,14 @@ </desc> </func> <func> - <name>node_cookie(Node, Cookie) -> yes | no</name> + <name name="node_cookie" arity="2"/> <fsummary>Set the magic cookie for a node and verify authorization (deprecated)</fsummary> - <type> - <v>Node = node()</v> - <v>Cookie = atom()</v> - </type> <desc> - <p>Sets the magic cookie of <c>Node</c> to <c>Cookie</c>, and + <p>Sets the magic cookie of <c><anno>Node</anno></c> to <c><anno>Cookie</anno></c>, and verifies the status of the authorization. Equivalent to calling - <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(Node, Cookie)</seealso>, followed by - <seealso marker="#is_auth/1">auth:is_auth(Node)</seealso>.</p> + <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(<anno>Node</anno>, <anno>Cookie</anno>)</seealso>, followed by + <seealso marker="#is_auth/1">auth:is_auth(<anno>Node</anno>)</seealso>.</p> </desc> </func> </funcs> diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 4b8f934df1..6f85388c22 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -286,6 +286,12 @@ given to <c>set_path/1</c>.</p> </section> + <datatypes> + <datatype> + <name name="load_error_rsn"/> + </datatype> + </datatypes> + <funcs> <func> <name>set_path(Path) -> true | {error, What}</name> diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 324d4264cf..9721907162 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -179,13 +179,48 @@ reopen the log simultaneously.</p> </note> </description> + <datatypes> + <datatype> + <name name="log"/> + </datatype> + <datatype> + <name name="dlog_size"/> + </datatype> + <datatype> + <name name="dlog_format"/> + </datatype> + <datatype> + <name name="dlog_head_opt"/> + </datatype> + <datatype> + <name name="dlog_byte"/> + </datatype> + <datatype> + <name name="dlog_mode"/> + </datatype> + <datatype> + <name name="dlog_type"/> + </datatype> + <datatype> + <name name="continuation"/> + <desc><p>Chunk continuation returned by + <c>chunk/2,3</c>, <c>bchunk/2,3</c>, or <c>chunk_step/3</c>.</p> + </desc> + </datatype> + <datatype> + <name name="bytes"/> + </datatype> + <datatype> + <name name="invalid_header"/> + </datatype> + <datatype> + <name name="file_error"/> + </datatype> + </datatypes> <funcs> <func> - <name>accessible_logs() -> {[LocalLog], [DistributedLog]}</name> + <name name="accessible_logs" arity="0"/> <fsummary>Return the accessible disk logs on the current node.</fsummary> - <type> - <v>LocalLog = DistributedLog = term()</v> - </type> <desc> <p>The <c>accessible_logs/0</c> function returns the names of the disk logs accessible on the current node. @@ -195,16 +230,13 @@ </desc> </func> <func> - <name>alog(Log, Term)</name> - <name>balog(Log, Bytes) -> ok | {error, Reason}</name> + <name name="alog" arity="2"/> + <name name="balog" arity="2"/> + <type variable="Log"/> + <type variable="Term" name_i="1"/> + <type variable="Bytes"/> + <type name="notify_ret"/> <fsummary>Asynchronously log an item onto a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Term = term()</v> - <v>Bytes = binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log</v> - </type> <desc> <p>The <c>alog/2</c> and <c>balog/2</c> functions asynchronously append an item to a disk log. The function <c>alog/2</c> is @@ -225,17 +257,13 @@ </desc> </func> <func> - <name>alog_terms(Log, TermList)</name> - <name>balog_terms(Log, BytesList) -> ok | {error, Reason}</name> + <name name="alog_terms" arity="2"/> + <name name="balog_terms" arity="2"/> <fsummary>Asynchronously log several items onto a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>TermList = [term()]</v> - <v>BytesList = [Bytes]</v> - <v>Bytes = binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log</v> - </type> + <type variable="Log"/> + <type variable="TermList" name_i="1"/> + <type variable="ByteList"/> + <type name="notify_ret"/> <desc> <p>The <c>alog_terms/2</c> and <c>balog_terms/2</c> functions asynchronously append a list of items to a disk log. @@ -257,14 +285,10 @@ </desc> </func> <func> - <name>block(Log)</name> - <name>block(Log, QueueLogRecords) -> ok | {error, Reason}</name> + <name name="block" arity="1"/> + <name name="block" arity="2"/> + <type name="block_error_rsn"/> <fsummary>Block a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>QueueLogRecords = bool()</v> - <v>Reason = no_such_log | nonode | {blocked_log, Log}</v> - </type> <desc> <p>With a call to <c>block/1,2</c> a process can block a log. If the blocking process is not an owner of the log, a temporary @@ -280,52 +304,32 @@ affected by the block. Any other attempt than those hitherto mentioned to update or read a blocked log suspends the calling process until the log is unblocked or returns an - error message <c>{blocked_log, Log}</c>, depending on - whether the value of <c>QueueLogRecords</c> is <c>true</c> - or <c>false</c>. The default value of <c>QueueLogRecords</c> + error message <c>{blocked_log, <anno>Log</anno>}</c>, depending on + whether the value of <c><anno>QueueLogRecords</anno></c> is <c>true</c> + or <c>false</c>. The default value of <c><anno>QueueLogRecords</anno></c> is <c>true</c>, which is used by <c>block/1</c>. </p> </desc> </func> <func> - <name>change_header(Log, Header) -> ok | {error, Reason}</name> + <name name="change_header" arity="2"/> <fsummary>Change the head or head_func option for an owner of a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Header = {head, Head} | {head_func, {M,F,A}}</v> - <v>Head = none | term() | binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {badarg, head}</v> - </type> <desc> <p>The <c>change_header/2</c> function changes the value of the <c>head</c> or <c>head_func</c> option of a disk log.</p> </desc> </func> <func> - <name>change_notify(Log, Owner, Notify) -> ok | {error, Reason}</name> + <name name="change_notify" arity="3"/> <fsummary>Change the notify option for an owner of a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Owner = pid()</v> - <v>Notify = bool()</v> - <v>Reason = no_such_log | nonode | {blocked_log, Log} | {badarg, notify} | {not_owner, Owner}</v> - </type> <desc> <p>The <c>change_notify/3</c> function changes the value of the <c>notify</c> option for an owner of a disk log. </p> </desc> </func> <func> - <name>change_size(Log, Size) -> ok | {error, Reason}</name> + <name name="change_size" arity="2"/> <fsummary>Change the size of an open disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Size = integer() > 0 | infinity | {MaxNoBytes, MaxNoFiles}</v> - <v>MaxNoBytes = integer() > 0</v> - <v>MaxNoFiles = integer() > 0</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {new_size_too_small, CurrentSize} | {badarg, size} | {file_error, FileName, FileError}</v> - </type> <desc> <p>The <c>change_size/2</c> function changes the size of an open log. For a halt log it is always possible to increase the size, @@ -363,21 +367,17 @@ </desc> </func> <func> - <name>chunk(Log, Continuation)</name> - <name>chunk(Log, Continuation, N) -> {Continuation2, Terms} | {Continuation2, Terms, Badbytes} | eof | {error, Reason}</name> - <name>bchunk(Log, Continuation)</name> - <name>bchunk(Log, Continuation, N) -> {Continuation2, Binaries} | {Continuation2, Binaries, Badbytes} | eof | {error, Reason}</name> + <name name="chunk" arity="2"/> + <name name="chunk" arity="3"/> + <name name="bchunk" arity="2"/> + <name name="bchunk" arity="3"/> <fsummary>Read a chunk of items written to a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Continuation = start | cont()</v> - <v>N = integer() > 0 | infinity</v> - <v>Continuation2 = cont()</v> - <v>Terms = [term()]</v> - <v>Badbytes = integer()</v> - <v>Reason = no_such_log | {format_external, Log} | {blocked_log, Log} | {badarg, continuation} | {not_internal_wrap, Log} | {corrupt_log_file, FileName} | {file_error, FileName, FileError}</v> - <v>Binaries = [binary()]</v> - </type> + <type variable="Log"/> + <type variable="Continuation"/> + <type variable="N"/> + <type name="chunk_ret"/> + <type name="bchunk_ret"/> + <type name="chunk_error_rsn"/> <desc> <p>The <c>chunk/2,3</c> and <c>bchunk/2,3</c> functions make it possible to efficiently read the terms which have been @@ -394,31 +394,31 @@ individual distributed log on some other node is chosen, if such a log exists. </p> - <p>When <c>chunk/3</c> is called, <c>N</c> controls the + <p>When <c>chunk/3</c> is called, <c><anno>N</anno></c> controls the maximum number of terms that are read from the log in each chunk. Default is <c>infinity</c>, which means that all the terms contained in the 64 kilobyte chunk are read. If less than - <c>N</c> terms are returned, this does not necessarily mean + <c><anno>N</anno></c> terms are returned, this does not necessarily mean that the end of the file has been reached. </p> <p>The <c>chunk</c> function returns a tuple - <c>{Continuation2, Terms}</c>, where <c>Terms</c> is a list - of terms found in the log. <c>Continuation2</c> is yet + <c>{<anno>Continuation2</anno>, <anno>Terms</anno>}</c>, where <c><anno>Terms</anno></c> is a list + of terms found in the log. <c><anno>Continuation2</anno></c> is yet another continuation which must be passed on to any subsequent calls to <c>chunk</c>. With a series of calls to <c>chunk</c> it is possible to extract all terms from a log. </p> <p>The <c>chunk</c> function returns a tuple - <c>{Continuation2, Terms, Badbytes}</c> if the log is opened - in read-only mode and the read chunk is corrupt. <c>Badbytes</c> + <c>{<anno>Continuation2</anno>, <anno>Terms</anno>, <anno>Badbytes</anno>}</c> if the log is opened + in read-only mode and the read chunk is corrupt. <c><anno>Badbytes</anno></c> is the number of bytes in the file which were found not to be Erlang terms in the chunk. Note also that the log is not repaired. When trying to read chunks from a log opened in read-write mode, - the tuple <c>{corrupt_log_file, FileName}</c> is returned if the + the tuple <c>{corrupt_log_file, <anno>FileName</anno>}</c> is returned if the read chunk is corrupt. </p> <p><c>chunk</c> returns <c>eof</c> when the end of the log is - reached, or <c>{error, Reason}</c> if an error occurs. Should + reached, or <c>{error, <anno>Reason</anno>}</c> if an error occurs. Should a wrap log file be missing, a message is output on the error log. </p> <p>When <c>chunk/2,3</c> is used with wrap logs, the returned @@ -431,12 +431,8 @@ </desc> </func> <func> - <name>chunk_info(Continuation) -> InfoList | {error, Reason}</name> + <name name="chunk_info" arity="1"/> <fsummary>Return information about a chunk continuation of a disk log.</fsummary> - <type> - <v>Continuation = cont()</v> - <v>Reason = {no_continuation, Continuation}</v> - </type> <desc> <p>The <c>chunk_info/1</c> function returns the following pair describing the chunk continuation returned by @@ -444,29 +440,22 @@ </p> <list type="bulleted"> <item> - <p><c>{node, Node}</c>. Terms are read from - the disk log running on <c>Node</c>.</p> + <p><c>{node, <anno>Node</anno>}</c>. Terms are read from + the disk log running on <c><anno>Node</anno></c>.</p> </item> </list> </desc> </func> <func> - <name>chunk_step(Log, Continuation, Step) -> {ok, Continuation2} | {error, Reason}</name> + <name name="chunk_step" arity="3"/> <fsummary>Step forward or backward among the wrap log files of a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Continuation = start | cont()</v> - <v>Step = integer()</v> - <v>Continuation2 = cont()</v> - <v>Reason = no_such_log | end_of_log | {format_external, Log} | {blocked_log, Log} | {badarg, continuation} | {file_error, FileName, FileError}</v> - </type> <desc> <p>The function <c>chunk_step</c> can be used in conjunction with <c>chunk/2,3</c> and <c>bchunk/2,3</c> to search through an internally formatted wrap log. It takes as argument a continuation as returned by <c>chunk/2,3</c>, <c>bchunk/2,3</c>, or <c>chunk_step/3</c>, and steps forward - (or backward) <c>Step</c> files in the wrap log. The + (or backward) <c><anno>Step</anno></c> files in the wrap log. The continuation returned points to the first log item in the new current file. </p> @@ -482,11 +471,9 @@ </desc> </func> <func> - <name>close(Log) -> ok | {error, Reason}</name> + <name name="close" arity="1"/> <fsummary>Close a disk log.</fsummary> - <type> - <v>Reason = no_such_log | nonode | {file_error, FileName, FileError}</v> - </type> + <type name="close_error_rsn"/> <desc> <p> <marker id="close_1"></marker> The function <c>close/1</c> closes a @@ -511,11 +498,8 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>format_error(Error) -> Chars</name> + <name name="format_error" arity="1"/> <fsummary>Return an English description of a disk log error reply.</fsummary> - <type> - <v>Chars = [char() | Chars]</v> - </type> <desc> <p>Given the error returned by any function in this module, the function <c>format_error</c> returns a descriptive string @@ -524,11 +508,10 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>inc_wrap_file(Log) -> ok | {error, Reason}</name> + <name name="inc_wrap_file" arity="1"/> <fsummary>Change to the next wrap log file of a disk log.</fsummary> - <type> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {halt_log, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v> - </type> + <type name="inc_wrap_error_rsn"/> + <type name="invalid_header"/> <desc> <p>The <c>inc_wrap_file/1</c> function forces the internally formatted disk log to start logging to the @@ -543,8 +526,9 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>info(Log) -> InfoList | {error, no_such_log}</name> + <name name="info" arity="1"/> <fsummary>Return information about a disk log.</fsummary> + <type name="dlog_info"/> <desc> <p>The <c>info/1</c> function returns a list of <c>{Tag, Value}</c> pairs describing the log. If there is a disk log process running @@ -556,55 +540,55 @@ The function <c>close/1</c> closes a </p> <list type="bulleted"> <item> - <p><c>{name, Log}</c>, where <c>Log</c> is the name of + <p><c>{name, <anno>Log</anno>}</c>, where <c><anno>Log</anno></c> is the name of the log as given by the <c>open/1</c> option <c>name</c>.</p> </item> <item> - <p><c>{file, File}</c>. For halt logs <c>File</c> is the - filename, and for wrap logs <c>File</c> is the base name.</p> + <p><c>{file, <anno>File</anno>}</c>. For halt logs <c><anno>File</anno></c> is the + filename, and for wrap logs <c><anno>File</anno></c> is the base name.</p> </item> <item> - <p><c>{type, Type}</c>, where <c>Type</c> is the type of + <p><c>{type, <anno>Type</anno>}</c>, where <c><anno>Type</anno></c> is the type of the log as given by the <c>open/1</c> option <c>type</c>.</p> </item> <item> - <p><c>{format, Format}</c>, where <c>Format</c> is the format + <p><c>{format, <anno>Format</anno>}</c>, where <c><anno>Format</anno></c> is the format of the log as given by the <c>open/1</c> option <c>format</c>.</p> </item> <item> - <p><c>{size, Size}</c>, where <c>Size</c> is the size + <p><c>{size, <anno>Size</anno>}</c>, where <c><anno>Size</anno></c> is the size of the log as given by the <c>open/1</c> option <c>size</c>, or the size set by <c>change_size/2</c>. The value set by <c>change_size/2</c> is reflected immediately.</p> </item> <item> - <p><c>{mode, Mode}</c>, where <c>Mode</c> is the mode + <p><c>{mode, <anno>Mode</anno>}</c>, where <c><anno>Mode</anno></c> is the mode of the log as given by the <c>open/1</c> option <c>mode</c>.</p> </item> <item> - <p><c>{owners, [{pid(), Notify}]}</c> where <c>Notify</c> + <p><c>{owners, [{pid(), <anno>Notify</anno>}]}</c> where <c><anno>Notify</anno></c> is the value set by the <c>open/1</c> option <c>notify</c> or the function <c>change_notify/3</c> for the owners of the log.</p> </item> <item> - <p><c>{users, Users}</c> where <c>Users</c> is the number + <p><c>{users, <anno>Users</anno>}</c> where <c><anno>Users</anno></c> is the number of anonymous users of the log, see the <c>open/1</c> option <seealso marker="#linkto">linkto</seealso>.</p> </item> <item> - <p><c>{status, Status}</c>, where <c>Status</c> is <c>ok</c> - or <c>{blocked, QueueLogRecords}</c> as set by the functions + <p><c>{status, <anno>Status</anno>}</c>, where <c><anno>Status</anno></c> is <c>ok</c> + or <c>{blocked, <anno>QueueLogRecords</anno>}</c> as set by the functions <c>block/1,2</c> and <c>unblock/1</c>.</p> </item> <item> - <p><c>{node, Node}</c>. The information returned by the + <p><c>{node, <anno>Node</anno>}</c>. The information returned by the current invocation of the <c>info/1</c> function has been - gathered from the disk log process running on <c>Node</c>.</p> + gathered from the disk log process running on <c><anno>Node</anno></c>.</p> </item> <item> - <p><c>{distributed, Dist}</c>. If the log is local on - the current node, then <c>Dist</c> has the value <c>local</c>, + <p><c>{distributed, <anno>Dist</anno>}</c>. If the log is local on + the current node, then <c><anno>Dist</anno></c> has the value <c>local</c>, otherwise all nodes where the log is distributed are returned as a list.</p> </item> @@ -614,16 +598,16 @@ The function <c>close/1</c> closes a </p> <list type="bulleted"> <item> - <p><c>{head, Head}</c>. Depending of the value of + <p><c>{head, <anno>Head</anno>}</c>. Depending of the value of the <c>open/1</c> options <c>head</c> and <c>head_func</c> or set by the function <c>change_header/2</c>, the value - of <c>Head</c> is <c>none</c> (default), + of <c><anno>Head</anno></c> is <c>none</c> (default), <c>{head, H}</c> (<c>head</c> option) or <c>{M,F,A}</c> (<c>head_func</c> option).</p> </item> <item> - <p><c>{no_written_items, NoWrittenItems}</c>, where - <c>NoWrittenItems</c> is the number of items + <p><c>{no_written_items, <anno>NoWrittenItems</anno>}</c>, where + <c><anno>NoWrittenItems</anno></c> is the number of items written to the log since the disk log process was created.</p> </item> </list> @@ -632,7 +616,7 @@ The function <c>close/1</c> closes a </p> <list type="bulleted"> <item> - <p><c>{full, Full}</c>, where <c>Full</c> is <c>true</c> or + <p><c>{full, <anno>Full</anno>}</c>, where <c><anno>Full</anno></c> is <c>true</c> or <c>false</c> depending on whether the halt log is full or not.</p> </item> </list> @@ -660,8 +644,8 @@ The function <c>close/1</c> closes a <c>size</c> or set by <c>change_size/2</c>.</p> </item> <item> - <p><c>{no_overflows, {SinceLogWasOpened, SinceLastInfo}}</c>, - where <c>SinceLogWasOpened</c> (<c>SinceLastInfo</c>) is + <p><c>{no_overflows, {<anno>SinceLogWasOpened</anno>, <anno>SinceLastInfo</anno>}}</c>, + where <c><anno>SinceLogWasOpened</anno></c> (<c><anno>SinceLastInfo</anno></c>) is the number of times a wrap log file has been filled up and a new one opened or <c>inc_wrap_file/1</c> has been called since the disk log was last opened (<c>info/1</c> @@ -677,21 +661,18 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>lclose(Log)</name> - <name>lclose(Log, Node) -> ok | {error, Reason}</name> + <name name="lclose" arity="1"/> + <name name="lclose" arity="2"/> + <type name="lclose_error_rsn"/> <fsummary>Close a disk log on one node.</fsummary> - <type> - <v>Node = node()</v> - <v>Reason = no_such_log | {file_error, FileName, FileError}</v> - </type> <desc> <p>The function <c>lclose/1</c> closes a local log or an individual distributed log on the current node. The function <c>lclose/2</c> closes an individual distributed log on the specified node if the node is not the current one. - <c>lclose(Log)</c> is equivalent to - <c>lclose(Log, node())</c>. + <c>lclose(<anno>Log</anno>)</c> is equivalent to + <c>lclose(<anno>Log</anno>, node())</c>. See also <seealso marker="#close_1">close/1</seealso>. </p> <p>If there is no log with the given name @@ -700,20 +681,17 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>log(Log, Term)</name> - <name>blog(Log, Bytes) -> ok | {error, Reason}</name> + <name name="log" arity="2"/> + <name name="blog" arity="2"/> <fsummary>Log an item onto a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Term = term()</v> - <v>Bytes = binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {format_external, Log} | {blocked_log, Log} | {full, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v> - </type> + <type variable="Log"/> + <type variable="Term" name_i="1"/> + <type variable="Bytes"/> + <type name="log_error_rsn"/> <desc> <p>The <c>log/2</c> and <c>blog/2</c> functions synchronously append a term to a disk log. They return <c>ok</c> or - <c>{error, Reason}</c> when the term has been written to + <c>{error, <anno>Reason</anno>}</c> when the term has been written to disk. If the log is distributed, <c>ok</c> is always returned, unless all nodes are down. Terms are written by means of the ordinary <c>write()</c> function of the @@ -736,17 +714,13 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>log_terms(Log, TermList)</name> - <name>blog_terms(Log, BytesList) -> ok | {error, Reason}</name> + <name name="log_terms" arity="2"/> + <name name="blog_terms" arity="2"/> <fsummary>Log several items onto a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>TermList = [term()]</v> - <v>BytesList = [Bytes]</v> - <v>Bytes = binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {format_external, Log} | {blocked_log, Log} | {full, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v> - </type> + <type variable="Log"/> + <type variable="TermList" name_i="1"/> + <type variable="BytesList"/> + <type name="log_error_rsn"/> <desc> <p>The <c>log_terms/2</c> and <c>blog_terms/2</c> functions synchronously append a list of items to the log. The benefit @@ -769,47 +743,33 @@ The function <c>close/1</c> closes a </desc> </func> <func> - <name>open(ArgL) -> OpenRet | DistOpenRet</name> + <name name="open" arity="1"/> + <type name="dlog_options"/> + <type name="dlog_option"/> + <type name="open_ret"/> + <type name="ret"/> + <type name="dist_open_ret"/> + <type name="dist_error_rsn"/> + <type name="open_error_rsn"/> + <type name="dlog_optattr"/> + <type name="dlog_size"/> <fsummary>Open a disk log file.</fsummary> - <type> - <v>ArgL = [Opt]</v> - <v>Opt = {name, term()} | {file, FileName}, {linkto, LinkTo} | {repair, Repair} | {type, Type} | {format, Format} | {size, Size} | {distributed, [Node]} | {notify, bool()} | {head, Head} | {head_func, {M,F,A}} | {mode, Mode}</v> - <v>FileName = string() | atom()</v> - <v>LinkTo = pid() | none</v> - <v>Repair = true | false | truncate</v> - <v>Type = halt | wrap</v> - <v>Format = internal | external</v> - <v>Size = integer() > 0 | infinity | {MaxNoBytes, MaxNoFiles}</v> - <v>MaxNoBytes = integer() > 0</v> - <v>MaxNoFiles = 0 < integer() < 65000</v> - <v>Rec = integer()</v> - <v>Bad = integer()</v> - <v>Head = none | term() | binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Mode = read_write | read_only</v> - <v>OpenRet = Ret | {error, Reason}</v> - <v>DistOpenRet = {[{Node, Ret}], [{BadNode, {error, DistReason}}]}</v> - <v>Node = BadNode = atom()</v> - <v>Ret = {ok, Log} | {repaired, Log, {recovered, Rec}, {badbytes, Bad}}</v> - <v>DistReason = nodedown | Reason</v> - <v>Reason = no_such_log | {badarg, Arg} | {size_mismatch, CurrentSize, NewSize} | {arg_mismatch, OptionName, CurrentValue, Value} | {name_already_open, Log} | {open_read_write, Log} | {open_read_only, Log} | {need_repair, Log} | {not_a_log_file, FileName} | {invalid_index_file, FileName} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError} | {node_already_open, Log}</v> - </type> <desc> - <p>The <c>ArgL</c> parameter is a list of options which have + <p>The <c><anno>ArgL</anno></c> parameter is a list of options which have the following meanings:</p> <list type="bulleted"> <item> - <p><c>{name, Log}</c> specifies the name of the log. + <p><c>{name, <anno>Log</anno>}</c> specifies the name of the log. This is the name which must be passed on as a parameter in all subsequent logging operations. A name must always be supplied. </p> </item> <item> - <p><c>{file, FileName}</c> specifies the name of the + <p><c>{file, <anno>FileName</anno>}</c> specifies the name of the file which will be used for logged terms. If this value is omitted and the name of the log is either an atom or a string, - the file name will default to <c>lists:concat([Log, ".LOG"])</c> for halt logs. For wrap logs, this will be + the file name will default to <c>lists:concat([<anno>Log</anno>, ".LOG"])</c> for halt logs. For wrap logs, this will be the base name of the files. Each file in a wrap log will be called <c><![CDATA[<base_name>.N]]></c>, where <c>N</c> is an integer. Each wrap log will also have two files called @@ -817,22 +777,22 @@ The function <c>close/1</c> closes a </p> </item> <item> - <p><c>{linkto, LinkTo}</c>. <marker id="linkto"></marker> + <p><c>{linkto, <anno>LinkTo</anno>}</c>. <marker id="linkto"></marker> If - <c>LinkTo</c> is a pid, that pid becomes an owner of the - log. If <c>LinkTo</c> is <c>none</c> the log records + <c><anno>LinkTo</anno></c> is a pid, that pid becomes an owner of the + log. If <c><anno>LinkTo</anno></c> is <c>none</c> the log records that it is used anonymously by some process by incrementing the <c>users</c> counter. By default, the process which calls <c>open/1</c> owns the log. </p> </item> <item> - <p><c>{repair, Repair}</c>. If <c>Repair</c> is <c>true</c>, + <p><c>{repair, <anno>Repair</anno>}</c>. If <c><anno>Repair</anno></c> is <c>true</c>, the current log file will be repaired, if needed. As the restoration is initiated, a message is output on the error log. If <c>false</c> is given, no automatic repair will be attempted. Instead, the - tuple <c>{error, {need_repair, Log}}</c> is returned if an + tuple <c>{error, {need_repair, <anno>Log</anno>}}</c> is returned if an attempt is made to open a corrupt log file. If <c>truncate</c> is given, the log file will be truncated, creating an empty log. Default is @@ -841,41 +801,41 @@ If </p> </item> <item> - <p><c>{type, Type}</c> is the type of the log. Default + <p><c>{type, <anno>Type</anno>}</c> is the type of the log. Default is <c>halt</c>. </p> </item> <item> - <p><c>{format, Format}</c> specifies the format of the + <p><c>{format, <anno>Format</anno>}</c> specifies the format of the disk log. Default is <c>internal</c>. </p> </item> <item> - <p><c>{size, Size}</c> specifies the size of the log. + <p><c>{size, <anno>Size</anno>}</c> specifies the size of the log. When a halt log has reached its maximum size, all attempts to log more items are rejected. The default size is <c>infinity</c>, which for halt implies that there is no - maximum size. For wrap logs, the <c>Size</c> parameter + maximum size. For wrap logs, the <c><anno>Size</anno></c> parameter may be either a pair - <c>{MaxNoBytes, MaxNoFiles}</c> or <c>infinity</c>. In the + <c>{<anno>MaxNoBytes</anno>, <anno>MaxNoFiles</anno>}</c> or <c>infinity</c>. In the latter case, if the files of an already existing wrap log with the same name can be found, the size is read from the existing wrap log, otherwise an error is returned. - Wrap logs write at most <c>MaxNoBytes</c> bytes on each file - and use <c>MaxNoFiles</c> files before starting all over with - the first wrap log file. Regardless of <c>MaxNoBytes</c>, + Wrap logs write at most <c><anno>MaxNoBytes</anno></c> bytes on each file + and use <c><anno>MaxNoFiles</anno></c> files before starting all over with + the first wrap log file. Regardless of <c><anno>MaxNoBytes</anno></c>, at least the header (if there is one) and one item is written on each wrap log file before wrapping to the next file. When opening an existing wrap log, it is not necessary to supply a value for the option <c>Size</c>, but any supplied value must equal the current size of the log, otherwise - the tuple <c>{error, {size_mismatch, CurrentSize, NewSize}}</c> + the tuple <c>{error, {size_mismatch, <anno>CurrentSize</anno>, <anno>NewSize</anno>}}</c> is returned. </p> </item> <item> - <p><c>{distributed, Nodes}</c>. This option can be used for + <p><c>{distributed, <anno>Nodes</anno>}</c>. This option can be used for adding members to a distributed disk log. The default value is <c>[]</c>, which means that the log is local on the current node. @@ -946,10 +906,10 @@ If </list> </item> <item> - <p><c>{head, Head}</c> specifies a header to be + <p><c>{head, <anno>Head</anno>}</c> specifies a header to be written first on the log file. If the log is a wrap - log, the item <c>Head</c> is written first in each new file. - <c>Head</c> should be a term if the format is + log, the item <c><anno>Head</anno></c> is written first in each new file. + <c><anno>Head</anno></c> should be a term if the format is <c>internal</c>, and a deep list of bytes (or a binary) otherwise. Default is <c>none</c>, which means that no header is written first on the file. @@ -966,17 +926,17 @@ If </p> </item> <item> - <p><c>{mode, Mode}</c> specifies if the log is to be + <p><c>{mode, <anno>Mode</anno>}</c> specifies if the log is to be opened in read-only or read-write mode. It defaults to <c>read_write</c>. </p> </item> </list> - <p>The <c>open/1</c> function returns <c>{ok, Log}</c> if the + <p>The <c>open/1</c> function returns <c>{ok, <anno>Log</anno>}</c> if the log file was successfully opened. If the file was - successfully repaired, the tuple <c>{repaired, Log, {recovered, Rec}, {badbytes, Bad}}</c> is returned, where - <c>Rec</c> is the number of whole Erlang terms found in the - file and <c>Bad</c> is the number of bytes in the file which + successfully repaired, the tuple <c>{repaired, <anno>Log</anno>, {recovered, <anno>Rec</anno>}, {badbytes, <anno>Bad</anno>}}</c> is returned, where + <c><anno>Rec</anno></c> is the number of whole Erlang terms found in the + file and <c><anno>Bad</anno></c> is the number of bytes in the file which were non-Erlang terms. If the <c>distributed</c> parameter was given, <c>open/1</c> returns a list of successful replies and a list of erroneous replies. Each @@ -988,7 +948,7 @@ If position after the last logged item, and the logging of items will commence from there. If the format is <c>internal</c> and the existing file is not recognized as an internally - formatted log, a tuple <c>{error, {not_a_log_file, FileName}}</c> + formatted log, a tuple <c>{error, {not_a_log_file, <anno>FileName</anno>}}</c> is returned. </p> <p>The <c>open/1</c> function cannot be used for changing the @@ -1000,15 +960,15 @@ If or <c>change_size/2</c>. As a consequence, none of the options except <c>name</c> is mandatory. If some given value differs from the current value, a tuple - <c>{error, {arg_mismatch, OptionName, CurrentValue, Value}}</c> + <c>{error, {arg_mismatch, <anno>OptionName</anno>, <anno>CurrentValue</anno>, <anno>Value</anno>}}</c> is returned. Caution: an owner's attempt to open a log as owner once again is acknowledged with the return value - <c>{ok, Log}</c>, but the state of the disk log is not + <c>{ok, <anno>Log</anno>}</c>, but the state of the disk log is not affected in any way. </p> <p>If a log with a given name is local on some node, and one tries to open the log distributed on the same node, - then the tuple <c>{error, {node_already_open, Name}}</c> is + then the tuple <c>{error, {node_already_open, <anno>Log</anno>}}</c> is returned. The same tuple is returned if the log is distributed on some node, and one tries to open the log locally on the same node. Opening individual distributed disk logs for the first time @@ -1036,12 +996,8 @@ If </desc> </func> <func> - <name>pid2name(Pid) -> {ok, Log} | undefined</name> + <name name="pid2name" arity="1"/> <fsummary>Return the name of the disk log handled by a pid.</fsummary> - <type> - <v>Log = term()</v> - <v>Pid = pid()</v> - </type> <desc> <p>The <c>pid2name/1</c> function returns the name of the log given the pid of a disk log process on the current node, or @@ -1052,26 +1008,23 @@ If </desc> </func> <func> - <name>reopen(Log, File)</name> - <name>reopen(Log, File, Head)</name> - <name>breopen(Log, File, BHead) -> ok | {error, Reason}</name> + <name name="reopen" arity="2"/> + <name name="reopen" arity="3"/> + <name name="breopen" arity="3"/> <fsummary>Reopen a disk log and save the old log.</fsummary> - <type> - <v>Log = term()</v> - <v>File = string()</v> - <v>Head = term()</v> - <v>BHead = binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {same_file_name, Log} | {invalid_index_file, FileName} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v> - </type> + <type variable="Log"/> + <type variable="File" name_i="1"/> + <type variable="Head" name_i="2"/> + <type variable="BHead"/> + <type name="reopen_error_rsn"/> <desc> <p>The <c>reopen</c> functions first rename the log file - to <c>File</c> and then re-create a new log file. - In case of a wrap log, <c>File</c> is used as the base name + to <c><anno>File</anno></c> and then re-create a new log file. + In case of a wrap log, <c><anno>File</anno></c> is used as the base name of the renamed files. By default the header given to <c>open/1</c> is written first in - the newly opened log file, but if the <c>Head</c> or the - <c>BHead</c> argument is given, this item is used instead. + the newly opened log file, but if the <c><anno>Head</anno></c> or the + <c><anno>BHead</anno></c> argument is given, this item is used instead. The header argument is used once only; next time a wrap log file is opened, the header given to <c>open/1</c> is used. </p> @@ -1089,12 +1042,9 @@ If </desc> </func> <func> - <name>sync(Log) -> ok | {error, Reason}</name> + <name name="sync" arity="1"/> + <type name="sync_error_rsn"/> <fsummary>Flush the contents of a disk log to the disk.</fsummary> - <type> - <v>Log = term()</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {file_error, FileName, FileError}</v> - </type> <desc> <p>The <c>sync/1</c> function ensures that the contents of the log are actually written to the disk. @@ -1103,20 +1053,17 @@ If </desc> </func> <func> - <name>truncate(Log)</name> - <name>truncate(Log, Head)</name> - <name>btruncate(Log, BHead) -> ok | {error, Reason}</name> + <name name="truncate" arity="1"/> + <name name="truncate" arity="2"/> + <name name="btruncate" arity="2"/> <fsummary>Truncate a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Head = term()</v> - <v>BHead = binary() | [Byte]</v> - <v>Byte = [Byte] | 0 =< integer() =< 255</v> - <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v> - </type> + <type variable="Log"/> + <type variable="Head" name_i="2"/> + <type variable="BHead"/> + <type name="trunc_error_rsn"/> <desc> <p>The <c>truncate</c> functions remove all items from a disk log. - If the <c>Head</c> or the <c>BHead</c> argument is + If the <c><anno>Head</anno></c> or the <c><anno>BHead</anno></c> argument is given, this item is written first in the newly truncated log, otherwise the header given to <c>open/1</c> is used. The header argument is only used once; next time a wrap log file @@ -1138,12 +1085,9 @@ If </desc> </func> <func> - <name>unblock(Log) -> ok | {error, Reason}</name> + <name name="unblock" arity="1"/> + <type name="unblock_error_rsn"/> <fsummary>Unblock a disk log.</fsummary> - <type> - <v>Log = term()</v> - <v>Reason = no_such_log | nonode | {not_blocked, Log} | {not_blocked_by_pid, Log}</v> - </type> <desc> <p>The <c>unblock/1</c> function unblocks a log. A log can only be unblocked by the blocking process. @@ -1159,4 +1103,3 @@ If <seealso marker="wrap_log_reader">wrap_log_reader(3)</seealso></p> </section> </erlref> - diff --git a/lib/kernel/doc/src/erl_boot_server.xml b/lib/kernel/doc/src/erl_boot_server.xml index 4e7533810e..472671a80e 100644 --- a/lib/kernel/doc/src/erl_boot_server.xml +++ b/lib/kernel/doc/src/erl_boot_server.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -49,29 +49,17 @@ </description> <funcs> <func> - <name>start(Slaves) -> {ok, Pid} | {error, What}</name> + <name name="start" arity="1"/> <fsummary>Start the boot server</fsummary> - <type> - <v>Slaves = [Host]</v> - <v>Host = atom()</v> - <v>Pid = pid()</v> - <v>What = term()</v> - </type> <desc> - <p>Starts the boot server. <c>Slaves</c> is a list of IP + <p>Starts the boot server. <c><anno>Slaves</anno></c> is a list of IP addresses for hosts which are allowed to use this server as a boot server.</p> </desc> </func> <func> - <name>start_link(Slaves) -> {ok, Pid} | {error, What}</name> + <name name="start_link" arity="1"/> <fsummary>Start the boot server and links the caller</fsummary> - <type> - <v>Slaves = [Host]</v> - <v>Host = atom()</v> - <v>Pid = pid()</v> - <v>What = term()()</v> - </type> <desc> <p>Starts the boot server and links to the caller. This function is used to start the server if it is included in a supervision @@ -79,37 +67,23 @@ </desc> </func> <func> - <name>add_slave(Slave) -> ok | {error, What}</name> + <name name="add_slave" arity="1"/> <fsummary>Add a slave to the list of allowed slaves</fsummary> - <type> - <v>Slave = Host</v> - <v>Host = atom()</v> - <v>What = term()</v> - </type> <desc> - <p>Adds a <c>Slave</c> node to the list of allowed slave hosts.</p> + <p>Adds a <c><anno>Slave</anno></c> node to the list of allowed slave hosts.</p> </desc> </func> <func> - <name>delete_slave(Slave) -> ok | {error, What}</name> + <name name="delete_slave" arity="1"/> <fsummary>Delete a slave from the list of allowed slaves</fsummary> - <type> - <v>Slave = Host</v> - <v>Host = atom()</v> - <v>What = void()</v> - </type> <desc> - <p>Deletes a <c>Slave</c> node from the list of allowed slave + <p>Deletes a <c><anno>Slave</anno></c> node from the list of allowed slave hosts.</p> </desc> </func> <func> - <name>which_slaves() -> Slaves</name> + <name name="which_slaves" arity="0"/> <fsummary>Return the current list of allowed slave hosts</fsummary> - <type> - <v>Slaves = [Host]</v> - <v>Host = atom()</v> - </type> <desc> <p>Returns the current list of allowed slave hosts.</p> </desc> diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml index 9a62b45d63..f9514dda2f 100644 --- a/lib/kernel/doc/src/erl_ddll.xml +++ b/lib/kernel/doc/src/erl_ddll.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2010</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -172,6 +172,14 @@ </item> </taglist> </description> + <datatypes> + <datatype> + <name name="driver"/> + </datatype> + <datatype> + <name name="path"/> + </datatype> + </datatypes> <funcs> <func> <name>demonitor(MonitorRef) -> ok</name> @@ -189,37 +197,21 @@ </desc> </func> <func> - <name>info() -> AllInfoList</name> + <name name="info" arity="0"/> <fsummary>Retrieve information about all drivers</fsummary> - <type> - <v>AllInfoList = [ DriverInfo ]</v> - <v>DriverInfo = {DriverName, InfoList}</v> - <v>DriverName = string()</v> - <v>InfoList = [ InfoItem ]</v> - <v>InfoItem = {Tag, Value}</v> - <v>Tag = atom()</v> - <v>Value = term()</v> - </type> <desc> - <p>Returns a list of tuples <c>{DriverName, InfoList}</c>, where - <c>InfoList</c> is the result of calling <seealso marker="#info/1">info/1</seealso> for that - <c>DriverName</c>. Only dynamically linked in drivers are + <p>Returns a list of tuples <c>{<anno>DriverName</anno>, <anno>InfoList</anno>}</c>, where + <c><anno>InfoList</anno></c> is the result of calling <seealso marker="#info/1">info/1</seealso> for that + <c><anno>DriverName</anno></c>. Only dynamically linked in drivers are included in the list.</p> </desc> </func> <func> - <name>info(Name) -> InfoList</name> + <name name="info" arity="1"/> <fsummary>Retrieve information about one driver</fsummary> - <type> - <v>Name = string() | atom()</v> - <v>InfoList = [ InfoItem ]</v> - <v>InfoItem = {Tag, Value}</v> - <v>Tag = atom()</v> - <v>Value = term()</v> - </type> <desc> - <p>Returns a list of tuples <c>{Tag, Value}</c>, where - <c>Tag</c> is the information item and <c>Value</c> is the result + <p>Returns a list of tuples <c>{<anno>Tag</anno>, <anno>Value</anno>}</c>, where + <c><anno>Tag</anno></c> is the information item and <c><anno>Value</anno></c> is the result of calling <seealso marker="#info/2">info/2</seealso> with this driver name and this tag. The result being a tuple list containing all information available about a driver. </p> @@ -305,22 +297,18 @@ </desc> </func> <func> - <name>load(Path, Name) -> ok | {error, ErrorDesc}</name> + <name name="load" arity="2"/> <fsummary>Load a driver</fsummary> - <type> - <v>Path = Name = string() | atom()</v> - <v>ErrorDesc = term()</v> - </type> <desc> - <p>Loads and links the dynamic driver <c>Name</c>. <c>Path</c> + <p>Loads and links the dynamic driver <c><anno>Name</anno></c>. <c><anno>Path</anno></c> is a file path to the directory containing the driver. - <c>Name</c> must be a sharable object/dynamic library. Two - drivers with different <c>Path</c> parameters cannot be - loaded under the same name. The <c>Name</c> is a string or + <c><anno>Name</anno></c> must be a sharable object/dynamic library. Two + drivers with different <c><anno>Path</anno></c> parameters cannot be + loaded under the same name. The <c><anno>Name</anno></c> is a string or atom containing at least one character.</p> - <p>The <c>Name</c> given should correspond to the filename + <p>The <c><anno>Name</anno></c> given should correspond to the filename of the actual dynamically loadable object file residing in - the directory given as <c>Path</c>, but <em>without</em> the + the directory given as <c><anno>Path</anno></c>, but <em>without</em> the extension (i.e. <c>.so</c>). The driver name provided in the driver initialization routine must correspond with the filename, in much the same way as erlang module names @@ -328,14 +316,14 @@ <p>If the driver has been previously unloaded, but is still present due to open ports against it, a call to <c>load/2</c> will stop the unloading and keep the driver - (as long as the <c>Path</c> is the same) and <c>ok</c> is + (as long as the <c><anno>Path</anno></c> is the same) and <c>ok</c> is returned. If one actually wants the object code to be reloaded, one uses <seealso marker="#reload/2">reload/2</seealso> or the low-level interface <seealso marker="#try_load/3">try_load/3</seealso> instead. Please refer to the description of <seealso marker="#scenarios">different scenarios</seealso> for loading/unloading in the introduction.</p> <p>If more than one process tries to load an already loaded - driver withe the same <c>Path</c>, or if the same process + driver withe the same <c><anno>Path</anno></c>, or if the same process tries to load it several times, the function will return <c>ok</c>. The emulator will keep track of the <c>load/2</c> calls, so that a corresponding number of @@ -349,16 +337,16 @@ several drivers with the same name but with different <c>Path</c> parameters.</p> <note> - <p>Note especially that the <c>Path</c> is interpreted + <p>Note especially that the <c><anno>Path</anno></c> is interpreted literally, so that all loaders of the same driver needs to - give the same <em>literal</em><c>Path</c> string, even + give the same <em>literal</em><c><anno>Path</anno></c> string, even though different paths might point out the same directory in the filesystem (due to use of relative paths and links).</p> </note> <p>On success, the function returns <c>ok</c>. On - failure, the return value is <c>{error,ErrorDesc}</c>, - where <c>ErrorDesc</c> is an opaque term to be + failure, the return value is <c>{error,<anno>ErrorDesc</anno>}</c>, + where <c><anno>ErrorDesc</anno></c> is an opaque term to be translated into human readable form by the <seealso marker="#format_error/1">format_error/1</seealso> function.</p> <p>For more control over the error handling, again use the @@ -369,20 +357,16 @@ </desc> </func> <func> - <name>load_driver(Path, Name) -> ok | {error, ErrorDesc}</name> + <name name="load_driver" arity="2"/> <fsummary>Load a driver</fsummary> - <type> - <v>Path = Name = string() | atom()</v> - <v>ErrorDesc = term()</v> - </type> <desc> <p>Works essentially as <c>load/2</c>, but will load the driver - with options other options. All ports that are using the + with other options. All ports that are using the driver will get killed with the reason <c>driver_unloaded</c> when the driver is to be unloaded.</p> <p>The number of loads and unloads by different <seealso marker="#users">users</seealso> influence the actual loading and unloading of a driver file. The port killing will - therefore only happen when the <em>last</em><seealso marker="#users">user</seealso> unloads the driver, or the + therefore only happen when the <em>last</em> <seealso marker="#users">user</seealso> unloads the driver, or the last process having loaded the driver exits.</p> <p>This interface (or at least the name of the functions) is kept for backward compatibility. Using <seealso marker="#try_load/3">try_load/3</seealso> with @@ -551,16 +535,11 @@ </desc> </func> <func> - <name>reload(Path, Name) -> ok | {error, ErrorDesc}</name> + <name name="reload" arity="2"/> <fsummary>Replace a driver</fsummary> - <type> - <v>Path = Name = string() | atom()</v> - <v>ErrorDesc = pending_process | OpaqueError</v> - <v>OpaqueError = term()</v> - </type> <desc> - <p>Reloads the driver named <c>Name</c> from a possibly - different <c>Path</c> than was previously used. This + <p>Reloads the driver named <c><anno>Name</anno></c> from a possibly + different <c><anno>Path</anno></c> than was previously used. This function is used in the code change <seealso marker="#scenarios">scenario</seealso> described in the introduction.</p> <p>If there are other <seealso marker="#users">users</seealso> @@ -574,7 +553,7 @@ <p>If one wants to avoid hanging on open ports, one should use the <seealso marker="#try_load/3">try_load/3</seealso> function instead.</p> - <p>The <c>Name</c> and <c>Path</c> parameters have exactly the + <p>The <c><anno>Name</anno></c> and <c><anno>Path</anno></c> parameters have exactly the same meaning as when calling the plain <seealso marker="#load/2">load/2</seealso> function.</p> <note> <p>Avoid mixing @@ -594,13 +573,8 @@ </desc> </func> <func> - <name>reload_driver(Path, Name) -> ok | {error, ErrorDesc}</name> + <name name="reload_driver" arity="2"/> <fsummary>Replace a driver</fsummary> - <type> - <v>Path = Name = string() | atom()</v> - <v>ErrorDesc = pending_process | OpaqueError</v> - <v>OpaqueError = term()</v> - </type> <desc> <p>Works exactly as <seealso marker="#reload/2">reload/2</seealso>, but for drivers loaded with the <seealso marker="#load_driver/2">load_driver/2</seealso> interface. </p> @@ -1066,15 +1040,11 @@ </desc> </func> <func> - <name>unload(Name) -> ok | {error, ErrorDesc}</name> + <name name="unload" arity="1"/> <fsummary>Unload a driver</fsummary> - <type> - <v>Name = string() | atom()</v> - <v>ErrorDesc = term()</v> - </type> <desc> <p>Unloads, or at least dereferences the driver named - <c>Name</c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, and there + <c><anno>Name</anno></c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, and there are no more open ports using the driver, the driver will actually get unloaded. In all other cases, actual unloading will be delayed until all ports are closed and there are no @@ -1084,7 +1054,7 @@ is no longer considered a user of the driver. For usage scenarios, see the <seealso marker="#scenarios">description</seealso> in the beginning of this document. </p> - <p>The <c>ErrorDesc</c> returned is an opaque value to be + <p>The <c><anno>ErrorDesc</anno></c> returned is an opaque value to be passed further on to the <seealso marker="#format_error/1">format_error/1</seealso> function. For more control over the operation, use the <seealso marker="#try_unload/2">try_unload/2</seealso> @@ -1094,15 +1064,11 @@ </desc> </func> <func> - <name>unload_driver(Name) -> ok | {error, ErrorDesc}</name> + <name name="unload_driver" arity="1"/> <fsummary>Unload a driver</fsummary> - <type> - <v>Name = string() | atom()</v> - <v>ErrorDesc = term()</v> - </type> <desc> <p>Unloads, or at least dereferences the driver named - <c>Name</c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, all + <c><anno>Name</anno></c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, all remaining open ports using the driver will get killed with the reason <c>driver_unloaded</c> and the driver will eventually get unloaded.</p> @@ -1112,7 +1078,7 @@ <seealso marker="#users">user</seealso>. For usage scenarios, see the <seealso marker="#scenarios">description</seealso> in the beginning of this document.</p> - <p>The <c>ErrorDesc</c> returned is an opaque value to be + <p>The <c><anno>ErrorDesc</anno></c> returned is an opaque value to be passed further on to the <seealso marker="#format_error/1">format_error/1</seealso> function. For more control over the operation, use the <seealso marker="#try_unload/2">try_unload/2</seealso> @@ -1125,7 +1091,7 @@ <name>loaded_drivers() -> {ok, Drivers}</name> <fsummary>List loaded drivers</fsummary> <type> - <v>Drivers = [Driver()]</v> + <v>Drivers = [Driver]</v> <v>Driver = string()</v> </type> <desc> @@ -1138,13 +1104,10 @@ </desc> </func> <func> - <name>format_error(ErrorDesc) -> string()</name> + <name name="format_error" arity="1"/> <fsummary>Format an error descriptor</fsummary> - <type> - <v>ErrorDesc -- see below</v> - </type> <desc> - <p>Takes an <c>ErrorDesc</c> returned by load, unload or + <p>Takes an <c><anno>ErrorDesc</anno></c> returned by load, unload or reload functions and returns a string which describes the error or warning.</p> <note> diff --git a/lib/kernel/doc/src/error_handler.xml b/lib/kernel/doc/src/error_handler.xml index 7f78322472..acbf9a2c6e 100644 --- a/lib/kernel/doc/src/error_handler.xml +++ b/lib/kernel/doc/src/error_handler.xml @@ -37,48 +37,44 @@ </description> <funcs> <func> - <name>undefined_function(Module, Function, Args) -> term()</name> + <name name="undefined_function" arity="3"/> <fsummary>Called when an undefined function is encountered</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <d>A (possibly empty) list of arguments <c>Arg1,..,ArgN</c></d> - </type> + <type_desc variable="Args"> + A (possibly empty) list of arguments <c>Arg1,..,ArgN</c> + </type_desc> <desc> <p>This function is evaluated if a call is made to - <c>Module:Function(Arg1,.., ArgN)</c> and - <c>Module:Function/N</c> is undefined. Note that + <c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> and + <c><anno>Module</anno>:<anno>Function</anno>/N</c> is undefined. Note that <c>undefined_function/3</c> is evaluated inside the process making the original call.</p> - <p>If <c>Module</c> is interpreted, the interpreter is invoked + <p>If <c><anno>Module</anno></c> is interpreted, the interpreter is invoked and the return value of the interpreted - <c>Function(Arg1,.., ArgN)</c> call is returned.</p> + <c><anno>Function</anno>(Arg1,.., ArgN)</c> call is returned.</p> <p>Otherwise, it returns, if possible, the value of - <c>apply(Module, Function, Args)</c> after an attempt has been - made to autoload <c>Module</c>. If this is not possible, the - call to <c>Module:Function(Arg1,.., ArgN)</c> fails with + <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> after an attempt has been + made to autoload <c><anno>Module</anno></c>. If this is not possible, the + call to <c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> fails with exit reason <c>undef</c>.</p> </desc> </func> <func> - <name>undefined_lambda(Module, Fun, Args) -> term()</name> + <name name="undefined_lambda" arity="3"/> <fsummary>Called when an undefined lambda (fun) is encountered</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <d>A (possibly empty) list of arguments <c>Arg1,..,ArgN</c></d> - </type> + <type_desc variable="Args"> + A (possibly empty) list of arguments <c>Arg1,..,ArgN</c> + </type_desc> <desc> <p>This function is evaluated if a call is made to - <c>Fun(Arg1,.., ArgN)</c> when the module defining the fun is + <c><anno>Fun</anno>(Arg1,.., ArgN)</c> when the module defining the fun is not loaded. The function is evaluated inside the process making the original call.</p> - <p>If <c>Module</c> is interpreted, the interpreter is invoked + <p>If <c><anno>Module</anno></c> is interpreted, the interpreter is invoked and the return value of the interpreted - <c>Fun(Arg1,.., ArgN)</c> call is returned.</p> + <c><anno>Fun</anno>(Arg1,.., ArgN)</c> call is returned.</p> <p>Otherwise, it returns, if possible, the value of - <c>apply(Fun, Args)</c> after an attempt has been made to - autoload <c>Module</c>. If this is not possible, the call + <c>apply(<anno>Fun</anno>, <anno>Args</anno>)</c> after an attempt has been made to + autoload <c><anno>Module</anno></c>. If this is not possible, the call fails with exit reason <c>undef</c>.</p> </desc> </func> diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index e107d9b746..2d95f96ac7 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -65,19 +65,20 @@ be tagged as warnings or info. Tagging them as warnings may require rewriting existing user defined event handlers.</p> </description> + <datatypes> + <datatype> + <name name="report"/> + </datatype> + </datatypes> <funcs> <func> - <name>error_msg(Format) -> ok</name> - <name>error_msg(Format, Data) -> ok</name> - <name>format(Format, Data) -> ok</name> + <name name="error_msg" arity="1"/> + <name name="error_msg" arity="2"/> + <name name="format" arity="2"/> <fsummary>Send an standard error event to the error logger</fsummary> - <type> - <v>Format = string()</v> - <v>Data = [term()]</v> - </type> <desc> <p>Sends a standard error event to the error logger. - The <c>Format</c> and <c>Data</c> arguments are the same as + The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments are the same as the arguments of <c>io:format/2</c>. The event is handled by the standard event handler.</p> <pre> @@ -94,12 +95,8 @@ ok</pre> </desc> </func> <func> - <name>error_report(Report) -> ok</name> + <name name="error_report" arity="1"/> <fsummary>Send a standard error report event to the error logger</fsummary> - <type> - <v>Report = [{Tag, Data} | term()] | string() | term()</v> - <v> Tag = Data = term()</v> - </type> <desc> <p>Sends a standard error report event to the error logger. The event is handled by the standard event handler.</p> @@ -119,18 +116,13 @@ ok</pre> </desc> </func> <func> - <name>error_report(Type, Report) -> ok</name> + <name name="error_report" arity="2"/> <fsummary>Send a user defined error report event to the error logger</fsummary> - <type> - <v>Type = term()</v> - <v>Report = [{Tag, Data} | term()] | string() | term()</v> - <v> Tag = Data = term()</v> - </type> <desc> <p>Sends a user defined error report event to the error logger. An event handler to handle the event is supposed to have been added. The event is ignored by the standard event handler.</p> - <p>It is recommended that <c>Report</c> follows the same + <p>It is recommended that <c><anno>Report</anno></c> follows the same structure as for <c>error_report/1</c>.</p> </desc> </func> @@ -174,16 +166,12 @@ ok</pre> </desc> </func> <func> - <name>warning_msg(Format) -> ok</name> - <name>warning_msg(Format, Data) -> ok</name> + <name name="warning_msg" arity="1"/> + <name name="warning_msg" arity="2"/> <fsummary>Send a standard warning event to the error logger</fsummary> - <type> - <v>Format = string()</v> - <v>Data = [term()]</v> - </type> <desc> <p>Sends a standard warning event to the error logger. - The <c>Format</c> and <c>Data</c> arguments are the same as + The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments are the same as the arguments of <c>io:format/2</c>. The event is handled by the standard event handler. It is tagged either as an error, warning or info, see @@ -196,12 +184,8 @@ ok</pre> </desc> </func> <func> - <name>warning_report(Report) -> ok</name> + <name name="warning_report" arity="1"/> <fsummary>Send a standard warning report event to the error logger</fsummary> - <type> - <v>Report = [{Tag, Data} | term()] | string() | term()</v> - <v> Tag = Data = term()</v> - </type> <desc> <p>Sends a standard warning report event to the error logger. The event is handled by the standard event handler. It is @@ -210,13 +194,8 @@ ok</pre> </desc> </func> <func> - <name>warning_report(Type, Report) -> ok</name> + <name name="warning_report" arity="2"/> <fsummary>Send a user defined warning report event to the error logger</fsummary> - <type> - <v>Type = term()</v> - <v>Report = [{Tag, Data} | term()] | string() | term()</v> - <v> Tag = Data = term()</v> - </type> <desc> <p>Sends a user defined warning report event to the error logger. An event handler to handle the event is supposed to @@ -227,16 +206,12 @@ ok</pre> </desc> </func> <func> - <name>info_msg(Format) -> ok</name> - <name>info_msg(Format, Data) -> ok</name> + <name name="info_msg" arity="1"/> + <name name="info_msg" arity="2"/> <fsummary>Send a standard information event to the error logger</fsummary> - <type> - <v>Format = string()</v> - <v>Data = [term()]</v> - </type> <desc> <p>Sends a standard information event to the error logger. - The <c>Format</c> and <c>Data</c> arguments are the same as + The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments are the same as the arguments of <c>io:format/2</c>. The event is handled by the standard event handler.</p> <pre> @@ -253,12 +228,8 @@ ok</pre> </desc> </func> <func> - <name>info_report(Report) -> ok</name> + <name name="info_report" arity="1"/> <fsummary>Send a standard information report event to the error logger</fsummary> - <type> - <v>Report = [{Tag, Data} | term()] | string() | term()</v> - <v> Tag = Data = term()</v> - </type> <desc> <p>Sends a standard information report event to the error logger. The event is handled by the standard event handler.</p> @@ -278,63 +249,49 @@ ok</pre> </desc> </func> <func> - <name>info_report(Type, Report) -> ok</name> + <name name="info_report" arity="2"/> <fsummary>Send a user defined information report event to the error logger</fsummary> - <type> - <v>Type = term()</v> - <v>Report = [{Tag, Data} | term()] | string() | term()</v> - <v> Tag = Data = term()</v> - </type> <desc> <p>Sends a user defined information report event to the error logger. An event handler to handle the event is supposed to have been added. The event is ignored by the standard event handler.</p> - <p>It is recommended that <c>Report</c> follows the same + <p>It is recommended that <c><anno>Report</anno></c> follows the same structure as for <c>info_report/1</c>.</p> </desc> </func> <func> - <name>add_report_handler(Handler) -> Result</name> - <name>add_report_handler(Handler, Args) -> Result</name> + <name name="add_report_handler" arity="1"/> + <name name="add_report_handler" arity="2"/> <fsummary>Add an event handler to the error logger</fsummary> - <type> - <v>Handler, Args, Result -- see gen_event:add_handler/3</v> - </type> <desc> <p>Adds a new event handler to the error logger. The event handler must be implemented as a <c>gen_event</c> callback module, see <seealso marker="stdlib:gen_event">gen_event(3)</seealso>.</p> - <p><c>Handler</c> is typically the name of the callback module - and <c>Args</c> is an optional term (defaults to []) passed - to the initialization callback function <c>Module:init/1</c>. + <p><c><anno>Handler</anno></c> is typically the name of the callback module + and <c><anno>Args</anno></c> is an optional term (defaults to []) passed + to the initialization callback function <c><anno>Handler</anno>:init/1</c>. The function returns <c>ok</c> if successful.</p> <p>The event handler must be able to handle the <seealso marker="#events">events</seealso> described below.</p> </desc> </func> <func> - <name>delete_report_handler(Handler) -> Result</name> + <name name="delete_report_handler" arity="1"/> <fsummary>Delete an event handler from the error logger</fsummary> - <type> - <v>Handler, Result -- see gen_event:delete_handler/3</v> - </type> <desc> <p>Deletes an event handler from the error logger by calling - <c>gen_event:delete_handler(error_logger, Handler, [])</c>, + <c>gen_event:delete_handler(error_logger, <anno>Handler</anno>, [])</c>, see <seealso marker="stdlib:gen_event">gen_event(3)</seealso>.</p> </desc> </func> <func> - <name>tty(Flag) -> ok</name> + <name name="tty" arity="1"/> <fsummary>Enable or disable printouts to the tty</fsummary> - <type> - <v>Flag = bool()</v> - </type> <desc> - <p>Enables (<c>Flag == true</c>) or disables - (<c>Flag == false</c>) printout of standard events to the tty.</p> + <p>Enables (<c><anno>Flag</anno> == true</c>) or disables + (<c><anno>Flag</anno> == false</c>) printout of standard events to the tty.</p> <p>This is done by adding or deleting the standard event handler for output to tty, thus calling this function overrides the value of the Kernel <c>error_logger</c> configuration @@ -342,13 +299,15 @@ ok</pre> </desc> </func> <func> - <name>logfile(Request) -> ok | Filename | {error, What}</name> + <name name="logfile" arity="1" clause_i="1"/> + <name name="logfile" arity="1" clause_i="2"/> + <name name="logfile" arity="1" clause_i="3"/> + <type variable="Filename"/> + <type variable="OpenReason" name_i="1"/> + <type variable="CloseReason" name_i="2"/> + <type variable="FilenameReason" name_i="3"/> + <type name="open_error"/> <fsummary>Enable or disable error printouts to a file</fsummary> - <type> - <v>Request = {open, Filename} | close | filename</v> - <v> Filename = atom() | string()</v> - <v>What = allready_have_logfile | no_log_file | term()</v> - </type> <desc> <p>Enables or disables printout of standard events to a file.</p> <p>This is done by adding or deleting the standard event handler @@ -361,22 +320,22 @@ ok</pre> There can only be one active log file at a time.</p> <p><c>Request</c> is one of:</p> <taglist> - <tag><c>{open, Filename}</c></tag> + <tag><c>{open, <anno>Filename</anno>}</c></tag> <item> - <p>Opens the log file <c>Filename</c>. Returns <c>ok</c> if + <p>Opens the log file <c><anno>Filename</anno></c>. Returns <c>ok</c> if successful, or <c>{error, allready_have_logfile}</c> if logging to file is already enabled, or an error tuple if - another error occurred. For example, if <c>Filename</c> + another error occurred. For example, if <c><anno>Filename</anno></c> could not be opened.</p> </item> <tag><c>close</c></tag> <item> <p>Closes the current log file. Returns <c>ok</c>, or - <c>{error, What}</c>.</p> + <c>{error, module_not_found}</c>.</p> </item> <tag><c>filename</c></tag> <item> - <p>Returns the name of the log file <c>Filename</c>, or + <p>Returns the name of the log file <c><anno>Filename</anno></c>, or <c>{error, no_log_file}</c> if logging to file is not enabled.</p> </item> diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 36fce464c5..e0feaf6ee7 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -93,47 +93,76 @@ is UTF-8...</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -iodata() = iolist() | binary() - iolist() = [char() | binary() | iolist()] - -io_device() - as returned by file:open/2, a process handling IO protocols - -name() = string() | atom() | DeepList | RawFilename - DeepList = [char() | atom() | DeepList] - RawFilename = binary() - If VM is in unicode filename mode, string() and char() are allowed to be > 255. - RawFilename is a filename not subject to Unicode translation, meaning that it - can contain characters not conforming to the Unicode encoding expected from the - filesystem (i.e. non-UTF-8 characters although the VM is started in Unicode - filename mode). - -posix() - an atom which is named from the POSIX error codes used in - Unix, and in the runtime libraries of most C compilers - -ext_posix() = posix() | badarg + <datatypes> + <datatype> + <name name="bindings"/> + </datatype> + <datatype> + <name name="deep_list"/> + </datatype> + <datatype> + <name name="fd"/> + </datatype> + <datatype> + <name name="filename"/> + </datatype> + <datatype> + <name name="io_device"/> + <desc> + <p>As returned by + <seealso marker="#open/2">file:open/2</seealso>, + a process handling IO protocols.</p> + </desc> + </datatype> + <datatype> + <name name="name"/> + <desc> + <p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c> + are allowed to be > 255. + <c><anno>RawFilename</anno></c> is a filename not subject to + Unicode translation, + meaning that it can contain characters not conforming to + the Unicode encoding expected from the filesystem + (i.e. non-UTF-8 characters although the VM is started + in Unicode filename mode). + </p> + </desc> + </datatype> + <datatype> + <name name="posix"/> + <desc> + <p>An atom which is named from the POSIX error codes used in + Unix, and in the runtime libraries of most C compilers.</p> + </desc> + </datatype> + <datatype> + <name name="date"/> + </datatype> + <datatype> + <name name="time"/> + </datatype> + <datatype> + <name name="date_time"/> + <desc> + <p>Must denote a valid date and time.</p> + </desc> + </datatype> + <datatype> + <name name="file_info"/> + </datatype> + <datatype> + <name name="location"/> + </datatype> + <datatype> + <name name="mode"/> + </datatype> + </datatypes> -time() = {{Year, Month, Day}, {Hour, Minute, Second}} - Year = Month = Day = Hour = Minute = Second = int() - Must denote a valid date and time</code> - </section> <funcs> <func> - <name>advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason}</name> + <name name="advise" arity="4"/> <fsummary>Predeclare an access pattern for file data</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Offset = int()</v> - <v>Length = int()</v> - <v>Advise = posix_file_advise()</v> - <v>posix_file_advise() = normal | sequential | random | no_reuse - | will_need | dont_need</v> - <v>Reason = ext_posix()</v> - </type> + <type name="posix_file_advise"/> <desc> <p><c>advise/4</c> can be used to announce an intention to access file data in a specific pattern in the future, thus allowing the @@ -142,93 +171,58 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}} </desc> </func> <func> - <name>change_group(Filename, Gid) -> ok | {error, Reason}</name> + <name name="change_group" arity="2"/> <fsummary>Change group of a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Gid = int()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Changes group of a file. See <seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p> </desc> </func> <func> - <name>change_mode(Filename, Mode) -> ok | {error, Reason}</name> + <name name="change_mode" arity="2"/> <fsummary>Change permissions of a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Mode = int()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Changes permissions of a file. See <seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p> </desc> </func> <func> - <name>change_owner(Filename, Uid) -> ok | {error, Reason}</name> + <name name="change_owner" arity="2"/> <fsummary>Change owner of a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Uid = int()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Changes owner of a file. See <seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p> </desc> </func> <func> - <name>change_owner(Filename, Uid, Gid) -> ok | {error, Reason}</name> + <name name="change_owner" arity="3"/> <fsummary>Change owner and group of a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Uid = int()</v> - <v>Gid = int()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Changes owner and group of a file. See <seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p> </desc> </func> <func> - <name>change_time(Filename, Mtime) -> ok | {error, Reason}</name> + <name name="change_time" arity="2"/> <fsummary>Change the modification time of a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Mtime = time()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Changes the modification and access times of a file. See <seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p> </desc> </func> <func> - <name>change_time(Filename, Mtime, Atime) -> ok | {error, Reason}</name> + <name name="change_time" arity="3"/> <fsummary>Change the modification and last access time of a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Mtime = Atime = time()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Changes the modification and last access times of a file. See <seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p> </desc> </func> <func> - <name>close(IoDevice) -> ok | {error, Reason}</name> + <name name="close" arity="1"/> <fsummary>Close a file</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> - <p>Closes the file referenced by <c>IoDevice</c>. It mostly + <p>Closes the file referenced by <c><anno>IoDevice</anno></c>. It mostly returns <c>ok</c>, expect for some severe errors such as out of memory.</p> <p>Note that if the option <c>delayed_write</c> was @@ -238,20 +232,13 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}} </desc> </func> <func> - <name>consult(Filename) -> {ok, Terms} | {error, Reason}</name> + <name name="consult" arity="1"/> <fsummary>Read Erlang terms from a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Terms = [term()]</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> - <p>Reads Erlang terms, separated by '.', from <c>Filename</c>. - Returns one of the following:</p> + <p>Reads Erlang terms, separated by '.', from + <c><anno>Filename</anno></c>. Returns one of the following:</p> <taglist> - <tag><c>{ok, Terms}</c></tag> + <tag><c>{ok, <anno>Terms</anno>}</c></tag> <item> <p>The file was successfully read.</p> </item> @@ -261,7 +248,8 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}} See <seealso marker="#open/2">open/2</seealso> for a list of typical error codes.</p> </item> - <tag><c>{error, {Line, Mod, Term}}</c></tag> + <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>, + <anno>Term</anno>}}</c></tag> <item> <p>An error occurred when interpreting the Erlang terms in the file. Use <c>format_error/1</c> to convert @@ -279,53 +267,46 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>copy(Source, Destination) -></name> - <name>copy(Source, Destination, ByteCount) -> {ok, BytesCopied} | {error, Reason}</name> + <name name="copy" arity="2"/> + <name name="copy" arity="3"/> <fsummary>Copy file contents</fsummary> - <type> - <v>Source = Destination = io_device() | Filename | {Filename, Modes}</v> - <v> Filename = name()</v> - <v> Modes = [Mode] -- see open/2</v> - <v>ByteCount = int() >= 0 | infinity</v> - <v>BytesCopied = int()</v> - </type> <desc> - <p>Copies <c>ByteCount</c> bytes from <c>Source</c> to - <c>Destination</c>. <c>Source</c> and <c>Destination</c> refer + <p>Copies <c><anno>ByteCount</anno></c> bytes from + <c><anno>Source</anno></c> to <c><anno>Destination</anno></c>. + <c><anno>Source</anno></c> and <c><anno>Destination</anno></c> refer to either filenames or IO devices from e.g. <c>open/2</c>. - <c>ByteCount</c> defaults <c>infinity</c>, denoting an + <c><anno>ByteCount</anno></c> defaults to <c>infinity</c>, denoting an infinite number of bytes.</p> - <p>The argument <c>Modes</c> is a list of possible modes, see - <seealso marker="#open/2">open/2</seealso>, and defaults to + <p>The argument <c><anno>Modes</anno></c> is a list of possible modes, + see <seealso marker="#open/2">open/2</seealso>, and defaults to [].</p> - <p>If both <c>Source</c> and <c>Destination</c> refer to + <p>If both <c><anno>Source</anno></c> and + <c><anno>Destination</anno></c> refer to filenames, the files are opened with <c>[read, binary]</c> and <c>[write, binary]</c> prepended to their mode lists, respectively, to optimize the copy.</p> - <p>If <c>Source</c> refers to a filename, it is opened with + <p>If <c><anno>Source</anno></c> refers to a filename, it is opened with <c>read</c> mode prepended to the mode list before the copy, and closed when done.</p> - <p>If <c>Destination</c> refers to a filename, it is opened + <p>If <c><anno>Destination</anno></c> refers to a filename, it is opened with <c>write</c> mode prepended to the mode list before the copy, and closed when done.</p> - <p>Returns <c>{ok, BytesCopied}</c> where <c>BytesCopied</c> is + <p>Returns <c>{ok, <anno>BytesCopied</anno>}</c> where + <c><anno>BytesCopied</anno></c> is the number of bytes that actually was copied, which may be - less than <c>ByteCount</c> if end of file was encountered on - the source. If the operation fails, <c>{error, Reason}</c> is - returned.</p> + less than <c><anno>ByteCount</anno></c> if end of file was + encountered on the source. If the operation fails, + <c>{error, <anno>Reason</anno>}</c> is returned.</p> <p>Typical error reasons: As for <c>open/2</c> if a file had to be opened, and as for <c>read/2</c> and <c>write/2</c>.</p> </desc> </func> <func> - <name>del_dir(Dir) -> ok | {error, Reason}</name> + <name name="del_dir" arity="1"/> <fsummary>Delete a directory</fsummary> - <type> - <v>Dir = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>Tries to delete the directory <c>Dir</c>. The directory must + <p>Tries to delete the directory <c><anno>Dir</anno></c>. + The directory must be empty before it can be deleted. Returns <c>ok</c> if successful.</p> <p>Typical error reasons are:</p> @@ -333,7 +314,7 @@ f.txt: {person, "kalle", 25}. <tag><c>eacces</c></tag> <item> <p>Missing search or write permissions for the parent - directories of <c>Dir</c>.</p> + directories of <c><anno>Dir</anno></c>.</p> </item> <tag><c>eexist</c></tag> <item> @@ -345,8 +326,8 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>enotdir</c></tag> <item> - <p>A component of <c>Dir</c> is not a directory. On some - platforms, <c>enoent</c> is returned instead.</p> + <p>A component of <c><anno>Dir</anno></c> is not a directory. + On some platforms, <c>enoent</c> is returned instead.</p> </item> <tag><c>einval</c></tag> <item> @@ -357,15 +338,11 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>delete(Filename) -> ok | {error, Reason}</name> + <name name="delete" arity="1"/> <fsummary>Delete a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>Tries to delete the file <c>Filename</c>. Returns <c>ok</c> - if successful.</p> + <p>Tries to delete the file <c><anno>Filename</anno></c>. + Returns <c>ok</c> if successful.</p> <p>Typical error reasons are:</p> <taglist> <tag><c>enoent</c></tag> @@ -387,30 +364,25 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>einval</c></tag> <item> - <p><c>Filename</c> had an improper type, such as tuple.</p> + <p><c><anno>Filename</anno></c> had an improper type, such as tuple.</p> </item> </taglist> <warning> - <p>In a future release, a bad type for the <c>Filename</c> - argument will probably generate an exception.</p> + <p>In a future release, a bad type for the + <c><anno>Filename</anno></c> argument will probably generate + an exception.</p> <p></p> </warning> </desc> </func> <func> - <name>eval(Filename) -> ok | {error, Reason}</name> + <name name="eval" arity="1"/> <fsummary>Evaluate Erlang expressions in a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> <p>Reads and evaluates Erlang expressions, separated by '.' (or ',', a sequence of expressions is also an expression), from - <c>Filename</c>. The actual result of the evaluation is not - returned; any expression sequence in the file must be there + <c><anno>Filename</anno></c>. The actual result of the evaluation + is not returned; any expression sequence in the file must be there for its side effect. Returns one of the following:</p> <taglist> <tag><c>ok</c></tag> @@ -422,7 +394,8 @@ f.txt: {person, "kalle", 25}. <p>An error occurred when opening the file or reading it. See <c>open/2</c> for a list of typical error codes.</p> </item> - <tag><c>{error, {Line, Mod, Term}}</c></tag> + <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>, + <anno>Term</anno>}}</c></tag> <item> <p>An error occurred when interpreting the Erlang expressions in the file. Use <c>format_error/1</c> to @@ -433,18 +406,11 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>eval(Filename, Bindings) -> ok | {error, Reason}</name> + <name name="eval" arity="2"/> <fsummary>Evaluate Erlang expressions in a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Bindings -- see erl_eval(3)</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see eval/1</v> - </type> <desc> <p>The same as <c>eval/1</c> but the variable bindings - <c>Bindings</c> are used in the evaluation. See + <c><anno>Bindings</anno></c> are used in the evaluation. See <seealso marker="stdlib:erl_eval">erl_eval(3)</seealso> about variable bindings.</p> </desc> @@ -458,27 +424,19 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>format_error(Reason) -> Chars</name> + <name name="format_error" arity="1"/> <fsummary>Return a descriptive string for an error reason</fsummary> - <type> - <v>Reason = atom() | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see eval/1</v> - <v>Chars = [char() | Chars]</v> - </type> <desc> <p>Given the error reason returned by any function in this module, returns a descriptive string of the error in English.</p> </desc> </func> <func> - <name>get_cwd() -> {ok, Dir} | {error, Reason}</name> + <name name="get_cwd" arity="0"/> <fsummary>Get the current working directory</fsummary> - <type> - <v>Dir = string()</v> - <v>Reason = posix()</v> - </type> <desc> - <p>Returns <c>{ok, Dir}</c>, where <c>Dir</c> is the current + <p>Returns <c>{ok, <anno>Dir</anno>}</c>, where <c><anno>Dir</anno></c> + is the current working directory of the file server.</p> <note> <p>In rare circumstances, this function can fail on Unix. @@ -496,17 +454,14 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>get_cwd(Drive) -> {ok, Dir} | {error, Reason}</name> + <name name="get_cwd" arity="1"/> <fsummary>Get the current working directory for the drive specified</fsummary> - <type> - <v>Drive = string() -- see below</v> - <v>Dir = string()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p><c>Drive</c> should be of the form "<c>Letter</c><c>:</c>", - for example "c:". Returns <c>{ok, Dir}</c> or - <c>{error, Reason}</c>, where <c>Dir</c> is the current + <p><c><anno>Drive</anno></c> should be of the form + "<c>Letter</c><c>:</c>", + for example "c:". Returns <c>{ok, <anno>Dir</anno>}</c> or + <c>{error, <anno>Reason</anno>}</c>, where <c><anno>Dir</anno></c> + is the current working directory of the drive specified.</p> <p>This function returns <c>{error, enotsup}</c> on platforms which have no concept of current drive (Unix, for example).</p> @@ -514,7 +469,7 @@ f.txt: {person, "kalle", 25}. <taglist> <tag><c>enotsup</c></tag> <item> - <p>The operating system have no concept of drives.</p> + <p>The operating system has no concept of drives.</p> </item> <tag><c>eacces</c></tag> <item> @@ -522,32 +477,27 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>einval</c></tag> <item> - <p>The format of <c>Drive</c> is invalid.</p> + <p>The format of <c><anno>Drive</anno></c> is invalid.</p> </item> </taglist> </desc> </func> <func> - <name>list_dir(Dir) -> {ok, Filenames} | {error, Reason}</name> + <name name="list_dir" arity="1"/> <fsummary>List files in a directory</fsummary> - <type> - <v>Dir = name()</v> - <v>Filenames = [Filename]</v> - <v> Filename = string()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Lists all the files in a directory. Returns - <c>{ok, Filenames}</c> if successful. Otherwise, it returns - <c>{error, Reason}</c>. <c>Filenames</c> is a list of + <c>{ok, <anno>Filenames</anno>}</c> if successful. + Otherwise, it returns <c>{error, <anno>Reason</anno>}</c>. + <c><anno>Filenames</anno></c> is a list of the names of all the files in the directory. The names are not sorted.</p> <p>Typical error reasons are:</p> <taglist> <tag><c>eacces</c></tag> <item> - <p>Missing search or write permissions for <c>Dir</c> or - one of its parent directories.</p> + <p>Missing search or write permissions for <c><anno>Dir</anno></c> + or one of its parent directories.</p> </item> <tag><c>enoent</c></tag> <item> @@ -557,14 +507,10 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>make_dir(Dir) -> ok | {error, Reason}</name> + <name name="make_dir" arity="1"/> <fsummary>Make a directory</fsummary> - <type> - <v>Dir = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>Tries to create the directory <c>Dir</c>. Missing parent + <p>Tries to create the directory <c><anno>Dir</anno></c>. Missing parent directories are <em>not</em> created. Returns <c>ok</c> if successful.</p> <p>Typical error reasons are:</p> @@ -572,15 +518,15 @@ f.txt: {person, "kalle", 25}. <tag><c>eacces</c></tag> <item> <p>Missing search or write permissions for the parent - directories of <c>Dir</c>.</p> + directories of <c><anno>Dir</anno></c>.</p> </item> <tag><c>eexist</c></tag> <item> - <p>There is already a file or directory named <c>Dir</c>.</p> + <p>There is already a file or directory named <c><anno>Dir</anno></c>.</p> </item> <tag><c>enoent</c></tag> <item> - <p>A component of <c>Dir</c> does not exist.</p> + <p>A component of <c><anno>Dir</anno></c> does not exist.</p> </item> <tag><c>enospc</c></tag> <item> @@ -588,35 +534,33 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>enotdir</c></tag> <item> - <p>A component of <c>Dir</c> is not a directory. On some - platforms, <c>enoent</c> is returned instead.</p> + <p>A component of <c><anno>Dir</anno></c> is not a directory. + On some platforms, <c>enoent</c> is returned instead.</p> </item> </taglist> </desc> </func> <func> - <name>make_link(Existing, New) -> ok | {error, Reason}</name> + <name name="make_link" arity="2"/> <fsummary>Make a hard link to a file</fsummary> - <type> - <v>Existing = New = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>Makes a hard link from <c>Existing</c> to <c>New</c>, on + <p>Makes a hard link from <c><anno>Existing</anno></c> to + <c><anno>New</anno></c>, on platforms that support links (Unix). This function returns <c>ok</c> if the link was successfully created, or - <c>{error, Reason}</c>. On platforms that do not support + <c>{error, <anno>Reason</anno>}</c>. On platforms that do not support links, <c>{error,enotsup}</c> is returned.</p> <p>Typical error reasons:</p> <taglist> <tag><c>eacces</c></tag> <item> <p>Missing read or write permissions for the parent - directories of <c>Existing</c> or <c>New</c>.</p> + directories of <c><anno>Existing</anno></c> or + <c><anno>New</anno></c>.</p> </item> <tag><c>eexist</c></tag> <item> - <p><c>New</c> already exists.</p> + <p><c><anno>New</anno></c> already exists.</p> </item> <tag><c>enotsup</c></tag> <item> @@ -626,30 +570,28 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>make_symlink(Name1, Name2) -> ok | {error, Reason}</name> + <name name="make_symlink" arity="2"/> <fsummary>Make a symbolic link to a file or directory</fsummary> - <type> - <v>Name1 = Name2 = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>This function creates a symbolic link <c>Name2</c> to - the file or directory <c>Name1</c>, on platforms that support - symbolic links (most Unix systems). <c>Name1</c> need not + <p>This function creates a symbolic link <c><anno>Name2</anno></c> to + the file or directory <c><anno>Name1</anno></c>, on platforms that + support + symbolic links (most Unix systems). <c><anno>Name1</anno></c> need not exist. This function returns <c>ok</c> if the link was - successfully created, or <c>{error, Reason}</c>. On platforms + successfully created, or <c>{error, <anno>Reason</anno>}</c>. + On platforms that do not support symbolic links, <c>{error, enotsup}</c> is returned.</p> <p>Typical error reasons:</p> <taglist> <tag><c>eacces</c></tag> <item> - <p>Missing read or write permissions for the parent - directories of <c>Name1</c> or <c>Name2</c>.</p> + <p>Missing read or write permissions for the parent directories + of <c><anno>Name1</anno></c> or <c><anno>Name2</anno></c>.</p> </item> <tag><c>eexist</c></tag> <item> - <p><c>Name2</c> already exists.</p> + <p><c><anno>Name2</anno></c> already exists.</p> </item> <tag><c>enotsup</c></tag> <item> @@ -668,22 +610,12 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>open(Filename, Modes) -> {ok, IoDevice} | {error, Reason}</name> + <name name="open" arity="2"/> <fsummary>Open a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Modes = [Mode]</v> - <v> Mode = read | write | append | exclusive | raw | binary | {delayed_write, Size, Delay} | delayed_write | {read_ahead, Size} | read_ahead | compressed | {encoding, Encoding}</v> - <v> Size = Delay = int()</v> - <v> Encoding = latin1 | unicode | utf8 | utf16 | {utf16, Endian} | utf32 | {utf32, Endian}</v> - <v> Endian = big | little</v> - <v>IoDevice = io_device()</v> - <v>Reason = ext_posix() | system_limit</v> - </type> <desc> - <p>Opens the file <c>Filename</c> in the mode determined by - <c>Modes</c>, which may contain one or more of the following - items:</p> + <p>Opens the file <c><anno>Filename</anno></c> in the mode determined + by <c><anno>Modes</anno></c>, which may contain one or more of the + following items:</p> <taglist> <tag><c>read</c></tag> <item> @@ -841,23 +773,23 @@ f.txt: {person, "kalle", 25}. </taglist> <p>Returns:</p> <taglist> - <tag><c>{ok, IoDevice}</c></tag> + <tag><c>{ok, <anno>IoDevice</anno>}</c></tag> <item> <p>The file has been opened in the requested mode. - <c>IoDevice</c> is a reference to the file.</p> + <c><anno>IoDevice</anno></c> is a reference to the file.</p> </item> - <tag><c>{error, Reason}</c></tag> + <tag><c>{error, <anno>Reason</anno>}</c></tag> <item> <p>The file could not be opened.</p> </item> </taglist> - <p><c>IoDevice</c> is really the pid of the process which + <p><c><anno>IoDevice</anno></c> is really the pid of the process which handles the file. This process is linked to the process which originally opened the file. If any process to which - the <c>IoDevice</c> is linked terminates, the file will be - closed and the process itself will be terminated. - An <c>IoDevice</c> returned from this call can be used as an - argument to the IO functions (see + the <c><anno>IoDevice</anno></c> is linked terminates, the file will + be closed and the process itself will be terminated. + An <c><anno>IoDevice</anno></c> returned from this call can be used + as an argument to the IO functions (see <seealso marker="stdlib:io">io(3)</seealso>).</p> <note> <p>In previous versions of <c>file</c>, modes were given @@ -897,34 +829,25 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason}</name> + <name name="path_consult" arity="2"/> <fsummary>Read Erlang terms from a file</fsummary> - <type> - <v>Path = [Dir]</v> - <v> Dir = name()</v> - <v>Filename = name()</v> - <v>Terms = [term()]</v> - <v>FullName = string()</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> - <p>Searches the path <c>Path</c> (a list of directory names) - until the file <c>Filename</c> is found. If <c>Filename</c> - is an absolute filename, <c>Path</c> is ignored. + <p>Searches the path <c><anno>Path</anno></c> (a list of directory + names) until the file <c><anno>Filename</anno></c> is found. + If <c><anno>Filename</anno></c> + is an absolute filename, <c><anno>Path</anno></c> is ignored. Then reads Erlang terms, separated by '.', from the file. Returns one of the following:</p> <taglist> - <tag><c>{ok, Terms, FullName}</c></tag> + <tag><c>{ok, <anno>Terms</anno>, <anno>FullName</anno>}</c></tag> <item> - <p>The file was successfully read. <c>FullName</c> is + <p>The file was successfully read. <c><anno>FullName</anno></c> is the full name of the file.</p> </item> <tag><c>{error, enoent}</c></tag> <item> <p>The file could not be found in any of the directories in - <c>Path</c>.</p> + <c><anno>Path</anno></c>.</p> </item> <tag><c>{error, atom()}</c></tag> <item> @@ -932,7 +855,8 @@ f.txt: {person, "kalle", 25}. See <seealso marker="#open/2">open/2</seealso> for a list of typical error codes.</p> </item> - <tag><c>{error, {Line, Mod, Term}}</c></tag> + <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>, + <anno>Term</anno>}}</c></tag> <item> <p>An error occurred when interpreting the Erlang terms in the file. Use <c>format_error/1</c> to convert @@ -943,36 +867,28 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>path_eval(Path, Filename) -> {ok, FullName} | {error, Reason}</name> + <name name="path_eval" arity="2"/> <fsummary>Evaluate Erlang expressions in a file</fsummary> - <type> - <v>Path = [Dir]</v> - <v> Dir = name()</v> - <v>Filename = name()</v> - <v>FullName = string()</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> - <p>Searches the path <c>Path</c> (a list of directory names) - until the file <c>Filename</c> is found. If <c>Filename</c> - is an absolute file name, <c>Path</c> is ignored. Then reads + <p>Searches the path <c><anno>Path</anno></c> (a list of directory + names) until the file <c><anno>Filename</anno></c> is found. + If <c><anno>Filename</anno></c> is an absolute file name, + <c><anno>Path</anno></c> is ignored. Then reads and evaluates Erlang expressions, separated by '.' (or ',', a sequence of expressions is also an expression), from the file. The actual result of evaluation is not returned; any expression sequence in the file must be there for its side effect. Returns one of the following:</p> <taglist> - <tag><c>{ok, FullName}</c></tag> + <tag><c>{ok, <anno>FullName</anno>}</c></tag> <item> - <p>The file was read and evaluated. <c>FullName</c> is + <p>The file was read and evaluated. <c><anno>FullName</anno></c> is the full name of the file.</p> </item> <tag><c>{error, enoent}</c></tag> <item> <p>The file could not be found in any of the directories in - <c>Path</c>.</p> + <c><anno>Path</anno></c>.</p> </item> <tag><c>{error, atom()}</c></tag> <item> @@ -980,7 +896,8 @@ f.txt: {person, "kalle", 25}. See <seealso marker="#open/2">open/2</seealso> for a list of typical error codes.</p> </item> - <tag><c>{error, {Line, Mod, Term}}</c></tag> + <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>, + <anno>Term</anno>}}</c></tag> <item> <p>An error occurred when interpreting the Erlang expressions in the file. Use <c>format_error/1</c> to @@ -991,34 +908,26 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>path_open(Path, Filename, Modes) -> {ok, IoDevice, FullName} | {error, Reason}</name> + <name name="path_open" arity="3"/> <fsummary>Open a file</fsummary> - <type> - <v>Path = [Dir]</v> - <v> Dir = name()</v> - <v>Filename = name()</v> - <v>Modes = [Mode] -- see open/2</v> - <v>IoDevice = io_device()</v> - <v>FullName = string()</v> - <v>Reason = ext_posix() | system_limit</v> - </type> <desc> - <p>Searches the path <c>Path</c> (a list of directory names) - until the file <c>Filename</c> is found. If <c>Filename</c> - is an absolute file name, <c>Path</c> is ignored. - Then opens the file in the mode determined by <c>Modes</c>. + <p>Searches the path <c><anno>Path</anno></c> (a list of directory + names) until the file <c><anno>Filename</anno></c> is found. + If <c><anno>Filename</anno></c> + is an absolute file name, <c><anno>Path</anno></c> is ignored. + Then opens the file in the mode determined by <c><anno>Modes</anno></c>. Returns one of the following:</p> <taglist> - <tag><c>{ok, IoDevice, FullName}</c></tag> + <tag><c>{ok, <anno>IoDevice</anno>, <anno>FullName</anno>}</c></tag> <item> <p>The file has been opened in the requested mode. - <c>IoDevice</c> is a reference to the file and - <c>FullName</c> is the full name of the file.</p> + <c><anno>IoDevice</anno></c> is a reference to the file and + <c><anno>FullName</anno></c> is the full name of the file.</p> </item> <tag><c>{error, enoent}</c></tag> <item> <p>The file could not be found in any of the directories in - <c>Path</c>.</p> + <c><anno>Path</anno></c>.</p> </item> <tag><c>{error, atom()}</c></tag> <item> @@ -1028,36 +937,27 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>path_script(Path, Filename) -> {ok, Value, FullName} | {error, Reason}</name> + <name name="path_script" arity="2"/> <fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary> - <type> - <v>Path = [Dir]</v> - <v> Dir = name()</v> - <v>Filename = name()</v> - <v>Value = term()</v> - <v>FullName = string()</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> - <p>Searches the path <c>Path</c> (a list of directory names) - until the file <c>Filename</c> is found. If <c>Filename</c> - is an absolute file name, <c>Path</c> is ignored. Then reads + <p>Searches the path <c><anno>Path</anno></c> (a list of directory + names) until the file <c><anno>Filename</anno></c> is found. + If <c><anno>Filename</anno></c> is an absolute file name, + <c><anno>Path</anno></c> is ignored. Then reads and evaluates Erlang expressions, separated by '.' (or ',', a sequence of expressions is also an expression), from the file. Returns one of the following:</p> <taglist> - <tag><c>{ok, Value, FullName}</c></tag> + <tag><c>{ok, <anno>Value</anno>, <anno>FullName</anno>}</c></tag> <item> - <p>The file was read and evaluated. <c>FullName</c> is - the full name of the file and <c>Value</c> the value of + <p>The file was read and evaluated. <c><anno>FullName</anno></c> is + the full name of the file and <c><anno>Value</anno></c> the value of the last expression.</p> </item> <tag><c>{error, enoent}</c></tag> <item> <p>The file could not be found in any of the directories in - <c>Path</c>.</p> + <c><anno>Path</anno></c>.</p> </item> <tag><c>{error, atom()}</c></tag> <item> @@ -1065,7 +965,8 @@ f.txt: {person, "kalle", 25}. See <seealso marker="#open/2">open/2</seealso> for a list of typical error codes.</p> </item> - <tag><c>{error, {Line, Mod, Term}}</c></tag> + <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>, + <anno>Term</anno>}}</c></tag> <item> <p>An error occurred when interpreting the Erlang expressions in the file. Use <c>format_error/1</c> to @@ -1076,42 +977,28 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>path_script(Path, Filename, Bindings) -> {ok, Value, FullName} | {error, Reason}</name> + <name name="path_script" arity="3"/> <fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary> - <type> - <v>Path = [Dir]</v> - <v> Dir = name()</v> - <v>Filename = name()</v> - <v>Bindings -- see erl_eval(3)</v> - <v>Value = term()</v> - <v>FullName = string()</v> - <v>Reason = posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see path_script/2</v> - </type> <desc> <p>The same as <c>path_script/2</c> but the variable bindings - <c>Bindings</c> are used in the evaluation. See + <c><anno>Bindings</anno></c> are used in the evaluation. See <seealso marker="stdlib:erl_eval">erl_eval(3)</seealso> about variable bindings.</p> </desc> </func> <func> - <name>pid2name(Pid) -> string() | undefined</name> + <name name="pid2name" arity="1"/> <fsummary>Return the name of the file handled by a pid</fsummary> - <type> - <v>Pid = pid()</v> - </type> <desc> - <p>If <c>Pid</c> is an IO device, that is, a pid returned from + <p>If <c><anno>Pid</anno></c> is an IO device, that is, a pid returned from <c>open/2</c>, this function returns the filename, or rather:</p> <taglist> - <tag><c>{ok, Filename}</c></tag> + <tag><c>{ok, <anno>Filename</anno>}</c></tag> <item> <p>If this node's file server is not a slave, the file was opened by this node's file server, (this implies that - <c>Pid</c> must be a local pid) and the file is not - closed. <c>Filename</c> is the filename in flat string + <c><anno>Pid</anno></c> must be a local pid) and the file is not + closed. <c><anno>Filename</anno></c> is the filename in flat string format.</p> </item> <tag><c>undefined</c></tag> @@ -1125,21 +1012,15 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason}</name> + <name name="position" arity="2"/> <fsummary>Set position in a file</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Location = Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof</v> - <v> Offset = int()</v> - <v>NewPosition = int()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> - <p>Sets the position of the file referenced by <c>IoDevice</c> - to <c>Location</c>. Returns <c>{ok, NewPosition}</c> (as + <p>Sets the position of the file referenced by <c><anno>IoDevice</anno></c> + to <c><anno>Location</anno></c>. Returns + <c>{ok, <anno>NewPosition</anno>}</c> (as absolute offset) if successful, otherwise - <c>{error, Reason}</c>. <c>Location</c> is one of - the following:</p> + <c>{error, <anno>Reason</anno>}</c>. <c><anno>Location</anno></c> is + one of the following:</p> <taglist> <tag><c>Offset</c></tag> <item> @@ -1167,7 +1048,8 @@ f.txt: {person, "kalle", 25}. <taglist> <tag><c>einval</c></tag> <item> - <p>Either <c>Location</c> was illegal, or it evaluated to a + <p>Either <c><anno>Location</anno></c> was illegal, or it + evaluated to a negative offset in the file. Note that if the resulting position is a negative value, the result is an error, and after the call the file position is undefined.</p> @@ -1176,22 +1058,14 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason}</name> + <name name="pread" arity="2"/> <fsummary>Read from a file at certain positions</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>LocNums = [{Location, Number}]</v> - <v> Location -- see position/2</v> - <v> Number = int()</v> - <v>DataL = [Data]</v> - <v> Data = [char()] | binary()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Performs a sequence of <c>pread/3</c> in one operation, which is more efficient than calling them one at a time. - Returns <c>{ok, [Data, ...]}</c> or <c>{error, Reason}</c>, - where each <c>Data</c>, the result of the corresponding + Returns <c>{ok, [<anno>Data</anno>, ...]}</c> or + <c>{error, <anno>Reason</anno>}</c>, + where each <c><anno>Data</anno></c>, the result of the corresponding <c>pread</c>, is either a list or a binary depending on the mode of the file, or <c>eof</c> if the requested position was beyond end of file.</p> @@ -1199,76 +1073,53 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>pread(IoDevice, Location, Number) -> {ok, Data} | eof | {error, Reason}</name> + <name name="pread" arity="3"/> <fsummary>Read from a file at a certain position</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Location -- see position/2</v> - <v>Number = int()</v> - <v>Data = [char()] | binary()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Combines <c>position/2</c> and <c>read/2</c> in one operation, which is more efficient than calling them one at a - time. If <c>IoDevice</c> has been opened in raw mode, some - restrictions apply: <c>Location</c> is only allowed to be an + time. If <c><anno>IoDevice</anno></c> has been opened in raw mode, + some restrictions apply: <c><anno>Location</anno></c> is only allowed + to be an integer; and the current position of the file is undefined after the operation.</p> <p>As the position is given as a byte-offset, special caution has to be taken when working with files where <c>encoding</c> is set to something else than <c>latin1</c>, as not every byte position will be a valid character boundary on such a file.</p> </desc> </func> <func> - <name>pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}}</name> + <name name="pwrite" arity="2"/> <fsummary>Write to a file at certain positions</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>LocBytes = [{Location, Bytes}]</v> - <v> Location -- see position/2</v> - <v> Bytes = iodata()</v> - <v>N = int()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Performs a sequence of <c>pwrite/3</c> in one operation, which is more efficient than calling them one at a time. - Returns <c>ok</c> or <c>{error, {N, Reason}}</c>, where - <c>N</c> is the number of successful writes that was done + Returns <c>ok</c> or <c>{error, {<anno>N</anno>, + <anno>Reason</anno>}}</c>, where + <c><anno>N</anno></c> is the number of successful writes that was done before the failure.</p> <p>When positioning in a file with other <c>encoding</c> than <c>latin1</c>, caution must be taken to set the position on a correct character boundary, see <seealso marker="#position/2">position/2</seealso> for details.</p> </desc> </func> <func> - <name>pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason}</name> + <name name="pwrite" arity="3"/> <fsummary>Write to a file at a certain position</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Location -- see position/2</v> - <v>Bytes = iodata()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Combines <c>position/2</c> and <c>write/2</c> in one operation, which is more efficient than calling them one at a - time. If <c>IoDevice</c> has been opened in raw mode, some - restrictions apply: <c>Location</c> is only allowed to be an + time. If <c><anno>IoDevice</anno></c> has been opened in raw mode, + some restrictions apply: <c><anno>Location</anno></c> is only allowed + to be an integer; and the current position of the file is undefined after the operation.</p> <p>When positioning in a file with other <c>encoding</c> than <c>latin1</c>, caution must be taken to set the position on a correct character boundary, see <seealso marker="#position/2">position/2</seealso> for details.</p> </desc> </func> <func> - <name>read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}</name> + <name name="read" arity="2"/> <fsummary>Read from a file</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Number = int()</v> - <v>Data = [char()] | binary()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> - <p>Reads <c>Number</c> bytes/characters from the file referenced by - <c>IoDevice</c>. The functions <c>read/2</c>, <c>pread/3</c> + <p>Reads <c><anno>Number</anno></c> bytes/characters from the file + referenced by <c><anno>IoDevice</anno></c>. The functions + <c>read/2</c>, <c>pread/3</c> and <c>read_line/1</c> are the only ways to read from a file opened in raw mode (although they work for normally opened files, too).</p> @@ -1276,7 +1127,7 @@ f.txt: {person, "kalle", 25}. <p>Also if <c>encoding</c> is set to something else than <c>latin1</c>, the <c>read/3</c> call will fail if the data contains characters larger than 255, why the <seealso marker="stdlib:io">io(3)</seealso> module is to be preferred when reading such a file.</p> <p>The function returns:</p> <taglist> - <tag><c>{ok, Data}</c></tag> + <tag><c>{ok, <anno>Data</anno>}</c></tag> <item> <p>If the file was opened in binary mode, the read bytes are returned in a binary, otherwise in a list. The list or @@ -1285,10 +1136,10 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>eof</c></tag> <item> - <p>Returned if <c>Number>0</c> and end of file was reached - before anything at all could be read.</p> + <p>Returned if <c><anno>Number</anno>>0</c> and end of file was + reached before anything at all could be read.</p> </item> - <tag><c>{error, Reason}</c></tag> + <tag><c>{error, <anno>Reason</anno>}</c></tag> <item> <p>An error occurred.</p> </item> @@ -1307,17 +1158,14 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>read_file(Filename) -> {ok, Binary} | {error, Reason}</name> + <name name="read_file" arity="1"/> <fsummary>Read a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Binary = binary()</v> - <v>Reason = ext_posix() | terminated | system_limit</v> - </type> <desc> - <p>Returns <c>{ok, Binary}</c>, where <c>Binary</c> is a binary - data object that contains the contents of <c>Filename</c>, or - <c>{error, Reason}</c> if an error occurs.</p> + <p>Returns <c>{ok, <anno>Binary</anno>}</c>, where + <c><anno>Binary</anno></c> is a binary + data object that contains the contents of + <c><anno>Filename</anno></c>, or + <c>{error, <anno>Reason</anno>}</c> if an error occurs.</p> <p>Typical error reasons:</p> <taglist> <tag><c>enoent</c></tag> @@ -1346,17 +1194,13 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>read_file_info(Filename) -> {ok, FileInfo} | {error, Reason}</name> + <name name="read_file_info" arity="1"/> <fsummary>Get information about a file</fsummary> - <type> - <v>Filename = name()</v> - <v>FileInfo = #file_info{}</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Retrieves information about a file. Returns - <c>{ok, FileInfo}</c> if successful, otherwise - <c>{error, Reason}</c>. <c>FileInfo</c> is a record + <c>{ok, <anno>FileInfo</anno>}</c> if successful, otherwise + <c>{error, <anno>Reason</anno>}</c>. <c><anno>FileInfo</anno></c> + is a record <c>file_info</c>, defined in the Kernel include file <c>file.hrl</c>. Include the following directive in the module from which the function is called:</p> @@ -1364,7 +1208,7 @@ f.txt: {person, "kalle", 25}. -include_lib("kernel/include/file.hrl").</code> <p>The record <c>file_info</c> contains the following fields.</p> <taglist> - <tag><c>size = int()</c></tag> + <tag><c>size = integer()</c></tag> <item> <p>Size of file in bytes.</p> </item> @@ -1391,7 +1235,7 @@ f.txt: {person, "kalle", 25}. the file or the inode was changed. In Windows, it is the create time.</p> </item> - <tag><c>mode = int()</c></tag> + <tag><c>mode = integer()</c></tag> <item> <p>The file permissions as the sum of the following bit values:</p> @@ -1422,33 +1266,33 @@ f.txt: {person, "kalle", 25}. <p>On Unix platforms, other bits than those listed above may be set.</p> </item> - <tag><c>links = int()</c></tag> + <tag><c>links = integer()</c></tag> <item> <p>Number of links to the file (this will always be 1 for file systems which have no concept of links).</p> </item> - <tag><c>major_device = int()</c></tag> + <tag><c>major_device = integer()</c></tag> <item> <p>Identifies the file system where the file is located. In Windows, the number indicates a drive as follows: 0 means A:, 1 means B:, and so on.</p> </item> - <tag><c>minor_device = int()</c></tag> + <tag><c>minor_device = integer()</c></tag> <item> <p>Only valid for character devices on Unix. In all other cases, this field is zero.</p> </item> - <tag><c>inode = int()</c></tag> + <tag><c>inode = integer()</c></tag> <item> <p>Gives the <c>inode</c> number. On non-Unix file systems, this field will be zero.</p> </item> - <tag><c>uid = int()</c></tag> + <tag><c>uid = integer()</c></tag> <item> <p>Indicates the owner of the file. Will be zero for non-Unix file systems.</p> </item> - <tag><c>gid = int()</c></tag> + <tag><c>gid = integer()</c></tag> <item> <p>Gives the group that the owner of the file belongs to. Will be zero for non-Unix file systems.</p> @@ -1474,21 +1318,16 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>read_line(IoDevice) -> {ok, Data} | eof | {error, Reason}</name> + <name name="read_line" arity="1"/> <fsummary>Read a line from a file</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Data = [char()] | binary()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Reads a line of bytes/characters from the file referenced by - <c>IoDevice</c>. Lines are defined to be delimited by the linefeed (LF, <c>\n</c>) character, but any carriage return (CR, <c>\r</c>) followed by a newline is also treated as a single LF character (the carriage return is silently ignored). The line is returned <em>including</em> the LF, but excluding any CR immediately followed by a LF. This behaviour is consistent with the behaviour of <seealso marker="stdlib:io#get_line/2">io:get_line/2</seealso>. If end of file is reached without any LF ending the last line, a line with no trailing LF is returned.</p> + <c><anno>IoDevice</anno></c>. Lines are defined to be delimited by the linefeed (LF, <c>\n</c>) character, but any carriage return (CR, <c>\r</c>) followed by a newline is also treated as a single LF character (the carriage return is silently ignored). The line is returned <em>including</em> the LF, but excluding any CR immediately followed by a LF. This behaviour is consistent with the behaviour of <seealso marker="stdlib:io#get_line/2">io:get_line/2</seealso>. If end of file is reached without any LF ending the last line, a line with no trailing LF is returned.</p> <p>The function can be used on files opened in <c>raw</c> mode. It is however inefficient to use it on <c>raw</c> files if the file is not opened with the option <c>{read_ahead, Size}</c> specified, why combining <c>raw</c> and <c>{read_ahead, Size}</c> is highly recommended when opening a text file for raw line oriented reading.</p> <p>If <c>encoding</c> is set to something else than <c>latin1</c>, the <c>read_line/1</c> call will fail if the data contains characters larger than 255, why the <seealso marker="stdlib:io">io(3)</seealso> module is to be preferred when reading such a file.</p> <p>The function returns:</p> <taglist> - <tag><c>{ok, Data}</c></tag> + <tag><c>{ok, <anno>Data</anno>}</c></tag> <item> <p>One line from the file is returned, including the trailing LF, but with CRLF sequences replaced by a single LF (see above).</p> <p>If the file was opened in binary mode, the read bytes are @@ -1499,7 +1338,7 @@ f.txt: {person, "kalle", 25}. <p>Returned if end of file was reached before anything at all could be read.</p> </item> - <tag><c>{error, Reason}</c></tag> + <tag><c>{error, <anno>Reason</anno>}</c></tag> <item> <p>An error occurred.</p> </item> @@ -1518,23 +1357,19 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>read_link(Name) -> {ok, Filename} | {error, Reason}</name> + <name name="read_link" arity="1"/> <fsummary>See what a link is pointing to</fsummary> - <type> - <v>Name = name()</v> - <v>Filename = string()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>This function returns <c>{ok, Filename}</c> if <c>Name</c> - refers to a symbolic link or <c>{error, Reason}</c> otherwise. + <p>This function returns <c>{ok, <anno>Filename</anno>}</c> if + <c><anno>Name</anno></c> refers to a symbolic link or + <c>{error, <anno>Reason</anno>}</c> otherwise. On platforms that do not support symbolic links, the return value will be <c>{error,enotsup}</c>.</p> <p>Typical error reasons:</p> <taglist> <tag><c>einval</c></tag> <item> - <p><c>Linkname</c> does not refer to a symbolic link.</p> + <p><c><anno>Name</anno></c> does not refer to a symbolic link.</p> </item> <tag><c>enoent</c></tag> <item> @@ -1548,34 +1383,26 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>read_link_info(Name) -> {ok, FileInfo} | {error, Reason}</name> + <name name="read_link_info" arity="1"/> <fsummary>Get information about a link or file</fsummary> - <type> - <v>Name = name()</v> - <v>FileInfo = #file_info{}, see read_file_info/1</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>This function works like <c>read_file_info/1</c>, except that - if <c>Name</c> is a symbolic link, information about the link - will be returned in the <c>file_info</c> record and + if <c><anno>Name</anno></c> is a symbolic link, information about + the link will be returned in the <c>file_info</c> record and the <c>type</c> field of the record will be set to <c>symlink</c>.</p> - <p>If <c>Name</c> is not a symbolic link, this function returns + <p>If <c><anno>Name</anno></c> is not a symbolic link, this function returns exactly the same result as <c>read_file_info/1</c>. On platforms that do not support symbolic links, this function is always equivalent to <c>read_file_info/1</c>.</p> </desc> </func> <func> - <name>rename(Source, Destination) -> ok | {error, Reason}</name> + <name name="rename" arity="2"/> <fsummary>Rename a file</fsummary> - <type> - <v>Source = Destination = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> - <p>Tries to rename the file <c>Source</c> to <c>Destination</c>. + <p>Tries to rename the file <c><anno>Source</anno></c> to + <c><anno>Destination</anno></c>. It can be used to move files (and directories) between directories, but it is not sufficient to specify the destination only. The destination file name must also be @@ -1593,25 +1420,28 @@ f.txt: {person, "kalle", 25}. <tag><c>eacces</c></tag> <item> <p>Missing read or write permissions for the parent - directories of <c>Source</c> or <c>Destination</c>. On + directories of <c><anno>Source</anno></c> or + <c><anno>Destination</anno></c>. On some platforms, this error is given if either - <c>Source</c> or <c>Destination</c> is open.</p> + <c><anno>Source</anno></c> or <c><anno>Destination</anno></c> + is open.</p> </item> <tag><c>eexist</c></tag> <item> - <p><c>Destination</c> is not an empty directory. On some - platforms, also given when <c>Source</c> and - <c>Destination</c> are not of the same type.</p> + <p><c><anno>Destination</anno></c> is not an empty directory. + On some platforms, also given when <c><anno>Source</anno></c> and + <c><anno>Destination</anno></c> are not of the same type.</p> </item> <tag><c>einval</c></tag> <item> - <p><c>Source</c> is a root directory, or <c>Destination</c> - is a sub-directory of <c>Source</c>.</p> + <p><c><anno>Source</anno></c> is a root directory, or + <c><anno>Destination</anno></c> + is a sub-directory of <c><anno>Source</anno></c>.</p> </item> <tag><c>eisdir</c></tag> <item> - <p><c>Destination</c> is a directory, but <c>Source</c> is - not.</p> + <p><c><anno>Destination</anno></c> is a directory, but + <c><anno>Source</anno></c> is not.</p> </item> <tag><c>enoent</c></tag> <item> @@ -1619,35 +1449,28 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>enotdir</c></tag> <item> - <p><c>Source</c> is a directory, but <c>Destination</c> is - not.</p> + <p><c><anno>Source</anno></c> is a directory, but + <c><anno>Destination</anno></c> is not.</p> </item> <tag><c>exdev</c></tag> <item> - <p><c>Source</c> and <c>Destination</c> are on different - file systems.</p> + <p><c><anno>Source</anno></c> and <c><anno>Destination</anno></c> + are on different file systems.</p> </item> </taglist> </desc> </func> <func> - <name>script(Filename) -> {ok, Value} | {error, Reason}</name> + <name name="script" arity="1"/> <fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Value = term()</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> <p>Reads and evaluates Erlang expressions, separated by '.' (or ',', a sequence of expressions is also an expression), from the file. Returns one of the following:</p> <taglist> - <tag><c>{ok, Value}</c></tag> + <tag><c>{ok, <anno>Value</anno>}</c></tag> <item> - <p>The file was read and evaluated. <c>Value</c> is + <p>The file was read and evaluated. <c><anno>Value</anno></c> is the value of the last expression.</p> </item> <tag><c>{error, atom()}</c></tag> @@ -1656,7 +1479,8 @@ f.txt: {person, "kalle", 25}. See <seealso marker="#open/2">open/2</seealso> for a list of typical error codes.</p> </item> - <tag><c>{error, {Line, Mod, Term}}</c></tag> + <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>, + <anno>Term</anno>}}</c></tag> <item> <p>An error occurred when interpreting the Erlang expressions in the file. Use <c>format_error/1</c> to @@ -1667,33 +1491,21 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>script(Filename, Bindings) -> {ok, Value} | {error, Reason}</name> + <name name="script" arity="2"/> <fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Bindings -- see erl_eval(3)</v> - <v>Value = term()</v> - <v>Reason = ext_posix() | terminated | system_limit - | {Line, Mod, Term}</v> - <v> Line, Mod, Term -- see below</v> - </type> <desc> <p>The same as <c>script/1</c> but the variable bindings - <c>Bindings</c> are used in the evaluation. See + <c><anno>Bindings</anno></c> are used in the evaluation. See <seealso marker="stdlib:erl_eval">erl_eval(3)</seealso> about variable bindings.</p> </desc> </func> <func> - <name>set_cwd(Dir) -> ok | {error,Reason}</name> + <name name="set_cwd" arity="1"/> <fsummary>Set the current working directory</fsummary> - <type> - <v>Dir = name()</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Sets the current working directory of the file server to - <c>Dir</c>. Returns <c>ok</c> if successful.</p> + <c><anno>Dir</anno></c>. Returns <c>ok</c> if successful.</p> <p>Typical error reasons are:</p> <taglist> <tag><c>enoent</c></tag> @@ -1702,8 +1514,8 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>enotdir</c></tag> <item> - <p>A component of <c>Dir</c> is not a directory. On some - platforms, <c>enoent</c> is returned.</p> + <p>A component of <c><anno>Dir</anno></c> is not a directory. + On some platforms, <c>enoent</c> is returned.</p> </item> <tag><c>eacces</c></tag> <item> @@ -1712,23 +1524,21 @@ f.txt: {person, "kalle", 25}. </item> <tag><c>badarg</c></tag> <item> - <p><c>Filename</c> had an improper type, such as tuple.</p> + <p><c><anno>Dir</anno></c> had an improper type, + such as tuple.</p> </item> </taglist> <warning> - <p>In a future release, a bad type for the <c>Filename</c> + <p>In a future release, a bad type for the + <c><anno>Dir</anno></c> argument will probably generate an exception.</p> <p></p> </warning> </desc> </func> <func> - <name>sync(IoDevice) -> ok | {error, Reason}</name> + <name name="sync" arity="1"/> <fsummary>Synchronizes the in-memory state of a file with that on the physical medium</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Makes sure that any buffers kept by the operating system (not by the Erlang runtime system) are written to disk. On @@ -1743,12 +1553,8 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>datasync(IoDevice) -> ok | {error, Reason}</name> + <name name="datasync" arity="1"/> <fsummary>Synchronizes the in-memory data of a file, ignoring most of its metadata, with that on the physical medium</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> <p>Makes sure that any buffers kept by the operating system (not by the Erlang runtime system) are written to disk. In @@ -1770,32 +1576,23 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>truncate(IoDevice) -> ok | {error, Reason}</name> + <name name="truncate" arity="1"/> <fsummary>Truncate a file</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> - <p>Truncates the file referenced by <c>IoDevice</c> at + <p>Truncates the file referenced by <c><anno>IoDevice</anno></c> at the current position. Returns <c>ok</c> if successful, - otherwise <c>{error, Reason}</c>.</p> + otherwise <c>{error, <anno>Reason</anno>}</c>.</p> </desc> </func> <func> - <name>write(IoDevice, Bytes) -> ok | {error, Reason}</name> + <name name="write" arity="2"/> <fsummary>Write to a file</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Bytes = iodata()</v> - <v>Reason = ext_posix() | terminated</v> - </type> <desc> - <p>Writes <c>Bytes</c> to the file referenced by - <c>IoDevice</c>. This function is the only way to write to a + <p>Writes <c><anno>Bytes</anno></c> to the file referenced by + <c><anno>IoDevice</anno></c>. This function is the only way to write to a file opened in raw mode (although it works for normally opened files, too). Returns <c>ok</c> if successful, and - <c>{error, Reason}</c> otherwise.</p> + <c>{error, <anno>Reason</anno>}</c> otherwise.</p> <p>If the file is opened with <c>encoding</c> set to something else than <c>latin1</c>, each byte written might result in several bytes actually being written to the file, as the byte range 0..255 might represent anything between one and four bytes depending on value and UTF encoding type.</p> <p>Typical error reasons are:</p> <taglist> @@ -1811,18 +1608,14 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>write_file(Filename, Bytes) -> ok | {error, Reason}</name> + <name name="write_file" arity="2"/> <fsummary>Write a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Bytes = iodata()</v> - <v>Reason = ext_posix() | terminated | system_limit</v> - </type> <desc> - <p>Writes the contents of the iodata term <c>Bytes</c> to the - file <c>Filename</c>. The file is created if it does not + <p>Writes the contents of the iodata term <c><anno>Bytes</anno></c> + to the file <c><anno>Filename</anno></c>. + The file is created if it does not exist. If it exists, the previous contents are - overwritten. Returns <c>ok</c>, or <c>{error, Reason}</c>.</p> + overwritten. Returns <c>ok</c>, or <c>{error, <anno>Reason</anno>}</c>.</p> <p>Typical error reasons are:</p> <taglist> <tag><c>enoent</c></tag> @@ -1851,33 +1644,23 @@ f.txt: {person, "kalle", 25}. </desc> </func> <func> - <name>write_file(Filename, Bytes, Modes) -> ok | {error, Reason}</name> + <name name="write_file" arity="3"/> <fsummary>Write a file</fsummary> - <type> - <v>Filename = name()</v> - <v>Bytes = iodata()</v> - <v>Modes = [Mode] -- see open/2</v> - <v>Reason = ext_posix() | terminated | system_limit</v> - </type> <desc> <p>Same as <c>write_file/2</c>, but takes a third argument - <c>Modes</c>, a list of possible modes, see + <c><anno>Modes</anno></c>, a list of possible modes, see <seealso marker="#open/2">open/2</seealso>. The mode flags <c>binary</c> and <c>write</c> are implicit, so they should not be used.</p> </desc> </func> <func> - <name>write_file_info(Filename, FileInfo) -> ok | {error, Reason}</name> + <name name="write_file_info" arity="2"/> <fsummary>Change information about a file</fsummary> - <type> - <v>Filename = name()</v> - <v>FileInfo = #file_info{} -- see also read_file_info/1</v> - <v>Reason = ext_posix()</v> - </type> <desc> <p>Change file information. Returns <c>ok</c> if successful, - otherwise <c>{error, Reason}</c>. <c>FileInfo</c> is a record + otherwise <c>{error, <anno>Reason</anno>}</c>. + <c><anno>FileInfo</anno></c> is a record <c>file_info</c>, defined in the Kernel include file <c>file.hrl</c>. Include the following directive in the module from which the function is called:</p> @@ -1901,7 +1684,7 @@ f.txt: {person, "kalle", 25}. time). On Windows, this field is the new creation time to set for the file.</p> </item> - <tag><c>mode = int()</c></tag> + <tag><c>mode = integer()</c></tag> <item> <p>The file permissions as the sum of the following bit values:</p> @@ -1932,12 +1715,12 @@ f.txt: {person, "kalle", 25}. <p>On Unix platforms, other bits than those listed above may be set.</p> </item> - <tag><c>uid = int()</c></tag> + <tag><c>uid = integer()</c></tag> <item> <p>Indicates the owner of the file. Ignored for non-Unix file systems.</p> </item> - <tag><c>gid = int()</c></tag> + <tag><c>gid = integer()</c></tag> <item> <p>Gives the group that the owner of the file belongs to. Ignored non-Unix file systems.</p> diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml index fb09092f1c..5ceb82ae41 100644 --- a/lib/kernel/doc/src/gen_sctp.xml +++ b/lib/kernel/doc/src/gen_sctp.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2007</year><year>2010</year> + <year>2007</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -65,77 +65,71 @@ <item><seealso marker="#seealso">SEE ALSO</seealso></item> <item><seealso marker="#authors">AUTHORS</seealso></item> </list> + <marker id="types"></marker> </section> - <section> - <marker id="types"></marker> - <title>DATA TYPES</title> - <marker id="type-assoc_id"></marker> - <taglist> - <tag><c>assoc_id()</c></tag> - <item> + <datatypes> + <datatype> + <name name="assoc_id"/> + <desc> <p>An opaque term returned in for example #sctp_paddr_change{} that identifies an association for an SCTP socket. The term is opaque except for the special value <c>0</c> that has a - meaning such as "the whole endpoint" or "all future associations".</p> - <marker id="type-charlist"></marker> - </item> - <tag><c>charlist() = [char()]</c></tag> - <item> <marker id="type-iolist"></marker> -</item> - <tag><c>iolist() = [char() | binary()]</c></tag> - <item> <marker id="type-ip_address"></marker> -</item> - <tag><c>ip_address()</c></tag> - <item> + meaning such as "the whole endpoint" or "all future associations". + </p> + </desc> + </datatype> + <datatype> + <name name="hostname"/> + </datatype> + <datatype> + <name name="ip_address"/> + <desc> <p>Represents an address of an SCTP socket. It is a tuple as explained in <seealso marker="inet">inet(3)</seealso>.</p> - <marker id="type-port_number"></marker> - </item> - <tag><c>port_number() = 0 .. 65535</c></tag> - <item> <marker id="type-posix"></marker> -</item> - <tag><c>posix()</c></tag> - <item> - <p>See - <seealso marker="inet#error_codes">inet(3); POSIX Error Codes.</seealso></p> - <marker id="type-sctp_option"></marker> - </item> - <tag><c>sctp_option()</c></tag> - <item> + </desc> + </datatype> + <datatype> + <name name="port_number"/> + </datatype> + <datatype> + <name name="posix"/> + <desc> + <p>See <seealso marker="inet#error_codes"> + inet(3); POSIX Error Codes</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="sctp_option"/> + <desc> <p>One of the <seealso marker="#options">SCTP Socket Options.</seealso></p> <marker id="type-sctp_socket"></marker> - </item> - <tag><c>sctp_socket()</c></tag> - <item> + </desc> + </datatype> + <datatype> + <name name="sctp_socket"/> + <desc> <p>Socket identifier returned from <c>open/*</c>.</p> - <marker id="type-timeout"></marker> - </item> - <tag><c>timeout() = int() | infinity</c></tag> - <item> - <p>Timeout used in SCTP connect and receive calls.</p> - </item> - </taglist> - <marker id="exports"></marker> - </section> + <marker id="exports"></marker> + </desc> + </datatype> + </datatypes> + <funcs> <func> - <name>abort(sctp_socket(), Assoc) -> ok | {error, posix()}</name> + <name name="abort" arity="2"/> <fsummary>Abnormally terminate the association given by Assoc, without flushing of unsent data</fsummary> - <type> - <v>Assoc = #sctp_assoc_change{}</v> - </type> <desc> - <p>Abnormally terminates the association given by <c>Assoc</c>, without + <p>Abnormally terminates the association given by <c><anno>Assoc</anno></c>, without flushing of unsent data. The socket itself remains open. Other associations opened on this socket are still valid, and it can be used in new associations.</p> </desc> </func> <func> - <name>close(sctp_socket()) -> ok | {error, posix()}</name> + <name name="close" arity="1"/> <fsummary>Completely close the socket and all associations on it</fsummary> <desc> <p>Completely closes the socket and all associations on it. The unsent @@ -148,35 +142,26 @@ </desc> </func> <func> - <name>connect(Socket, Addr, Port, Opts) -> {ok,Assoc} | {error, posix()}</name> + <name name="connect" arity="4"/> <fsummary>Same as <c>connect(Socket, Addr, Port, Opts, infinity)</c>.</fsummary> <desc> - <p>Same as <c>connect(Socket, Addr, Port, Opts, infinity)</c>.</p> + <p>Same as <c>connect(<anno>Socket</anno>, <anno>Addr</anno>, <anno>Port</anno>, <anno>Opts</anno>, infinity)</c>.</p> </desc> </func> <func> - <name>connect(Socket, Addr, Port, [Opt], Timeout) -> {ok, Assoc} | {error, posix()}</name> + <name name="connect" arity="5"/> <fsummary>Establish a new association for the socket <c>Socket</c>, with a peer (SCTP server socket)</fsummary> - <type> - <v>Socket = sctp_socket()</v> - <v>Addr = ip_address() | Host</v> - <v>Port = port_number()</v> - <v>Opt = sctp_option()</v> - <v>Timeout = timeout()</v> - <v>Host = atom() | string()</v> - <v>Assoc = #sctp_assoc_change{}</v> - </type> <desc> - <p>Establishes a new association for the socket <c>Socket</c>, + <p>Establishes a new association for the socket <c><anno>Socket</anno></c>, with the peer (SCTP server socket) given by - <c>Addr</c> and <c>Port</c>. The <c>Timeout</c>, + <c><anno>Addr</anno></c> and <c><anno>Port</anno></c>. The <c><anno>Timeout</anno></c>, is expressed in milliseconds. A socket can be associated with multiple peers.</p> - <p><b>WARNING:</b>Using a value of <c>Timeout</c> less than + <p><b>WARNING:</b>Using a value of <c><anno>Timeout</anno></c> less than the maximum time taken by the OS to establish an association (around 4.5 minutes if the default values from RFC 4960 are used) can result in inconsistent or incorrect return values. This is especially - relevant for associations sharing the same <c>Socket</c> + relevant for associations sharing the same <c><anno>Socket</anno></c> (i.e. source address and port) since the controlling process blocks until <c>connect/*</c> returns. <seealso marker="#connect_init/4">connect_init/*</seealso> @@ -185,7 +170,7 @@ <p><marker id="record-sctp_assoc_change"></marker> The result of <c>connect/*</c> is an <c>#sctp_assoc_change{}</c> event which contains, in particular, the new - <seealso marker="#type-assoc_id">Association ID:</seealso></p> + <seealso marker="#type-assoc_id">Association ID</seealso>.</p> <pre> #sctp_assoc_change{ state = atom(), @@ -198,13 +183,13 @@ giving an <c>sctp_initmsg</c> option to <c>connect</c> as in:</p> <pre> - connect(Socket, Ip, Port, + connect(<anno>Socket</anno>, Ip, <anno>Port</anno>, [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams, max_instreams=MaxInStreams}}]) </pre> - <p>All options <c>Opt</c> are set on the socket before the + <p>All options <c><anno>Opt</anno></c> are set on the socket before the association is attempted. If an option record has got undefined field values, the options record is first read from the socket - for those values. In effect, <c>Opt</c> option records only + for those values. In effect, <c><anno>Opt</anno></c> option records only define field values to change before connecting.</p> <p>The returned <c>outbound_streams</c> and <c>inbound_streams</c> are the actual stream numbers on the socket, which may be different @@ -242,27 +227,19 @@ </desc> </func> <func> - <name>connect_init(Socket, Addr, Port, Opts) -> ok | {error, posix()}</name> + <name name="connect_init" arity="4"/> <fsummary>Same as <c>connect_init(Socket, Addr, Port, Opts, infinity)</c>.</fsummary> <desc> - <p>Same as <c>connect_init(Socket, Addr, Port, Opts, infinity)</c>.</p> + <p>Same as <c>connect_init(<anno>Socket</anno>, <anno>Addr</anno>, <anno>Port</anno>, <anno>Opts</anno>, infinity)</c>.</p> </desc> </func> <func> - <name>connect_init(Socket, Addr, Port, [Opt], Timeout) -> ok | {error, posix()}</name> + <name name="connect_init" arity="5"/> <fsummary>Initiate a new association for the socket <c>Socket</c>, with a peer (SCTP server socket)</fsummary> - <type> - <v>Socket = sctp_socket()</v> - <v>Addr = ip_address() | Host</v> - <v>Port = port_number()</v> - <v>Opt = sctp_option()</v> - <v>Timeout = timeout()</v> - <v>Host = atom() | string()</v> - </type> <desc> - <p>Initiates a new association for the socket <c>Socket</c>, + <p>Initiates a new association for the socket <c><anno>Socket</anno></c>, with the peer (SCTP server socket) given by - <c>Addr</c> and <c>Port</c>.</p> + <c><anno>Addr</anno></c> and <c><anno>Port</anno></c>.</p> <p>The fundamental difference between this API and <c>connect/*</c> is that the return value is that of the underlying OS connect(2) system call. If <c>ok</c> is returned @@ -275,64 +252,52 @@ active option.</p> <p>The parameters are as described in <seealso marker="#connect/5">connect/*</seealso>, with the - exception of the <c>Timeout</c> value.</p> - <p>The timer associated with <c>Timeout</c> only supervises - IP resolution of <c>Addr</c></p> + exception of the <c><anno>Timeout</anno></c> value.</p> + <p>The timer associated with <c><anno>Timeout</anno></c> only supervises + IP resolution of <c><anno>Addr</anno></c></p> </desc> </func> <func> - <name>controlling_process(sctp_socket(), pid()) -> ok</name> + <name name="controlling_process" arity="2"/> <fsummary>Assign a new controlling process pid to the socket</fsummary> <desc> - <p>Assigns a new controlling process Pid to Socket. Same implementation + <p>Assigns a new controlling process <c><anno>Pid</anno></c> to <c><anno>Socket</anno></c>. Same implementation as <c>gen_udp:controlling_process/2</c>.</p> </desc> </func> <func> - <name>eof(Socket, Assoc) -> ok | {error, Reason}</name> + <name name="eof" arity="2"/> <fsummary>Gracefully terminate the association given by Assoc, with flushing of all unsent data</fsummary> - <type> - <v>Socket = sctp_socket()</v> - <v>Assoc = #sctp_assoc_change{}</v> - </type> <desc> - <p>Gracefully terminates the association given by <c>Assoc</c>, with + <p>Gracefully terminates the association given by <c><anno>Assoc</anno></c>, with flushing of all unsent data. The socket itself remains open. Other associations opened on this socket are still valid, and it can be used in new associations.</p> </desc> </func> <func> - <name>listen(Socket, IsServer) -> ok | {error, Reason}</name> + <name name="listen" arity="2"/> <fsummary>Set up a socket to listen.</fsummary> - <type> - <v>Socket = sctp_socket()</v> - <v>IsServer = bool()</v> - </type> <desc> <p>Sets up a socket to listen on the IP address and port number - it is bound to. IsServer must be 'true' or 'false'. + it is bound to. <c><anno>IsServer</anno></c> must be <c>true</c> + or <c>false</c>. In the contrast to TCP, in SCTP there is no listening queue length. - If IsServer is 'true' the socket accepts new associations, i.e. + If <c><anno>IsServer</anno></c> is <c>true</c> the socket accepts new associations, i.e. it will become an SCTP server socket.</p> </desc> </func> <func> - <name>open() -> {ok, Socket} | {error, posix()}</name> - <name>open(Port) -> {ok, Socket} | {error, posix()}</name> - <name>open([Opt]) -> {ok, Socket} | {error, posix()}</name> - <name>open(Port, [Opt]) -> {ok, Socket} | {error, posix()}</name> + <name name="open" arity="0"/> + <name name="open" arity="1" clause_i="1"/> + <name name="open" arity="1" clause_i="2"/> + <name name="open" arity="2"/> <fsummary>Create an SCTP socket and bind it to local addresses</fsummary> - <type> - <v>Opt = {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option()</v> - <v>IP = ip_address() | any | loopback</v> - <v>Port = port_number()</v> - </type> <desc> <p>Creates an SCTP socket and binds it to the local addresses - specified by all <c>{ip,IP}</c> (or synonymously <c>{ifaddr,IP}</c>) + specified by all <c>{ip,<anno>IP</anno>}</c> (or synonymously <c>{ifaddr,<anno>IP</anno>}</c>) options (this feature is called SCTP multi-homing). - The default <c>IP</c> and <c>Port</c> are <c>any</c> + The default <c><anno>IP</anno></c> and <c><anno>Port</anno></c> are <c>any</c> and <c>0</c>, meaning bind to all local addresses on any one free port.</p> <p>A default set of socket <seealso marker="#options">options</seealso> @@ -345,27 +310,16 @@ </desc> </func> <func> - <name>recv(sctp_socket()) -> {ok, {FromIP, FromPort, AncData, BinMsg}} | {error, Reason}</name> - <name>recv(sctp_socket(), timeout()) -> {ok, {FromIP, FromPort, AncData, Data}} | {error, Reason}</name> + <name name="recv" arity="1"/> + <name name="recv" arity="2"/> <fsummary>Receive a message from a socket</fsummary> - <type> - <v>FromIP = ip_address()</v> - <v>FromPort = port_number()</v> - <v>AncData = [#sctp_sndrcvinfo{}]</v> - <v>Data = binary() | charlist() | #sctp_sndrcvinfo{} | - #sctp_assoc_change{} | #sctp_paddr_change{} | - #sctp_adaptation_event{} </v> - <v>Reason = posix() | #sctp_send_failed{} | #scpt_paddr_change{} | - #sctp_pdapi_event{} | #sctp_remote_error{} | - #sctp_shutdown_event{}</v> - </type> <desc> - <p>Receives the <c>Data</c> message from any association of the socket. + <p>Receives the <c><anno>Data</anno></c> message from any association of the socket. If the receive times out <c>{error,timeout</c> is returned. The default timeout is <c>infinity</c>. - <c>FromIP</c> and <c>FromPort</c> indicate the sender's address.</p> - <p><c>AncData</c> is a list of Ancillary Data items which - may be received along with the main <c>Data</c>. + <c><anno>FromIP</anno></c> and <c><anno>FromPort</anno></c> indicate the sender's address.</p> + <p><c><anno>AncData</anno></c> is a list of Ancillary Data items which + may be received along with the main <c><anno>Data</anno></c>. This list can be empty, or contain a single <seealso marker="#record-sctp_sndrcvinfo">#sctp_sndrcvinfo{}</seealso> record, if receiving of such ancillary data is enabled @@ -375,10 +329,10 @@ provide an easy way of determining the association and stream over which the message has been received. (An alternative way would be to get the Association ID from the - <c>FromIP</c> and <c>FromPort</c> using the + <c><anno>FromIP</anno></c> and <c><anno>FromPort</anno></c> using the <seealso marker="#option-sctp_get_peer_addr_info">sctp_get_peer_addr_info</seealso> socket option, but this would still not produce the Stream number).</p> - <p>The actual <c>Data</c> received may be a <c>binary()</c>, + <p>The actual <c><anno>Data</anno></c> received may be a <c>binary()</c>, or <c>list()</c> of bytes (integers in the range 0 through 255) depending on the socket mode, or an SCTP Event. <marker id="sctp_events"></marker> @@ -476,15 +430,10 @@ </desc> </func> <func> - <name>send(Socket, SndRcvInfo, Data) -> ok | {error, Reason}</name> + <name name="send" arity="3"/> <fsummary>Send a message using an <c>#sctp_sndrcvinfo{}</c>record</fsummary> - <type> - <v>Socket = sctp_socket()</v> - <v>SndRcvInfo = #sctp_sndrcvinfo{}</v> - <v>Data = binary() | iolist()</v> - </type> <desc> - <p>Sends the <c>Data</c> message with all sending parameters from a + <p>Sends the <c><anno>Data</anno></c> message with all sending parameters from a <seealso marker="#record-sctp_sndrcvinfo">#sctp_sndrcvinfo{}</seealso> record. This way, the user can specify the PPID (passed to the remote end) and Context (passed to the local SCTP layer) which can be used @@ -494,21 +443,15 @@ </desc> </func> <func> - <name>send(Socket, Assoc, Stream, Data) -> ok | {error, Reason}</name> + <name name="send" arity="4"/> <fsummary>Send a message over an existing association and given stream</fsummary> - <type> - <v>Socket = sctp_socket()</v> - <v>Assoc = #sctp_assoc_change{} | assoc_id()</v> - <v>Stream = integer()</v> - <v>Data = binary() | iolist()</v> - </type> <desc> - <p>Sends <c>Data</c> message over an existing association and given + <p>Sends <c><anno>Data</anno></c> message over an existing association and given stream.</p> </desc> </func> <func> - <name>error_string(integer()) -> ok | string() | undefined</name> + <name name="error_string" arity="1"/> <fsummary>Translate an SCTP error number into a string</fsummary> <desc> <p>Translates an SCTP error number from for example diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index aa171c77c2..f1d42d9faa 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2010</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -63,36 +63,45 @@ do_recv(Sock, Bs) -> <p>For more examples, see the <seealso marker="#examples">examples</seealso> section.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -ip_address() - see inet(3) - -posix() - see inet(3) + <datatypes> + <datatype> + <name name="hostname"/> + </datatype> + <datatype> + <name name="ip_address"/> + <desc> + <p>Represents an address of a TCP socket. + It is a tuple as explained in + <seealso marker="inet">inet(3)</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="port_number"/> + </datatype> + <datatype> + <name name="posix"/> + <desc> + <p>See <seealso marker="inet#error_codes"> + inet(3); POSIX Error Codes</seealso>.</p> + </desc> + </datatype> + <datatype> + <name><marker id="type-socket">socket()</marker></name> + <desc> + <p>As returned by accept/1,2 and connect/3,4.</p> + <marker id="connect"></marker> + </desc> + </datatype> + </datatypes> -socket() - as returned by accept/1,2 and connect/3,4</code> - <marker id="connect"></marker> - </section> <funcs> <func> - <name>connect(Address, Port, Options) -> {ok, Socket} | {error, Reason}</name> - <name>connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason}</name> + <name name="connect" arity="3"/> + <name name="connect" arity="4"/> <fsummary>Connect to a TCP port</fsummary> - <type> - <v>Address = string() | atom() | ip_address()</v> - <v>Port = 0..65535</v> - <v>Options = [Opt]</v> - <v> Opt -- see below</v> - <v>Timeout = int() | infinity</v> - <v>Socket = socket()</v> - <v>Reason = posix()</v> - </type> <desc> - <p>Connects to a server on TCP port <c>Port</c> on the host - with IP address <c>Address</c>. The <c>Address</c> argument + <p>Connects to a server on TCP port <c><anno>Port</anno></c> on the host + with IP address <c><anno>Address</anno></c>. The <c><anno>Address</anno></c> argument can be either a hostname, or an IP address.</p> <p>The available options are:</p> <taglist> @@ -127,13 +136,13 @@ socket() <item> <p>Set up the socket for IPv4.</p> </item> - <tag>Opt</tag> + <tag><c>Opt</c></tag> <item> <p>See <seealso marker="inet#setopts/2">inet:setopts/2</seealso>.</p> </item> </taglist> - <p>Packets can be sent to the returned socket <c>Socket</c> + <p>Packets can be sent to the returned socket <c><anno>Socket</anno></c> using <c>send/2</c>. Packets sent from the peer are delivered as messages:</p> <code type="none"> @@ -148,7 +157,7 @@ socket() <p>unless <c>{active, false}</c> is specified in the option list for the socket, in which case packets are retrieved by calling <c>recv/2</c>.</p> - <p>The optional <c>Timeout</c> parameter specifies a timeout in + <p>The optional <c><anno>Timeout</anno></c> parameter specifies a timeout in milliseconds. The default value is <c>infinity</c>.</p> <note> <p>The default values for options given to <c>connect</c> can @@ -159,19 +168,12 @@ socket() </desc> </func> <func> - <name>listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}</name> + <name name="listen" arity="2"/> <fsummary>Set up a socket to listen on a port</fsummary> - <type> - <v>Port = 0..65535</v> - <v>Options = [Opt]</v> - <v> Opt -- see below</v> - <v>ListenSocket -- see below</v> - <v>Reason = posix()</v> - </type> <desc> - <p>Sets up a socket to listen on the port <c>Port</c> on + <p>Sets up a socket to listen on the port <c><anno>Port</anno></c> on the local host.</p> - <p>If <c>Port == 0</c>, the underlying OS assigns an available + <p>If <c><anno>Port</anno> == 0</c>, the underlying OS assigns an available port number, use <c>inet:port/1</c> to retrieve it.</p> <p>The available options are:</p> <taglist> @@ -214,7 +216,7 @@ socket() <seealso marker="inet#setopts/2">inet:setopts/2</seealso>.</p> </item> </taglist> - <p>The returned socket <c>ListenSocket</c> can only be used in + <p>The returned socket <c><anno>ListenSocket</anno></c> can only be used in calls to <c>accept/1,2</c>.</p> <note> <p>The default values for options given to <c>listen</c> can @@ -225,27 +227,23 @@ socket() </desc> </func> <func> - <name>accept(ListenSocket) -> {ok, Socket} | {error, Reason}</name> - <name>accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}</name> + <name name="accept" arity="1"/> + <name name="accept" arity="2"/> <fsummary>Accept an incoming connection request on a listen socket</fsummary> - <type> - <v>ListenSocket -- see listen/2</v> - <v>Timeout = int() | infinity</v> - <v>Socket = socket()</v> - <v>Reason = closed | timeout | posix()</v> - </type> + <type_desc variable="ListenSocket">Returned by <c>listen/2</c>. + </type_desc> <desc> <p>Accepts an incoming connection request on a listen socket. - <c>Socket</c> must be a socket returned from <c>listen/2</c>. - <c>Timeout</c> specifies a timeout value in ms, defaults to + <c><anno>Socket</anno></c> must be a socket returned from <c>listen/2</c>. + <c><anno>Timeout</anno></c> specifies a timeout value in ms, defaults to <c>infinity</c>.</p> - <p>Returns <c>{ok, Socket}</c> if a connection is established, - or <c>{error, closed}</c> if <c>ListenSocket</c> is closed, + <p>Returns <c>{ok, <anno>Socket</anno>}</c> if a connection is established, + or <c>{error, closed}</c> if <c><anno>ListenSocket</anno></c> is closed, or <c>{error, timeout}</c> if no connection is established within the specified time. May also return a POSIX error value if something else goes wrong, see inet(3) for possible error values.</p> - <p>Packets can be sent to the returned socket <c>Socket</c> + <p>Packets can be sent to the returned socket <c><anno>Socket</anno></c> using <c>send/2</c>. Packets sent from the peer are delivered as messages:</p> <code type="none"> @@ -264,13 +262,8 @@ socket() </desc> </func> <func> - <name>send(Socket, Packet) -> ok | {error, Reason}</name> + <name name="send" arity="2"/> <fsummary>Send a packet</fsummary> - <type> - <v>Socket = socket()</v> - <v>Packet = [char()] | binary()</v> - <v>Reason = posix()</v> - </type> <desc> <p>Sends a packet on a socket. </p> <p>There is no <c>send</c> call with timeout option, you use the @@ -279,70 +272,52 @@ socket() </desc> </func> <func> - <name>recv(Socket, Length) -> {ok, Packet} | {error, Reason}</name> - <name>recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason}</name> + <name name="recv" arity="2"/> + <name name="recv" arity="3"/> <fsummary>Receive a packet from a passive socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Length = int()</v> - <v>Packet = [char()] | binary() | HttpPacket</v> - <v>Timeout = int() | infinity</v> - <v>Reason = closed | posix()</v> - <v>HttpPacket = see the description of <c>HttpPacket</c> in <seealso marker="erts:erlang#decode_packet/3">erlang:decode_packet/3</seealso></v> - </type> + <type_desc variable="HttpPacket">See the description of + <c>HttpPacket</c> in <seealso marker="erts:erlang#decode_packet/3"> + erlang:decode_packet/3</seealso>. + </type_desc> <desc> <p>This function receives a packet from a socket in passive mode. A closed socket is indicated by a return value <c>{error, closed}</c>.</p> - <p>The <c>Length</c> argument is only meaningful when + <p>The <c><anno>Length</anno></c> argument is only meaningful when the socket is in <c>raw</c> mode and denotes the number of - bytes to read. If <c>Length</c> = 0, all available bytes are - returned. If <c>Length</c> > 0, exactly <c>Length</c> + bytes to read. If <c><anno>Length</anno></c> = 0, all available bytes are + returned. If <c><anno>Length</anno></c> > 0, exactly <c><anno>Length</anno></c> bytes are returned, or an error; possibly discarding less - than <c>Length</c> bytes of data when the socket gets closed + than <c><anno>Length</anno></c> bytes of data when the socket gets closed from the other side.</p> - <p>The optional <c>Timeout</c> parameter specifies a timeout in + <p>The optional <c><anno>Timeout</anno></c> parameter specifies a timeout in milliseconds. The default value is <c>infinity</c>.</p> </desc> </func> <func> - <name>controlling_process(Socket, Pid) -> ok | {error, Reason}</name> + <name name="controlling_process" arity="2"/> <fsummary>Change controlling process of a socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Pid = pid()</v> - <v>Reason = closed | not_owner | posix()</v> - </type> <desc> - <p>Assigns a new controlling process <c>Pid</c> to - <c>Socket</c>. The controlling process is the process which + <p>Assigns a new controlling process <c><anno>Pid</anno></c> to + <c><anno>Socket</anno></c>. The controlling process is the process which receives messages from the socket. If called by any other process than the current controlling process, <c>{error, eperm}</c> is returned.</p> </desc> </func> <func> - <name>close(Socket) -> ok | {error, Reason}</name> + <name name="close" arity="1"/> <fsummary>Close a TCP socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Reason = posix()</v> - </type> <desc> <p>Closes a TCP socket.</p> </desc> </func> <func> - <name>shutdown(Socket, How) -> ok | {error, Reason}</name> + <name name="shutdown" arity="2"/> <fsummary>Immediately close a socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>How = read | write | read_write</v> - <v>Reason = posix()</v> - </type> <desc> <p>Immediately close a socket in one or two directions.</p> - <p><c>How == write</c> means closing the socket for writing, + <p><c><anno>How</anno> == write</c> means closing the socket for writing, reading from it is still possible.</p> <p>To be able to handle that the peer has done a shutdown on the write side, the <c>{exit_on_close, false}</c> option diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index 71f2e9bd83..c0e783f508 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -34,32 +34,43 @@ with sockets using the UDP protocol.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -ip_address() - see inet(3) - -posix() - see inet(3) + <datatypes> + <datatype> + <name name="hostname"/> + </datatype> + <datatype> + <name name="ip_address"/> + <desc> + <p>Represents an address of a TCP socket. + It is a tuple as explained in + <seealso marker="inet">inet(3)</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="port_number"/> + </datatype> + <datatype> + <name name="posix"/> + <desc> + <p>See <seealso marker="inet#error_codes"> + inet(3); POSIX Error Codes</seealso>.</p> + </desc> + </datatype> + <datatype> + <name><marker id="type-socket">socket()</marker></name> + <desc> + <p>As returned by open/1,2.</p> + </desc> + </datatype> + </datatypes> -socket() - as returned by open/1,2</code> - </section> <funcs> <func> - <name>open(Port) -> {ok, Socket} | {error, Reason}</name> - <name>open(Port, Options) -> {ok, Socket} | {error, Reason}</name> + <name name="open" arity="1"/> + <name name="open" arity="2"/> <fsummary>Associate a UDP port number with the process calling it</fsummary> - <type> - <v>Port = 0..65535</v> - <v>Options = [Opt]</v> - <v> Opt -- see below</v> - <v>Socket = socket()</v> - <v>Reason = posix()</v> - </type> <desc> - <p>Associates a UDP port number (<c>Port</c>) with the calling + <p>Associates a UDP port number (<c><anno>Port</anno></c>) with the calling process.</p> <p>The available options are:</p> <taglist> @@ -96,7 +107,7 @@ socket() <seealso marker="inet#setopts/2">inet:setopts/2</seealso>.</p> </item> </taglist> - <p>The returned socket <c>Socket</c> is used to send packets + <p>The returned socket <c><anno>Socket</anno></c> is used to send packets from this port with <c>send/4</c>. When UDP packets arrive at the opened port, they are delivered as messages:</p> <code type="none"> @@ -110,66 +121,42 @@ socket() binary if the option <c>binary</c> was specified.</p> <p>Default value for the receive buffer option is <c>{recbuf, 8192}</c>.</p> - <p>If <c>Port == 0</c>, the underlying OS assigns a free UDP + <p>If <c><anno>Port</anno> == 0</c>, the underlying OS assigns a free UDP port, use <c>inet:port/1</c> to retrieve it.</p> </desc> </func> <func> - <name>send(Socket, Address, Port, Packet) -> ok | {error, Reason}</name> + <name name="send" arity="4"/> <fsummary>Send a packet</fsummary> - <type> - <v>Socket = socket()</v> - <v>Address = string() | atom() | ip_address()</v> - <v>Port = 0..65535</v> - <v>Packet = [char()] | binary()</v> - <v>Reason = not_owner | posix()</v> - </type> <desc> <p>Sends a packet to the specified address and port. - The <c>Address</c> argument can be either a hostname, or an + The <c><anno>Address</anno></c> argument can be either a hostname, or an IP address.</p> </desc> </func> <func> - <name>recv(Socket, Length) -> {ok, {Address, Port, Packet}} | {error, Reason}</name> - <name>recv(Socket, Length, Timeout) -> {ok, {Address, Port, Packet}} | {error, Reason}</name> + <name name="recv" arity="2"/> + <name name="recv" arity="3"/> <fsummary>Receive a packet from a passive socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Length = int()</v> - <v>Address = ip_address()</v> - <v>Port = 0..65535</v> - <v>Packet = [char()] | binary()</v> - <v>Timeout = int() | infinity</v> - <v>Reason = not_owner | posix()</v> - </type> <desc> <p>This function receives a packet from a socket in passive mode.</p> - <p>The optional <c>Timeout</c> parameter specifies a timeout in + <p>The optional <c><anno>Timeout</anno></c> parameter specifies a timeout in milliseconds. The default value is <c>infinity</c>.</p> </desc> </func> <func> - <name>controlling_process(Socket, Pid) -> ok</name> + <name name="controlling_process" arity="2"/> <fsummary>Change controlling process of a socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Pid = pid()</v> - </type> <desc> - <p>Assigns a new controlling process <c>Pid</c> to - <c>Socket</c>. The controlling process is the process which + <p>Assigns a new controlling process <c><anno>Pid</anno></c> to + <c><anno>Socket</anno></c>. The controlling process is the process which receives messages from the socket.</p> </desc> </func> <func> - <name>close(Socket) -> ok | {error, Reason}</name> + <name name="close" arity="1"/> <fsummary>Close a UDP socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Reason = not_owner | posix()</v> - </type> <desc> <p>Closes a UDP socket.</p> </desc> diff --git a/lib/kernel/doc/src/global.xml b/lib/kernel/doc/src/global.xml index 077109d6c9..304a9b1d88 100644 --- a/lib/kernel/doc/src/global.xml +++ b/lib/kernel/doc/src/global.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -106,45 +106,37 @@ </description> + <datatypes> + <datatype> + <name name="id"/> + </datatype> + </datatypes> + <funcs> <func> - <name>del_lock(Id)</name> - <name>del_lock(Id, Nodes) -> void()</name> + <name name="del_lock" arity="1"/> + <name name="del_lock" arity="2"/> <fsummary>Delete a lock</fsummary> - <type> - <v>Id = {ResourceId, LockRequesterId}</v> - <v> ResourceId = term()</v> - <v> LockRequesterId = term()</v> - <v>Nodes = [node()]</v> - </type> <desc> - <p>Deletes the lock <c>Id</c> synchronously.</p> + <p>Deletes the lock <c><anno>Id</anno></c> synchronously.</p> </desc> </func> <func> - <name>notify_all_name(Name, Pid1, Pid2) -> none</name> + <name name="notify_all_name" arity="3"/> <fsummary>Name resolving function that notifies both pids</fsummary> - <type> - <v>Name = term()</v> - <v>Pid1 = Pid2 = pid()</v> - </type> <desc> <p>This function can be used as a name resolving function for <c>register_name/3</c> and <c>re_register_name/3</c>. It unregisters both pids, and sends the message - <c>{global_name_conflict, Name, OtherPid}</c> to both + <c>{global_name_conflict, <anno>Name</anno>, OtherPid}</c> to both processes.</p> </desc> </func> <func> - <name>random_exit_name(Name, Pid1, Pid2) -> Pid1 | Pid2</name> + <name name="random_exit_name" arity="3"/> <fsummary>Name resolving function that kills one pid</fsummary> - <type> - <v>Name = term()</v> - <v>Pid1 = Pid2 = pid()</v> - </type> <desc> <p>This function can be used as a name resolving function for <c>register_name/3</c> and <c>re_register_name/3</c>. It @@ -154,33 +146,27 @@ </func> <func> - <name>random_notify_name(Name, Pid1, Pid2) -> Pid1 | Pid2</name> + <name name="random_notify_name" arity="3"/> <fsummary>Name resolving function that notifies one pid</fsummary> - <type> - <v>Name = term()</v> - <v>Pid1 = Pid2 = pid()</v> - </type> <desc> <p>This function can be used as a name resolving function for <c>register_name/3</c> and <c>re_register_name/3</c>. It randomly chooses one of the pids for registration, and sends - the message <c>{global_name_conflict, Name}</c> to the other + the message <c>{global_name_conflict, <anno>Name</anno>}</c> to the other pid.</p> </desc> </func> <func> - <name>register_name(Name, Pid)</name> - <name>register_name(Name, Pid, Resolve) -> yes | no</name> + <name name="register_name" arity="2"/> + <name name="register_name" arity="3"/> <fsummary>Globally register a name for a pid</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Resolve = fun() or {Module, Function} where</v> - <v> Resolve(Name, Pid, Pid2) -> Pid | Pid2 | none</v> - </type> + <type name="method"/> + <type_desc name="method">{<c>Module</c>, <c>Function</c>} + is also allowed + </type_desc> <desc> - <p>Globally associates the name <c>Name</c> with a pid, that is, + <p>Globally associates the name <c><anno>Name</anno></c> with a pid, that is, Globally notifies all nodes of a new global name in a network of Erlang nodes.</p> @@ -188,7 +174,7 @@ of the globally registered names that already exist. The network is also informed of any global names in newly connected nodes. If any name clashes are discovered, - the <c>Resolve</c> function is called. Its purpose is to + the <c><anno>Resolve</anno></c> function is called. Its purpose is to decide which pid is correct. If the function crashes, or returns anything other than one of the pids, the name is unregistered. This function is called once for each name @@ -196,7 +182,7 @@ <p>There are three pre-defined resolve functions: <c>random_exit_name/3</c>, <c>random_notify_name/3</c>, and - <c>notify_all_name/3</c>. If no <c>Resolve</c> function is + <c>notify_all_name/3</c>. If no <c><anno>Resolve</anno></c> function is defined, <c>random_exit_name</c> is used. This means that one of the two registered processes will be selected as correct while the other is killed.</p> @@ -225,78 +211,63 @@ </func> <func> - <name>registered_names() -> [Name]</name> + <name name="registered_names" arity="0"/> <fsummary>All globally registered names</fsummary> - <type> - <v>Name = term()</v> - </type> <desc> <p>Returns a lists of all globally registered names.</p> </desc> </func> <func> - <name>re_register_name(Name, Pid)</name> - <name>re_register_name(Name, Pid, Resolve) -> void()</name> + <name name="re_register_name" arity="2"/> + <name name="re_register_name" arity="3"/> <fsummary>Atomically re-register a name</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Resolve = fun() or {Module, Function} where</v> - <v> Resolve(Name, Pid, Pid2) -> Pid | Pid2 | none</v> - </type> + <type name="method"/> + <type_desc name="method">{<c>Module</c>, <c>Function</c>} + is also allowed + </type_desc> <desc> - <p>Atomically changes the registered name <c>Name</c> on all - nodes to refer to <c>Pid</c>.</p> + <p>Atomically changes the registered name <c><anno>Name</anno></c> on all + nodes to refer to <c><anno>Pid</anno></c>.</p> - <p>The <c>Resolve</c> function has the same behavior as in + <p>The <c><anno>Resolve</anno></c> function has the same behavior as in <c>register_name/2,3</c>.</p> </desc> </func> <func> - <name>send(Name, Msg) -> Pid</name> + <name name="send" arity="2"/> <fsummary>Send a message to a globally registered pid</fsummary> - <type> - <v>Name = term()</v> - <v>Msg = term()</v> - <v>Pid = pid()</v> - </type> <desc> - <p>Sends the message <c>Msg</c> to the pid globally registered - as <c>Name</c>.</p> + <p>Sends the message <c><anno>Msg</anno></c> to the pid globally registered + as <c><anno>Name</anno></c>.</p> - <p>Failure: If <c>Name</c> is not a globally registered + <p>Failure: If <c><anno>Name</anno></c> is not a globally registered name, the calling function will exit with reason - <c>{badarg, {Name, Msg}}</c>.</p> + <c>{badarg, {<anno>Name</anno>, <anno>Msg</anno>}}</c>.</p> </desc> </func> <func> - <name>set_lock(Id)</name> - <name>set_lock(Id, Nodes)</name> - <name>set_lock(Id, Nodes, Retries) -> boolean()</name> + <name name="set_lock" arity="1"/> + <name name="set_lock" arity="2"/> + <name name="set_lock" arity="3"/> <fsummary>Set a lock on the specified nodes</fsummary> - <type> - <v>Id = {ResourceId, LockRequesterId}</v> - <v> ResourceId = term()</v> - <v> LockRequesterId = term()</v> - <v>Nodes = [node()]</v> - <v>Retries = int() >= 0 | infinity</v> - </type> + <type name="id"/> + <type name="retries"/> <desc> <p>Sets a lock on the specified nodes (or on all nodes if none - are specified) on <c>ResourceId</c> for - <c>LockRequesterId</c>. If a lock already exists on - <c>ResourceId</c> for another requester than - <c>LockRequesterId</c>, and <c>Retries</c> is not equal to 0, + are specified) on <c><anno>ResourceId</anno></c> for + <c><anno>LockRequesterId</anno></c>. If a lock already exists on + <c><anno>ResourceId</anno></c> for another requester than + <c><anno>LockRequesterId</anno></c>, and <c><anno>Retries</anno></c> is not equal to 0, the process sleeps for a while and will try to execute - the action later. When <c>Retries</c> attempts have been made, + the action later. When <c><anno>Retries</anno></c> attempts have been made, <c>false</c> is returned, otherwise <c>true</c>. If - <c>Retries</c> is <c>infinity</c>, <c>true</c> is eventually + <c><anno>Retries</anno></c> is <c>infinity</c>, <c>true</c> is eventually returned (unless the lock is never released).</p> - <p>If no value for <c>Retries</c> is given, <c>infinity</c> is + <p>If no value for <c><anno>Retries</anno></c> is given, <c>infinity</c> is used.</p> <p>This function is completely synchronous.</p> @@ -315,7 +286,7 @@ application to detect and rectify a deadlock.</p> <note> - <p>Some values of <c>ResourceId</c> should be avoided or + <p>Some values of <c><anno>ResourceId</anno></c> should be avoided or Erlang/OTP will not work properly. A list of resources to avoid: <c>global</c>, <c>dist_ac</c>, <c>mnesia_table_lock</c>, <c>mnesia_adjust_log_writes</c>, @@ -326,7 +297,7 @@ </func> <func> - <name>sync() -> void()</name> + <name name="sync" arity="0"/> <fsummary>Synchronize the global name server</fsummary> <desc> <p>Synchronizes the global name server with all nodes known to @@ -335,56 +306,45 @@ the global name server will receive global information from all nodes. This function can be called when new nodes are added to the network.</p> + <p>The only possible error reason <c>Reason</c> is + <c>{"global_groups definition error", Error}</c>.</p> </desc> </func> <func> - <name>trans(Id, Fun)</name> - <name>trans(Id, Fun, Nodes)</name> - <name>trans(Id, Fun, Nodes, Retries) -> Res | aborted</name> + <name name="trans" arity="2"/> + <name name="trans" arity="3"/> + <name name="trans" arity="4"/> <fsummary>Micro transaction facility</fsummary> - <type> - <v>Id = {ResourceId, LockRequesterId}</v> - <v> ResourceId = term()</v> - <v> LockRequesterId = term()</v> - <v>Fun = fun() | {M, F}</v> - <v>Nodes = [node()]</v> - <v>Retries = int() >= 0 | infinity</v> - <v>Res = term()</v> - </type> + <type name="retries"/> + <type name="trans_fun"/> <desc> - <p>Sets a lock on <c>Id</c> (using <c>set_lock/3</c>). If this - succeeds, <c>Fun()</c> is evaluated and the result <c>Res</c> + <p>Sets a lock on <c><anno>Id</anno></c> (using <c>set_lock/3</c>). If this + succeeds, <c><anno>Fun</anno>()</c> is evaluated and the result <c><anno>Res</anno></c> is returned. Returns <c>aborted</c> if the lock attempt - failed. If <c>Retries</c> is set to <c>infinity</c>, + failed. If <c><anno>Retries</anno></c> is set to <c>infinity</c>, the transaction will not abort.</p> <p><c>infinity</c> is the default setting and will be used if - no value is given for <c>Retries</c>.</p> + no value is given for <c><anno>Retries</anno></c>.</p> </desc> </func> <func> - <name>unregister_name(Name) -> void()</name> + <name name="unregister_name" arity="1"/> <fsummary>Remove a globally registered name for a pid</fsummary> - <type> - <v>Name = term()</v> - </type> <desc> - <p>Removes the globally registered name <c>Name</c> from + <p>Removes the globally registered name <c><anno>Name</anno></c> from the network of Erlang nodes.</p> </desc> </func> <func> - <name>whereis_name(Name) -> pid() | undefined</name> + <name name="whereis_name" arity="1"/> <fsummary>Get the pid with a given globally registered name</fsummary> - <type> - <v>Name = term()</v> - </type> <desc> <p>Returns the pid with the globally registered name - <c>Name</c>. Returns <c>undefined</c> if the name is not + <c><anno>Name</anno></c>. Returns <c>undefined</c> if the name is not globally registered.</p> </desc> </func> diff --git a/lib/kernel/doc/src/global_group.xml b/lib/kernel/doc/src/global_group.xml index 4facf4a4aa..abf6178fc4 100644 --- a/lib/kernel/doc/src/global_group.xml +++ b/lib/kernel/doc/src/global_group.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1998</year><year>2009</year> + <year>1998</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -42,26 +42,7 @@ <seealso marker="kernel_app">kernel(6)</seealso>, <seealso marker="config">config(4)</seealso>:</p> <code type="none"> -{global_groups, [GroupTuple]}</code> - <p>Types:</p> - <list type="bulleted"> - <item><c>GroupTuple = {GroupName, [Node]} | {GroupName, PublishType, [Node]}</c></item> - <item><c>GroupName = atom()</c> (naming a global group)</item> - <item><c>PublishType = normal | hidden</c></item> - <item><c>Node = atom()</c> (naming a node)</item> - </list> - <p>A <c>GroupTuple</c> without <c>PublishType</c> is the same as a - <c>GroupTuple</c> with <c>PublishType == normal</c>.</p> - <p>A node started with the command line flag <c>-hidden</c>, see - <seealso marker="erts:erl">erl(1)</seealso>, is said to be a - <em>hidden</em> node. A hidden node will establish hidden - connections to nodes not part of the same global group, but - normal (visible) connections to nodes part of the same global - group.</p> - <p>A global group defined with <c>PublishType == hidden</c>, is - said to be a hidden global group. All nodes in a hidden global - group are hidden nodes, regardless if they are started with - the <c>-hidden</c> command line flag or not.</p> +{global_groups, [GroupTuple :: group_tuple()]}</code> <p>For the processes and nodes to run smoothly using the global group functionality, the following criteria must be met:</p> <list type="bulleted"> @@ -82,14 +63,44 @@ <p>In the following description, a <em>group node</em> is a node belonging to the same global group as the local node.</p> </description> + <datatypes> + <datatype> + <name name="group_tuple"/> + <desc> + <p>A <c>GroupTuple</c> without <c>PublishType</c> is the same as a + <c>GroupTuple</c> with <c>PublishType == normal</c>.</p> + </desc> + </datatype> + <datatype> + <name name="group_name"/> + </datatype> + <datatype> + <name name="publish_type"/> + <desc> + <p>A node started with the command line flag <c>-hidden</c>, see + <seealso marker="erts:erl">erl(1)</seealso>, is said to be a + <em>hidden</em> node. A hidden node will establish hidden + connections to nodes not part of the same global group, but + normal (visible) connections to nodes part of the same global + group.</p> + <p>A global group defined with <c>PublishType == hidden</c>, is + said to be a hidden global group. All nodes in a hidden global + group are hidden nodes, regardless if they are started with + the <c>-hidden</c> command line flag or not.</p> + </desc> + </datatype> + <datatype> + <name name="name"/> + <desc><p>A registered name.</p></desc> + </datatype> + <datatype> + <name name="where"/> + </datatype> + </datatypes> <funcs> <func> - <name>global_groups() -> {GroupName, GroupNames} | undefined</name> + <name name="global_groups" arity="0"/> <fsummary>Return the global group names</fsummary> - <type> - <v>GroupName = atom()</v> - <v>GroupNames = [GroupName]</v> - </type> <desc> <p>Returns a tuple containing the name of the global group the local node belongs to, and the list of all other known @@ -98,53 +109,52 @@ </desc> </func> <func> - <name>info() -> [{Item, Info}]</name> + <name name="info" arity="0"/> <fsummary>Information about global groups</fsummary> - <type> - <v>Item, Info -- see below</v> - </type> + <type name="info_item"/> + <type name="sync_state"/> <desc> <p>Returns a list containing information about the global groups. Each element of the list is a tuple. The order of the tuples is not defined.</p> <taglist> - <tag><c>{state, State}</c></tag> + <tag><c>{state, <anno>State</anno>}</c></tag> <item> <p>If the local node is part of a global group, - <c>State == synced</c>. If no global groups are defined, - <c>State == no_conf</c>.</p> + <c><anno>State</anno> == synced</c>. If no global groups are defined, + <c><anno>State</anno> == no_conf</c>.</p> </item> - <tag><c>{own_group_name, GroupName}</c></tag> + <tag><c>{own_group_name, <anno>GroupName</anno>}</c></tag> <item> <p>The name (atom) of the group that the local node belongs to.</p> </item> - <tag><c>{own_group_nodes, Nodes}</c></tag> + <tag><c>{own_group_nodes, <anno>Nodes</anno>}</c></tag> <item> <p>A list of node names (atoms), the group nodes.</p> </item> - <tag><c>{synced_nodes, Nodes}</c></tag> + <tag><c>{synced_nodes, <anno>Nodes</anno>}</c></tag> <item> <p>A list of node names, the group nodes currently synchronized with the local node.</p> </item> - <tag><c>{sync_error, Nodes}</c></tag> + <tag><c>{sync_error, <anno>Nodes</anno>}</c></tag> <item> <p>A list of node names, the group nodes with which the local node has failed to synchronize.</p> </item> - <tag><c>{no_contact, Nodes}</c></tag> + <tag><c>{no_contact, <anno>Nodes</anno>}</c></tag> <item> <p>A list of node names, the group nodes to which there are currently no connections.</p> </item> - <tag><c>{other_groups, Groups}</c></tag> + <tag><c>{other_groups, <anno>Groups</anno>}</c></tag> <item> - <p><c>Groups</c> is a list of tuples - <c>{GroupName, Nodes}</c>, specifying the name and nodes + <p><c><anno>Groups</anno></c> is a list of tuples + <c>{<anno>GroupName</anno>, <anno>Nodes</anno>}</c>, specifying the name and nodes of the other global groups.</p> </item> - <tag><c>{monitoring, Pids}</c></tag> + <tag><c>{monitoring, <anno>Pids</anno>}</c></tag> <item> <p>A list of pids, specifying the processes which have subscribed to <c>nodeup</c> and <c>nodedown</c> messages.</p> @@ -153,73 +163,52 @@ </desc> </func> <func> - <name>monitor_nodes(Flag) -> ok </name> + <name name="monitor_nodes" arity="1"/> <fsummary>Subscribe to node status changes</fsummary> - <type> - <v>Flag = bool()</v> - </type> <desc> - <p>Depending on <c>Flag</c>, the calling process starts - subscribing (<c>Flag == true</c>) or stops subscribing - (<c>Flag == false</c>) to node status change messages.</p> + <p>Depending on <c><anno>Flag</anno></c>, the calling process starts + subscribing (<c><anno>Flag</anno> == true</c>) or stops subscribing + (<c><anno>Flag</anno> == false</c>) to node status change messages.</p> <p>A process which has subscribed will receive the messages <c>{nodeup, Node}</c> and <c>{nodedown, Node}</c> when a group node connects or disconnects, respectively.</p> </desc> </func> <func> - <name>own_nodes() -> Nodes</name> + <name name="own_nodes" arity="0"/> <fsummary>Return the group nodes</fsummary> - <type> - <v>Nodes = [Node]</v> - <v> Node = node()</v> - </type> <desc> <p>Returns the names of all group nodes, regardless of their current status.</p> </desc> </func> <func> - <name>registered_names(Where) -> Names</name> + <name name="registered_names" arity="1"/> <fsummary>Return globally registered names</fsummary> - <type> - <v>Where = {node, Node} | {group, GroupName}</v> - <v> Node = node()</v> - <v> GroupName = atom()</v> - <v>Names = [Name]</v> - <v> Name = atom()</v> - </type> <desc> <p>Returns a list of all names which are globally registered on the specified node or in the specified global group.</p> </desc> </func> <func> - <name>send(Name, Msg) -> pid() | {badarg, {Name, Msg}}</name> - <name>send(Where, Name, Msg) -> pid() | {badarg, {Name, Msg}}</name> + <name name="send" arity="2"/> + <name name="send" arity="3"/> <fsummary>Send a message to a globally registered pid</fsummary> - <type> - <v>Where = {node, Node} | {group, GroupName}</v> - <v> Node = node()</v> - <v> GroupName = atom()</v> - <v>Name = atom()</v> - <v>Msg = term()</v> - </type> <desc> - <p>Searches for <c>Name</c>, globally registered on + <p>Searches for <c><anno>Name</anno></c>, globally registered on the specified node or in the specified global group, or -- - if the <c>Where</c> argument is not provided -- in any global + if the <c><anno>Where</anno></c> argument is not provided -- in any global group. The global groups are searched in the order in which they appear in the value of the <c>global_groups</c> configuration parameter.</p> - <p>If <c>Name</c> is found, the message <c>Msg</c> is sent to + <p>If <c><anno>Name</anno></c> is found, the message <c><anno>Msg</anno></c> is sent to the corresponding pid. The pid is also the return value of the function. If the name is not found, the function returns - <c>{badarg, {Name, Msg}}</c>.</p> + <c>{badarg, {<anno>Name</anno>, <anno>Msg</anno>}}</c>.</p> </desc> </func> <func> - <name>sync() -> ok</name> + <name name="sync" arity="0"/> <fsummary>Synchronize the group nodes</fsummary> <desc> <p>Synchronizes the group nodes, that is, the global name @@ -235,23 +224,17 @@ </desc> </func> <func> - <name>whereis_name(Name) -> pid() | undefined</name> - <name>whereis_name(Where, Name) -> pid() | undefined</name> + <name name="whereis_name" arity="1"/> + <name name="whereis_name" arity="2"/> <fsummary>Get the pid with a given globally registered name</fsummary> - <type> - <v>Where = {node, Node} | {group, GroupName}</v> - <v> Node = node()</v> - <v> GroupName = atom()</v> - <v>Name = atom()</v> - </type> <desc> - <p>Searches for <c>Name</c>, globally registered on + <p>Searches for <c><anno>Name</anno></c>, globally registered on the specified node or in the specified global group, or -- if - the <c>Where</c> argument is not provided -- in any global + the <c><anno>Where</anno></c> argument is not provided -- in any global group. The global groups are searched in the order in which they appear in the value of the <c>global_groups</c> configuration parameter.</p> - <p>If <c>Name</c> is found, the corresponding pid is returned. + <p>If <c><anno>Name</anno></c> is found, the corresponding pid is returned. If the name is not found, the function returns <c>undefined</c>.</p> </desc> diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml index 0df699572d..e2dbcbe63d 100644 --- a/lib/kernel/doc/src/heart.xml +++ b/lib/kernel/doc/src/heart.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -76,11 +76,8 @@ </description> <funcs> <func> - <name>set_cmd(Cmd) -> ok | {error, {bad_cmd, Cmd}}</name> + <name name="set_cmd" arity="1"/> <fsummary>Set a temporary reboot command</fsummary> - <type> - <v>Cmd = string()</v> - </type> <desc> <p>Sets a temporary reboot command. This command is used if a <c>HEART_COMMAND</c> other than the one specified with @@ -88,12 +85,12 @@ the system. The new Erlang runtime system will (if it misbehaves) use the environment variable <c>HEART_COMMAND</c> to reboot.</p> - <p>Limitations: The length of the <c>Cmd</c> command string + <p>Limitations: The length of the <c><anno>Cmd</anno></c> command string must be less than 2047 characters.</p> </desc> </func> <func> - <name>clear_cmd() -> ok</name> + <name name="clear_cmd" arity="0"/> <fsummary>Clear the temporary boot command</fsummary> <desc> <p>Clears the temporary boot command. If the system terminates, @@ -101,11 +98,8 @@ </desc> </func> <func> - <name>get_cmd() -> {ok, Cmd}</name> + <name name="get_cmd" arity="0"/> <fsummary>Get the temporary reboot command</fsummary> - <type> - <v>Cmd = string()</v> - </type> <desc> <p>Get the temporary reboot command. If the command is cleared, the empty string will be returned.</p> diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index a22c0a8346..fd843b00d9 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2010</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -54,33 +54,6 @@ $ <input>erl -sname test -kernel \</input> <input>inet_default_listen_options '[{delay_send,true}]'</input></pre> <p>Note that the default option <c>{active, true}</c> currently cannot be changed, for internal reasons.</p> - </description> - - <section> - <title>DATA TYPES</title> - <code type="none"> -#hostent{h_addr_list = [ip_address()] % list of addresses for this host - h_addrtype = inet | inet6 - h_aliases = [hostname()] % list of aliases - h_length = int() % length of address in bytes - h_name = hostname() % official name for host - The record is defined in the Kernel include file "inet.hrl" - Add the following directive to the module: - -include_lib("kernel/include/inet.hrl"). - -hostname() = atom() | string() - -ip_address() = {N1,N2,N3,N4} % IPv4 - | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6 - Ni = 0..255 - Ki = 0..65535 - -posix() - an atom which is named from the Posix error codes used in - Unix, and in the runtime libraries of most C compilers - -socket() - see gen_tcp(3), gen_udp(3)</code> <p>Addresses as inputs to functions can be either a string or a tuple. For instance, the IP address 150.236.20.73 can be passed to <c>gethostbyaddr/1</c> either as the string "150.236.20.73" @@ -109,24 +82,58 @@ fe80::204:acff:fe17:bf38 {ok,{192,168,42,2}} 2> <input>inet_parse:address("FFFF::192.168.42.2").</input> {ok,{65535,0,0,0,0,0,49320,10754}}</pre> - </section> + </description> + + <datatypes> + <datatype> + <name name="hostent"/> + <desc> + <p>The record is defined in the Kernel include file "inet.hrl". + Add the following directive to the module:</p> +<code>-include_lib("kernel/include/inet.hrl").</code></desc> + </datatype> + <datatype> + <name name="hostname"/> + </datatype> + <datatype> + <name name="ip_address"/> + </datatype> + <datatype> + <name name="ip4_address"/> + </datatype> + <datatype> + <name name="ip6_address"/> + </datatype> + <datatype> + <name name="posix"/> + <desc><p>An atom which is named from the Posix error codes + used in Unix, and in the runtime libraries of most + C compilers. See + <seealso marker="#error_codes">POSIX Error Codes</seealso>.</p> + </desc> + </datatype> + <datatype> + <name><marker id="type-socket">socket()</marker></name> + <desc><p>See <seealso marker="gen_tcp#type-socket">gen_tcp(3)</seealso> + and <seealso marker="gen_udp#type-socket">gen_udp(3)</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="family_option"/> + </datatype> + </datatypes> + <funcs> <func> - <name>close(Socket) -> ok</name> + <name name="close" arity="1"/> <fsummary>Close a socket of any type</fsummary> - <type> - <v>Socket = socket()</v> - </type> <desc> <p>Closes a socket of any type.</p> </desc> </func> <func> - <name>get_rc() -> [{Par, Val}]</name> + <name name="get_rc" arity="0"/> <fsummary>Return a list of IP configuration parameters</fsummary> - <type> - <v>Par, Val -- see below</v> - </type> <desc> <p>Returns the state of the Inet configuration database in form of a list of recorded configuration parameters. (See the @@ -135,116 +142,74 @@ fe80::204:acff:fe17:bf38 </desc> </func> <func> - <name>format_error(Posix) -> string()</name> + <name name="format_error" arity="1"/> <fsummary>Return a descriptive string for an error reason</fsummary> - <type> - <v>Posix = posix()</v> - </type> <desc> <p>Returns a diagnostic error string. See the section below - for possible <c>Posix</c> values and the corresponding + for possible <c><anno>Posix</anno></c> values and the corresponding strings.</p> </desc> </func> <func> - <name>getaddr(Host, Family) -> {ok, Address} | {error, posix()}</name> + <name name="getaddr" arity="2"/> <fsummary>Return the IP-address for a host</fsummary> - <type> - <v>Host = ip_address() | string() | atom()</v> - <v>Family = inet | inet6</v> - <v>Address = ip_address()</v> - <v>posix() = term()</v> - </type> <desc> - <p>Returns the IP-address for <c>Host</c> as a tuple of - integers. <c>Host</c> can be an IP-address, a single hostname + <p>Returns the IP-address for <c><anno>Host</anno></c> as a tuple of + integers. <c><anno>Host</anno></c> can be an IP-address, a single hostname or a fully qualified hostname.</p> </desc> </func> <func> - <name>getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()}</name> + <name name="getaddrs" arity="2"/> <fsummary>Return the IP-addresses for a host</fsummary> - <type> - <v>Host = ip_address() | string() | atom()</v> - <v>Addresses = [ip_address()]</v> - <v>Family = inet | inet6</v> - </type> <desc> - <p>Returns a list of all IP-addresses for <c>Host</c>. - <c>Host</c> can be an IP-address, a single hostname or a fully + <p>Returns a list of all IP-addresses for <c><anno>Host</anno></c>. + <c><anno>Host</anno></c> can be an IP-address, a single hostname or a fully qualified hostname.</p> </desc> </func> <func> - <name>gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}</name> + <name name="gethostbyaddr" arity="1"/> <fsummary>Return a hostent record for the host with the given address</fsummary> - <type> - <v>Address = string() | ip_address()</v> - <v>Hostent = #hostent{}</v> - </type> <desc> <p>Returns a <c>hostent</c> record given an address.</p> </desc> </func> <func> - <name>gethostbyname(Name) -> {ok, Hostent} | {error, posix()}</name> + <name name="gethostbyname" arity="1"/> <fsummary>Return a hostent record for the host with the given name</fsummary> - <type> - <v>Hostname = hostname()</v> - <v>Hostent = #hostent{}</v> - </type> <desc> <p>Returns a <c>hostent</c> record given a hostname.</p> </desc> </func> <func> - <name>gethostbyname(Name, Family) -> {ok, Hostent} | {error, posix()}</name> + <name name="gethostbyname" arity="2"/> <fsummary>Return a hostent record for the host with the given name</fsummary> - <type> - <v>Hostname = hostname()</v> - <v>Family = inet | inet6</v> - <v>Hostent = #hostent{}</v> - </type> <desc> <p>Returns a <c>hostent</c> record given a hostname, restricted to the given address family.</p> </desc> </func> <func> - <name>gethostname() -> {ok, Hostname}</name> + <name name="gethostname" arity="0"/> <fsummary>Return the local hostname</fsummary> - <type> - <v>Hostname = string()</v> - </type> <desc> <p>Returns the local hostname. Will never fail.</p> </desc> </func> <func> - <name>getifaddrs() -> {ok,Iflist} | {error,posix}</name> + <name name="getifaddrs" arity="0"/> <fsummary>Return a list of interfaces and their addresses</fsummary> - <type> - <v>Iflist = {Ifname,[Ifopt]}</v> - <v>Ifname = string()</v> - <v>Ifopt = {flag,[Flag]} | {addr,Addr} | {netmask,Netmask} - | {broadaddr,Broadaddr} | {dstaddr,Dstaddr} - | {hwaddr,Hwaddr}</v> - <v>Flag = up | broadcast | loopback | pointtopoint - | running | multicast</v> - <v>Addr = Netmask = Broadadddr = Dstaddr = ip_address()</v> - <v>Hwaddr = [byte()]</v> - </type> - </func> <desc> <p> Returns a list of 2-tuples containing interface names and the - interface's addresses. <c>Ifname</c> is a Unicode string. - <c>Hwaddr</c> is hardware dependent, e.g on Ethernet interfaces + interface's addresses. <c><anno>Ifname</anno></c> is a Unicode string. + <c><anno>Hwaddr</anno></c> is hardware dependent, e.g on Ethernet interfaces it is the 6-byte Ethernet address (MAC address (EUI-48 address)). </p> <p> - The <c>{addr,Addr}</c>, <c>{netmask,_}</c> and <c>{broadaddr,_}</c> + The <c>{addr,<anno>Addr</anno>}</c>, <c>{netmask,_}</c> and <c>{broadaddr,_}</c> tuples are repeated in the result list iff the interface has multiple addresses. If you come across an interface that has multiple <c>{flag,_}</c> or <c>{hwaddr,_}</c> tuples you have @@ -252,8 +217,8 @@ fe80::204:acff:fe17:bf38 The <c>{flag,_}</c> tuple is mandatory, all other optional. </p> <p> - Do not rely too much on the order of <c>Flag</c> atoms or - <c>Ifopt</c> tuples. There are some rules, though: + Do not rely too much on the order of <c><anno>Flag</anno></c> atoms or + <c><anno>Ifopt</anno></c> tuples. There are some rules, though: <list> <item> Immediately after <c>{addr,_}</c> follows <c>{netmask,_}</c> @@ -261,7 +226,7 @@ fe80::204:acff:fe17:bf38 <item> Immediately thereafter follows <c>{broadaddr,_}</c> if the <c>broadcast</c> flag is <em>not</em> set and the - <c>pointtopoint</c>flag <em>is</em> set. + <c>pointtopoint</c> flag <em>is</em> set. </item> <item> Any <c>{netmask,_}</c>, <c>{broadaddr,_}</c> or @@ -277,11 +242,12 @@ fe80::204:acff:fe17:bf38 </p> <p> On Windows, the data is fetched from quite different OS API - functions, so the <c>Netmask</c> and <c>Broadaddr</c> - values may be calculated, just as some <c>Flag</c> values. + functions, so the <c><anno>Netmask</anno></c> and <c><anno>Broadaddr</anno></c> + values may be calculated, just as some <c><anno>Flag</anno></c> values. You have been warned. Report flagrant bugs. </p> </desc> + </func> <func> <name>getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name> @@ -291,13 +257,14 @@ fe80::204:acff:fe17:bf38 <v>Options = [Opt | RawOptReq]</v> <v>Opt = atom()</v> <v>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</v> - <v>Protocol = int()</v> - <v>OptionNum = int()</v> + <v>Protocol = integer()</v> + <v>OptionNum = integer()</v> <v>ValueSpec = ValueSize | ValueBin</v> - <v>ValueSize = int()</v> + <v>ValueSize = integer()</v> <v>ValueBin = binary()</v> <v>OptionValues = [{Opt, Val} | {raw, Protocol, OptionNum, ValueBin}]</v> </type> + <type name="socket_getopt"/> <desc> <p>Gets one or more options for a socket. See <seealso marker="#setopts/2">setopts/2</seealso> @@ -419,37 +386,27 @@ fe80::204:acff:fe17:bf38 </func> <func> - <name>peername(Socket) -> {ok, {Address, Port}} | {error, posix()}</name> + <name name="peername" arity="1"/> <fsummary>Return the address and port for the other end of a connection</fsummary> - <type> - <v>Socket = socket()</v> - <v>Address = ip_address()</v> - <v>Port = int()</v> - </type> <desc> <p>Returns the address and port for the other end of a connection.</p> </desc> </func> <func> - <name>port(Socket) -> {ok, Port}</name> + <name>port(Socket) -> {ok, Port} | {error, any()}</name> <fsummary>Return the local port number for a socket</fsummary> <type> <v>Socket = socket()</v> - <v>Port = int()</v> + <v>Port = integer()</v> </type> <desc> <p>Returns the local port number for a socket.</p> </desc> </func> <func> - <name>sockname(Socket) -> {ok, {Address, Port}} | {error, posix()}</name> + <name name="sockname" arity="1"/> <fsummary>Return the local address and port number for a socket</fsummary> - <type> - <v>Socket = socket()</v> - <v>Address = ip_address()</v> - <v>Port = int()</v> - </type> <desc> <p>Returns the local address and port number for a socket.</p> </desc> @@ -460,8 +417,8 @@ fe80::204:acff:fe17:bf38 <type> <v>Socket = term()</v> <v>Options = [{Opt, Val} | {raw, Protocol, Option, ValueBin}]</v> - <v>Protocol = int()</v> - <v>OptionNum = int()</v> + <v>Protocol = integer()</v> + <v>OptionNum = integer()</v> <v>ValueBin = binary()</v> <v> Opt, Val -- see below</v> </type> diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml index d8fe23544b..bf73ccf13d 100644 --- a/lib/kernel/doc/src/inet_res.xml +++ b/lib/kernel/doc/src/inet_res.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2009</year><year>2009</year> + <year>2009</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -76,64 +76,38 @@ query is tried for the <c>alt_nameservers</c>.</p> </section> - - - - <section> - <title>DATA TYPES</title> - <p>As defined in the module - <seealso marker="kernel:inet">inet</seealso>:</p> - <code type="none"> -hostent() = #hostent{} -posix() = some atom()s -ip_address() = tuple of integers of arity 4 or 8</code> - + <datatypes> <p>Resolver types:</p> - <code type="none">These correspond to resolver options: - -res_option() = - [ {alt_nameservers, [ nameserver() ]} - | {edns, 0 | false} % Use EDNS - | {inet6, bool()} % Return IPv6 addresses - | {nameservers, [ nameserver() ]} % List of nameservers - | {recurse, bool()} % Request server recursion - | {retry, integer()} % UDP retries - | {timeout, integer()} % UDP query timeout - | {udp_payload_size, integer()} % EDNS payload size - | {usevc, bool()} ] % Use TCP (Virtual Circuit) - -nameserver() = {ip_address(),Port} - Port = integer(1..65535) - -res_error() = - formerr | - qfmterror | - servfail | - nxdomain | - notimp | - refused | - badvers | - timeout -</code> - - <p>DNS types:</p> - <marker id="dns_types"/> - <code type="none">dns_name() = string() with no adjacent dots - -rr_type() = a | aaaa | cname | gid | hinfo | ns | mb | md | mg | mf - | minfo | mx | naptr | null | ptr | soa | spf | srv | txt - | uid | uinfo | unspec | wks - -query_type() = axfr | mailb | maila | any | rr_type() - -dns_class() = in | chaos | hs | any - + <datatype> + <name name="res_option"/> + </datatype> + <datatype> + <name name="nameserver"/> + </datatype> + <datatype> + <name name="res_error"/> + </datatype> + + <p><marker id="dns_types"/>DNS types:</p> + <datatype> + <name name="dns_name"/> + <desc><p>A string with no adjacent dots.</p></desc> + </datatype> + <datatype> + <name name="rr_type"/> + </datatype> + <datatype> + <name name="dns_class"/> + </datatype> + <datatype> + <name name="dns_msg"/> + <desc> + <p>This is the start of a hiearchy of opaque data structures + that can be examined with access functions in inet_dns that + return lists of {Field,Value} tuples. The arity 2 functions + just return the value for a given field. +<pre> dns_msg() = DnsMsg - This is the start of a hiearchy of opaque data structures - that can be examined with access functions in inet_dns - that return lists of {Field,Value} tuples. The arity 2 - functions just return the value for a given field. - inet_dns:msg(DnsMsg) -> [ {header, dns_header()} | {qdlist, dns_query()} @@ -143,19 +117,21 @@ dns_msg() = DnsMsg inet_dns:msg(DnsMsg, header) -> dns_header() % for example inet_dns:msg(DnsMsg, Field) -> Value -dhs_header() = DnsHeader +dns_header() = DnsHeader inet_dns:header(DnsHeader) -> [ {id, integer()} - | {qr, bool()} + | {qr, boolean()} | {opcode, 'query' | iquery | status | integer()} - | {aa, bool()} - | {tc, bool()} - | {rd, bool()} - | {ra, bool()} - | {pr, bool()} + | {aa, boolean()} + | {tc, boolean()} + | {rd, boolean()} + | {ra, boolean()} + | {pr, boolean()} | {rcode, integer(0..16)} ] inet_dns:header(DnsHeader, Field) -> Value +query_type() = axfr | mailb | maila | any | rr_type() + dns_query() = DnsQuery inet_dns:dns_query(DnsQuery) -> [ {domain, dns_name()} @@ -179,32 +155,6 @@ dns_rr() = DnsRr | {data, dns_data()} ] inet_dns:rr(DnsRr, Field) -> Value -dns_data() = % for dns_type() - [ dns_name() % ns, md, mf, cname, mb, mg, mr, ptr - | ip_address(v4) % a - | ip_address(v6) % aaaa - | {MName,RName,Serial,Refresh,Retry,Expiry,Minimum} % soa - | {ip_address(v4),Proto,BitMap} % wks - | {CpuString,OsString} % hinfo - | {RM,EM} % minfo - | {Prio,dns_name()} % mx - | {Prio,Weight,Port,dns_name()} % srv - | {Order,Preference,Flags,Services,Regexp,dns_name()} % naptr - | [ string() ] % txt, spf - | binary() ] % null, integer() -MName, RName = dns_name() -Serial, Refresh, Retry, Expiry, Minimum = integer(), -Proto = integer() -BitMap = binary() -CpuString, OsString = string() -RM = EM = dns_name() -Prio, Weight, Port = integer() -Order, Preference = integer() -Flags, Services = string(), -Regexp = string(utf8) - - - There is an info function for the types above: inet_dns:record_type(dns_msg()) -> msg; @@ -214,26 +164,25 @@ inet_dns:record_type(dns_rr()) -> rr; inet_dns:record_type(_) -> undefined. So; inet_dns:(inet_dns:record_type(X))(X) will convert -any of these data structures into a {Field,Value} list.</code> - </section> - +any of these data structures into a {Field,Value} list.</pre></p> + </desc> + </datatype> + <datatype> + <name name="dns_data"/> + <desc><p><c><anno>Regexp</anno></c> is a string with characters encoded in the + UTF-8 coding standard.</p> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>getbyname(Name, Type) -> {ok,hostent()} | {error,Reason}</name> - <name>getbyname(Name, Type, Timeout) -> - {ok,hostent()} | {error,Reason} - </name> + <name name="getbyname" arity="2"/> + <name name="getbyname" arity="3"/> <fsummary>Resolve a DNS record of the given type for the given host </fsummary> - <type> - <v>Name = dns_name()</v> - <v>Type = rr_type()</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Reason = posix() | res_error()</v> - </type> <desc> <p>Resolve a DNS record of the given type for the given host, of class <c>in</c>. On success returns a <c>hostent()</c> record with @@ -252,17 +201,10 @@ any of these data structures into a {Field,Value} list.</code> </func> <func> - <name>gethostbyaddr(Address) -> {ok,hostent()} | {error,Reason}</name> - <name>gethostbyaddr(Address, Timeout) -> - {ok,hostent()} | {error,Reason} - </name> + <name name="gethostbyaddr" arity="1"/> + <name name="gethostbyaddr" arity="2"/> <fsummary>Return a hostent record for the host with the given address </fsummary> - <type> - <v>Address = ip_address()</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Reason = posix() | res_error()</v> - </type> <desc> <p>Backend functions used by <seealso marker="kernel:inet#gethostbyaddr/1"> @@ -273,20 +215,11 @@ any of these data structures into a {Field,Value} list.</code> </func> <func> - <name>gethostbyname(Name) -> {ok,hostent()} | Reason}</name> - <name>gethostbyname(Name, Family) -> - {ok,hostent()} | {error,Reason}} - </name> - <name>gethostbyname(Name, Family, Timeout) -> - {ok,hostent()} | {error,Reason} - </name> + <name name="gethostbyname" arity="1"/> + <name name="gethostbyname" arity="2"/> + <name name="gethostbyname" arity="3"/> <fsummary>Return a hostent record for the host with the given name </fsummary> - <type> - <v>Name = dns_name()</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Reason = posix() | res_error()</v> - </type> <desc> <p>Backend functions used by <seealso marker="kernel:inet#gethostbyname/1"> @@ -305,26 +238,16 @@ any of these data structures into a {Field,Value} list.</code> </func> <func> - <name>lookup(Name, Class, Type) -> [ dns_data() ] - </name> - <name>lookup(Name, Class, Type, Opts) -> [ dns_data() ] - </name> - <name>lookup(Name, Class, Type, Opts, Timeout) -> [ dns_data() ] - </name> + <name name="lookup" arity="3"/> + <name name="lookup" arity="4"/> + <name name="lookup" arity="5"/> <fsummary>Resolve the DNS data for the record of the given type and class for the given name </fsummary> - <type> - <v>Name = dns_name() | ip_address()</v> - <v>Type = rr_type()</v> - <v>Opts = res_option() | verbose</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Reason = posix() | res_error()</v> - </type> <desc> <p>Resolve the DNS data for the record of the given type and class for the given name. On success filters out the answer records - with the correct <c>Class</c> and <c>Type</c> and returns + with the correct <c><anno>Class</anno></c> and <c><anno>Type</anno></c> and returns a list of their data fields. So a lookup for type <c>any</c> will give an empty answer since the answer records have specific types that are not <c>any</c>. An empty answer @@ -332,44 +255,33 @@ any of these data structures into a {Field,Value} list.</code> </p><p> Calls <seealso marker="#resolve/3">resolve/2..4</seealso> with the same arguments and filters the result, so - <c>Opts</c> is explained there. + <c><anno>Opts</anno></c> is explained there. </p> </desc> </func> <func> - <name>resolve(Name, Class, Type) -> {ok,dns_msg()} | Error - </name> - <name>resolve(Name, Class, Type, Opts) -> {ok,dns_msg()} | Error - </name> - <name>resolve(Name, Class, Type, Opts, Timeout) -> {ok,dns_msg()} | Error - </name> + <name name="resolve" arity="3"/> + <name name="resolve" arity="4"/> + <name name="resolve" arity="5"/> <fsummary>Resolve a DNS record of the given type and class for the given name </fsummary> - <type> - <v>Name = dns_name() | ip_address()</v> - <v>Type = rr_type()</v> - <v>Opts = res_option() | verbose | atom()</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Error = {error,Reason} | {error,{Reason,dns_msg()}}</v> - <v>Reason = posix() | res_error()</v> - </type> <desc> <p>Resolve a DNS record of the given type and class for the given name. The returned <c>dns_msg()</c> can be examined using access functions in <c>inet_db</c> as described in <seealso marker="#dns_types">DNS types</seealso>. </p><p> - If <c>Name</c> is an <c>ip_address()</c>, the domain name + If <c><anno>Name</anno></c> is an <c>ip_address()</c>, the domain name to query for is generated as the standard reverse ".IN-ADDR.ARPA." name for an IPv4 address, or the ".IP6.ARPA." name for an IPv6 address. In this case you most probably want to use - <c>Class = in</c> and <c>Type = ptr</c> but it + <c><anno>Class</anno> = in</c> and <c><anno>Type</anno> = ptr</c> but it is not done automatically. </p><p> - <c>Opts</c> override the corresponding resolver options. + <c><anno>Opts</anno></c> override the corresponding resolver options. If the option <c>nameservers</c> is given, it is also assumed that it is the complete list of nameserves, so the resolver option <c>alt_nameserves</c> is ignored. @@ -382,14 +294,14 @@ any of these data structures into a {Field,Value} list.</code> of queries, replies retransmissions, etc, similar to from utilities like <c>dig</c>, <c>nslookup</c> et.al. </p><p> - If <c>Opt</c> is an arbitrary atom it is interpreted - as <c>{Opt,true}</c> unless the atom string starts with - <c>"no"</c> making the interpretation <c>{Opt,false}</c>. + If <c><anno>Opt</anno></c> is an arbitrary atom it is interpreted + as <c>{<anno>Opt</anno>,true}</c> unless the atom string starts with + <c>"no"</c> making the interpretation <c>{<anno>Opt</anno>,false}</c>. For example: <c>usevc</c> is an alias for <c>{usevc,true}</c>, and <c>nousevc</c> an alias for <c>{usevc,false}</c>. </p><p> The <c>inet6</c> option currently has no effect on this function. - You probably want to use <c>Type = a | aaaa</c> instead. + You probably want to use <c><anno>Type</anno> = a | aaaa</c> instead. </p> </desc> </func> @@ -430,24 +342,18 @@ any of these data structures into a {Field,Value} list.</code> <funcs> <func> - <name>nslookup(Name, Class, Type) -> {ok,dns_msg()} | {error,Reason} - </name> - <name>nslookup(Name, Class, Type, Timeout) -> - {ok,dns_msg()} | {error,Reason} - </name> - <name>nslookup(Name, Class, Type, Nameservers) -> - {ok,dns_msg()} | {error,Reason} - </name> + <name name="nslookup" arity="3"/> + <name name="nslookup" arity="4" clause_i="1"/> + <name name="nslookup" arity="4" clause_i="2"/> <fsummary>Resolve a DNS record of the given type and class for the given name </fsummary> - <type> - <v>Name = dns_name() | ip_address()</v> - <v>Type = rr_type()</v> - <v>Nameservers = [ nameserver() ]</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Reason = posix() | res_error()</v> - </type> + <type variable="Name"/> + <type variable="Class"/> + <type variable="Type"/> + <type variable="Timeout" name_i="2"/> + <type variable="Nameservers"/> + <type variable="Reason"/> <desc> <p>Resolve a DNS record of the given type and class for the given name. </p> @@ -455,22 +361,11 @@ any of these data structures into a {Field,Value} list.</code> </func> <func> - <name>nnslookup(Name, Class, Type, Nameservers) -> - {ok,dns_msg()} | {error,posix()} - </name> - <name>nnslookup(Name, Class, Type, Nameservers, Timeout) -> - {ok,dns_msg()} | {error,posix()} - </name> + <name name="nnslookup" arity="4"/> + <name name="nnslookup" arity="5"/> <fsummary>Resolve a DNS record of the given type and class for the given name </fsummary> - <type> - <v>Name = dns_name() | ip_address()</v> - <v>Type = rr_type()</v> - <v>Nameservers = [ nameserver() ]</v> - <v>Timeout = integer() >= 0 | infinity</v> - <v>Reason = posix() | res_error()</v> - </type> <desc> <p>Resolve a DNS record of the given type and class for the given name. </p> diff --git a/lib/kernel/doc/src/net_adm.xml b/lib/kernel/doc/src/net_adm.xml index 7ec4f7f0e7..f2aac9282c 100644 --- a/lib/kernel/doc/src/net_adm.xml +++ b/lib/kernel/doc/src/net_adm.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -34,94 +34,70 @@ </description> <funcs> <func> - <name>dns_hostname(Host) -> {ok, Name} | {error, Host}</name> + <name name="dns_hostname" arity="1"/> <fsummary>Official name of a host</fsummary> - <type> - <v>Host = atom() | string()</v> - <v>Name = string()</v> - </type> <desc> - <p>Returns the official name of <c>Host</c>, or - <c>{error, Host}</c> if no such name is found. See also + <p>Returns the official name of <c><anno>Host</anno></c>, or + <c>{error, <anno>Host</anno>}</c> if no such name is found. See also <c>inet(3)</c>.</p> </desc> </func> <func> - <name>host_file() -> Hosts | {error, Reason}</name> + <name name="host_file" arity="0"/> <fsummary>Read the <c>.hosts.erlang</c>file</fsummary> - <type> - <v>Hosts = [Host]</v> - <v> Host = atom()</v> - <v>Reason = term()</v> - </type> <desc> <p>Reads the <c>.hosts.erlang</c> file, see the section <em>Files</em> below. Returns the hosts in this file as a - list, or returns <c>{error, Reason}</c> if the file could not - be read. See <c>file(3)</c> for possible values of - <c>Reason</c>.</p> + list, or returns <c>{error, <anno>Reason</anno>}</c> if the file could not + be read or the Erlang terms on the file could not be interpreted.</p> </desc> </func> <func> - <name>localhost() -> Name</name> + <name name="localhost" arity="0"/> <fsummary>Name of the local host</fsummary> - <type> - <v>Name = string()</v> - </type> <desc> <p>Returns the name of the local host. If Erlang was started - with the <c>-name</c> command line flag, <c>Name</c> is + with the <c>-name</c> command line flag, <c><anno>Name</anno></c> is the fully qualified name.</p> </desc> </func> <func> - <name>names() -> {ok, [{Name, Port}]} | {error, Reason}</name> - <name>names(Host) -> {ok, [{Name, Port}]} | {error, Reason}</name> + <name name="names" arity="0"/> + <name name="names" arity="1"/> <fsummary>Names of Erlang nodes at a host</fsummary> - <type> - <v>Name = string()</v> - <v>Port = int()</v> - <v>Reason = address | term()</v> - </type> <desc> <p>Similar to <c>epmd -names</c>, see <c>epmd(1)</c>. - <c>Host</c> defaults to the local host. Returns the names and + <c><anno>Host</anno></c> defaults to the local host. Returns the names and associated port numbers of the Erlang nodes that <c>epmd</c> at the specified host has registered.</p> <p>Returns <c>{error, address}</c> if <c>epmd</c> is not - running. See <c>inet(3)</c> for other possible values of - <c>Reason</c>.</p> + running.</p> <pre> (arne@dunn)1> <input>net_adm:names().</input> {ok,[{"arne",40262}]}</pre> </desc> </func> <func> - <name>ping(Node) -> pong | pang</name> + <name name="ping" arity="1"/> <fsummary>Set up a connection to a node</fsummary> - <type> - <v>Node = node()</v> - </type> <desc> - <p>Tries to set up a connection to <c>Node</c>. Returns + <p>Tries to set up a connection to <c><anno>Node</anno></c>. Returns <c>pang</c> if it fails, or <c>pong</c> if it is successful.</p> </desc> </func> <func> - <name>world() -> [node()]</name> - <name>world(Arg) -> [node()]</name> + <name name="world" arity="0"/> + <name name="world" arity="1"/> + <type name="verbosity"/> <fsummary>Lookup and connect to all nodes at all hosts in <c>.hosts.erlang</c></fsummary> - <type> - <v>Arg = silent | verbose</v> - </type> <desc> <p>This function calls <c>names(Host)</c> for all hosts which are specified in the Erlang host file <c>.hosts.erlang</c>, collects the replies and then evaluates <c>ping(Node)</c> on all those nodes. Returns the list of all nodes that were, successfully pinged.</p> - <p><c>Arg</c> defaults to <c>silent</c>. - If <c>Arg == verbose</c>, the function writes information about which + <p><c><anno>Arg</anno></c> defaults to <c>silent</c>. + If <c><anno>Arg</anno> == verbose</c>, the function writes information about which nodes it is pinging to stdout.</p> <p>This function can be useful when a node is started, and the names of the other nodes in the network are not initially @@ -131,14 +107,10 @@ </desc> </func> <func> - <name>world_list(Hosts) -> [node()]</name> - <name>world_list(Hosts, Arg) -> [node()]</name> + <name name="world_list" arity="1"/> + <name name="world_list" arity="2"/> + <type name="verbosity"/> <fsummary>Lookup and connect to all nodes at specified hosts</fsummary> - <type> - <v>Hosts = [Host]</v> - <v> Host = atom()</v> - <v>Arg = silent | verbose</v> - </type> <desc> <p>As <c>world/0,1</c>, but the hosts are given as argument instead of being read from <c>.hosts.erlang</c>.</p> diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml index a18226e779..96e2aa665d 100644 --- a/lib/kernel/doc/src/net_kernel.xml +++ b/lib/kernel/doc/src/net_kernel.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -64,50 +64,38 @@ $ <input>erl -sname foobar</input></pre> </description> <funcs> <func> - <name>allow(Nodes) -> ok | error</name> + <name name="allow" arity="1"/> <fsummary>Limit access to a specified set of nodes</fsummary> - <type> - <v>Nodes = [node()]</v> - </type> <desc> <p>Limits access to the specified set of nodes. Any access - attempts made from (or to) nodes not in <c>Nodes</c> will be + attempts made from (or to) nodes not in <c><anno>Nodes</anno></c> will be rejected.</p> - <p>Returns <c>error</c> if any element in <c>Nodes</c> is not + <p>Returns <c>error</c> if any element in <c><anno>Nodes</anno></c> is not an atom.</p> </desc> </func> <func> - <name>connect_node(Node) -> true | false | ignored</name> + <name name="connect_node" arity="1"/> <fsummary>Establish a connection to a node</fsummary> - <type> - <v>Node = node()</v> - </type> <desc> - <p>Establishes a connection to <c>Node</c>. Returns <c>true</c> + <p>Establishes a connection to <c><anno>Node</anno></c>. Returns <c>true</c> if successful, <c>false</c> if not, and <c>ignored</c> if the local node is not alive.</p> </desc> </func> <func> - <name>monitor_nodes(Flag) -> ok | Error</name> - <name>monitor_nodes(Flag, Options) -> ok | Error</name> + <name name="monitor_nodes" arity="1"/> + <name name="monitor_nodes" arity="2"/> <fsummary>Subscribe to node status change messages</fsummary> - <type> - <v>Flag = true | false</v> - <v>Options = [Option]</v> - <v> Option -- see below</v> - <v>Error = error | {error, term()}</v> - </type> <desc> <p>The calling process subscribes or unsubscribes to node status change messages. A <c>nodeup</c> message is delivered to all subscribing process when a new node is connected, and a <c>nodedown</c> message is delivered when a node is disconnected.</p> - <p>If <c>Flag</c> is <c>true</c>, a new subscription is started. - If <c>Flag</c> is <c>false</c>, all previous subscriptions -- - started with the same <c>Options</c> -- are stopped. Two + <p>If <c><anno>Flag</anno></c> is <c>true</c>, a new subscription is started. + If <c><anno>Flag</anno></c> is <c>false</c>, all previous subscriptions -- + started with the same <c><anno>Options</anno></c> -- are stopped. Two option lists are considered the same if they contain the same set of options.</p> <p>As of <c>kernel</c> version 2.11.4, and <c>erts</c> version @@ -139,23 +127,23 @@ $ <input>erl -sname foobar</input></pre> <p>Note, that this is <em>not</em> guaranteed for <c>kernel</c> versions before 2.13.</p> <p>The format of the node status change messages depends on - <c>Options</c>. If <c>Options</c> is [], which is the default, + <c><anno>Options</anno></c>. If <c><anno>Options</anno></c> is [], which is the default, the format is:</p> <code type="none"> {nodeup, Node} | {nodedown, Node} Node = node()</code> - <p>If <c>Options /= []</c>, the format is:</p> + <p>If <c><anno>Options</anno> /= []</c>, the format is:</p> <code type="none"> {nodeup, Node, InfoList} | {nodedown, Node, InfoList} Node = node() InfoList = [{Tag, Val}]</code> <p><c>InfoList</c> is a list of tuples. Its contents depends on - <c>Options</c>, see below.</p> + <c><anno>Options</anno></c>, see below.</p> <p>Also, when <c>OptionList == []</c> only visible nodes, that is, nodes that appear in the result of <seealso marker="erts:erlang#nodes/0">nodes/0</seealso>, are monitored.</p> - <p><c>Option</c> can be any of the following:</p> + <p><c><anno>Option</anno></c> can be any of the following:</p> <taglist> <tag><c>{node_type, NodeType}</c></tag> <item> @@ -209,61 +197,51 @@ $ <input>erl -sname foobar</input></pre> </desc> </func> <func> - <name>get_net_ticktime() -> Res</name> + <name name="get_net_ticktime" arity="0"/> <fsummary>Get <c>net_ticktime</c></fsummary> - <type> - <v>Res = NetTicktime | {ongoing_change_to, NetTicktime}</v> - <v> NetTicktime = int()</v> - </type> <desc> <p>Gets <c>net_ticktime</c> (see <seealso marker="kernel_app">kernel(6)</seealso>).</p> - <p>Currently defined return values (<c>Res</c>):</p> + <p>Currently defined return values (<c><anno>Res</anno></c>):</p> <taglist> - <tag><c>NetTicktime</c></tag> + <tag><c><anno>NetTicktime</anno></c></tag> <item> - <p><c>net_ticktime</c> is <c>NetTicktime</c> seconds.</p> + <p><c>net_ticktime</c> is <c><anno>NetTicktime</anno></c> seconds.</p> </item> - <tag><c>{ongoing_change_to, NetTicktime}</c></tag> + <tag><c>{ongoing_change_to, <anno>NetTicktime</anno>}</c></tag> <item> <p><c>net_kernel</c> is currently changing - <c>net_ticktime</c> to <c>NetTicktime</c> seconds.</p> + <c>net_ticktime</c> to <c><anno>NetTicktime</anno></c> seconds.</p> </item> </taglist> </desc> </func> <func> - <name>set_net_ticktime(NetTicktime) -> Res</name> - <name>set_net_ticktime(NetTicktime, TransitionPeriod) -> Res</name> + <name name="set_net_ticktime" arity="1"/> + <name name="set_net_ticktime" arity="2"/> <fsummary>Set <c>net_ticktime</c></fsummary> - <type> - <v>NetTicktime = int() > 0</v> - <v>TransitionPeriod = int() >= 0</v> - <v>Res = unchanged | change_initiated | {ongoing_change_to, NewNetTicktime}</v> - <v> NewNetTicktime = int() > 0</v> - </type> <desc> <p>Sets <c>net_ticktime</c> (see <seealso marker="kernel_app">kernel(6)</seealso>) to - <c>NetTicktime</c> seconds. <c>TransitionPeriod</c> defaults + <c><anno>NetTicktime</anno></c> seconds. <c><anno>TransitionPeriod</anno></c> defaults to 60.</p> <p>Some definitions:</p> <p></p> <taglist> <tag>The minimum transition traffic interval (<c>MTTI</c>)</tag> <item> - <p><c>minimum(NetTicktime, PreviousNetTicktime)*1000 div 4</c> milliseconds.</p> + <p><c>minimum(<anno>NetTicktime</anno>, PreviousNetTicktime)*1000 div 4</c> milliseconds.</p> </item> <tag>The transition period</tag> <item> <p>The time of the least number of consecutive <c>MTTI</c>s - to cover <c>TransitionPeriod</c> seconds following + to cover <c><anno>TransitionPeriod</anno></c> seconds following the call to <c>set_net_ticktime/2</c> (i.e. - ((<c>TransitionPeriod*1000 - 1) div MTTI + 1)*MTTI</c> + ((<c><anno>TransitionPeriod</anno>*1000 - 1) div MTTI + 1)*MTTI</c> milliseconds).</p> </item> </taglist> - <p>If <c><![CDATA[NetTicktime < PreviousNetTicktime]]></c>, the actual + <p>If <c><![CDATA[<anno>NetTicktime</anno> < PreviousNetTicktime]]></c>, the actual <c>net_ticktime</c> change will be done at the end of the transition period; otherwise, at the beginning. During the transition period, <c>net_kernel</c> will ensure that @@ -271,7 +249,7 @@ $ <input>erl -sname foobar</input></pre> every <c>MTTI</c> millisecond.</p> <note> <p>The <c>net_ticktime</c> changes have to be initiated on all - nodes in the network (with the same <c>NetTicktime</c>) + nodes in the network (with the same <c><anno>NetTicktime</anno></c>) before the end of any transition period on any node; otherwise, connections may erroneously be disconnected.</p> </note> @@ -280,18 +258,18 @@ $ <input>erl -sname foobar</input></pre> <tag><c>unchanged</c></tag> <item> <p><c>net_ticktime</c> already had the value of - <c>NetTicktime</c> and was left unchanged.</p> + <c><anno>NetTicktime</anno></c> and was left unchanged.</p> </item> <tag><c>change_initiated</c></tag> <item> <p><c>net_kernel</c> has initiated the change of - <c>net_ticktime</c> to <c>NetTicktime</c> seconds.</p> + <c>net_ticktime</c> to <c><anno>NetTicktime</anno></c> seconds.</p> </item> - <tag><c>{ongoing_change_to, NewNetTicktime}</c></tag> + <tag><c>{ongoing_change_to, <anno>NewNetTicktime</anno>}</c></tag> <item> <p>The request was <em>ignored</em>; because, <c>net_kernel</c> was busy changing <c>net_ticktime</c> to - <c>NewTicktime</c> seconds.</p> + <c><anno>NewNetTicktime</anno></c> seconds.</p> </item> </taglist> </desc> @@ -315,7 +293,7 @@ $ <input>erl -sname foobar</input></pre> </desc> </func> <func> - <name>stop() -> ok | {error, not_allowed | not_found}</name> + <name name="stop" arity="0"/> <fsummary>Turn a node into a non-distributed Erlang runtime system</fsummary> <desc> <p>Turns a distributed node into a non-distributed node. For diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 065b24c53d..f92837dfe5 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2010</year> + <year>2004</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index 2c9cc33eb7..56fc1834ec 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -38,13 +38,10 @@ </description> <funcs> <func> - <name>cmd(Command) -> string()</name> + <name name="cmd" arity="1"/> <fsummary>Execute a command in a shell of the target OS</fsummary> - <type> - <v>Command = string() | atom()</v> - </type> <desc> - <p>Executes <c>Command</c> in a command shell of the target OS, + <p>Executes <c><anno>Command</anno></c> in a command shell of the target OS, captures the standard output of the command and returns this result as a string. This function is a replacement of the previous <c>unix:cmd/1</c>; on a Unix platform they are @@ -60,23 +57,18 @@ DirOut = os:cmd("dir"), % on Win32 platform</code> </desc> </func> <func> - <name>find_executable(Name) -> Filename | false</name> - <name>find_executable(Name, Path) -> Filename | false</name> + <name name="find_executable" arity="1"/> + <name name="find_executable" arity="2"/> <fsummary>Absolute filename of a program</fsummary> - <type> - <v>Name = string()</v> - <v>Path = string()</v> - <v>Filename = string()</v> - </type> <desc> <p>These two functions look up an executable program given its name and a search path, in the same way as the underlying operating system. <c>find_executable/1</c> uses the current execution path (that is, the environment variable PATH on Unix and Windows).</p> - <p><c>Path</c>, if given, should conform to the syntax of + <p><c><anno>Path</anno></c>, if given, should conform to the syntax of execution paths on the operating system. The absolute - filename of the executable program <c>Name</c> is returned, + filename of the executable program <c><anno>Name</anno></c> is returned, or <c>false</c> if the program was not found.</p> </desc> </func> @@ -137,7 +129,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code> <name>timestamp() -> {MegaSecs, Secs, MicroSecs}</name> <fsummary>Returna a timestamp from the OS in the erlang:now/0 format</fsummary> <type> - <v>MegaSecs = Secs = MicroSecs = int()</v> + <v>MegaSecs = Secs = MicroSecs = integer() >= 0</v> </type> <desc> <p>Returns a tuple in the same format as <seealso marker="erts:erlang#now/0">erlang:now/0</seealso>. The difference is that this function returns what the operating system thinks (a.k.a. the wall clock time) without any attempts at time correction. The result of two different calls to this function is <em>not</em> guaranteed to be different.</p> @@ -165,19 +157,15 @@ format_utc_timestamp() -> </desc> </func> <func> - <name>type() -> {Osfamily, Osname} | Osfamily</name> + <name name="type" arity="0"/> <fsummary>Return the OS family and, in some cases, OS name of the current operating system</fsummary> - <type> - <v>Osfamily = win32 | unix | vxworks</v> - <v>Osname = atom()</v> - </type> <desc> - <p>Returns the <c>Osfamily</c> and, in some cases, <c>Osname</c> + <p>Returns the <c><anno>Osfamily</anno></c> and, in some cases, <c><anno>Osname</anno></c> of the current operating system.</p> - <p>On Unix, <c>Osname</c> will have same value as + <p>On Unix, <c><anno>Osname</anno></c> will have same value as <c>uname -s</c> returns, but in lower case. For example, on Solaris 1 and 2, it will be <c>sunos</c>.</p> - <p>In Windows, <c>Osname</c> will be either <c>nt</c> (on + <p>In Windows, <c><anno>Osname</anno></c> will be either <c>nt</c> (on Windows NT), or <c>windows</c> (on Windows 95).</p> <p>On VxWorks the OS family alone is returned, that is <c>vxworks</c>.</p> @@ -185,17 +173,13 @@ format_utc_timestamp() -> <p>Think twice before using this function. Use the <c>filename</c> module if you want to inspect or build file names in a portable way. - Avoid matching on the <c>Osname</c> atom.</p> + Avoid matching on the <c><anno>Osname</anno></c> atom.</p> </note> </desc> </func> <func> - <name>version() -> {Major, Minor, Release} | VersionString</name> + <name name="version" arity="0"/> <fsummary>Return the Operating System version</fsummary> - <type> - <v>Major = Minor = Release = integer()</v> - <v>VersionString = string()</v> - </type> <desc> <p>Returns the operating system version. On most systems, this function returns a tuple, but a string diff --git a/lib/kernel/doc/src/pg2.xml b/lib/kernel/doc/src/pg2.xml index 7463fd10f5..d26ff0fc6b 100644 --- a/lib/kernel/doc/src/pg2.xml +++ b/lib/kernel/doc/src/pg2.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -60,13 +60,16 @@ to avoid name clashes.</p> </warning> </description> + <datatypes> + <datatype> + <name name="name"/> + <desc><p>The name of a process group.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>create(Name) -> void()</name> + <name name="create" arity="1"/> <fsummary>Create a new, empty process group</fsummary> - <type> - <v>Name = term()</v> - </type> <desc> <p>Creates a new, empty process group. The group is globally visible on all nodes. If the group exists, nothing happens. @@ -74,24 +77,16 @@ </desc> </func> <func> - <name>delete(Name) -> void()</name> + <name name="delete" arity="1"/> <fsummary>Delete a process group</fsummary> - <type> - <v>Name = term()</v> - </type> <desc> <p>Deletes a process group. </p> </desc> </func> <func> - <name>get_closest_pid(Name) -> Pid | {error, Reason}</name> + <name name="get_closest_pid" arity="1"/> <fsummary>Common dispatch function</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Reason = {no_process, Name} | {no_such_group, Name}</v> - </type> <desc> <p>This is a useful dispatch function which can be used from client functions. It returns a process on the local node, if @@ -100,13 +95,8 @@ </desc> </func> <func> - <name>get_members(Name) -> [Pid] | {error, Reason}</name> + <name name="get_members" arity="1"/> <fsummary>Return all processes in a group</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Reason = {no_such_group, Name}</v> - </type> <desc> <p>Returns all processes in the group <c>Name</c>. This function should be used from within a client function that @@ -115,13 +105,8 @@ </desc> </func> <func> - <name>get_local_members(Name) -> [Pid] | {error, Reason}</name> + <name name="get_local_members" arity="1"/> <fsummary>Return all local processes in a group</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Reason = {no_such_group, Name}</v> - </type> <desc> <p>Returns all processes running on the local node in the group <c>Name</c>. This function should to be used from @@ -131,13 +116,8 @@ </desc> </func> <func> - <name>join(Name, Pid) -> ok | {error, Reason}</name> + <name name="join" arity="2"/> <fsummary>Join a process to a group</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Reason = {no_such_group, Name}</v> - </type> <desc> <p>Joins the process <c>Pid</c> to the group <c>Name</c>. A process can join a group several times; it must then @@ -146,13 +126,8 @@ </desc> </func> <func> - <name>leave(Name, Pid) -> ok | {error, Reason}</name> + <name name="leave" arity="2"/> <fsummary>Make a process leave a group</fsummary> - <type> - <v>Name = term()</v> - <v>Pid = pid()</v> - <v>Reason = {no_such_group, Name}</v> - </type> <desc> <p>Makes the process <c>Pid</c> leave the group <c>Name</c>. If the process is not a member of the group, <c>ok</c> is @@ -161,24 +136,17 @@ </desc> </func> <func> - <name>which_groups() -> [Name]</name> + <name name="which_groups" arity="0"/> <fsummary>Return a list of all known groups</fsummary> - <type> - <v>Name = term()</v> - </type> <desc> <p>Returns a list of all known groups. </p> </desc> </func> <func> - <name>start()</name> - <name>start_link() -> {ok, Pid} | {error, Reason}</name> + <name name="start" arity="0"/> + <name name="start_link" arity="0"/> <fsummary>Start the pg2 server</fsummary> - <type> - <v>Pid = pid()</v> - <v>Reason = term()</v> - </type> <desc> <p>Starts the pg2 server. Normally, the server does not need to be started explicitly, as it is started dynamically if it diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml index 86c6ea9178..b01ff16c85 100644 --- a/lib/kernel/doc/src/rpc.xml +++ b/lib/kernel/doc/src/rpc.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -37,40 +37,34 @@ for collecting information on a remote node, or for running a function with some specific side effects on the remote node.</p> </description> + <datatypes> + <datatype> + <name name="key"/> + <desc> + <p>As returned by <seealso marker="#async_call/4"> + <c>async_call/4</c>.</seealso></p> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>call(Node, Module, Function, Args) -> Res | {badrpc, Reason}</name> + <name name="call" arity="4"/> <fsummary>Evaluate a function call on a node</fsummary> - <type> - <v>Node = node()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Res = term()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Evaluates <c>apply(Module, Function, Args)</c> on the node - <c>Node</c> and returns the corresponding value <c>Res</c>, or - <c>{badrpc, Reason}</c> if the call fails.</p> + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node + <c><anno>Node</anno></c> and returns the corresponding value <c><anno>Res</anno></c>, or + <c>{badrpc, <anno>Reason</anno>}</c> if the call fails.</p> </desc> </func> <func> - <name>call(Node, Module, Function, Args, Timeout) -> Res | {badrpc, Reason}</name> + <name name="call" arity="5"/> <fsummary>Evaluate a function call on a node</fsummary> - <type> - <v>Node = node()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Res = term()</v> - <v>Reason = timeout | term()</v> - <v>Timeout = int() | infinity</v> - </type> <desc> - <p>Evaluates <c>apply(Module, Function, Args)</c> on the node - <c>Node</c> and returns the corresponding value <c>Res</c>, or - <c>{badrpc, Reason}</c> if the call fails. <c>Timeout</c> is + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node + <c><anno>Node</anno></c> and returns the corresponding value <c><anno>Res</anno></c>, or + <c>{badrpc, <anno>Reason</anno>}</c> if the call fails. <c><anno>Timeout</anno></c> is a timeout value in milliseconds. If the call times out, - <c>Reason</c> is <c>timeout</c>.</p> + <c><anno>Reason</anno></c> is <c>timeout</c>.</p> <p>If the reply arrives after the call times out, no message will contaminate the caller's message queue, since this function spawns off a middleman process to act as (a void) @@ -80,17 +74,10 @@ </desc> </func> <func> - <name>block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason}</name> + <name name="block_call" arity="4"/> <fsummary>Evaluate a function call on a node in the RPC server's context</fsummary> - <type> - <v>Node = node()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Res = term()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Like <c>call/4</c>, but the RPC server at <c>Node</c> does + <p>Like <c>call/4</c>, but the RPC server at <c><anno>Node</anno></c> does not create a separate process to handle the call. Thus, this function can be used if the intention of the call is to block the RPC server from any other incoming requests until @@ -101,50 +88,31 @@ </desc> </func> <func> - <name>block_call(Node, Module, Function, Args, Timeout) -> Res | {badrpc, Reason}</name> + <name name="block_call" arity="5"/> <fsummary>Evaluate a function call on a node in the RPC server's context</fsummary> - <type> - <v>Node = node()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Timeout = int() | infinity</v> - <v>Res = term()</v> - <v>Reason = term()</v> - </type> <desc> <p>Like <c>block_call/4</c>, but with a timeout value in the same manner as <c>call/5</c>.</p> </desc> </func> <func> - <name>async_call(Node, Module, Function, Args) -> Key</name> + <name name="async_call" arity="4"/> <fsummary>Evaluate a function call on a node, asynchronous version</fsummary> - <type> - <v>Node = node()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Key -- see below</v> - </type> <desc> <p>Implements <em>call streams with promises</em>, a type of RPC which does not suspend the caller until the result is finished. Instead, a key is returned which can be used at a later stage to collect the value. The key can be viewed as a promise to deliver the answer.</p> - <p>In this case, the key <c>Key</c> is returned, which can be + <p>In this case, the key <c><anno>Key</anno></c> is returned, which can be used in a subsequent call to <c>yield/1</c> or <c>nb_yield/1,2</c> to retrieve the value of evaluating - <c>apply(Module, Function, Args)</c> on the node <c>Node</c>.</p> + <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node <c><anno>Node</anno></c>.</p> </desc> </func> <func> - <name>yield(Key) -> Res | {badrpc, Reason}</name> + <name name="yield" arity="1"/> <fsummary>Deliver the result of evaluating a function call on a node (blocking)</fsummary> - <type> - <v>Key -- see async_call/4</v> - <v>Res = term()</v> - <v>Reason = term()</v> - </type> <desc> <p>Returns the promised answer from a previous <c>async_call/4</c>. If the answer is available, it is @@ -153,87 +121,46 @@ </desc> </func> <func> - <name>nb_yield(Key) -> {value, Val} | timeout</name> + <name name="nb_yield" arity="1"/> <fsummary>Deliver the result of evaluating a function call on a node (non-blocking)</fsummary> - <type> - <v>Key -- see async_call/4</v> - <v>Val = Res | {badrpc, Reason}</v> - <v> Res = term()</v> - <v> Reason = term()</v> - </type> <desc> - <p>Equivalent to <c>nb_yield(Key, 0)</c>.</p> + <p>Equivalent to <c>nb_yield(<anno>Key</anno>, 0)</c>.</p> </desc> </func> <func> - <name>nb_yield(Key, Timeout) -> {value, Val} | timeout</name> + <name name="nb_yield" arity="2"/> <fsummary>Deliver the result of evaluating a function call on a node (non-blocking)</fsummary> - <type> - <v>Key -- see async_call/4</v> - <v>Timeout = int() | infinity</v> - <v>Val = Res | {badrpc, Reason}</v> - <v> Res = term()</v> - <v> Reason = term()</v> - </type> <desc> <p>This is a non-blocking version of <c>yield/1</c>. It returns - the tuple <c>{value, Val}</c> when the computation has - finished, or <c>timeout</c> when <c>Timeout</c> milliseconds + the tuple <c>{value, <anno>Val</anno>}</c> when the computation has + finished, or <c>timeout</c> when <c><anno>Timeout</anno></c> milliseconds has elapsed.</p> </desc> </func> <func> - <name>multicall(Module, Function, Args) -> {ResL, BadNodes}</name> + <name name="multicall" arity="3"/> <fsummary>Evaluate a function call on a number of nodes</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>ResL = [term()]</v> - <v>BadNodes = [node()]</v> - </type> <desc> - <p>Equivalent to <c>multicall([node()|nodes()], Module, Function, Args, infinity)</c>.</p> + <p>Equivalent to <c>multicall([node()|nodes()], <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>, infinity)</c>.</p> </desc> </func> <func> - <name>multicall(Nodes, Module, Function, Args) -> {ResL, BadNodes}</name> + <name name="multicall" arity="4" clause_i="1"/> <fsummary>Evaluate a function call on a number of nodes</fsummary> - <type> - <v>Nodes = [node()]</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>ResL = [term()]</v> - <v>BadNodes = [node()]</v> - </type> <desc> - <p>Equivalent to <c>multicall(Nodes, Module, Function, Args, infinity)</c>.</p> + <p>Equivalent to <c>multicall(<anno>Nodes</anno>, <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>, infinity)</c>.</p> </desc> </func> <func> - <name>multicall(Module, Function, Args, Timeout) -> {ResL, BadNodes}</name> + <name name="multicall" arity="4" clause_i="2"/> <fsummary>Evaluate a function call on a number of nodes</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Timeout = int() | infinity</v> - <v>ResL = [term()]</v> - <v>BadNodes = [node()]</v> - </type> <desc> - <p>Equivalent to <c>multicall([node()|nodes()], Module, Function, Args, Timeout)</c>.</p> + <p>Equivalent to <c>multicall([node()|nodes()], <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>, <anno>Timeout</anno>)</c>.</p> </desc> </func> <func> - <name>multicall(Nodes, Module, Function, Args, Timeout) -> {ResL, BadNodes}</name> + <name name="multicall" arity="5"/> <fsummary>Evaluate a function call on a number of nodes</fsummary> - <type> - <v>Nodes = [node()]</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Timeout = int() | infinity</v> - <v>ResL = [term()]</v> - <v>BadNodes = [node()]</v> - </type> <desc> <p>In contrast to an RPC, a multicall is an RPC which is sent concurrently from one client to multiple servers. This is @@ -243,12 +170,12 @@ making a series of RPCs on all the nodes, but the multicall is faster as all the requests are sent at the same time and are collected one by one as they come back.</p> - <p>The function evaluates <c>apply(Module, Function, Args)</c> + <p>The function evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the specified nodes and collects the answers. It returns - <c>{ResL, Badnodes}</c>, where <c>Badnodes</c> is a list + <c>{<anno>ResL</anno>, <anno>BadNodes</anno>}</c>, where <c><anno>BadNodes</anno></c> is a list of the nodes that terminated or timed out during computation, - and <c>ResL</c> is a list of the return values. - <c>Timeout</c> is a time (integer) in milliseconds, or + and <c><anno>ResL</anno></c> is a list of the return values. + <c><anno>Timeout</anno></c> is a time (integer) in milliseconds, or <c>infinity</c>.</p> <p>The following example is useful when new object code is to be loaded on all nodes in the network, and also indicates @@ -264,93 +191,60 @@ </desc> </func> <func> - <name>cast(Node, Module, Function, Args) -> void()</name> + <name name="cast" arity="4"/> <fsummary>Run a function on a node ignoring the result</fsummary> - <type> - <v>Node = node()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - </type> <desc> - <p>Evaluates <c>apply(Module, Function, Args)</c> on the node - <c>Node</c>. No response is delivered and the calling + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node + <c><anno>Node</anno></c>. No response is delivered and the calling process is not suspended until the evaluation is complete, as is the case with <c>call/4,5</c>.</p> </desc> </func> <func> - <name>eval_everywhere(Module, Funtion, Args) -> void()</name> + <name name="eval_everywhere" arity="3"/> <fsummary>Run a function on all nodes, ignoring the result</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - </type> <desc> - <p>Equivalent to <c>eval_everywhere([node()|nodes()], Module, Function, Args)</c>.</p> + <p>Equivalent to <c>eval_everywhere([node()|nodes()], <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c>.</p> </desc> </func> <func> - <name>eval_everywhere(Nodes, Module, Function, Args) -> void()</name> + <name name="eval_everywhere" arity="4"/> <fsummary>Run a function on specific nodes, ignoring the result</fsummary> - <type> - <v>Nodes = [node()]</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - </type> <desc> - <p>Evaluates <c>apply(Module, Function, Args)</c> on + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the specified nodes. No answers are collected.</p> </desc> </func> <func> - <name>abcast(Name, Msg) -> void()</name> + <name name="abcast" arity="2"/> <fsummary>Broadcast a message asynchronously to a registered process on all nodes</fsummary> - <type> - <v>Name = atom()</v> - <v>Msg = term()</v> - </type> <desc> - <p>Equivalent to <c>abcast([node()|nodes()], Name, Msg)</c>.</p> + <p>Equivalent to <c>abcast([node()|nodes()], <anno>Name</anno>, <anno>Msg</anno>)</c>.</p> </desc> </func> <func> - <name>abcast(Nodes, Name, Msg) -> void()</name> + <name name="abcast" arity="3"/> <fsummary>Broadcast a message asynchronously to a registered process on specific nodes</fsummary> - <type> - <v>Nodes = [node()]</v> - <v>Name = atom()</v> - <v>Msg = term()</v> - </type> <desc> - <p>Broadcasts the message <c>Msg</c> asynchronously to - the registered process <c>Name</c> on the specified nodes.</p> + <p>Broadcasts the message <c><anno>Msg</anno></c> asynchronously to + the registered process <c><anno>Name</anno></c> on the specified nodes.</p> </desc> </func> <func> - <name>sbcast(Name, Msg) -> {GoodNodes, BadNodes}</name> + <name name="sbcast" arity="2"/> <fsummary>Broadcast a message synchronously to a registered process on all nodes</fsummary> - <type> - <v>Name = atom()</v> - <v>Msg = term()</v> - <v>GoodNodes = BadNodes = [node()]</v> - </type> <desc> - <p>Equivalent to <c>sbcast([node()|nodes()], Name, Msg)</c>.</p> + <p>Equivalent to <c>sbcast([node()|nodes()], <anno>Name</anno>, <anno>Msg</anno>)</c>.</p> </desc> </func> <func> - <name>sbcast(Nodes, Name, Msg) -> {GoodNodes, BadNodes}</name> + <name name="sbcast" arity="3"/> <fsummary>Broadcast a message synchronously to a registered process on specific nodes</fsummary> - <type> - <v>Name = atom()</v> - <v>Msg = term()</v> - <v>Nodes = GoodNodes = BadNodes = [node()]</v> - </type> <desc> - <p>Broadcasts the message <c>Msg</c> synchronously to - the registered process <c>Name</c> on the specified nodes.</p> - <p>Returns <c>{GoodNodes, BadNodes}</c>, where <c>GoodNodes</c> - is the list of nodes which have <c>Name</c> as a registered + <p>Broadcasts the message <c><anno>Msg</anno></c> synchronously to + the registered process <c><anno>Name</anno></c> on the specified nodes.</p> + <p>Returns <c>{<anno>GoodNodes</anno>, <anno>BadNodes</anno>}</c>, where <c><anno>GoodNodes</anno></c> + is the list of nodes which have <c><anno>Name</anno></c> as a registered process.</p> <p>The function is synchronous in the sense that it is known that all servers have received the message when the call @@ -362,67 +256,46 @@ </desc> </func> <func> - <name>server_call(Node, Name, ReplyWrapper, Msg) -> Reply | {error, Reason}</name> + <name name="server_call" arity="4"/> <fsummary>Interact with a server on a node</fsummary> - <type> - <v>Node = node()</v> - <v>Name = atom()</v> - <v>ReplyWrapper = Msg = Reply = term()</v> - <v>Reason = term()</v> - </type> <desc> <p>This function can be used when interacting with a server - called <c>Name</c> at node <c>Node</c>. It is assumed that + called <c><anno>Name</anno></c> at node <c><anno>Node</anno></c>. It is assumed that the server receives messages in the format - <c>{From, Msg}</c> and replies using <c>From ! {ReplyWrapper, Node, Reply}</c>. This function makes such + <c>{From, <anno>Msg</anno>}</c> and replies using <c>From ! {<anno>ReplyWrapper</anno>, <anno>Node</anno>, <anno>Reply</anno>}</c>. This function makes such a server call and ensures that the entire call is packed into an atomic transaction which either succeeds or fails. It never hangs, unless the server itself hangs.</p> - <p>The function returns the answer <c>Reply</c> as produced by - the server <c>Name</c>, or <c>{error, Reason}</c>.</p> + <p>The function returns the answer <c><anno>Reply</anno></c> as produced by + the server <c><anno>Name</anno></c>, or <c>{error, <anno>Reason</anno>}</c>.</p> </desc> </func> <func> - <name>multi_server_call(Name, Msg) -> {Replies, BadNodes}</name> + <name name="multi_server_call" arity="2"/> <fsummary>Interact with the servers on a number of nodes</fsummary> - <type> - <v>Name = atom()</v> - <v>Msg = term()</v> - <v>Replies = [Reply]</v> - <v> Reply = term()</v> - <v>BadNodes = [node()]</v> - </type> <desc> - <p>Equivalent to <c>multi_server_call([node()|nodes()], Name, Msg)</c>.</p> + <p>Equivalent to <c>multi_server_call([node()|nodes()], <anno>Name</anno>, <anno>Msg</anno>)</c>.</p> </desc> </func> <func> - <name>multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes}</name> + <name name="multi_server_call" arity="3"/> <fsummary>Interact with the servers on a number of nodes</fsummary> - <type> - <v>Nodes = [node()]</v> - <v>Name = atom()</v> - <v>Msg = term()</v> - <v>Replies = [Reply]</v> - <v> Reply = term()</v> - <v>BadNodes = [node()]</v> - </type> <desc> <p>This function can be used when interacting with servers - called <c>Name</c> on the specified nodes. It is assumed that - the servers receive messages in the format <c>{From, Msg}</c> - and reply using <c>From ! {Name, Node, Reply}</c>, where + called <c><anno>Name</anno></c> on the specified nodes. It is assumed that + the servers receive messages in the format <c>{From, <anno>Msg</anno>}</c> + and reply using <c>From ! {<anno>Name</anno>, Node, <anno>Reply</anno>}</c>, where <c>Node</c> is the name of the node where the server is - located. The function returns <c>{Replies, Badnodes}</c>, - where <c>Replies</c> is a list of all <c>Reply</c> values and - <c>BadNodes</c> is a list of the nodes which did not exist, or + located. The function returns <c>{<anno>Replies</anno>, <anno>BadNodes</anno>}</c>, + where <c><anno>Replies</anno></c> is a list of all <c><anno>Reply</anno></c> values and + <c><anno>BadNodes</anno></c> is a list of the nodes which did not exist, or where the server did not exist, or where the server terminated before sending any reply.</p> </desc> </func> <func> - <name>safe_multi_server_call(Name, Msg) -> {Replies, BadNodes}</name> - <name>safe_multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes}</name> + <name name="safe_multi_server_call" arity="2"/> + <name name="safe_multi_server_call" arity="3"/> <fsummary>Interact with the servers on a number of nodes (deprecated)</fsummary> <desc> <warning> @@ -432,66 +305,47 @@ <p>In Erlang/OTP R6B and earlier releases, <c>multi_server_call/2,3</c> could not handle the case where the remote node exists, but there is no server called - <c>Name</c>. Instead this function had to be used. In + <c><anno>Name</anno></c>. Instead this function had to be used. In Erlang/OTP R7B and later releases, however, the functions are equivalent, except for this function being slightly slower.</p> </desc> </func> <func> - <name>parallel_eval(FuncCalls) -> ResL</name> + <name name="parallel_eval" arity="1"/> <fsummary>Evaluate several function calls on all nodes in parallel</fsummary> - <type> - <v>FuncCalls = [{Module, Function, Args}]</v> - <v> Module = Function = atom()</v> - <v> Args = [term()]</v> - <v>ResL = [term()]</v> - </type> <desc> - <p>For every tuple in <c>FuncCalls</c>, evaluates - <c>apply(Module, Function, Args)</c> on some node in + <p>For every tuple in <c><anno>FuncCalls</anno></c>, evaluates + <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on some node in the network. Returns the list of return values, in the same - order as in <c>FuncCalls</c>.</p> + order as in <c><anno>FuncCalls</anno></c>.</p> </desc> </func> <func> - <name>pmap({Module, Function}, ExtraArgs, List2) -> List1</name> + <name name="pmap" arity="3"/> <fsummary>Parallell evaluation of mapping a function over a list </fsummary> - <type> - <v>Module = Function = atom()</v> - <v>ExtraArgs = [term()]</v> - <v>List1 = [Elem]</v> - <v> Elem = term()</v> - <v>List2 = [term()]</v> - </type> <desc> - <p>Evaluates <c>apply(Module, Function, [Elem|ExtraArgs])</c>, - for every element <c>Elem</c> in <c>List1</c>, in parallel. + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, [<anno>Elem</anno>|<anno>ExtraArgs</anno>])</c>, + for every element <c><anno>Elem</anno></c> in <c><anno>List1</anno></c>, in parallel. Returns the list of return values, in the same order as in - <c>List1</c>.</p> + <c><anno>List1</anno></c>.</p> </desc> </func> <func> - <name>pinfo(Pid) -> [{Item, Info}] | undefined</name> + <name name="pinfo" arity="1"/> <fsummary>Information about a process</fsummary> - <type> - <v>Pid = pid()</v> - <v>Item, Info -- see erlang:process_info/1</v> - </type> <desc> <p>Location transparent version of the BIF - <c>process_info/1</c>.</p> + <seealso marker="erts:erlang#process_info/1"> + <c>process_info/1</c></seealso>.</p> </desc> </func> <func> - <name>pinfo(Pid, Item) -> {Item, Info} | undefined | []</name> + <name name="pinfo" arity="2"/> <fsummary>Information about a process</fsummary> - <type> - <v>Pid = pid()</v> - <v>Item, Info -- see erlang:process_info/1</v> - </type> <desc> <p>Location transparent version of the BIF - <c>process_info/2</c>.</p> + <seealso marker="erts:erlang#process_info/2"> + <c>process_info/2</c></seealso>.</p> </desc> </func> </funcs> diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml index 6c043dd767..1ab955bd8a 100644 --- a/lib/kernel/doc/src/seq_trace.xml +++ b/lib/kernel/doc/src/seq_trace.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1998</year><year>2009</year> + <year>1998</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -47,17 +47,22 @@ from users.</p> </note> </description> + <datatypes> + <datatype> + <name name="token"/> + <desc> + <p>An opaque term (a tuple) representing a trace token.</p> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>set_token(Token) -> PreviousToken</name> + <name name="set_token" arity="1"/> <fsummary>Set the trace token</fsummary> - <type> - <v>Token = PreviousToken = term() | []</v> - </type> <desc> - <p>Sets the trace token for the calling process to <c>Token</c>. - If <c>Token == []</c> then tracing is disabled, otherwise - <c>Token</c> should be an Erlang term returned from + <p>Sets the trace token for the calling process to <c><anno>Token</anno></c>. + If <c><anno>Token</anno> == []</c> then tracing is disabled, otherwise + <c><anno>Token</anno></c> should be an Erlang term returned from <c>get_token/0</c> or <c>set_token/1</c>. <c>set_token/1</c> can be used to temporarily exclude message passing from the trace by setting the trace token to empty like this:</p> @@ -72,18 +77,16 @@ seq_trace:set_token(OldToken), % activate the trace token again </desc> </func> <func> - <name>set_token(Component, Val) -> {Component, OldVal}</name> + <name name="set_token" arity="2"/> <fsummary>Set a component of the trace token</fsummary> - <type> - <v>Component = label | serial | Flag</v> - <v> Flag = send | 'receive' | print | timestamp </v> - <v>Val = OldVal -- see below</v> - </type> + <type name="component"/> + <type name="flag"/> + <type name="value"/> <desc> - <p>Sets the individual <c>Component</c> of the trace token to - <c>Val</c>. Returns the previous value of the component.</p> + <p>Sets the individual <c><anno>Component</anno></c> of the trace token to + <c><anno>Val</anno></c>. Returns the previous value of the component.</p> <taglist> - <tag><c>set_token(label, Int)</c></tag> + <tag><c>set_token(label, <anno>Integer</anno>)</c></tag> <item> <p>The <c>label</c> component is an integer which identifies all events belonging to the same sequential @@ -93,31 +96,31 @@ seq_trace:set_token(OldToken), % activate the trace token again </item> <tag><c>set_token(serial, SerialValue)</c></tag> <item> - <p><c>SerialValue = {Previous, Current}</c>. + <p><c>SerialValue = {<anno>Previous</anno>, <anno>Current</anno>}</c>. The <c>serial</c> component contains counters which enables the traced messages to be sorted, should never be set explicitly by the user as these counters are updated automatically. Default is <c>{0, 0}</c>.</p> </item> - <tag><c>set_token(send, Bool)</c></tag> + <tag><c>set_token(send, <anno>Bool</anno>)</c></tag> <item> <p>A trace token flag (<c>true | false</c>) which enables/disables tracing on message sending. Default is <c>false</c>.</p> </item> - <tag><c>set_token('receive', Bool)</c></tag> + <tag><c>set_token('receive', <anno>Bool</anno>)</c></tag> <item> <p>A trace token flag (<c>true | false</c>) which enables/disables tracing on message reception. Default is <c>false</c>.</p> </item> - <tag><c>set_token(print, Bool)</c></tag> + <tag><c>set_token(print, <anno>Bool</anno>)</c></tag> <item> <p>A trace token flag (<c>true | false</c>) which enables/disables tracing on explicit calls to <c>seq_trace:print/1</c>. Default is <c>false</c>.</p> </item> - <tag><c>set_token(timestamp, Bool)</c></tag> + <tag><c>set_token(timestamp, <anno>Bool</anno>)</c></tag> <item> <p>A trace token flag (<c>true | false</c>) which enables/disables a timestamp to be generated for each @@ -127,11 +130,8 @@ seq_trace:set_token(OldToken), % activate the trace token again </desc> </func> <func> - <name>get_token() -> TraceToken</name> + <name name="get_token" arity="0"/> <fsummary>Return the value of the trace token</fsummary> - <type> - <v>TraceToken = term() | []</v> - </type> <desc> <p>Returns the value of the trace token for the calling process. If <c>[]</c> is returned, it means that tracing is not active. @@ -141,13 +141,11 @@ seq_trace:set_token(OldToken), % activate the trace token again </desc> </func> <func> - <name>get_token(Component) -> {Component, Val}</name> + <name name="get_token" arity="1"/> <fsummary>Return the value of a trace token component</fsummary> - <type> - <v>Component = label | serial | Flag</v> - <v> Flag = send | 'receive' | print | timestamp </v> - <v>Val -- see set_token/2</v> - </type> + <type name="component"/> + <type name="flag"/> + <type name="value"/> <desc> <p>Returns the value of the trace token component <c>Component</c>. See @@ -156,33 +154,26 @@ seq_trace:set_token(OldToken), % activate the trace token again </desc> </func> <func> - <name>print(TraceInfo) -> void()</name> + <name name="print" arity="1"/> <fsummary>Put the Erlang term <c>TraceInfo</c>into the sequential trace output</fsummary> - <type> - <v>TraceInfo = term()</v> - </type> <desc> - <p>Puts the Erlang term <c>TraceInfo</c> into the sequential + <p>Puts the Erlang term <c><anno>TraceInfo</anno></c> into the sequential trace output if the calling process currently is executing within a sequential trace and the <c>print</c> flag of the trace token is set.</p> </desc> </func> <func> - <name>print(Label, TraceInfo) -> void()</name> + <name name="print" arity="2"/> <fsummary>Put the Erlang term <c>TraceInfo</c>into the sequential trace output</fsummary> - <type> - <v>Label = int()</v> - <v>TraceInfo = term()</v> - </type> <desc> <p>Same as <c>print/1</c> with the additional condition that - <c>TraceInfo</c> is output only if <c>Label</c> is equal to + <c><anno>TraceInfo</anno></c> is output only if <c>Label</c> is equal to the label component of the trace token.</p> </desc> </func> <func> - <name>reset_trace() -> void()</name> + <name name="reset_trace" arity="0"/> <fsummary>Stop all sequential tracing on the local node</fsummary> <desc> <p>Sets the trace token to empty for all processes on the @@ -194,26 +185,22 @@ seq_trace:set_token(OldToken), % activate the trace token again </desc> </func> <func> - <name>set_system_tracer(Tracer) -> OldTracer</name> + <name name="set_system_tracer" arity="1"/> <fsummary>Set the system tracer</fsummary> - <type> - <v>Tracer = OldTracer = pid() | port() | false</v> - </type> + <type name="tracer"/> <desc> <p>Sets the system tracer. The system tracer can be either a - process or port denoted by <c>Tracer</c>. Returns the previous + process or port denoted by <c><anno>Tracer</anno></c>. Returns the previous value (which can be <c>false</c> if no system tracer is active).</p> - <p>Failure: <c>{badarg, Info}}</c> if <c>Pid</c> is not an + <p>Failure: <c>{badarg, Info}}</c> if <c><anno>Pid</anno></c> is not an existing local pid.</p> </desc> </func> <func> - <name>get_system_tracer() -> Tracer</name> + <name name="get_system_tracer" arity="0"/> <fsummary>Return the pid() or port() of the current system tracer.</fsummary> - <type> - <v>Tracer = pid() | port() | false</v> - </type> + <type name="tracer"/> <desc> <p>Returns the pid or port identifier of the current system tracer or <c>false</c> if no system tracer is activated.</p> diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml new file mode 100644 index 0000000000..b41addaa0c --- /dev/null +++ b/lib/kernel/doc/src/specs.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="latin1" ?> +<specs xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="../specs/specs_application.xml"/> + <xi:include href="../specs/specs_auth.xml"/> + <xi:include href="../specs/specs_code.xml"/> + <xi:include href="../specs/specs_disk_log.xml"/> + <xi:include href="../specs/specs_erl_boot_server.xml"/> + <xi:include href="../specs/specs_erl_ddll.xml"/> + <xi:include href="../specs/specs_erl_prim_loader_stub.xml"/> + <xi:include href="../specs/specs_erlang_stub.xml"/> + <xi:include href="../specs/specs_error_handler.xml"/> + <xi:include href="../specs/specs_error_logger.xml"/> + <xi:include href="../specs/specs_file.xml"/> + <xi:include href="../specs/specs_gen_tcp.xml"/> + <xi:include href="../specs/specs_gen_udp.xml"/> + <xi:include href="../specs/specs_gen_sctp.xml"/> + <xi:include href="../specs/specs_global.xml"/> + <xi:include href="../specs/specs_global_group.xml"/> + <xi:include href="../specs/specs_heart.xml"/> + <xi:include href="../specs/specs_inet.xml"/> + <xi:include href="../specs/specs_inet_res.xml"/> + <xi:include href="../specs/specs_init_stub.xml"/> + <xi:include href="../specs/specs_net_adm.xml"/> + <xi:include href="../specs/specs_net_kernel.xml"/> + <xi:include href="../specs/specs_os.xml"/> + <xi:include href="../specs/specs_pg2.xml"/> + <xi:include href="../specs/specs_rpc.xml"/> + <xi:include href="../specs/specs_seq_trace.xml"/> + <xi:include href="../specs/specs_user.xml"/> + <xi:include href="../specs/specs_wrap_log_reader.xml"/> + <xi:include href="../specs/specs_zlib_stub.xml"/> + <xi:include href="../specs/specs_packages.xml"/> +</specs> diff --git a/lib/kernel/doc/src/wrap_log_reader.xml b/lib/kernel/doc/src/wrap_log_reader.xml index 18664a029f..6cf480b532 100644 --- a/lib/kernel/doc/src/wrap_log_reader.xml +++ b/lib/kernel/doc/src/wrap_log_reader.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1998</year><year>2009</year> + <year>1998</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -50,18 +50,20 @@ the called node, it is entirely up to the user to be sure that all items are read. </p> </description> + <datatypes> + <datatype> + <name name="continuation"/> + <desc><p>Continuation returned by + <c>open/1,2</c> or <c>chunk/1,2</c>.</p> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>chunk(Continuation)</name> - <name>chunk(Continuation, N) -> {Continuation2, Terms} | {Continuation2, Terms, Badbytes} | {Continuation2, eof} | {error, Reason}</name> + <name name="chunk" arity="1"/> + <name name="chunk" arity="2"/> <fsummary>Read a chunk of objects written to a wrap log.</fsummary> - <type> - <v>Continuation = continuation()</v> - <v>N = int() > 0 | infinity</v> - <v>Continuation2 = continuation()</v> - <v>Terms= [term()]</v> - <v>Badbytes = integer()</v> - </type> + <type name="chunk_ret"/> <desc> <p>This function makes it possible to efficiently read the terms which have been appended to a log. It minimises disk @@ -70,29 +72,29 @@ <p>The first time <c>chunk</c> is called an initial continuation returned from the <c>open/1</c>, <c>open/2</c> must be provided. </p> - <p>When <c>chunk/3</c> is called, <c>N</c> controls the + <p>When <c>chunk/3</c> is called, <c><anno>N</anno></c> controls the maximum number of terms that are read from the log in each chunk. Default is <c>infinity</c>, which means that all the terms contained in the 8K chunk are read. If less than - <c>N</c> terms are returned, this does not necessarily mean + <c><anno>N</anno></c> terms are returned, this does not necessarily mean that end of file is reached. </p> <p>The <c>chunk</c> function returns a tuple - <c>{Continuation2, Terms}</c>, where <c>Terms</c> is a list - of terms found in the log. <c>Continuation2</c> is yet + <c>{<anno>Continuation2</anno>, <anno>Terms</anno>}</c>, where <c><anno>Terms</anno></c> is a list + of terms found in the log. <c><anno>Continuation2</anno></c> is yet another continuation which must be passed on into any subsequent calls to <c>chunk</c>. With a series of calls to <c>chunk</c> it is then possible to extract all terms from a log. </p> <p>The <c>chunk</c> function returns a tuple - <c>{Continuation2, Terms, Badbytes}</c> if the log is opened - in read only mode and the read chunk is corrupt. <c>Badbytes</c> + <c>{<anno>Continuation2</anno>, <anno>Terms</anno>, <anno>Badbytes</anno>}</c> if the log is opened + in read only mode and the read chunk is corrupt. <c><anno>Badbytes</anno></c> indicates the number of non-Erlang terms found in the chunk. Note also that the log is not repaired. </p> - <p><c>chunk</c> returns <c>{Continuation2, eof}</c> when the end of the log is - reached, and <c>{error, Reason}</c> if an error occurs. + <p><c>chunk</c> returns <c>{<anno>Continuation2</anno>, eof}</c> when the end of the log is + reached, and <c>{error, <anno>Reason</anno>}</c> if an error occurs. </p> <p>The returned continuation may or may not be valid in the next call to <c>chunk</c>. This is because the log may wrap and delete @@ -103,37 +105,29 @@ </desc> </func> <func> - <name>close(Continuation) -> ok </name> + <name name="close" arity="1"/> <fsummary>Close a log</fsummary> - <type> - <v>Continuation = continuation()</v> - </type> <desc> <p>This function closes a log file properly. </p> </desc> </func> <func> - <name>open(Filename) -> OpenRet</name> - <name>open(Filename, N) -> OpenRet</name> + <name name="open" arity="1"/> + <name name="open" arity="2"/> <fsummary>Open a log file</fsummary> - <type> - <v>File = string() | atom()</v> - <v>N = integer()</v> - <v>OpenRet = {ok, Continuation} | {error, Reason} </v> - <v>Continuation = continuation()</v> - </type> + <type name="open_ret"/> <desc> - <p><c>Filename</c> specifies the name of the file which is to be read. </p> - <p><c>N</c> specifies the index of the file which is to be read. - If <c>N</c> is omitted the whole wrap log file will be read; if it + <p><c><anno>Filename</anno></c> specifies the name of the file which is to be read. </p> + <p><c><anno>N</anno></c> specifies the index of the file which is to be read. + If <c><anno>N</anno></c> is omitted the whole wrap log file will be read; if it is specified only the specified index file will be read. </p> - <p>The <c>open</c> function returns <c>{ok, Continuation}</c> if the - log/index file was successfully opened. The <c>Continuation</c> + <p>The <c>open</c> function returns <c>{ok, <anno>Continuation</anno>}</c> if the + log/index file was successfully opened. The <c><anno>Continuation</anno></c> is to be used when chunking or closing the file. </p> - <p>The function returns <c>{error, Reason}</c> for all errors. + <p>The function returns <c>{error, <anno>Reason</anno>}</c> for all errors. </p> </desc> </func> diff --git a/lib/kernel/include/inet.hrl b/lib/kernel/include/inet.hrl index 929b2ee294..3e64d4bb79 100644 --- a/lib/kernel/include/inet.hrl +++ b/lib/kernel/include/inet.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -19,18 +19,11 @@ %% This record is returned by inet:gethostbyaddr/2 and inet:gethostbyname/2. --type hostname() :: atom() | string(). --type ip4_address() :: {0..255,0..255,0..255,0..255}. --type ip6_address() :: {0..65535,0..65535,0..65535,0..65535, - 0..65535,0..65535,0..65535,0..65535}. --type ip_address() :: ip4_address() | ip6_address(). --type ip_port() :: 0..65535. - -record(hostent, { - h_name :: hostname(), %% offical name of host - h_aliases = [] :: [hostname()], %% alias list + h_name :: inet:hostname(), %% offical name of host + h_aliases = [] :: [inet:hostname()], %% alias list h_addrtype :: 'inet' | 'inet6', %% host address type h_length :: non_neg_integer(), %% length of address - h_addr_list = [] :: [ip_address()] %% list of addresses from name server + h_addr_list = [] :: [inet:ip_address()]%% list of addresses from name server }). diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl index 2a193affd4..fa3a4c3d36 100644 --- a/lib/kernel/src/application.erl +++ b/lib/kernel/src/application.erl @@ -32,20 +32,30 @@ %%%----------------------------------------------------------------- +-type start_type() :: 'normal' + | {'takeover', Node :: node()} + | {'failover', Node :: node()}. -type restart_type() :: 'permanent' | 'transient' | 'temporary'. --type application_opt() :: {'description', string()} - | {'vsn', string()} - | {'id', string()} - | {'modules', [atom() | {atom(), any()}]} - | {'registered', [atom()]} - | {'applications', [atom()]} - | {'included_applications', [atom()]} - | {'env', [{atom(), any()}]} - | {'start_phases', [{atom(), any()}] | 'undefined'} - | {'maxT', timeout()} % max timeout - | {'maxP', integer() | 'infinity'} % max processes - | {'mod', {atom(), any()}}. --type application_spec() :: {'application', atom(), [application_opt()]}. +-type application_opt() :: {'description', Description :: string()} + | {'vsn', Vsn :: string()} + | {'id', Id :: string()} + | {'modules', [(Module :: module()) | + {Module :: module(), Version :: term()}]} + | {'registered', Names :: [Name :: atom()]} + | {'applications', [Application :: atom()]} + | {'included_applications', [Application :: atom()]} + | {'env', [{Par :: atom(), Val :: term()}]} + | {'start_phases', + [{Phase :: atom(), PhaseArgs :: term()}] | 'undefined'} + | {'maxT', MaxT :: timeout()} % max timeout + | {'maxP', + MaxP :: pos_integer() | 'infinity'} % max processes + | {'mod', Start :: {Module :: module(), StartArgs :: term()}}. +-type application_spec() :: {'application', + Application :: atom(), + AppSpecKeys :: [application_opt()]}. + +-type(tuple_of(_T) :: tuple()). %%------------------------------------------------------------------ @@ -61,16 +71,29 @@ behaviour_info(_Other) -> %%% application_master. %%%----------------------------------------------------------------- --spec load(Application :: atom() | application_spec()) -> - 'ok' | {'error', term()}. +-spec load(AppDescr) -> 'ok' | {'error', Reason} when + AppDescr :: Application | (AppSpec :: application_spec()), + Application :: atom(), + Reason :: term(). load(Application) -> - load(Application, []). - --spec load(Application :: atom() | application_spec(), - Distributed :: any()) -> 'ok' | {'error', term()}. + load1(Application, []). + +-spec load(AppDescr, Distributed) -> 'ok' | {'error', Reason} when + AppDescr :: Application | (AppSpec :: application_spec()), + Application :: atom(), + Distributed :: {Application,Nodes} + | {Application,Time,Nodes} + | 'default', + Nodes :: [node() | tuple_of(node())], + Time :: pos_integer(), + Reason :: term(). load(Application, DistNodes) -> + load1(Application, DistNodes). + +%% Workaround due to specs. +load1(Application, DistNodes) -> case application_controller:load_application(Application) of ok when DistNodes =/= [] -> AppName = get_appl_name(Application), @@ -85,18 +108,24 @@ load(Application, DistNodes) -> Else end. --spec unload(Application :: atom()) -> 'ok' | {'error', term()}. +-spec unload(Application) -> 'ok' | {'error', Reason} when + Application :: atom(), + Reason :: term(). unload(Application) -> application_controller:unload_application(Application). --spec start(Application :: atom()) -> 'ok' | {'error', term()}. +-spec start(Application) -> 'ok' | {'error', Reason} when + Application :: atom(), + Reason :: term(). start(Application) -> start(Application, temporary). --spec start(Application :: atom() | application_spec(), - RestartType :: restart_type()) -> any(). +-spec start(Application, Type) -> 'ok' | {'error', Reason} when + Application :: atom(), + Type :: restart_type(), + Reason :: term(). start(Application, RestartType) -> case load(Application) of @@ -120,12 +149,18 @@ start_boot(Application) -> start_boot(Application, RestartType) -> application_controller:start_boot_application(Application, RestartType). --spec takeover(Application :: atom(), RestartType :: restart_type()) -> any(). +-spec takeover(Application, Type) -> 'ok' | {'error', Reason} when + Application :: atom(), + Type :: restart_type(), + Reason :: term(). takeover(Application, RestartType) -> dist_ac:takeover_application(Application, RestartType). --spec permit(Application :: atom(), Bool :: boolean()) -> 'ok' | {'error', term()}. +-spec permit(Application, Permission) -> 'ok' | {'error', Reason} when + Application :: atom(), + Permission :: boolean(), + Reason :: term(). permit(Application, Bool) -> case Bool of @@ -142,105 +177,146 @@ permit(Application, Bool) -> LocalResult end. --spec stop(Application :: atom()) -> 'ok' | {'error', term()}. +-spec stop(Application) -> 'ok' | {'error', Reason} when + Application :: atom(), + Reason :: term(). stop(Application) -> application_controller:stop_application(Application). --spec which_applications() -> [{atom(), string(), string()}]. +-spec which_applications() -> [{Application, Description, Vsn}] when + Application :: atom(), + Description :: string(), + Vsn :: string(). which_applications() -> application_controller:which_applications(). --spec which_applications(timeout()) -> [{atom(), string(), string()}]. +-spec which_applications(Timeout) -> [{Application, Description, Vsn}] when + Timeout :: timeout(), + Application :: atom(), + Description :: string(), + Vsn :: string(). which_applications(infinity) -> application_controller:which_applications(infinity); which_applications(Timeout) when is_integer(Timeout), Timeout>=0 -> application_controller:which_applications(Timeout). --spec loaded_applications() -> [{atom(), string(), string()}]. +-spec loaded_applications() -> [{Application, Description, Vsn}] when + Application :: atom(), + Description :: string(), + Vsn :: string(). loaded_applications() -> application_controller:loaded_applications(). --spec info() -> any(). +-spec info() -> term(). info() -> application_controller:info(). --spec set_env(Application :: atom(), Key :: atom(), Value :: any()) -> 'ok'. +-spec set_env(Application, Par, Val) -> 'ok' when + Application :: atom(), + Par :: atom(), + Val :: term(). set_env(Application, Key, Val) -> application_controller:set_env(Application, Key, Val). --spec set_env(Application :: atom(), Key :: atom(), - Value :: any(), Timeout :: timeout()) -> 'ok'. +-spec set_env(Application, Par, Val, Timeout) -> 'ok' when + Application :: atom(), + Par :: atom(), + Val :: term(), + Timeout :: timeout(). set_env(Application, Key, Val, infinity) -> application_controller:set_env(Application, Key, Val, infinity); set_env(Application, Key, Val, Timeout) when is_integer(Timeout), Timeout>=0 -> application_controller:set_env(Application, Key, Val, Timeout). --spec unset_env(atom(), atom()) -> 'ok'. +-spec unset_env(Application, Par) -> 'ok' when + Application :: atom(), + Par :: atom(). unset_env(Application, Key) -> application_controller:unset_env(Application, Key). --spec unset_env(atom(), atom(), timeout()) -> 'ok'. +-spec unset_env(Application, Par, Timeout) -> 'ok' when + Application :: atom(), + Par :: atom(), + Timeout :: timeout(). unset_env(Application, Key, infinity) -> application_controller:unset_env(Application, Key, infinity); unset_env(Application, Key, Timeout) when is_integer(Timeout), Timeout>=0 -> application_controller:unset_env(Application, Key, Timeout). --spec get_env(atom()) -> 'undefined' | {'ok', term()}. +-spec get_env(Par) -> 'undefined' | {'ok', Val} when + Par :: atom(), + Val :: term(). get_env(Key) -> application_controller:get_pid_env(group_leader(), Key). --spec get_env(atom(), atom()) -> 'undefined' | {'ok', term()}. +-spec get_env(Application, Par) -> 'undefined' | {'ok', Val} when + Application :: atom(), + Par :: atom(), + Val :: term(). get_env(Application, Key) -> application_controller:get_env(Application, Key). --spec get_all_env() -> [{atom(), any()}]. +-spec get_all_env() -> Env when + Env :: [{Par :: atom(), Val :: term()}]. get_all_env() -> application_controller:get_pid_all_env(group_leader()). --spec get_all_env(atom()) -> [{atom(), any()}]. +-spec get_all_env(Application) -> Env when + Application :: atom(), + Env :: [{Par :: atom(), Val :: term()}]. get_all_env(Application) -> application_controller:get_all_env(Application). --spec get_key(atom()) -> 'undefined' | {'ok', term()}. +-spec get_key(Key) -> 'undefined' | {'ok', Val} when + Key :: atom(), + Val :: term(). get_key(Key) -> application_controller:get_pid_key(group_leader(), Key). --spec get_key(atom(), atom()) -> 'undefined' | {'ok', term()}. +-spec get_key(Application, Key) -> 'undefined' | {'ok', Val} when + Application :: atom(), + Key :: atom(), + Val :: term(). get_key(Application, Key) -> application_controller:get_key(Application, Key). --spec get_all_key() -> 'undefined' | [] | {'ok', [{atom(),any()},...]}. +-spec get_all_key() -> [] | {'ok', Keys} when + Keys :: [{Key :: atom(),Val :: term()},...]. get_all_key() -> application_controller:get_pid_all_key(group_leader()). --spec get_all_key(atom()) -> 'undefined' | {'ok', [{atom(),any()},...]}. +-spec get_all_key(Application) -> 'undefined' | Keys when + Application :: atom(), + Keys :: {'ok', [{Key :: atom(),Val :: term()},...]}. get_all_key(Application) -> application_controller:get_all_key(Application). --spec get_application() -> 'undefined' | {'ok', atom()}. +-spec get_application() -> 'undefined' | {'ok', Application} when + Application :: atom(). get_application() -> application_controller:get_application(group_leader()). --spec get_application(Pid :: pid()) -> 'undefined' | {'ok', atom()} - ; (Module :: atom()) -> 'undefined' | {'ok', atom()}. +-spec get_application(PidOrModule) -> 'undefined' | {'ok', Application} when + PidOrModule :: (Pid :: pid()) | (Module :: module()), + Application :: atom(). get_application(Pid) when is_pid(Pid) -> case process_info(Pid, group_leader) of @@ -252,8 +328,8 @@ get_application(Pid) when is_pid(Pid) -> get_application(Module) when is_atom(Module) -> application_controller:get_application_module(Module). --spec start_type() -> 'undefined' | 'local' | 'normal' - | {'takeover', node()} | {'failover', node()}. +-spec start_type() -> StartType | 'undefined' | 'local' when + StartType :: start_type(). start_type() -> application_controller:start_type(group_leader()). diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl index 5c7fe2421d..25c88a4e1d 100644 --- a/lib/kernel/src/auth.erl +++ b/lib/kernel/src/auth.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -57,7 +57,8 @@ start_link() -> %%--Deprecated interface------------------------------------------------ --spec is_auth(Node :: node()) -> 'yes' | 'no'. +-spec is_auth(Node) -> 'yes' | 'no' when + Node :: Node :: node(). is_auth(Node) -> case net_adm:ping(Node) of @@ -65,12 +66,15 @@ is_auth(Node) -> pang -> no end. --spec cookie() -> cookie(). +-spec cookie() -> Cookie when + Cookie :: cookie(). cookie() -> get_cookie(). --spec cookie(Cookies :: [cookie(),...] | cookie()) -> 'true'. +-spec cookie(TheCookie) -> 'true' when + TheCookie :: Cookie | [Cookie], + Cookie :: cookie(). cookie([Cookie]) -> set_cookie(Cookie); @@ -82,7 +86,9 @@ cookie(Cookie) -> node_cookie([Node, Cookie]) -> node_cookie(Node, Cookie). --spec node_cookie(Node :: node(), Cookie :: cookie()) -> 'yes' | 'no'. +-spec node_cookie(Node, Cookie) -> 'yes' | 'no' when + Node :: node(), + Cookie :: cookie(). node_cookie(Node, Cookie) -> set_cookie(Node, Cookie), diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 7f1b5f9ec6..9b8d2db437 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -70,9 +70,10 @@ %%% Contract type specifications %%%---------------------------------------------------------------------- +-opaque continuation() :: #continuation{}. + -type bytes() :: binary() | [byte()]. --type log() :: term(). % XXX: refine -type file_error() :: term(). % XXX: refine -type invalid_header() :: term(). % XXX: refine @@ -87,27 +88,30 @@ -type open_error_rsn() :: 'no_such_log' | {'badarg', term()} - | {'size_mismatch', dlog_size(), dlog_size()} - | {'arg_mismatch', dlog_optattr(), term(), term()} - | {'name_already_open', log()} - | {'open_read_write', log()} - | {'open_read_only', log()} - | {'need_repair', log()} - | {'not_a_log_file', string()} - | {'invalid_index_file', string()} + | {'size_mismatch', CurrentSize :: dlog_size(), + NewSize :: dlog_size()} + | {'arg_mismatch', OptionName :: dlog_optattr(), + CurrentValue :: term(), Value :: term()} + | {'name_already_open', Log :: log()} + | {'open_read_write', Log :: log()} + | {'open_read_only', Log :: log()} + | {'need_repair', Log :: log()} + | {'not_a_log_file', FileName :: file:filename()} + | {'invalid_index_file', FileName :: file:filename()} | {'invalid_header', invalid_header()} | {'file_error', file:filename(), file_error()} - | {'node_already_open', log()}. + | {'node_already_open', Log :: log()}. -type dist_error_rsn() :: 'nodedown' | open_error_rsn(). --type ret() :: {'ok', log()} - | {'repaired', log(), {'recovered', non_neg_integer()}, - {'badbytes', non_neg_integer()}}. +-type ret() :: {'ok', Log :: log()} + | {'repaired', Log :: log(), + {'recovered', Rec :: non_neg_integer()}, + {'badbytes', Bad :: non_neg_integer()}}. -type open_ret() :: ret() | {'error', open_error_rsn()}. -type dist_open_ret() :: {[{node(), ret()}], [{node(), {'error', dist_error_rsn()}}]}. --type all_open_ret() :: open_ret() | dist_open_ret(). --spec open(Args :: dlog_options()) -> all_open_ret(). +-spec open(ArgL) -> open_ret() | dist_open_ret() when + ArgL :: dlog_options(). open(A) -> disk_log_server:open(check_arg(A, #arg{options = A})). @@ -116,40 +120,57 @@ open(A) -> | {'full', log()} | {'invalid_header', invalid_header()} | {'file_error', file:filename(), file_error()}. --spec log(Log :: log(), Term :: term()) -> 'ok' | {'error', log_error_rsn()}. +-spec log(Log, Term) -> ok | {error, Reason :: log_error_rsn()} when + Log :: log(), + Term :: term(). log(Log, Term) -> req(Log, {log, term_to_binary(Term)}). --spec blog(Log :: log(), Bytes :: bytes()) -> 'ok' | {'error', log_error_rsn()}. +-spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when + Log :: log(), + Bytes :: bytes(). blog(Log, Bytes) -> req(Log, {blog, check_bytes(Bytes)}). --spec log_terms(Log :: log(), Terms :: [term()]) -> 'ok' | {'error', term()}. +-spec log_terms(Log, TermList) -> ok | {error, Resaon :: log_error_rsn()} when + Log :: log(), + TermList :: [term()]. log_terms(Log, Terms) -> Bs = terms2bins(Terms), req(Log, {log, Bs}). --spec blog_terms(Log :: log(), Bytes :: [bytes()]) -> 'ok' | {'error', term()}. +-spec blog_terms(Log, BytesList) -> + ok | {error, Reason :: log_error_rsn()} when + Log :: log(), + BytesList :: [bytes()]. blog_terms(Log, Bytess) -> Bs = check_bytes_list(Bytess, Bytess), req(Log, {blog, Bs}). -type notify_ret() :: 'ok' | {'error', 'no_such_log'}. --spec alog(Log :: log(), Term :: term()) -> notify_ret(). +-spec alog(Log, Term) -> notify_ret() when + Log :: log(), + Term :: term(). alog(Log, Term) -> notify(Log, {alog, term_to_binary(Term)}). --spec alog_terms(Log :: log(), Terms :: [term()]) -> notify_ret(). +-spec alog_terms(Log, TermList) -> notify_ret() when + Log :: log(), + TermList :: [term()]. alog_terms(Log, Terms) -> Bs = terms2bins(Terms), notify(Log, {alog, Bs}). --spec balog(Log :: log(), Bytes :: bytes()) -> notify_ret(). +-spec balog(Log, Bytes) -> notify_ret() when + Log :: log(), + Bytes :: bytes(). balog(Log, Bytes) -> notify(Log, {balog, check_bytes(Bytes)}). --spec balog_terms(Log :: log(), Bytes :: [bytes()]) -> notify_ret(). +-spec balog_terms(Log, ByteList) -> notify_ret() when + Log :: log(), + ByteList :: [bytes()]. balog_terms(Log, Bytess) -> Bs = check_bytes_list(Bytess, Bytess), notify(Log, {balog, Bs}). @@ -157,18 +178,22 @@ balog_terms(Log, Bytess) -> -type close_error_rsn() ::'no_such_log' | 'nonode' | {'file_error', file:filename(), file_error()}. --spec close(Log :: log()) -> 'ok' | {'error', close_error_rsn()}. +-spec close(Log) -> 'ok' | {'error', close_error_rsn()} when + Log :: log(). close(Log) -> req(Log, close). -type lclose_error_rsn() :: 'no_such_log' | {'file_error', file:filename(), file_error()}. --spec lclose(Log :: log()) -> 'ok' | {'error', lclose_error_rsn()}. +-spec lclose(Log) -> 'ok' | {'error', lclose_error_rsn()} when + Log :: log(). lclose(Log) -> lclose(Log, node()). --spec lclose(Log :: log(), Node :: node()) -> 'ok' | {'error', lclose_error_rsn()}. +-spec lclose(Log, Node) -> 'ok' | {'error', lclose_error_rsn()} when + Log :: log(), + Node :: node(). lclose(Log, Node) -> lreq(Log, close, Node). @@ -178,29 +203,49 @@ lclose(Log, Node) -> | {'invalid_header', invalid_header()} | {'file_error', file:filename(), file_error()}. --spec truncate(Log :: log()) -> 'ok' | {'error', trunc_error_rsn()}. +-spec truncate(Log) -> 'ok' | {'error', trunc_error_rsn()} when + Log :: log(). truncate(Log) -> req(Log, {truncate, none, truncate, 1}). --spec truncate(Log :: log(), Head :: term()) -> 'ok' | {'error', trunc_error_rsn()}. +-spec truncate(Log, Head) -> 'ok' | {'error', trunc_error_rsn()} when + Log :: log(), + Head :: term(). truncate(Log, Head) -> req(Log, {truncate, {ok, term_to_binary(Head)}, truncate, 2}). --spec btruncate(Log :: log(), Head :: bytes()) -> 'ok' | {'error', trunc_error_rsn()}. +-spec btruncate(Log, BHead) -> 'ok' | {'error', trunc_error_rsn()} when + Log :: log(), + BHead :: bytes(). btruncate(Log, Head) -> req(Log, {truncate, {ok, check_bytes(Head)}, btruncate, 2}). --spec reopen(Log :: log(), Filename :: file:filename()) -> 'ok' | {'error', term()}. +-type reopen_error_rsn() :: no_such_log + | nonode + | {read_only_mode, log()} + | {blocked_log, log()} + | {same_file_name, log()} | + {invalid_index_file, file:filename()} + | {invalid_header, invalid_header()} + | {'file_error', file:filename(), file_error()}. + +-spec reopen(Log, File) -> 'ok' | {'error', reopen_error_rsn()} when + Log :: log(), + File :: file:filename(). reopen(Log, NewFile) -> req(Log, {reopen, NewFile, none, reopen, 2}). --spec reopen(Log :: log(), Filename :: file:filename(), Head :: term()) -> - 'ok' | {'error', term()}. +-spec reopen(Log, File, Head) -> 'ok' | {'error', reopen_error_rsn()} when + Log :: log(), + File :: file:filename(), + Head :: term(). reopen(Log, NewFile, NewHead) -> req(Log, {reopen, NewFile, {ok, term_to_binary(NewHead)}, reopen, 3}). --spec breopen(Log :: log(), Filename :: file:filename(), Head :: bytes()) -> - 'ok' | {'error', term()}. +-spec breopen(Log, File, BHead) -> 'ok' | {'error', reopen_error_rsn()} when + Log :: log(), + File :: file:filename(), + BHead :: bytes(). breopen(Log, NewFile, NewHead) -> req(Log, {reopen, NewFile, {ok, check_bytes(NewHead)}, breopen, 3}). @@ -210,21 +255,36 @@ breopen(Log, NewFile, NewHead) -> | {'invalid_header', invalid_header()} | {'file_error', file:filename(), file_error()}. --spec inc_wrap_file(Log :: log()) -> 'ok' | {'error', inc_wrap_error_rsn()}. +-spec inc_wrap_file(Log) -> 'ok' | {'error', inc_wrap_error_rsn()} when + Log :: log(). inc_wrap_file(Log) -> req(Log, inc_wrap_file). --spec change_size(Log :: log(), Size :: dlog_size()) -> 'ok' | {'error', term()}. +-spec change_size(Log, Size) -> 'ok' | {'error', Reason} when + Log :: log(), + Size :: dlog_size(), + Reason :: no_such_log | nonode | {read_only_mode, Log} + | {blocked_log, Log} + | {new_size_too_small, CurrentSize :: pos_integer()} + | {badarg, size} + | {file_error, file:filename(), file_error()}. change_size(Log, NewSize) -> req(Log, {change_size, NewSize}). --spec change_notify(Log :: log(), Pid :: pid(), Notify :: boolean()) -> - 'ok' | {'error', term()}. +-spec change_notify(Log, Owner, Notify) -> 'ok' | {'error', Reason} when + Log :: log(), + Owner :: pid(), + Notify :: boolean(), + Reason :: no_such_log | nonode | {blocked_log, Log} + | {badarg, notify} | {not_owner, Owner}. change_notify(Log, Pid, NewNotify) -> req(Log, {change_notify, Pid, NewNotify}). --spec change_header(Log :: log(), Head :: {atom(), term()}) -> - 'ok' | {'error', term()}. +-spec change_header(Log, Header) -> 'ok' | {'error', Reason} when + Log :: log(), + Header :: {head, dlog_head_opt()} | {head_func, mfa()}, + Reason :: no_such_log | nonode | {read_only_mode, Log} + | {blocked_log, Log} | {badarg, head}. change_header(Log, NewHead) -> req(Log, {change_header, NewHead}). @@ -232,17 +292,21 @@ change_header(Log, NewHead) -> | {'blocked_log', log()} | {'file_error', file:filename(), file_error()}. --spec sync(Log :: log()) -> 'ok' | {'error', sync_error_rsn()}. +-spec sync(Log) -> 'ok' | {'error', sync_error_rsn()} when + Log :: log(). sync(Log) -> req(Log, sync). -type block_error_rsn() :: 'no_such_log' | 'nonode' | {'blocked_log', log()}. --spec block(Log :: log()) -> 'ok' | {'error', block_error_rsn()}. +-spec block(Log) -> 'ok' | {'error', block_error_rsn()} when + Log :: log(). block(Log) -> block(Log, true). --spec block(Log :: log(), QueueLogRecords :: boolean()) -> 'ok' | {'error', term()}. +-spec block(Log, QueueLogRecords) -> 'ok' | {'error', block_error_rsn()} when + Log :: log(), + QueueLogRecords :: boolean(). block(Log, QueueLogRecords) -> req(Log, {block, QueueLogRecords}). @@ -250,19 +314,46 @@ block(Log, QueueLogRecords) -> | {'not_blocked', log()} | {'not_blocked_by_pid', log()}. --spec unblock(Log :: log()) -> 'ok' | {'error', unblock_error_rsn()}. +-spec unblock(Log) -> 'ok' | {'error', unblock_error_rsn()} when + Log :: log(). unblock(Log) -> req(Log, unblock). --spec format_error(Error :: term()) -> string(). +-spec format_error(Error) -> io_lib:chars() when + Error :: term(). format_error(Error) -> do_format_error(Error). --spec info(Log :: log()) -> [{atom(), any()}] | {'error', term()}. +-type dlog_info() :: {name, Log :: log()} + | {file, File :: file:filename()} + | {type, Type :: dlog_type()} + | {format, Format :: dlog_format()} + | {size, Size :: dlog_size()} + | {mode, Mode :: dlog_mode()} + | {owners, [{pid(), Notify :: boolean()}]} + | {users, Users :: non_neg_integer()} + | {status, Status :: + ok | {blocked, QueueLogRecords :: boolean()}} + | {node, Node :: node()} + | {distributed, Dist :: local | [node()]} + | {head, Head :: none | {head, term()} | mfa()} + | {no_written_items, NoWrittenItems ::non_neg_integer()} + | {full, Full :: boolean} + | {no_current_bytes, non_neg_integer()} + | {no_current_items, non_neg_integer()} + | {no_items, non_neg_integer()} + | {current_file, pos_integer()} + | {no_overflows, {SinceLogWasOpened :: non_neg_integer(), + SinceLastInfo :: non_neg_integer()}}. +-spec info(Log) -> InfoList | {'error', no_such_log} when + Log :: log(), + InfoList :: [dlog_info()]. info(Log) -> sreq(Log, info). --spec pid2name(Pid :: pid()) -> {'ok', log()} | 'undefined'. +-spec pid2name(Pid) -> {'ok', Log} | 'undefined' when + Pid :: pid(), + Log :: log(). pid2name(Pid) -> disk_log_server:start(), case ets:lookup(?DISK_LOG_PID_TABLE, Pid) of @@ -274,13 +365,31 @@ pid2name(Pid) -> %% It retuns a {Cont2, ObjList} | eof | {error, Reason} %% The initial continuation is the atom 'start' --spec chunk(Log :: log(), Cont :: any()) -> - {'error', term()} | 'eof' | {any(), [any()]} | {any(), [any()], integer()}. +-type chunk_error_rsn() :: no_such_log + | {format_external, log()} + | {blocked_log, log()} + | {badarg, continuation} + | {not_internal_wrap, log()} + | {corrupt_log_file, FileName :: file:filename()} + | {file_error, file:filename(), file_error()}. + +-type chunk_ret() :: {Continuation2 :: continuation(), Terms :: [term()]} + | {Continuation2 :: continuation(), + Terms :: [term()], + Badbytes :: non_neg_integer()} + | eof + | {error, Reason :: chunk_error_rsn()}. + +-spec chunk(Log, Continuation) -> chunk_ret() when + Log :: log(), + Continuation :: start | continuation(). chunk(Log, Cont) -> chunk(Log, Cont, infinity). --spec chunk(Log :: log(), Cont :: any(), N :: pos_integer() | 'infinity') -> - {'error', term()} | 'eof' | {any(), [any()]} | {any(), [any()], integer()}. +-spec chunk(Log, Continuation, N) -> chunk_ret() when + Log :: log(), + Continuation :: start | continuation(), + N :: pos_integer() | infinity. chunk(Log, Cont, infinity) -> %% There cannot be more than ?MAX_CHUNK_SIZE terms in a chunk. ichunk(Log, Cont, ?MAX_CHUNK_SIZE); @@ -346,13 +455,24 @@ ichunk_bad_end([B | Bs], Mode, Log, C, Bad, A) -> ichunk_bad_end(Bs, Mode, Log, C, Bad, [T | A]) end. --spec bchunk(Log :: log(), Cont :: any()) -> - {'error', any()} | 'eof' | {any(), [binary()]} | {any(), [binary()], integer()}. +-type bchunk_ret() :: {Continuation2 :: continuation(), + Binaries :: [binary()]} + | {Continuation2 :: continuation(), + Binaries :: [binary()], + Badbytes :: non_neg_integer()} + | eof + | {error, Reason :: chunk_error_rsn()}. + +-spec bchunk(Log, Continuation) -> bchunk_ret() when + Log :: log(), + Continuation :: start | continuation(). bchunk(Log, Cont) -> bchunk(Log, Cont, infinity). --spec bchunk(Log :: log(), Cont :: any(), N :: 'infinity' | pos_integer()) -> - {'error', any()} | 'eof' | {any(), [binary()]} | {any(), [binary()], integer()}. +-spec bchunk(Log, Continuation, N) -> bchunk_ret() when + Log :: log(), + Continuation :: start | continuation(), + N :: pos_integer() | infinity. bchunk(Log, Cont, infinity) -> %% There cannot be more than ?MAX_CHUNK_SIZE terms in a chunk. bichunk(Log, Cont, ?MAX_CHUNK_SIZE); @@ -375,8 +495,14 @@ bichunk_end({C = #continuation{}, R, Bad}) -> bichunk_end(R) -> R. --spec chunk_step(Log :: log(), Cont :: any(), N :: integer()) -> - {'ok', any()} | {'error', term()}. +-spec chunk_step(Log, Continuation, Step) -> + {'ok', any()} | {'error', Reason} when + Log :: log(), + Continuation :: start | continuation(), + Step :: integer(), + Reason :: no_such_log | end_of_log | {format_external, Log} + | {blocked_log, Log} | {badarg, continuation} + | {file_error, file:filename(), file_error()}. chunk_step(Log, Cont, N) when is_integer(N) -> ichunk_step(Log, Cont, N). @@ -387,14 +513,18 @@ ichunk_step(_Log, More, N) when is_record(More, continuation) -> ichunk_step(_Log, _, _) -> {error, {badarg, continuation}}. --spec chunk_info(More :: any()) -> - [{'node', node()},...] | {'error', {'no_continuation', any()}}. +-spec chunk_info(Continuation) -> InfoList | {error, Reason} when + Continuation :: continuation(), + InfoList :: [{node, Node :: node()}, ...], + Reason :: {no_continuation, Continuation}. chunk_info(More = #continuation{}) -> [{node, node(More#continuation.pid)}]; chunk_info(BadCont) -> {error, {no_continuation, BadCont}}. --spec accessible_logs() -> {[_], [_]}. +-spec accessible_logs() -> {[LocalLog], [DistributedLog]} when + LocalLog :: log(), + DistributedLog :: log(). accessible_logs() -> disk_log_server:accessible_logs(). diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 9a94d4d3b9..259967650f 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -53,18 +53,34 @@ %% Types -- alphabetically %%------------------------------------------------------------------------ +-type dlog_byte() :: [dlog_byte()] | byte(). -type dlog_format() :: 'external' | 'internal'. -type dlog_format_type() :: 'halt_ext' | 'halt_int' | 'wrap_ext' | 'wrap_int'. -type dlog_head() :: 'none' | {'ok', binary()} | mfa(). +-type dlog_head_opt() :: none | term() | binary() | [dlog_byte()]. +-type log() :: term(). % XXX: refine -type dlog_mode() :: 'read_only' | 'read_write'. -type dlog_name() :: atom() | string(). -type dlog_optattr() :: 'name' | 'file' | 'linkto' | 'repair' | 'type' | 'format' | 'size' | 'distributed' | 'notify' | 'head' | 'head_func' | 'mode'. --type dlog_options() :: [{dlog_optattr(), any()}]. +-type dlog_option() :: {name, Log :: log()} + | {file, FileName :: file:filename()} + | {linkto, LinkTo :: none | pid()} + | {repair, Repair :: true | false | truncate} + | {type, Type :: dlog_type} + | {format, Format :: dlog_format()} + | {size, Size :: dlog_size()} + | {distributed, Nodes :: [node()]} + | {notify, boolean()} + | {head, Head :: dlog_head_opt()} + | {head_func, mfa()} + | {mode, Mode :: dlog_mode()}. +-type dlog_options() :: [dlog_option()]. -type dlog_repair() :: 'truncate' | boolean(). -type dlog_size() :: 'infinity' | pos_integer() - | {pos_integer(), pos_integer()}. + | {MaxNoBytes :: pos_integer(), + MaxNoFiles :: pos_integer()}. -type dlog_status() :: 'ok' | {'blocked', 'false' | [_]}. %QueueLogRecords -type dlog_type() :: 'halt' | 'wrap'. @@ -75,7 +91,7 @@ %% record of args for open -record(arg, {name = 0, version = undefined, - file = none :: 'none' | string(), + file = none :: 'none' | file:filename(), repair = true :: dlog_repair(), size = infinity :: dlog_size(), type = halt :: dlog_type(), diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl index b4c5f5e27c..0d68d3e198 100644 --- a/lib/kernel/src/erl_boot_server.erl +++ b/lib/kernel/src/erl_boot_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -59,7 +59,11 @@ -type ip4_address() :: {0..255,0..255,0..255,0..255}. --spec start(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}. +-spec start(Slaves) -> {'ok', Pid} | {'error', What} when + Slaves :: [Host], + Host :: atom(), + Pid :: pid(), + What :: any(). start(Slaves) -> case check_arg(Slaves) of @@ -69,7 +73,11 @@ start(Slaves) -> {error, {badarg, Slaves}} end. --spec start_link(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}. +-spec start_link(Slaves) -> {'ok', Pid} | {'error', What} when + Slaves :: [Host], + Host :: atom(), + Pid :: pid(), + What :: any(). start_link(Slaves) -> case check_arg(Slaves) of @@ -95,7 +103,10 @@ check_arg([], Result) -> check_arg(_, _Result) -> error. --spec add_slave(Slave :: atom()) -> 'ok' | {'error', any()}. +-spec add_slave(Slave) -> 'ok' | {'error', What} when + Slave :: Host, + Host :: atom(), + What :: any(). add_slave(Slave) -> case inet:getaddr(Slave, inet) of @@ -105,7 +116,10 @@ add_slave(Slave) -> {error, {badarg, Slave}} end. --spec delete_slave(Slave :: atom()) -> 'ok' | {'error', any()}. +-spec delete_slave(Slave) -> 'ok' | {'error', What} when + Slave :: Host, + Host :: atom(), + What :: any(). delete_slave(Slave) -> case inet:getaddr(Slave, inet) of @@ -131,7 +145,9 @@ add_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) -> delete_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) -> gen_server:call(boot_server, {delete, {Mask, Addr}}). --spec which_slaves() -> [atom()]. +-spec which_slaves() -> Slaves when + Slaves :: [Host], + Host :: atom(). which_slaves() -> gen_server:call(boot_server, which). diff --git a/lib/kernel/src/erl_ddll.erl b/lib/kernel/src/erl_ddll.erl index ce64589a29..646cac99c5 100644 --- a/lib/kernel/src/erl_ddll.erl +++ b/lib/kernel/src/erl_ddll.erl @@ -44,14 +44,18 @@ start() -> stop() -> ok. --spec load_driver(Path :: path(), Driver :: driver()) -> - 'ok' | {'error', any()}. +-spec load_driver(Path, Name) -> 'ok' | {'error', ErrorDesc} when + Path :: path(), + Name :: driver(), + ErrorDesc :: term(). load_driver(Path, Driver) -> do_load_driver(Path, Driver, [{driver_options,[kill_ports]}]). --spec load(Path :: path(), Driver :: driver()) -> - 'ok' | {'error', any()}. +-spec load(Path, Name) -> 'ok' | {'error', ErrorDesc} when + Path :: path(), + Name :: driver(), + ErrorDesc ::term(). load(Path, Driver) -> do_load_driver(Path, Driver, []). @@ -100,30 +104,41 @@ do_unload_driver(Driver,Flags) -> end end. --spec unload_driver(Driver :: driver()) -> 'ok' | {'error', any()}. +-spec unload_driver(Name) -> 'ok' | {'error', ErrorDesc} when + Name :: driver(), + ErrorDesc :: term(). unload_driver(Driver) -> do_unload_driver(Driver,[{monitor,pending_driver},kill_ports]). --spec unload(Driver :: driver()) -> 'ok' | {'error', any()}. +-spec unload(Name) -> 'ok' | {'error', ErrorDesc} when + Name :: driver(), + ErrorDesc :: term(). unload(Driver) -> do_unload_driver(Driver,[]). --spec reload(Path :: path(), Driver :: driver()) -> - 'ok' | {'error', any()}. +-spec reload(Path, Name) -> 'ok' | {'error', ErrorDesc} when + Path :: path(), + Name :: driver(), + ErrorDesc :: pending_process | OpaqueError, + OpaqueError :: term(). reload(Path,Driver) -> do_load_driver(Path, Driver, [{reload,pending_driver}]). --spec reload_driver(Path :: path(), Driver :: driver()) -> - 'ok' | {'error', any()}. +-spec reload_driver(Path, Name) -> 'ok' | {'error', ErrorDesc} when + Path :: path(), + Name :: driver(), + ErrorDesc :: pending_process | OpaqueError, + OpaqueError :: term(). reload_driver(Path,Driver) -> do_load_driver(Path, Driver, [{reload,pending_driver}, {driver_options,[kill_ports]}]). --spec format_error(Code :: atom()) -> string(). +-spec format_error(ErrorDesc) -> string() when + ErrorDesc :: term(). format_error(Code) -> case Code of @@ -135,7 +150,10 @@ format_error(Code) -> erl_ddll:format_error_int(Code) end. --spec info(Driver :: driver()) -> [{atom(), any()}, ...]. +-spec info(Name) -> InfoList when + Name :: driver(), + InfoList :: [InfoItem, ...], + InfoItem :: {Tag :: atom(), Value :: term()}. info(Driver) -> [{processes, erl_ddll:info(Driver,processes)}, @@ -146,7 +164,12 @@ info(Driver) -> {awaiting_load, erl_ddll:info(Driver,awaiting_load)}, {awaiting_unload, erl_ddll:info(Driver,awaiting_unload)}]. --spec info() -> [{string(), [{atom(), any()}]}]. +-spec info() -> AllInfoList when + AllInfoList :: [DriverInfo], + DriverInfo :: {DriverName, InfoList}, + DriverName :: string(), + InfoList :: [InfoItem], + InfoItem :: {Tag :: atom(), Value :: term()}. info() -> {ok,DriverList} = erl_ddll:loaded_drivers(), diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl index 6f69f4ccb9..e1f99bf417 100644 --- a/lib/kernel/src/error_handler.erl +++ b/lib/kernel/src/error_handler.erl @@ -28,8 +28,11 @@ -export([undefined_function/3, undefined_lambda/3, stub_function/3, breakpoint/3]). --spec undefined_function(Module :: atom(), Function :: atom(), Args :: [_]) -> - any(). +-spec undefined_function(Module, Function, Args) -> + any() when + Module :: atom(), + Function :: atom(), + Args :: list(). undefined_function(Module, Func, Args) -> case ensure_loaded(Module) of @@ -51,8 +54,10 @@ undefined_function(Module, Func, Args) -> crash(Module, Func, Args) end. --spec undefined_lambda(Module :: atom(), Function :: fun(), Args :: [_]) -> - any(). +-spec undefined_lambda(Module, Fun, Args) -> term() when + Module :: atom(), + Fun :: fun(), + Args :: list(). undefined_lambda(Module, Fun, Args) -> case ensure_loaded(Module) of diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index cafdc52e84..f94cca000f 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -69,17 +69,22 @@ start_link() -> %% Used for simple messages; error or information. %%----------------------------------------------------------------- --spec error_msg(Format :: string()) -> 'ok'. +-spec error_msg(Format) -> 'ok' when + Format :: string(). error_msg(Format) -> error_msg(Format,[]). --spec error_msg(Format :: string(), Args :: list()) -> 'ok'. +-spec error_msg(Format, Data) -> 'ok' when + Format :: string(), + Data :: list(). error_msg(Format, Args) -> notify({error, group_leader(), {self(), Format, Args}}). --spec format(Format :: string(), Args :: list()) -> 'ok'. +-spec format(Format, Data) -> 'ok' when + Format :: string(), + Data :: list(). format(Format, Args) -> notify({error, group_leader(), {self(), Format, Args}}). @@ -90,12 +95,18 @@ format(Format, Args) -> %% The 'std_error' error_report type can always be used. %%----------------------------------------------------------------- --spec error_report(Report :: any()) -> 'ok'. +-type report() :: + [{Tag :: term(), Data :: term()} | term()] | string() | term(). + +-spec error_report(Report) -> 'ok' when + Report :: report(). error_report(Report) -> error_report(std_error, Report). --spec error_report(Type :: any(), Report :: any()) -> 'ok'. +-spec error_report(Type, Report) -> 'ok' when + Type :: term(), + Report :: report(). error_report(Type, Report) -> notify({error_report, group_leader(), {self(), Type, Report}}). @@ -109,12 +120,15 @@ error_report(Type, Report) -> %% mapped to std_info or std_error accordingly. %%----------------------------------------------------------------- --spec warning_report(Report :: any()) -> 'ok'. +-spec warning_report(Report) -> 'ok' when + Report :: report(). warning_report(Report) -> warning_report(std_warning, Report). --spec warning_report(Type :: any(), Report :: any()) -> 'ok'. +-spec warning_report(Type, Report) -> 'ok' when + Type :: any(), + Report :: report(). warning_report(Type, Report) -> {Tag, NType} = case error_logger:warning_map() of @@ -143,12 +157,15 @@ warning_report(Type, Report) -> %% other types of reports. %%----------------------------------------------------------------- --spec warning_msg(Format :: string()) -> 'ok'. +-spec warning_msg(Format) -> 'ok' when + Format :: string(). warning_msg(Format) -> warning_msg(Format,[]). --spec warning_msg(Format :: string(), Args :: list()) -> 'ok'. +-spec warning_msg(Format, Data) -> 'ok' when + Format :: string(), + Data :: list(). warning_msg(Format, Args) -> Tag = case error_logger:warning_map() of @@ -167,12 +184,15 @@ warning_msg(Format, Args) -> %% The 'std_info' info_report type can always be used. %%----------------------------------------------------------------- --spec info_report(Report :: any()) -> 'ok'. +-spec info_report(Report) -> 'ok' when + Report :: report(). info_report(Report) -> info_report(std_info, Report). --spec info_report(Type :: any(), Report :: any()) -> 'ok'. +-spec info_report(Type, Report) -> 'ok' when + Type :: any(), + Report :: report(). info_report(Type, Report) -> notify({info_report, group_leader(), {self(), Type, Report}}). @@ -182,12 +202,15 @@ info_report(Type, Report) -> %% information messages. %%----------------------------------------------------------------- --spec info_msg(Format :: string()) -> 'ok'. +-spec info_msg(Format) -> 'ok' when + Format :: string(). info_msg(Format) -> info_msg(Format,[]). --spec info_msg(Format :: string(), Args :: list()) -> 'ok'. +-spec info_msg(Format, Data) -> 'ok' when + Format :: string(), + Data :: list(). info_msg(Format, Args) -> notify({info_msg, group_leader(), {self(), Format, Args}}). @@ -223,17 +246,23 @@ swap_handler(silent) -> swap_handler(false) -> ok. % keep primitive event handler as-is --spec add_report_handler(Module :: atom()) -> any(). +-spec add_report_handler(Handler) -> any() when + Handler :: module(). add_report_handler(Module) when is_atom(Module) -> gen_event:add_handler(error_logger, Module, []). --spec add_report_handler(atom(), any()) -> any(). +-spec add_report_handler(Handler, Args) -> Result when + Handler :: module(), + Args :: gen_event:handler_args(), + Result :: gen_event:add_handler_ret(). add_report_handler(Module, Args) when is_atom(Module) -> gen_event:add_handler(error_logger, Module, Args). --spec delete_report_handler(Module :: atom()) -> any(). +-spec delete_report_handler(Handler) -> Result when + Handler :: module(), + Result :: gen_event:del_handler_ret(). delete_report_handler(Module) when is_atom(Module) -> gen_event:delete_handler(error_logger, Module, []). @@ -250,9 +279,16 @@ simple_logger() -> %% Log all errors to File for all eternity --spec logfile(Request :: {'open', string()}) -> 'ok' | {'error',any()} - ; (Request :: 'close') -> 'ok' | {'error', any()} - ; (Request :: 'filename') -> atom() | string() | {'error', any()}. +-type open_error() :: file:posix() | badarg | system_limit. + +-spec logfile(Request :: {open, Filename}) -> ok | {error, OpenReason} when + Filename ::file:name(), + OpenReason :: allready_have_logfile | open_error() + ; (Request :: close) -> ok | {error, CloseReason} when + CloseReason :: module_not_found + ; (Request :: filename) -> Filename | {error, FilenameReason} when + Filename :: file:name(), + FilenameReason :: no_log_file. logfile({open, File}) -> case lists:member(error_logger_file_h, @@ -280,7 +316,8 @@ logfile(filename) -> %% Possibly turn off all tty printouts, maybe we only want the errors %% to go to a file --spec tty(Flag :: boolean()) -> 'ok'. +-spec tty(Flag) -> 'ok' when + Flag :: boolean(). tty(true) -> Hs = gen_event:which_handlers(error_logger), diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 88bcf9a9cc..f1a8aa9f77 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -79,15 +79,19 @@ -type file_info() :: #file_info{}. -type fd() :: #file_descriptor{}. -type io_device() :: pid() | fd(). --type location() :: integer() | {'bof', integer()} | {'cur', integer()} - | {'eof', integer()} | 'bof' | 'cur' | 'eof'. +-type location() :: integer() | {'bof', Offset :: integer()} + | {'cur', Offset :: integer()} + | {'eof', Offset :: integer()} | 'bof' | 'cur' | 'eof'. -type mode() :: 'read' | 'write' | 'append' | 'exclusive' | 'raw' | 'binary' - | {'delayed_write', non_neg_integer(), non_neg_integer()} - | 'delayed_write' | {'read_ahead', pos_integer()} + | {'delayed_write', + Size :: non_neg_integer(), + Delay :: non_neg_integer()} + | 'delayed_write' | {'read_ahead', Size :: pos_integer()} | 'read_ahead' | 'compressed' | {'encoding', unicode:encoding()}. --type name() :: string() | atom() | [name()] | binary(). +-type deep_list() :: [char() | atom() | deep_list()]. +-type name() :: string() | atom() | deep_list() | (RawFilename :: binary()). -type posix() :: 'eacces' | 'eagain' | 'ebadf' | 'ebusy' | 'edquot' | 'eexist' | 'efault' | 'efbig' | 'eintr' | 'einval' | 'eio' | 'eisdir' | 'eloop' | 'emfile' | 'emlink' @@ -96,10 +100,14 @@ | 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' | 'eperm' | 'epipe' | 'erofs' | 'espipe' | 'esrch' | 'estale' | 'exdev'. --type bindings() :: any(). - --type date() :: {pos_integer(), pos_integer(), pos_integer()}. --type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}. +-type bindings() :: erl_eval:binding_struct(). + +-type date() :: {Year :: pos_integer(), + Month :: pos_integer(), + Day ::pos_integer()}. +-type time() :: {Hour :: non_neg_integer(), + Minute :: non_neg_integer(), + Second :: non_neg_integer()}. -type date_time() :: {date(), time()}. -type posix_file_advise() :: 'normal' | 'sequential' | 'random' | 'no_reuse' | 'will_need' | 'dont_need'. @@ -107,8 +115,10 @@ %%%----------------------------------------------------------------- %%% General functions --spec format_error(Reason :: posix() | {integer(), atom(), any()}) -> - string(). +-spec format_error(Reason) -> Chars when + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}, + Chars :: string(). format_error({_Line, ?MODULE, undefined_script}) -> "no value returned from script"; @@ -129,7 +139,9 @@ format_error(terminated) -> format_error(ErrorId) -> erl_posix_msg:message(ErrorId). --spec pid2name(Pid :: pid()) -> {'ok', filename()} | 'undefined'. +-spec pid2name(Pid) -> {ok, Filename} | undefined when + Filename :: filename(), + Pid :: pid(). pid2name(Pid) when is_pid(Pid) -> case whereis(?FILE_SERVER) of @@ -148,42 +160,61 @@ pid2name(Pid) when is_pid(Pid) -> %%% File server functions. %%% Functions that do not operate on a single open file. %%% Stateless. --spec get_cwd() -> {'ok', filename()} | {'error', posix()}. +-spec get_cwd() -> {ok, Dir} | {error, Reason} when + Dir :: filename(), + Reason :: posix(). get_cwd() -> call(get_cwd, []). --spec get_cwd(Drive :: string()) -> {'ok', filename()} | {'error', posix()}. +-spec get_cwd(Drive) -> {ok, Dir} | {error, Reason} when + Drive :: string(), + Dir :: filename(), + Reason :: posix() | badarg. get_cwd(Drive) -> check_and_call(get_cwd, [file_name(Drive)]). --spec set_cwd(Dirname :: name()) -> 'ok' | {'error', posix()}. +-spec set_cwd(Dir) -> ok | {error, Reason} when + Dir :: name(), + Reason :: posix() | badarg. set_cwd(Dirname) -> check_and_call(set_cwd, [file_name(Dirname)]). --spec delete(Name :: name()) -> 'ok' | {'error', posix()}. +-spec delete(Filename) -> ok | {error, Reason} when + Filename :: name(), + Reason :: posix() | badarg. delete(Name) -> check_and_call(delete, [file_name(Name)]). --spec rename(From :: name(), To :: name()) -> 'ok' | {'error', posix()}. +-spec rename(Source, Destination) -> ok | {error, Reason} when + Source :: name(), + Destination :: name(), + Reason :: posix() | badarg. rename(From, To) -> check_and_call(rename, [file_name(From), file_name(To)]). --spec make_dir(Name :: name()) -> 'ok' | {'error', posix()}. +-spec make_dir(Dir) -> ok | {error, Reason} when + Dir :: name(), + Reason :: posix() | badarg. make_dir(Name) -> check_and_call(make_dir, [file_name(Name)]). --spec del_dir(Name :: name()) -> 'ok' | {'error', posix()}. +-spec del_dir(Dir) -> ok | {error, Reason} when + Dir :: name(), + Reason :: posix() | badarg. del_dir(Name) -> check_and_call(del_dir, [file_name(Name)]). --spec read_file_info(Name :: name()) -> {'ok', file_info()} | {'error', posix()}. +-spec read_file_info(Filename) -> {ok, FileInfo} | {error, Reason} when + Filename :: name(), + FileInfo :: file_info(), + Reason :: posix() | badarg. read_file_info(Name) -> check_and_call(read_file_info, [file_name(Name)]). @@ -193,45 +224,66 @@ read_file_info(Name) -> altname(Name) -> check_and_call(altname, [file_name(Name)]). --spec read_link_info(Name :: name()) -> {'ok', file_info()} | {'error', posix()}. +-spec read_link_info(Name) -> {ok, FileInfo} | {error, Reason} when + Name :: name(), + FileInfo :: file_info(), + Reason :: posix() | badarg. read_link_info(Name) -> check_and_call(read_link_info, [file_name(Name)]). --spec read_link(Name :: name()) -> {'ok', filename()} | {'error', posix()}. +-spec read_link(Name) -> {ok, Filename} | {error, Reason} when + Name :: name(), + Filename :: filename(), + Reason :: posix() | badarg. read_link(Name) -> check_and_call(read_link, [file_name(Name)]). --spec write_file_info(Name :: name(), Info :: file_info()) -> - 'ok' | {'error', posix()}. +-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason} when + Filename :: name(), + FileInfo :: file_info(), + Reason :: posix() | badarg. write_file_info(Name, Info = #file_info{}) -> check_and_call(write_file_info, [file_name(Name), Info]). --spec list_dir(Name :: name()) -> {'ok', [filename()]} | {'error', posix()}. +-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when + Dir :: name(), + Filenames :: [filename()], + Reason :: posix() | badarg. list_dir(Name) -> check_and_call(list_dir, [file_name(Name)]). --spec read_file(Name :: name()) -> - {'ok', binary()} | {'error', posix() | 'terminated' | 'system_limit'}. +-spec read_file(Filename) -> {ok, Binary} | {error, Reason} when + Filename :: name(), + Binary :: binary(), + Reason :: posix() | badarg | terminated | system_limit. read_file(Name) -> check_and_call(read_file, [file_name(Name)]). --spec make_link(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}. +-spec make_link(Existing, New) -> ok | {error, Reason} when + Existing :: name(), + New :: name(), + Reason :: posix() | badarg. make_link(Old, New) -> check_and_call(make_link, [file_name(Old), file_name(New)]). --spec make_symlink(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}. +-spec make_symlink(Name1, Name2) -> ok | {error, Reason} when + Name1 :: name(), + Name2 :: name(), + Reason :: posix() | badarg. make_symlink(Old, New) -> check_and_call(make_symlink, [file_name(Old), file_name(New)]). --spec write_file(Name :: name(), Bin :: iodata()) -> - 'ok' | {'error', posix() | 'terminated' | 'system_limit'}. +-spec write_file(Filename, Bytes) -> ok | {error, Reason} when + Filename :: name(), + Bytes :: iodata(), + Reason :: posix() | badarg | terminated | system_limit. write_file(Name, Bin) -> check_and_call(write_file, [file_name(Name), make_binary(Bin)]). @@ -240,8 +292,11 @@ write_file(Name, Bin) -> %% when it is time to change file server protocol again. %% Meanwhile, it is implemented here, slightly less efficient. --spec write_file(Name :: name(), Bin :: iodata(), Modes :: [mode()]) -> - 'ok' | {'error', posix()}. +-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason} when + Filename :: name(), + Bytes :: iodata(), + Modes :: [mode()], + Reason :: posix() | badarg | terminated | system_limit. write_file(Name, Bin, ModeList) when is_list(ModeList) -> case make_binary(Bin) of @@ -295,8 +350,11 @@ raw_write_file_info(Name, #file_info{} = Info) -> %% Contemporary mode specification - list of options --spec open(Name :: name(), Modes :: [mode()]) -> - {'ok', io_device()} | {'error', posix() | 'system_limit'}. +-spec open(Filename, Modes) -> {ok, IoDevice} | {error, Reason} when + Filename :: name(), + Modes :: [mode()], + IoDevice :: io_device(), + Reason :: posix() | badarg | system_limit. open(Item, ModeList) when is_list(ModeList) -> case lists:member(raw, ModeList) of @@ -349,7 +407,9 @@ open(Item, Mode) -> %%% The File argument must be either a Pid or a handle %%% returned from ?PRIM_FILE:open. --spec close(File :: io_device()) -> 'ok' | {'error', posix() | 'terminated'}. +-spec close(IoDevice) -> ok | {error, Reason} when + IoDevice :: io_device(), + Reason :: posix() | badarg | terminated. close(File) when is_pid(File) -> R = file_request(File, close), @@ -367,9 +427,12 @@ close(#file_descriptor{module = Module} = Handle) -> close(_) -> {error, badarg}. --spec advise(File :: io_device(), Offset :: integer(), - Length :: integer(), Advise :: posix_file_advise()) -> - 'ok' | {'error', posix()}. +-spec advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason} when + IoDevice :: io_device(), + Offset :: integer(), + Length :: integer(), + Advise :: posix_file_advise(), + Reason :: posix() | badarg. advise(File, Offset, Length, Advise) when is_pid(File) -> R = file_request(File, {advise, Offset, Length, Advise}), @@ -379,8 +442,11 @@ advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) -> advise(_, _, _, _) -> {error, badarg}. --spec read(File :: io_device() | atom(), Size :: non_neg_integer()) -> - 'eof' | {'ok', [char()] | binary()} | {'error', posix()}. +-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason} when + IoDevice :: io_device() | atom(), + Number :: non_neg_integer(), + Data :: string() | binary(), + Reason :: posix() | badarg | terminated. read(File, Sz) when (is_pid(File) orelse is_atom(File)), is_integer(Sz), Sz >= 0 -> case io:request(File, {get_chars, '', Sz}) of @@ -395,8 +461,10 @@ read(#file_descriptor{module = Module} = Handle, Sz) read(_, _) -> {error, badarg}. --spec read_line(File :: io_device() | atom()) -> - 'eof' | {'ok', [char()] | binary()} | {'error', posix()}. +-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason} when + IoDevice :: io_device() | atom(), + Data :: string() | binary(), + Reason :: posix() | badarg | terminated. read_line(File) when (is_pid(File) orelse is_atom(File)) -> case io:request(File, {get_line, ''}) of @@ -410,9 +478,12 @@ read_line(#file_descriptor{module = Module} = Handle) -> read_line(_) -> {error, badarg}. --spec pread(File :: io_device(), - LocationNumbers :: [{location(), non_neg_integer()}]) -> - {'ok', [string() | binary() | 'eof']} | {'error', posix()}. +-spec pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason} when + IoDevice :: io_device(), + LocNums :: [{Location :: location(), Number :: non_neg_integer()}], + DataL :: [Data], + Data :: string() | binary() | eof, + Reason :: posix() | badarg | terminated. pread(File, L) when is_pid(File), is_list(L) -> pread_int(File, L, []); @@ -435,10 +506,13 @@ pread_int(File, [{At, Sz} | T], R) when is_integer(Sz), Sz >= 0 -> pread_int(_, _, _) -> {error, badarg}. --spec pread(File :: io_device(), - Location :: location(), - Size :: non_neg_integer()) -> - 'eof' | {'ok', string() | binary()} | {'error', posix()}. +-spec pread(IoDevice, Location, Number) -> + {ok, Data} | eof | {error, Reason} when + IoDevice :: io_device(), + Location :: location(), + Number :: non_neg_integer(), + Data :: string() | binary(), + Reason :: posix() | badarg | terminated. pread(File, At, Sz) when is_pid(File), is_integer(Sz), Sz >= 0 -> R = file_request(File, {pread, At, Sz}), @@ -449,8 +523,10 @@ pread(#file_descriptor{module = Module} = Handle, Offs, Sz) pread(_, _, _) -> {error, badarg}. --spec write(File :: io_device() | atom(), Byte :: iodata()) -> - 'ok' | {'error', posix() | 'terminated'}. +-spec write(IoDevice, Bytes) -> ok | {error, Reason} when + IoDevice :: io_device() | atom(), + Bytes :: iodata(), + Reason :: posix() | badarg | terminated. write(File, Bytes) when (is_pid(File) orelse is_atom(File)) -> case make_binary(Bytes) of @@ -464,8 +540,11 @@ write(#file_descriptor{module = Module} = Handle, Bytes) -> write(_, _) -> {error, badarg}. --spec pwrite(File :: io_device(), L :: [{location(), iodata()}]) -> - 'ok' | {'error', {non_neg_integer(), posix()}}. +-spec pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}} when + IoDevice :: io_device(), + LocBytes :: [{Location :: location(), Bytes :: iodata()}], + N :: non_neg_integer(), + Reason :: posix() | badarg | terminated. pwrite(File, L) when is_pid(File), is_list(L) -> pwrite_int(File, L, 0); @@ -486,10 +565,11 @@ pwrite_int(File, [{At, Bytes} | T], R) -> pwrite_int(_, _, _) -> {error, badarg}. --spec pwrite(File :: io_device(), - Location :: location(), - Bytes :: iodata()) -> - 'ok' | {'error', posix()}. +-spec pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason} when + IoDevice :: io_device(), + Location :: location(), + Bytes :: iodata(), + Reason :: posix() | badarg | terminated. pwrite(File, At, Bytes) when is_pid(File) -> R = file_request(File, {pwrite, At, Bytes}), @@ -499,7 +579,9 @@ pwrite(#file_descriptor{module = Module} = Handle, Offs, Bytes) -> pwrite(_, _, _) -> {error, badarg}. --spec datasync(File :: io_device()) -> 'ok' | {'error', posix()}. +-spec datasync(IoDevice) -> ok | {error, Reason} when + IoDevice :: io_device(), + Reason :: posix() | badarg | terminated. datasync(File) when is_pid(File) -> R = file_request(File, datasync), @@ -509,7 +591,9 @@ datasync(#file_descriptor{module = Module} = Handle) -> datasync(_) -> {error, badarg}. --spec sync(File :: io_device()) -> 'ok' | {'error', posix()}. +-spec sync(IoDevice) -> ok | {error, Reason} when + IoDevice :: io_device(), + Reason :: posix() | badarg | terminated. sync(File) when is_pid(File) -> R = file_request(File, sync), @@ -519,8 +603,11 @@ sync(#file_descriptor{module = Module} = Handle) -> sync(_) -> {error, badarg}. --spec position(File :: io_device(), Location :: location()) -> - {'ok',integer()} | {'error', posix()}. +-spec position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason} when + IoDevice :: io_device(), + Location :: location(), + NewPosition :: integer(), + Reason :: posix() | badarg | terminated. position(File, At) when is_pid(File) -> R = file_request(File, {position,At}), @@ -530,7 +617,9 @@ position(#file_descriptor{module = Module} = Handle, At) -> position(_, _) -> {error, badarg}. --spec truncate(File :: io_device()) -> 'ok' | {'error', posix()}. +-spec truncate(IoDevice) -> ok | {error, Reason} when + IoDevice :: io_device(), + Reason :: posix() | badarg | terminated. truncate(File) when is_pid(File) -> R = file_request(File, truncate), @@ -540,17 +629,26 @@ truncate(#file_descriptor{module = Module} = Handle) -> truncate(_) -> {error, badarg}. --spec copy(Source :: io_device() | name() | {name(), [mode()]}, - Destination :: io_device() | name() | {name(), [mode()]}) -> - {'ok', non_neg_integer()} | {'error', posix()}. +-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason} when + Source :: io_device() | Filename | {Filename, Modes}, + Destination :: io_device() | Filename | {Filename, Modes}, + Filename :: name(), + Modes :: [mode()], + BytesCopied :: non_neg_integer(), + Reason :: posix() | badarg | terminated. copy(Source, Dest) -> copy_int(Source, Dest, infinity). --spec copy(Source :: io_device() | name() | {name(), [mode()]}, - Destination :: io_device() | name() | {name(), [mode()]}, - Length :: non_neg_integer() | 'infinity') -> - {'ok', non_neg_integer()} | {'error', posix()}. +-spec copy(Source, Destination, ByteCount) -> + {ok, BytesCopied} | {error, Reason} when + Source :: io_device() | Filename | {Filename, Modes}, + Destination :: io_device() | Filename | {Filename, Modes}, + Filename :: name(), + Modes :: [mode()], + ByteCount :: non_neg_integer() | infinity, + BytesCopied :: non_neg_integer(), + Reason :: posix() | badarg | terminated. copy(Source, Dest, Length) when is_integer(Length), Length >= 0; @@ -772,8 +870,11 @@ ipread_s32bu_p32bu_2(File, %%% The following functions, built upon the other interface functions, %%% provide a higher-lever interface to files. --spec consult(File :: name()) -> - {'ok', list()} | {'error', posix() | {integer(), atom(), any()}}. +-spec consult(Filename) -> {ok, Terms} | {error, Reason} when + Filename :: name(), + Terms :: [term()], + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. consult(File) -> case open(File, [read]) of @@ -785,8 +886,14 @@ consult(File) -> Error end. --spec path_consult(Paths :: [name()], File :: name()) -> - {'ok', list(), filename()} | {'error', posix() | {integer(), atom(), any()}}. +-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason} when + Path :: [Dir], + Dir :: name(), + Filename :: name(), + Terms :: [term()], + FullName :: filename(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. path_consult(Path, File) -> case path_open(Path, File, [read]) of @@ -803,13 +910,19 @@ path_consult(Path, File) -> E2 end. --spec eval(File :: name()) -> 'ok' | {'error', posix()}. +-spec eval(Filename) -> ok | {error, Reason} when + Filename :: name(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. eval(File) -> eval(File, erl_eval:new_bindings()). --spec eval(File :: name(), Bindings :: bindings()) -> - 'ok' | {'error', posix()}. +-spec eval(Filename, Bindings) -> ok | {error, Reason} when + Filename :: name(), + Bindings :: bindings(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. eval(File, Bs) -> case open(File, [read]) of @@ -821,14 +934,24 @@ eval(File, Bs) -> Error end. --spec path_eval(Paths :: [name()], File :: name()) -> - {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}. +-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason} when + Path :: [Dir :: name()], + Filename :: name(), + FullName :: filename(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. path_eval(Path, File) -> path_eval(Path, File, erl_eval:new_bindings()). --spec path_eval(Paths :: [name()], File :: name(), Bindings :: bindings()) -> - {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}. +-spec path_eval(Path, Filename, Bindings) -> + {ok, FullName} | {error, Reason} when + Path :: [Dir :: name()], + Filename :: name(), + Bindings :: bindings(), + FullName :: filename(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. path_eval(Path, File, Bs) -> case path_open(Path, File, [read]) of @@ -845,14 +968,21 @@ path_eval(Path, File, Bs) -> E2 end. --spec script(File :: name()) -> - {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}. +-spec script(Filename) -> {ok, Value} | {error, Reason} when + Filename :: name(), + Value :: term(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. script(File) -> script(File, erl_eval:new_bindings()). --spec script(File :: name(), Bindings :: bindings()) -> - {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}. +-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason} when + Filename :: name(), + Bindings :: bindings(), + Value :: term(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. script(File, Bs) -> case open(File, [read]) of @@ -864,16 +994,27 @@ script(File, Bs) -> Error end. --spec path_script/2 :: (Paths :: [name()], File :: name()) -> - {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}. +-spec path_script(Path, Filename) -> + {ok, Value, FullName} | {error, Reason} when + Path :: [Dir :: name()], + Filename :: name(), + Value :: term(), + FullName :: filename(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. path_script(Path, File) -> path_script(Path, File, erl_eval:new_bindings()). --spec path_script(Paths :: [name()], - File :: name(), - Bindings :: bindings()) -> - {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}. +-spec path_script(Path, Filename, Bindings) -> + {ok, Value, FullName} | {error, Reason} when + Path :: [Dir :: name()], + Filename :: name(), + Bindings :: bindings(), + Value :: term(), + FullName :: filename(), + Reason :: posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. path_script(Path, File, Bs) -> case path_open(Path, File, [read]) of @@ -898,8 +1039,14 @@ path_script(Path, File, Bs) -> %% Searches the Paths for file Filename which can be opened with Mode. %% The path list is ignored if Filename contains an absolute path. --spec path_open(Paths :: [name()], Name :: name(), Modes :: [mode()]) -> - {'ok', io_device(), filename()} | {'error', posix()}. +-spec path_open(Path, Filename, Modes) -> + {ok, IoDevice, FullName} | {error, Reason} when + Path :: [Dir :: name()], + Filename :: name(), + Modes :: [mode()], + IoDevice :: io_device(), + FullName :: filename(), + Reason :: posix() | badarg | system_limit. path_open(PathList, Name, Mode) -> case file_name(Name) of @@ -919,47 +1066,57 @@ path_open(PathList, Name, Mode) -> end end. --spec change_mode(Name :: name(), Mode :: integer()) -> - 'ok' | {'error', posix()}. +-spec change_mode(Filename, Mode) -> ok | {error, Reason} when + Filename :: name(), + Mode :: integer(), + Reason :: posix() | badarg. change_mode(Name, Mode) when is_integer(Mode) -> write_file_info(Name, #file_info{mode=Mode}). --spec change_owner(Name :: name(), OwnerId :: integer()) -> - 'ok' | {'error', posix()}. +-spec change_owner(Filename, Uid) -> ok | {error, Reason} when + Filename :: name(), + Uid :: integer(), + Reason :: posix() | badarg. change_owner(Name, OwnerId) when is_integer(OwnerId) -> write_file_info(Name, #file_info{uid=OwnerId}). --spec change_owner(Name :: name(), - OwnerId :: integer(), - GroupId :: integer()) -> - 'ok' | {'error', posix()}. +-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason} when + Filename :: name(), + Uid :: integer(), + Gid :: integer(), + Reason :: posix() | badarg. change_owner(Name, OwnerId, GroupId) when is_integer(OwnerId), is_integer(GroupId) -> write_file_info(Name, #file_info{uid=OwnerId, gid=GroupId}). --spec change_group(Name :: name(), GroupId :: integer()) -> - 'ok' | {'error', posix()}. +-spec change_group(Filename, Gid) -> ok | {error, Reason} when + Filename :: name(), + Gid :: integer(), + Reason :: posix() | badarg. change_group(Name, GroupId) when is_integer(GroupId) -> write_file_info(Name, #file_info{gid=GroupId}). --spec change_time(Name :: name(), Time :: date_time()) -> - 'ok' | {'error', posix()}. +-spec change_time(Filename, Mtime) -> ok | {error, Reason} when + Filename :: name(), + Mtime :: date_time(), + Reason :: posix() | badarg. change_time(Name, Time) when is_tuple(Time) -> write_file_info(Name, #file_info{mtime=Time}). --spec change_time(Name :: name(), - ATime :: date_time(), - MTime :: date_time()) -> - 'ok' | {'error', posix()}. +-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason} when + Filename :: name(), + Atime :: date_time(), + Mtime :: date_time(), + Reason :: posix() | badarg. change_time(Name, Atime, Mtime) when is_tuple(Atime), is_tuple(Mtime) -> diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl index cccfa75005..004f03f231 100644 --- a/lib/kernel/src/gen_sctp.erl +++ b/lib/kernel/src/gen_sctp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% Copyright Ericsson AB 2007-2011. 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 @@ -33,11 +33,57 @@ -export([error_string/1]). -export([controlling_process/2]). - +-opaque assoc_id() :: term(). +-type hostname() :: inet:hostname(). +-type ip_address() :: inet:ip_address(). +-type port_number() :: 0..65535. +-type posix() :: inet:posix(). +-type sctp_option() :: + {mode, list | binary} | list | binary + | {active, true | false | once} + | {buffer, non_neg_integer()} + | {tos, integer()} + | {priority, integer()} + | {dontroute, boolean()} + | {reuseaddr, boolean()} + | {linger, {boolean(), non_neg_integer()}} + | {sndbuf, non_neg_integer()} + | {recbuf, non_neg_integer()} + | {sctp_rtoinfo, #sctp_rtoinfo{}} + | {sctp_associnfo, #sctp_assocparams{}} + | {sctp_initmsg, #sctp_initmsg{}} + | {sctp_autoclose, timeout()} + | {sctp_nodelay, boolean()} + | {sctp_disable_fragments, boolean()} + | {sctp_i_want_mapped_v4_addr, boolean()} + | {sctp_maxseg, non_neg_integer()} + | {sctp_primary_addr, #sctp_prim{}} + | {sctp_set_peer_primary_addr, #sctp_setpeerprim{}} + | {sctp_adaptation_layer, #sctp_setadaptation{}} + | {sctp_peer_addr_params, #sctp_paddrparams{}} + | {sctp_default_send_param, #sctp_sndrcvinfo{}} + | {sctp_events, #sctp_event_subscribe{}} + | {sctp_delayed_ack_time, #sctp_assoc_value{}} + | {sctp_status, #sctp_status{}} + | {sctp_get_peer_addr_info, #sctp_paddrinfo{}}. +-opaque sctp_socket() :: port(). + +-spec open() -> {ok, Socket} | {error, posix()} when + Socket :: sctp_socket(). open() -> open([]). +-spec open(Port) -> {ok, Socket} | {error, posix()} when + Port :: port_number(), + Socket :: sctp_socket(); + (Opts) -> {ok, Socket} | {error, posix()} when + Opts :: [Opt], + Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(), + IP :: ip_address() | any | loopback, + Port :: port_number(), + Socket :: sctp_socket(). + open(Opts) when is_list(Opts) -> Mod = mod(Opts, undefined), case Mod:open(Opts) of @@ -52,11 +98,21 @@ open(Port) when is_integer(Port) -> open(X) -> erlang:error(badarg, [X]). +-spec open(Port, Opts) -> {ok, Socket} | {error, posix()} when + Opts :: [Opt], + Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(), + IP :: ip_address() | any | loopback, + Port :: port_number(), + Socket :: sctp_socket(). + open(Port, Opts) when is_integer(Port), is_list(Opts) -> open([{port,Port}|Opts]); open(Port, Opts) -> erlang:error(badarg, [Port,Opts]). +-spec close(Socket) -> ok | {error, posix()} when + Socket :: sctp_socket(). + close(S) when is_port(S) -> case inet_db:lookup_socket(S) of {ok,Mod} -> @@ -68,6 +124,11 @@ close(S) -> +-spec listen(Socket, IsServer) -> ok | {error, Reason} when + Socket :: sctp_socket(), + IsServer :: boolean(), + Reason :: term(). + listen(S, Flag) when is_port(S), is_boolean(Flag) -> case inet_db:lookup_socket(S) of {ok,Mod} -> @@ -77,9 +138,25 @@ listen(S, Flag) when is_port(S), is_boolean(Flag) -> listen(S, Flag) -> erlang:error(badarg, [S,Flag]). +-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, posix()} when + Socket :: sctp_socket(), + Addr :: ip_address() | hostname(), + Port :: port_number(), + Opts :: [Opt :: sctp_option()], + Assoc :: #sctp_assoc_change{}. + connect(S, Addr, Port, Opts) -> connect(S, Addr, Port, Opts, infinity). +-spec connect(Socket, Addr, Port, Opts, Timeout) -> + {ok, Assoc} | {error, posix()} when + Socket :: sctp_socket(), + Addr :: ip_address() | hostname(), + Port :: port_number(), + Opts :: [Opt :: sctp_option()], + Timeout :: timeout(), + Assoc :: #sctp_assoc_change{}. + connect(S, Addr, Port, Opts, Timeout) -> case do_connect(S, Addr, Port, Opts, Timeout, true) of badarg -> @@ -88,9 +165,24 @@ connect(S, Addr, Port, Opts, Timeout) -> Result end. +-spec connect_init(Socket, Addr, Port, Opts) -> + ok | {error, posix()} when + Socket :: sctp_socket(), + Addr :: ip_address() | hostname(), + Port :: port_number(), + Opts :: [sctp_option()]. + connect_init(S, Addr, Port, Opts) -> connect_init(S, Addr, Port, Opts, infinity). +-spec connect_init(Socket, Addr, Port, Opts, Timeout) -> + ok | {error, posix()} when + Socket :: sctp_socket(), + Addr :: ip_address() | hostname(), + Port :: port_number(), + Opts :: [sctp_option()], + Timeout :: timeout(). + connect_init(S, Addr, Port, Opts, Timeout) -> case do_connect(S, Addr, Port, Opts, Timeout, false) of badarg -> @@ -130,12 +222,20 @@ do_connect(_S, _Addr, _Port, _Opts, _Timeout, _ConnWait) -> badarg. +-spec eof(Socket, Assoc) -> ok | {error, Reason} when + Socket :: sctp_socket(), + Assoc :: #sctp_assoc_change{}, + Reason :: term(). eof(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) -> eof_or_abort(S, AssocId, eof); eof(S, Assoc) -> erlang:error(badarg, [S,Assoc]). +-spec abort(Socket, Assoc) -> ok | {error, posix()} when + Socket :: sctp_socket(), + Assoc :: #sctp_assoc_change{}. + abort(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) -> eof_or_abort(S, AssocId, abort); abort(S, Assoc) -> @@ -151,6 +251,11 @@ eof_or_abort(S, AssocId, Action) -> end. +-spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason} when + Socket :: sctp_socket(), + SndRcvInfo :: #sctp_sndrcvinfo{}, + Data :: binary | iolist(), + Reason :: term(). %% Full-featured send. Rarely needed. send(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) -> @@ -162,6 +267,13 @@ send(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) -> send(S, SRI, Data) -> erlang:error(badarg, [S,SRI,Data]). +-spec send(Socket, Assoc, Stream, Data) -> ok | {error, Reason} when + Socket :: sctp_socket(), + Assoc :: #sctp_assoc_change{} | assoc_id(), + Stream :: integer(), + Data :: binary | iolist(), + Reason :: term(). + send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data) when is_port(S), is_integer(Stream) -> case inet_db:lookup_socket(S) of @@ -179,9 +291,36 @@ send(S, AssocId, Stream, Data) send(S, AssocChange, Stream, Data) -> erlang:error(badarg, [S,AssocChange,Stream,Data]). +-spec recv(Socket) -> {ok, {FromIP, FromPort, AncData, Data}} + | {error, Reason} when + Socket :: sctp_socket(), + FromIP :: ip_address(), + FromPort :: port_number(), + AncData :: [#sctp_sndrcvinfo{}], + Data :: binary() | string() | #sctp_sndrcvinfo{} + | #sctp_assoc_change{} | #sctp_paddr_change{} + | #sctp_adaptation_event{}, + Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{} + | #sctp_pdapi_event{} | #sctp_remote_error{} + | #sctp_shutdown_event{}. + recv(S) -> recv(S, infinity). +-spec recv(Socket, Timeout) -> {ok, {FromIP, FromPort, AncData, Data}} + | {error, Reason} when + Socket :: sctp_socket(), + Timeout :: timeout(), + FromIP :: ip_address(), + FromPort :: port_number(), + AncData :: [#sctp_sndrcvinfo{}], + Data :: binary() | string() | #sctp_sndrcvinfo{} + | #sctp_assoc_change{} | #sctp_paddr_change{} + | #sctp_adaptation_event{}, + Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{} + | #sctp_pdapi_event{} | #sctp_remote_error{} + | #sctp_shutdown_event{}. + recv(S, Timeout) when is_port(S) -> case inet_db:lookup_socket(S) of {ok,Mod} -> @@ -192,6 +331,8 @@ recv(S, Timeout) -> erlang:error(badarg, [S,Timeout]). +-spec error_string(ErrorNumber) -> ok | string() | unknown_error when + ErrorNumber :: integer(). error_string(0) -> ok; @@ -224,6 +365,9 @@ error_string(X) -> erlang:error(badarg, [X]). +-spec controlling_process(Socket, Pid) -> ok when + Socket :: sctp_socket(), + Pid :: pid(). controlling_process(S, Pid) when is_port(S), is_pid(Pid) -> inet:udp_controlling_process(S, Pid); diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl index 16a87d71b6..bee61ca84a 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -28,12 +28,35 @@ -include("inet_int.hrl"). +-type hostname() :: inet:hostname(). +-type ip_address() :: inet:ip_address(). +-type port_number() :: 0..65535. +-type posix() :: inet:posix(). +-type socket() :: port(). + %% %% Connect a socket %% + +-spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when + Address :: ip_address() | hostname(), + Port :: port_number(), + Options :: [Opt :: term()], + Socket :: socket(), + Reason :: posix(). + connect(Address, Port, Opts) -> connect(Address,Port,Opts,infinity). +-spec connect(Address, Port, Options, Timeout) -> + {ok, Socket} | {error, Reason} when + Address :: ip_address() | hostname(), + Port :: port_number(), + Options :: [Opt :: term()], + Timeout :: timeout(), + Socket :: socket(), + Reason :: posix(). + connect(Address, Port, Opts, Time) -> Timer = inet:start_timer(Time), Res = (catch connect1(Address,Port,Opts,Timer)), @@ -72,6 +95,13 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) -> %% %% Listen on a tcp port %% + +-spec listen(Port, Options) -> {ok, ListenSocket} | {error, Reason} when + Port :: port_number(), + Options :: [Opt :: term()], + ListenSocket :: socket(), + Reason :: posix(). + listen(Port, Opts) -> Mod = mod(Opts, undefined), case Mod:getserv(Port) of @@ -85,6 +115,12 @@ listen(Port, Opts) -> %% %% Generic tcp accept %% + +-spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when + ListenSocket :: socket(), + Socket :: socket(), + Reason :: closed | timeout | posix(). + accept(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -93,6 +129,12 @@ accept(S) -> Error end. +-spec accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason} when + ListenSocket :: socket(), + Timeout :: timeout(), + Socket :: socket(), + Reason :: closed | timeout | posix(). + accept(S, Time) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -104,6 +146,12 @@ accept(S, Time) when is_port(S) -> %% %% Generic tcp shutdown %% + +-spec shutdown(Socket, How) -> ok | {error, Reason} when + Socket :: socket(), + How :: read | write | read_write, + Reason :: posix(). + shutdown(S, How) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -115,12 +163,22 @@ shutdown(S, How) when is_port(S) -> %% %% Close %% + +-spec close(Socket) -> ok when + Socket :: socket(). + close(S) -> inet:tcp_close(S). %% %% Send %% + +-spec send(Socket, Packet) -> ok | {error, Reason} when + Socket :: socket(), + Packet :: string() | binary(), + Reason :: posix(). + send(S, Packet) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -132,6 +190,14 @@ send(S, Packet) when is_port(S) -> %% %% Receive data from a socket (passive mode) %% + +-spec recv(Socket, Length) -> {ok, Packet} | {error, Reason} when + Socket :: socket(), + Length :: non_neg_integer(), + Packet :: string() | binary() | HttpPacket, + Reason :: closed | posix(), + HttpPacket :: term(). + recv(S, Length) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -140,6 +206,14 @@ recv(S, Length) when is_port(S) -> Error end. +-spec recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason} when + Socket :: socket(), + Length :: non_neg_integer(), + Timeout :: timeout(), + Packet :: string() | binary() | HttpPacket, + Reason :: closed | posix(), + HttpPacket :: term(). + recv(S, Length, Time) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -159,6 +233,12 @@ unrecv(S, Data) when is_port(S) -> %% %% Set controlling process %% + +-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when + Socket :: socket(), + Pid :: pid(), + Reason :: closed | not_owner | posix(). + controlling_process(S, NewOwner) -> case inet_db:lookup_socket(S) of {ok, _Mod} -> % Just check that this is an open socket diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl index 99020c7b6c..7d14615c04 100644 --- a/lib/kernel/src/gen_udp.erl +++ b/lib/kernel/src/gen_udp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -25,17 +25,44 @@ -include("inet_int.hrl"). +-type hostname() :: inet:hostname(). +-type ip_address() :: inet:ip_address(). +-type port_number() :: 0..65535. +-type posix() :: inet:posix(). +-type socket() :: port(). + +-spec open(Port) -> {ok, Socket} | {error, Reason} when + Port :: port_number(), + Socket :: socket(), + Reason :: posix(). + open(Port) -> open(Port, []). +-spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when + Port :: port_number(), + Opts :: [Opt :: term()], + Socket :: socket(), + Reason :: posix(). + open(Port, Opts) -> Mod = mod(Opts, undefined), {ok,UP} = Mod:getserv(Port), Mod:open(UP, Opts). +-spec close(Socket) -> ok when + Socket :: socket(). + close(S) -> inet:udp_close(S). +-spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when + Socket :: socket(), + Address :: ip_address() | hostname(), + Port :: port_number(), + Packet :: string() | binary(), + Reason :: not_owner | posix(). + send(S, Address, Port, Packet) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -61,6 +88,15 @@ send(S, Packet) when is_port(S) -> Error end. +-spec recv(Socket, Length) -> + {ok, {Address, Port, Packet}} | {error, Reason} when + Socket :: socket(), + Length :: non_neg_integer(), + Address :: ip_address(), + Port :: port_number(), + Packet :: string() | binary(), + Reason :: not_owner | posix(). + recv(S,Len) when is_port(S), is_integer(Len) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -69,6 +105,16 @@ recv(S,Len) when is_port(S), is_integer(Len) -> Error end. +-spec recv(Socket, Length, Timeout) -> + {ok, {Address, Port, Packet}} | {error, Reason} when + Socket :: socket(), + Length :: non_neg_integer(), + Timeout :: timeout(), + Address :: ip_address(), + Port :: port_number(), + Packet :: string() | binary(), + Reason :: not_owner | posix(). + recv(S,Len,Time) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> @@ -90,6 +136,10 @@ connect(S, Address, Port) when is_port(S) -> Error end. +-spec controlling_process(Socket, Pid) -> ok when + Socket :: socket(), + Pid :: pid(). + controlling_process(S, NewOwner) -> inet:udp_controlling_process(S, NewOwner). diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index 6343acd000..7d15f8bf83 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -166,7 +166,7 @@ start_link() -> stop() -> gen_server:call(global_name_server, stop, infinity). --spec sync() -> 'ok' | {'error', term()}. +-spec sync() -> 'ok' | {'error', Reason :: term()}. sync() -> case check_sync_nodes() of {error, _} = Error -> @@ -175,7 +175,7 @@ sync() -> gen_server:call(global_name_server, {sync, SyncNodes}, infinity) end. --spec sync([node()]) -> 'ok' | {'error', term()}. +-spec sync([node()]) -> 'ok' | {'error', Reason :: term()}. sync(Nodes) -> case check_sync_nodes(Nodes) of {error, _} = Error -> @@ -184,7 +184,10 @@ sync(Nodes) -> gen_server:call(global_name_server, {sync, SyncNodes}, infinity) end. --spec send(term(), term()) -> pid(). +-spec send(Name, Msg) -> Pid when + Name :: term(), + Msg :: term(), + Pid :: pid(). send(Name, Msg) -> case whereis_name(Name) of Pid when is_pid(Pid) -> @@ -195,7 +198,8 @@ send(Name, Msg) -> end. %% See OTP-3737. --spec whereis_name(term()) -> pid() | 'undefined'. +-spec whereis_name(Name) -> pid() | 'undefined' when + Name :: term(). whereis_name(Name) -> where(Name). @@ -219,13 +223,19 @@ node_disconnected(Node) -> %% undefined which one of them is used. %% Method blocks the name registration, but does not affect global locking. %%----------------------------------------------------------------- --spec register_name(term(), pid()) -> 'yes' | 'no'. +-spec register_name(Name, Pid) -> 'yes' | 'no' when + Name :: term(), + Pid :: pid(). register_name(Name, Pid) when is_pid(Pid) -> register_name(Name, Pid, fun random_exit_name/3). --type method() :: fun((term(), pid(), pid()) -> pid() | 'none'). +-type method() :: fun((Name :: term(), Pid :: pid(), Pid2 :: pid()) -> + pid() | 'none'). --spec register_name(term(), pid(), method()) -> 'yes' | 'no'. +-spec register_name(Name, Pid, Resolve) -> 'yes' | 'no' when + Name :: term(), + Pid :: pid(), + Resolve :: method(). register_name(Name, Pid, Method) when is_pid(Pid) -> Fun = fun(Nodes) -> case (where(Name) =:= undefined) andalso check_dupname(Name, Pid) of @@ -257,7 +267,8 @@ check_dupname(Name, Pid) -> end end. --spec unregister_name(term()) -> _. +-spec unregister_name(Name) -> _ when + Name :: term(). unregister_name(Name) -> case where(Name) of undefined -> @@ -273,11 +284,16 @@ unregister_name(Name) -> gen_server:call(global_name_server, {registrar, Fun}, infinity) end. --spec re_register_name(term(), pid()) -> _. +-spec re_register_name(Name, Pid) -> _ when + Name :: term(), + Pid :: pid(). re_register_name(Name, Pid) when is_pid(Pid) -> re_register_name(Name, Pid, fun random_exit_name/3). --spec re_register_name(term(), pid(), method()) -> _. +-spec re_register_name(Name, Pid, Resolve) -> _ when + Name :: term(), + Pid :: pid(), + Resolve :: method(). re_register_name(Name, Pid, Method) when is_pid(Pid) -> Fun = fun(Nodes) -> gen_server:multi_call(Nodes, @@ -288,7 +304,8 @@ re_register_name(Name, Pid, Method) when is_pid(Pid) -> ?trace({re_register_name, self(), Name, Pid, Method}), gen_server:call(global_name_server, {registrar, Fun}, infinity). --spec registered_names() -> [term()]. +-spec registered_names() -> [Name] when + Name :: term(). registered_names() -> MS = ets:fun2ms(fun({Name,_Pid,_M,_RP,_R}) -> Name end), ets:select(global_names, MS). @@ -329,19 +346,25 @@ register_name_external(Name, Pid, Method) when is_pid(Pid) -> unregister_name_external(Name) -> unregister_name(Name). --type id() :: {term(), term()}. +-type id() :: {ResourceId :: term(), LockRequesterId :: term()}. --spec set_lock(id()) -> boolean(). +-spec set_lock(Id) -> boolean() when + Id :: id(). set_lock(Id) -> set_lock(Id, [node() | nodes()], infinity, 1). -type retries() :: non_neg_integer() | 'infinity'. --spec set_lock(id(), [node()]) -> boolean(). +-spec set_lock(Id, Nodes) -> boolean() when + Id :: id(), + Nodes :: [node()]. set_lock(Id, Nodes) -> set_lock(Id, Nodes, infinity, 1). --spec set_lock(id(), [node()], retries()) -> boolean(). +-spec set_lock(Id, Nodes, Retries) -> boolean() when + Id :: id(), + Nodes :: [node()], + Retries :: retries(). set_lock(Id, Nodes, Retries) when is_integer(Retries), Retries >= 0 -> set_lock(Id, Nodes, Retries, 1); set_lock(Id, Nodes, infinity) -> @@ -363,11 +386,14 @@ set_lock({_ResourceId, _LockRequesterId} = Id, Nodes, Retries, Times) -> set_lock(Id, Nodes, dec(Retries), Times+1) end. --spec del_lock(id()) -> 'true'. +-spec del_lock(Id) -> 'true' when + Id :: id(). del_lock(Id) -> del_lock(Id, [node() | nodes()]). --spec del_lock(id(), [node()]) -> 'true'. +-spec del_lock(Id, Nodes) -> 'true' when + Id :: id(), + Nodes :: [node()]. del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) -> ?trace({del_lock, {me,self()}, Id, {nodes,Nodes}}), gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}), @@ -375,13 +401,25 @@ del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) -> -type trans_fun() :: function() | {module(), atom()}. --spec trans(id(), trans_fun()) -> term(). +-spec trans(Id, Fun) -> Res | aborted when + Id :: id(), + Fun :: trans_fun(), + Res :: term(). trans(Id, Fun) -> trans(Id, Fun, [node() | nodes()], infinity). --spec trans(id(), trans_fun(), [node()]) -> term(). +-spec trans(Id, Fun, Nodes) -> Res | aborted when + Id :: id(), + Fun :: trans_fun(), + Nodes :: [node()], + Res :: term(). trans(Id, Fun, Nodes) -> trans(Id, Fun, Nodes, infinity). --spec trans(id(), trans_fun(), [node()], retries()) -> term(). +-spec trans(Id, Fun, Nodes, Retries) -> Res | aborted when + Id :: id(), + Fun :: trans_fun(), + Nodes :: [node()], + Retries :: retries(), + Res :: term(). trans(Id, Fun, Nodes, Retries) -> case set_lock(Id, Nodes, Retries) of true -> @@ -1928,7 +1966,10 @@ resolve_it(Method, Name, Pid1, Pid2) -> minmax(P1,P2) -> if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end. --spec random_exit_name(term(), pid(), pid()) -> pid(). +-spec random_exit_name(Name, Pid1, Pid2) -> 'none' when + Name :: term(), + Pid1 :: pid(), + Pid2 :: pid(). random_exit_name(Name, Pid, Pid2) -> {Min, Max} = minmax(Pid, Pid2), error_logger:info_msg("global: Name conflict terminating ~w\n", @@ -1936,12 +1977,19 @@ random_exit_name(Name, Pid, Pid2) -> exit(Max, kill), Min. +-spec random_notify_name(Name, Pid1, Pid2) -> 'none' when + Name :: term(), + Pid1 :: pid(), + Pid2 :: pid(). random_notify_name(Name, Pid, Pid2) -> {Min, Max} = minmax(Pid, Pid2), Max ! {global_name_conflict, Name}, Min. --spec notify_all_name(term(), pid(), pid()) -> 'none'. +-spec notify_all_name(Name, Pid1, Pid2) -> 'none' when + Name :: term(), + Pid1 :: pid(), + Pid2 :: pid(). notify_all_name(Name, Pid, Pid2) -> Pid ! {global_name_conflict, Name, Pid2}, Pid2 ! {global_name_conflict, Name, Pid}, diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl index 7e141ac5c7..025a9b8a5b 100644 --- a/lib/kernel/src/global_group.erl +++ b/lib/kernel/src/global_group.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. 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 @@ -62,9 +62,10 @@ -type sync_state() :: 'no_conf' | 'synced'. -type group_name() :: atom(). --type group_tuple() :: {group_name(), [node()]} - | {group_name(), publish_type(), [node()]}. - +-type group_tuple() :: {GroupName :: group_name(), [node()]} + | {GroupName :: group_name(), + PublishType :: publish_type(), + [node()]}. %%%==================================================================================== %%% The state of the global_group process @@ -97,11 +98,14 @@ %%% External exported %%%==================================================================================== --spec global_groups() -> {group_name(), [group_name()]} | 'undefined'. +-spec global_groups() -> {GroupName, GroupNames} | undefined when + GroupName :: group_name(), + GroupNames :: [GroupName]. global_groups() -> request(global_groups). --spec monitor_nodes(boolean()) -> 'ok'. +-spec monitor_nodes(Flag) -> 'ok' when + Flag :: boolean(). monitor_nodes(Flag) -> case Flag of true -> request({monitor_nodes, Flag}); @@ -109,30 +113,41 @@ monitor_nodes(Flag) -> _ -> {error, not_boolean} end. --spec own_nodes() -> [node()]. +-spec own_nodes() -> Nodes when + Nodes :: [Node :: node()]. own_nodes() -> request(own_nodes). -type name() :: atom(). -type where() :: {'node', node()} | {'group', group_name()}. --spec registered_names(where()) -> [name()]. +-spec registered_names(Where) -> Names when + Where :: where(), + Names :: [Name :: name()]. registered_names(Arg) -> request({registered_names, Arg}). --spec send(name(), term()) -> pid() | {'badarg', {name(), term()}}. +-spec send(Name, Msg) -> pid() | {'badarg', {Name, Msg}} when + Name :: name(), + Msg :: term(). send(Name, Msg) -> request({send, Name, Msg}). --spec send(where(), name(), term()) -> pid() | {'badarg', {name(), term()}}. +-spec send(Where, Name, Msg) -> pid() | {'badarg', {Name, Msg}} when + Where :: where(), + Name :: name(), + Msg :: term(). send(Group, Name, Msg) -> request({send, Group, Name, Msg}). --spec whereis_name(name()) -> pid() | 'undefined'. +-spec whereis_name(Name) -> pid() | 'undefined' when + Name :: name(). whereis_name(Name) -> request({whereis_name, Name}). --spec whereis_name(where(), name()) -> pid() | 'undefined'. +-spec whereis_name(Where, Name) -> pid() | 'undefined' when + Where :: where(), + Name :: name(). whereis_name(Group, Name) -> request({whereis_name, Group, Name}). @@ -155,14 +170,14 @@ ng_add_check(Node, OthersNG) -> ng_add_check(Node, PubType, OthersNG) -> request({ng_add_check, Node, PubType, OthersNG}). --type info_item() :: {'state', sync_state()} - | {'own_group_name', group_name()} - | {'own_group_nodes', [node()]} - | {'synched_nodes', [node()]} - | {'sync_error', [node()]} - | {'no_contact', [node()]} - | {'other_groups', [group_tuple()]} - | {'monitoring', [pid()]}. +-type info_item() :: {'state', State :: sync_state()} + | {'own_group_name', GroupName :: group_name()} + | {'own_group_nodes', Nodes :: [node()]} + | {'synched_nodes', Nodes :: [node()]} + | {'sync_error', Nodes :: [node()]} + | {'no_contact', Nodes :: [node()]} + | {'other_groups', Groups :: [group_tuple()]} + | {'monitoring', Pids :: [pid()]}. -spec info() -> [info_item()]. info() -> @@ -1012,6 +1027,7 @@ grp_tuple({Name, normal, Nodes}) -> %%% The special process which checks that all nodes in the own global group %%% agrees on the configuration. %%%==================================================================================== +-spec sync_init(_, _, _, _) -> no_return(). sync_init(Type, Cname, PubType, Nodes) -> {Up, Down} = sync_check_node(lists:delete(node(), Nodes), [], []), sync_check_init(Type, Up, Cname, Nodes, Down, PubType). @@ -1032,9 +1048,11 @@ sync_check_node([Node|Nodes], Up, Down) -> %%% Check that all nodes are in agreement of the global %%% group configuration. %%%------------------------------------------------------------- +-spec sync_check_init(_, _, _, _, _, _) -> no_return(). sync_check_init(Type, Up, Cname, Nodes, Down, PubType) -> sync_check_init(Type, Up, Cname, Nodes, 3, [], Down, PubType). +-spec sync_check_init(_, _, _, _, _, _, _, _) -> no_return(). sync_check_init(_Type, NoContact, _Cname, _Nodes, 0, ErrorNodes, Down, _PubType) -> case ErrorNodes of [] -> diff --git a/lib/kernel/src/global_search.erl b/lib/kernel/src/global_search.erl index b723e18a1b..0bf53e29b8 100644 --- a/lib/kernel/src/global_search.erl +++ b/lib/kernel/src/global_search.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. 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 @@ -69,6 +69,7 @@ start(Flag, Arg) -> %%%==================================================================================== %%%==================================================================================== +-spec init_send(_) -> no_return(). init_send({any, NodesList, Name, Msg, From}) -> case whereis_any_loop(NodesList, Name) of undefined -> @@ -115,6 +116,7 @@ init_send({node, Node, Name, Msg, From}) -> %%%==================================================================================== %%%==================================================================================== +-spec init_whereis(_) -> no_return(). init_whereis({any, NodesList, Name, From}) -> R = whereis_any_loop(NodesList, Name), gen_server:cast(global_group, {find_name_res, R, self(), From}), @@ -146,6 +148,7 @@ init_whereis({node, Node, Name, From}) -> %%%==================================================================================== %%%==================================================================================== %%%==================================================================================== +-spec init_names(_) -> no_return(). init_names({group, Nodes, From}) -> case names_group_loop(Nodes) of group_down -> diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl index e78acfc7a6..255ae4e51b 100644 --- a/lib/kernel/src/heart.erl +++ b/lib/kernel/src/heart.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -85,19 +85,21 @@ init(Starter, Parent) -> Starter ! {start_error, self()} end. --spec set_cmd(string()) -> 'ok' | {'error', {'bad_cmd', string()}}. +-spec set_cmd(Cmd) -> 'ok' | {'error', {'bad_cmd', Cmd}} when + Cmd :: string(). set_cmd(Cmd) -> heart ! {self(), set_cmd, Cmd}, wait(). --spec get_cmd() -> 'ok'. +-spec get_cmd() -> {ok, Cmd} when + Cmd :: string(). get_cmd() -> heart ! {self(), get_cmd}, wait(). --spec clear_cmd() -> {'ok', string()}. +-spec clear_cmd() -> ok. clear_cmd() -> heart ! {self(), clear_cmd}, diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index f289b8110d..1d3eb926ca 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -258,7 +258,7 @@ find_callee_mfas(Patches) when is_list(Patches) -> amd64 -> []; arm -> find_callee_mfas(Patches, gb_sets:empty(), false); powerpc -> find_callee_mfas(Patches, gb_sets:empty(), true); - %% ppc64 -> find_callee_mfas(Patches, gb_sets:empty(), true); + ppc64 -> find_callee_mfas(Patches, gb_sets:empty(), true); ultrasparc -> []; x86 -> [] end. @@ -301,6 +301,7 @@ mk_trampoline_map(CalleeMFAs, Trampolines) -> SizeofLong = case erlang:system_info(hipe_architecture) of amd64 -> 8; + ppc64 -> 8; _ -> 4 end, mk_trampoline_map(tuple_size(CalleeMFAs), CalleeMFAs, @@ -625,15 +626,15 @@ patch_instr(Address, Value, Type) -> %% %% XXX: It appears this is used for inserting both code addresses %% and other data. In HiPE, code addresses are still 32-bit on -%% 64-bit machines. +%% some 64-bit machines. write_word(DataAddress, DataWord) -> case erlang:system_info(hipe_architecture) of amd64 -> hipe_bifs:write_u64(DataAddress, DataWord), DataAddress+8; - %% ppc64 -> - %% hipe_bifs:write_u64(DataAddress, DataWord), - %% DataAddress+8; + ppc64 -> + hipe_bifs:write_u64(DataAddress, DataWord), + DataAddress+8; _ -> hipe_bifs:write_u32(DataAddress, DataWord), DataAddress+4 diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 327e0f93f1..5649188c38 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -63,7 +63,8 @@ %% timer interface -export([start_timer/1, timeout/1, timeout/2, stop_timer/1]). --export_type([ip_address/0, socket/0]). +-export_type([family_option/0, hostent/0, hostname/0, ip4_address/0, + ip6_address/0, ip_address/0, posix/0, socket/0]). %% imports -import(lists, [append/1, duplicate/2, filter/2, foldl/3]). @@ -79,8 +80,16 @@ %%% --------------------------------- %%% Contract type definitions + +-type hostent() :: #hostent{}. +-type hostname() :: atom() | string(). +-type ip4_address() :: {0..255,0..255,0..255,0..255}. +-type ip6_address() :: {0..65535,0..65535,0..65535,0..65535, + 0..65535,0..65535,0..65535,0..65535}. +-type ip_address() :: ip4_address() | ip6_address(). +-type ip_port() :: 0..65535. +-type posix() :: exbadport | exbadseq | file:posix(). -type socket() :: port(). --type posix() :: atom(). -type socket_setopt() :: {'raw', non_neg_integer(), non_neg_integer(), binary()} | @@ -106,7 +115,7 @@ {'packet', 0 | 1 | 2 | 4 | 'raw' | 'sunrm' | 'asn1' | 'cdr' | 'fcgi' | 'line' | 'tpkt' | 'http' | 'httph' | 'http_bin' | 'httph_bin' } | - {'mode', list() | binary()} | + {'mode', 'list' | 'binary'} | {'port', 'port', 'term'} | {'exit_on_close', boolean()} | {'low_watermark', non_neg_integer()} | @@ -195,12 +204,13 @@ %%% --------------------------------- --spec get_rc() -> [{any(),any()}]. +-spec get_rc() -> [{Par :: any(), Val :: any()}]. get_rc() -> inet_db:get_rc(). --spec close(Socket :: socket()) -> 'ok'. +-spec close(Socket) -> 'ok' when + Socket :: socket(). close(Socket) -> prim_inet:close(Socket), @@ -211,8 +221,10 @@ close(Socket) -> ok end. --spec peername(Socket :: socket()) -> - {'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}. +-spec peername(Socket) -> {ok, {Address, Port}} | {error, posix()} when + Socket :: socket(), + Address :: ip_address(), + Port :: non_neg_integer(). peername(Socket) -> prim_inet:peername(Socket). @@ -226,8 +238,10 @@ setpeername(Socket, undefined) -> prim_inet:setpeername(Socket, undefined). --spec sockname(Socket :: socket()) -> - {'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}. +-spec sockname(Socket) -> {ok, {Address, Port}} | {error, posix()} when + Socket :: socket(), + Address :: ip_address(), + Port :: non_neg_integer(). sockname(Socket) -> prim_inet:sockname(Socket). @@ -260,8 +274,10 @@ send(Socket, Packet) -> setopts(Socket, Opts) -> prim_inet:setopts(Socket, Opts). --spec getopts(Socket :: socket(), Opts :: [socket_getopt()]) -> - {'ok', [socket_setopt()]} | {'error', posix()}. +-spec getopts(Socket, Options) -> + {'ok', [socket_setopt()]} | {'error', posix()} when + Socket :: socket(), + Options :: [socket_getopt()]. getopts(Socket, Opts) -> prim_inet:getopts(Socket, Opts). @@ -272,7 +288,19 @@ getopts(Socket, Opts) -> getifaddrs(Socket) -> prim_inet:getifaddrs(Socket). --spec getifaddrs() -> {'ok', [string()]} | {'error', posix()}. +-spec getifaddrs() -> {ok, Iflist} | {error, posix()} when + Iflist :: [{Ifname,[Ifopt]}], + Ifname :: string(), + Ifopt :: {flag,[Flag]} | {addr,Addr} | {netmask,Netmask} + | {broadaddr,Broadaddr} | {dstaddr,Dstaddr} + | {hwaddr,Hwaddr}, + Flag :: up | broadcast | loopback | pointtopoint + | running | multicast, + Addr :: ip_address(), + Netmask :: ip_address(), + Broadaddr :: ip_address(), + Dstaddr :: ip_address(), + Hwaddr :: [byte()]. getifaddrs() -> withsocket(fun(S) -> prim_inet:getifaddrs(S) end). @@ -371,7 +399,8 @@ popf(_Socket) -> % use of the DHCP-protocol % should never fail --spec gethostname() -> {'ok', string()}. +-spec gethostname() -> {'ok', Hostname} when + Hostname :: string(). gethostname() -> case inet_udp:open(0,[]) of @@ -402,19 +431,23 @@ getstat(Socket) -> getstat(Socket,What) -> prim_inet:getstat(Socket, What). --spec gethostbyname(Name :: string() | atom()) -> - {'ok', #hostent{}} | {'error', posix()}. +-spec gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()} when + Hostname :: hostname(), + Hostent :: hostent(). gethostbyname(Name) -> gethostbyname_tm(Name, inet, false). --spec gethostbyname(Name :: string() | atom(), Family :: family_option()) -> - {'ok', #hostent{}} | {'error', posix()}. +-spec gethostbyname(Hostname, Family) -> + {ok, Hostent} | {error, posix()} when + Hostname :: hostname(), + Family :: family_option(), + Hostent :: hostent(). gethostbyname(Name,Family) -> gethostbyname_tm(Name, Family, false). --spec gethostbyname(Name :: string() | atom(), +-spec gethostbyname(Name :: hostname(), Family :: family_option(), Timeout :: non_neg_integer() | 'infinity') -> {'ok', #hostent{}} | {'error', posix()}. @@ -439,8 +472,9 @@ gethostbyname_tm(Name,Family,Timer) -> gethostbyname_tm(Name, Family, Timer, Opts). --spec gethostbyaddr(Address :: string() | ip_address()) -> - {'ok', #hostent{}} | {'error', posix()}. +-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()} when + Address :: string() | ip_address(), + Hostent :: hostent(). gethostbyaddr(Address) -> gethostbyaddr_tm(Address, false). @@ -491,14 +525,15 @@ getfd(Socket) -> %% Lookup an ip address %% --spec getaddr(Host :: ip_address() | string() | atom(), - Family :: family_option()) -> - {'ok', ip_address()} | {'error', posix()}. +-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()} when + Host :: ip_address() | hostname(), + Family :: family_option(), + Address :: ip_address(). getaddr(Address, Family) -> getaddr(Address, Family, infinity). --spec getaddr(Host :: ip_address() | string() | atom(), +-spec getaddr(Host :: ip_address() | hostname(), Family :: family_option(), Timeout :: non_neg_integer() | 'infinity') -> {'ok', ip_address()} | {'error', posix()}. @@ -515,9 +550,11 @@ getaddr_tm(Address, Family, Timer) -> Error -> Error end. --spec getaddrs(Host :: ip_address() | string() | atom(), - Family :: family_option()) -> - {'ok', [ip_address()]} | {'error', posix()}. +-spec getaddrs(Host, Family) -> + {ok, Addresses} | {error, posix()} when + Host :: ip_address() | hostname(), + Family :: family_option(), + Addresses :: [ip_address()]. getaddrs(Address, Family) -> getaddrs(Address, Family, infinity). @@ -1237,7 +1274,8 @@ port_list(Name) -> %% utils %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec format_error(posix()) -> string(). +-spec format_error(Posix) -> string() when + Posix :: posix(). format_error(exbadport) -> "invalid port state"; format_error(exbadseq) -> "bad command sequence"; diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl index de0f23bf24..2276ddcd08 100644 --- a/lib/kernel/src/inet_res.erl +++ b/lib/kernel/src/inet_res.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -47,18 +47,93 @@ false -> ok end). +-type res_option() :: + {alt_nameservers, [nameserver()]} + | {edns, 0 | false} + | {inet6, boolean()} + | {nameservers, [nameserver()]} + | {recurse, boolean()} + | {retry, integer()} + | {timeout, integer()} + | {udp_payload_size, integer()} + | {usevc, boolean()}. + +-type nameserver() :: {inet:ip_address(), Port :: 1..65535}. + +-type res_error() :: formerr | qfmterror | servfail | nxdomain | + notimp | refused | badvers | timeout. + +-type dns_name() :: string(). + +-type rr_type() :: a | aaaa | cname | gid | hinfo | ns | mb | md | mg | mf + | minfo | mx | naptr | null | ptr | soa | spf | srv | txt + | uid | uinfo | unspec | wks. + +-type dns_class() :: in | chaos | hs | any. + +-opaque dns_msg() :: term(). + +-type dns_data() :: + dns_name() + | inet:ip4_address() + | inet:ip6_address() + | {MName :: dns_name(), + RName :: dns_name(), + Serial :: integer(), + Refresh :: integer(), + Retry :: integer(), + Expiry :: integer(), + Minimum :: integer()} + | {inet:ip4_address(), Proto :: integer(), BitMap :: binary()} + | {CpuString :: string(), OsString :: string()} + | {RM :: dns_name(), EM :: dns_name()} + | {Prio :: integer(), dns_name()} + | {Prio :: integer(),Weight :: integer(),Port :: integer(),dns_name()} + | {Order :: integer(),Preference :: integer(),Flags :: string(), + Services :: string(),Regexp :: string(), dns_name()} + | [string()] + | binary(). + %% -------------------------------------------------------------------------- %% resolve: %% %% Nameserver query %% +-spec resolve(Name, Class, Type) -> {ok, dns_msg()} | Error when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Error :: {error, Reason} | {error,{Reason,dns_msg()}}, + Reason :: inet:posix() | res_error(). + resolve(Name, Class, Type) -> resolve(Name, Class, Type, [], infinity). +-spec resolve(Name, Class, Type, Opts) -> + {ok, dns_msg()} | Error when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Opts :: [Opt], + Opt :: res_option() | verbose | atom(), + Error :: {error, Reason} | {error,{Reason,dns_msg()}}, + Reason :: inet:posix() | res_error(). + resolve(Name, Class, Type, Opts) -> resolve(Name, Class, Type, Opts, infinity). +-spec resolve(Name, Class, Type, Opts, Timeout) -> + {ok, dns_msg()} | Error when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Opts :: [Opt], + Opt :: res_option() | verbose | atom(), + Timeout :: timeout(), + Error :: {error, Reason} | {error,{Reason,dns_msg()}}, + Reason :: inet:posix() | res_error(). + resolve(Name, Class, Type, Opts, Timeout) -> case nsdname(Name) of {ok, Nm} -> @@ -76,12 +151,30 @@ resolve(Name, Class, Type, Opts, Timeout) -> %% Convenience wrapper to resolve/3,4,5 that filters out all answer data %% fields of the class and type asked for. +-spec lookup(Name, Class, Type) -> [dns_data()] when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(). + lookup(Name, Class, Type) -> lookup(Name, Class, Type, []). +-spec lookup(Name, Class, Type, Opts) -> [dns_data()] when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Opts :: [res_option() | verbose]. + lookup(Name, Class, Type, Opts) -> lookup(Name, Class, Type, Opts, infinity). +-spec lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()] when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Opts :: [res_option() | verbose], + Timeout :: timeout(). + lookup(Name, Class, Type, Opts, Timeout) -> lookup_filter(resolve(Name, Class, Type, Opts, Timeout), Class, Type). @@ -101,17 +194,55 @@ lookup_filter({error,_}, _, _) -> []. %% %% To be deprecated +-spec nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason} when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Reason :: inet:posix() | res_error(). + nslookup(Name, Class, Type) -> do_nslookup(Name, Class, Type, [], infinity). +-spec nslookup(Name, Class, Type, Timeout) -> + {ok, dns_msg()} | {error, Reason} when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Timeout :: timeout(), + Reason :: inet:posix() | res_error(); + (Name, Class, Type, Nameservers) -> + {ok, dns_msg()} | {error, Reason} when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Nameservers :: [nameserver()], + Reason :: inet:posix() | res_error(). + nslookup(Name, Class, Type, Timeout) when is_integer(Timeout), Timeout >= 0 -> do_nslookup(Name, Class, Type, [], Timeout); nslookup(Name, Class, Type, NSs) -> % For backwards compatibility nnslookup(Name, Class, Type, NSs). % with OTP R6B only +-spec nnslookup(Name, Class, Type, Nameservers) -> + {ok, dns_msg()} | {error, Reason} when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Nameservers :: [nameserver()], + Reason :: inet:posix(). + nnslookup(Name, Class, Type, NSs) -> nnslookup(Name, Class, Type, NSs, infinity). +-spec nnslookup(Name, Class, Type, Nameservers, Timeout) -> + {ok, dns_msg()} | {error, Reason} when + Name :: dns_name() | inet:ip_address(), + Class :: dns_class(), + Type :: rr_type(), + Timeout :: timeout(), + Nameservers :: [nameserver()], + Reason :: inet:posix(). + nnslookup(Name, Class, Type, NSs, Timeout) -> do_nslookup(Name, Class, Type, [{nameservers,NSs}], Timeout). @@ -192,8 +323,19 @@ make_options(Opts, [Name|Names]) -> %% %% -------------------------------------------------------------------------- +-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, Reason} when + Address :: inet:ip_address(), + Hostent :: inet:hostent(), + Reason :: inet:posix() | res_error(). + gethostbyaddr(IP) -> gethostbyaddr_tm(IP,false). +-spec gethostbyaddr(Address, Timeout) -> {ok, Hostent} | {error, Reason} when + Address :: inet:ip_address(), + Timeout :: timeout(), + Hostent :: inet:hostent(), + Reason :: inet:posix() | res_error(). + gethostbyaddr(IP,Timeout) -> Timer = inet:start_timer(Timeout), Res = gethostbyaddr_tm(IP,Timer), @@ -249,6 +391,11 @@ res_gethostbyaddr(Addr, IP, Timer) -> %% Caches the answer. %% -------------------------------------------------------------------------- +-spec gethostbyname(Name) -> {ok, Hostent} | {error, Reason} when + Name :: dns_name(), + Hostent :: inet:hostent(), + Reason :: inet:posix() | res_error(). + gethostbyname(Name) -> case inet_db:res_option(inet6) of true -> @@ -257,9 +404,23 @@ gethostbyname(Name) -> gethostbyname_tm(Name, inet, false) end. +-spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason} when + Name :: dns_name(), + Hostent :: inet:hostent(), + Family :: inet:family_option(), + Reason :: inet:posix() | res_error(). + gethostbyname(Name,Family) -> gethostbyname_tm(Name,Family,false). +-spec gethostbyname(Name, Family, Timeout) -> + {ok, Hostent} | {error, Reason} when + Name :: dns_name(), + Hostent :: inet:hostent(), + Timeout :: timeout(), + Family :: inet:family_option(), + Reason :: inet:posix() | res_error(). + gethostbyname(Name,Family,Timeout) -> Timer = inet:start_timer(Timeout), Res = gethostbyname_tm(Name,Family,Timer), @@ -298,14 +459,27 @@ gethostbyname_tm(_Name, _Family, _Timer) -> %% %% getbyname(domain_name(), Type) => {ok, hostent()} | {error, Reason} %% -%% where domain_name() is domain string or atom and Type is ?S_A, ?S_MX ... +%% where domain_name() is domain string and Type is ?S_A, ?S_MX ... %% %% Caches the answer. %% -------------------------------------------------------------------------- +-spec getbyname(Name, Type) -> {ok, Hostent} | {error, Reason} when + Name :: dns_name(), + Type :: rr_type(), + Hostent :: inet:hostent(), + Reason :: inet:posix() | res_error(). + getbyname(Name, Type) -> getbyname_tm(Name,Type,false). +-spec getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason} when + Name :: dns_name(), + Type :: rr_type(), + Timeout :: timeout(), + Hostent :: inet:hostent(), + Reason :: inet:posix() | res_error(). + getbyname(Name, Type, Timeout) -> Timer = inet:start_timer(Timeout), Res = getbyname_tm(Name, Type, Timer), @@ -539,27 +713,41 @@ udp_send(#sock{inet=I}, {A,B,C,D}=IP, Port, Buffer) when ?ip(A,B,C,D), ?port(Port) -> gen_udp:send(I, IP, Port, Buffer). -udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout) +udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout, Decode) when ?ip6(A,B,C,D,E,F,G,H), ?port(Port) -> - do_udp_recv(fun(T) -> gen_udp:recv(I, 0, T) end, IP, Port, Timeout); -udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout) + do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout); +udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout, Decode) when ?ip(A,B,C,D), ?port(Port) -> - do_udp_recv(fun(T) -> gen_udp:recv(I, 0, T) end, IP, Port, Timeout). - -do_udp_recv(Recv, IP, Port, Timeout) -> - do_udp_recv(Recv, IP, Port, Timeout, - if Timeout =/= 0 -> erlang:now(); true -> undefined end). - -do_udp_recv(Recv, IP, Port, Timeout, Then) -> - case Recv(Timeout) of - {ok,{IP,Port,Answer}} -> - {ok,Answer,erlang:max(0, Timeout - now_ms(erlang:now(), Then))}; - {ok,_} when Timeout =:= 0 -> - {error,timeout}; - {ok,_} -> - Now = erlang:now(), - T = erlang:max(0, Timeout - now_ms(Now, Then)), - do_udp_recv(Recv, IP, Port, T, Now); + do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout). + +do_udp_recv(_I, _IP, _Port, 0, _Decode, _Start, _T) -> + timeout; +do_udp_recv(I, IP, Port, Timeout, Decode, Start, T) -> + case gen_udp:recv(I, 0, T) of + {ok,Reply} -> + case Decode(Reply) of + false when T =:= 0 -> + %% This is a compromize between the hard way i.e + %% in the clause below if NewT becomes 0 bailout + %% immediately and risk that the right reply lies + %% ahead after some bad id replies, and the + %% forgiving way i.e go on with Timeout 0 until + %% the right reply comes or no reply (timeout) + %% which opens for a DOS attack by a malicious + %% DNS server flooding with bad id replies causing + %% an infinite loop here. + %% + %% Timeout is used as a sanity limit counter + %% just to put an end to the loop. + NewTimeout = erlang:max(0, Timeout - 50), + do_udp_recv(I, IP, Port, NewTimeout, Decode, Start, T); + false -> + Now = erlang:now(), + NewT = erlang:max(0, Timeout - now_ms(Now, Start)), + do_udp_recv(I, IP, Port, Timeout, Decode, Start, NewT); + Result -> + Result + end; Error -> Error end. @@ -580,6 +768,17 @@ udp_close(#sock{inet=I,inet6=I6}) -> %% end %% end %% +%% But that man page also says dig always use num_servers = 1. +%% +%% Our man page says: timeout/retry, then double for next retry, i.e +%% for i = 0 to retry - 1 +%% foreach nameserver +%% send query +%% wait((time * (2**i)) / retry) +%% end +%% end +%% +%% And that is what the code seems to do, now fixed, hopefully... do_query(_Q, [], _Timer) -> {error,nxdomain}; @@ -589,19 +788,16 @@ do_query(#q{options=#options{retry=Retry}}=Q, NSs, Timer) -> query_retries(_Q, _NSs, _Timer, Retry, Retry, S) -> udp_close(S), {error,timeout}; +query_retries(_Q, [], _Timer, _Retry, _I, S) -> + udp_close(S), + {error,timeout}; query_retries(Q, NSs, Timer, Retry, I, S0) -> - Num = length(NSs), - if Num =:= 0 -> - udp_close(S0), - {error,timeout}; - true -> - case query_nss(Q, NSs, Timer, Retry, I, S0, []) of - {S,{noanswer,ErrNSs}} -> %% remove unreachable nameservers - query_retries(Q, NSs--ErrNSs, Timer, Retry, I+1, S); - {S,Result} -> - udp_close(S), - Result - end + case query_nss(Q, NSs, Timer, Retry, I, S0, []) of + {S,{noanswer,ErrNSs}} -> %% remove unreachable nameservers + query_retries(Q, NSs--ErrNSs, Timer, Retry, I+1, S); + {S,Result} -> + udp_close(S), + Result end. query_nss(_Q, [], _Timer, _Retry, _I, S, ErrNSs) -> @@ -611,13 +807,13 @@ query_nss(#q{edns=undefined}=Q, NSs, Timer, Retry, I, S, ErrNSs) -> query_nss(Q, NSs, Timer, Retry, I, S, ErrNSs) -> query_nss_edns(Q, NSs, Timer, Retry, I, S, ErrNSs). -query_nss_edns(#q{options=#options{udp_payload_size=PSz}=Options, - edns={Id,Buffer}}=Q, - [{IP,Port}=NS|NSs]=NSs0, Timer, Retry, I, S0, ErrNSs) -> - {S,Res}=Reply = query_ns(S0, Id, Buffer, IP, Port, Timer, - Retry, I, Options, PSz), +query_nss_edns( + #q{options=#options{udp_payload_size=PSz}=Options,edns={Id,Buffer}}=Q, + [{IP,Port}=NS|NSs]=NSs0, Timer, Retry, I, S0, ErrNSs) -> + {S,Res}=Reply = + query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I, Options, PSz), case Res of - timeout -> {S,{error,timeout}}; + timeout -> {S,{error,timeout}}; % Bailout timeout {ok,_} -> Reply; {error,{nxdomain,_}} -> Reply; {error,{E,_}} when E =:= qfmterror; E =:= notimp; E =:= servfail; @@ -629,17 +825,19 @@ query_nss_edns(#q{options=#options{udp_payload_size=PSz}=Options, query_nss(Q, NSs, Timer, Retry, I, S, ErrNSs) end. -query_nss_dns(#q{dns=Qdns}=Q0, [{IP,Port}=NS|NSs], - Timer, Retry, I, S0, ErrNSs) -> +query_nss_dns( + #q{dns=Qdns}=Q0, + [{IP,Port}=NS|NSs], Timer, Retry, I, S0, ErrNSs) -> #q{options=Options,dns={Id,Buffer}}=Q = if is_function(Qdns, 0) -> Q0#q{dns=Qdns()}; true -> Q0 end, - {S,Res}=Reply = query_ns(S0, Id, Buffer, IP, Port, Timer, - Retry, I, Options, ?PACKETSZ), + {S,Res}=Reply = + query_ns( + S0, Id, Buffer, IP, Port, Timer, Retry, I, Options, ?PACKETSZ), case Res of - timeout -> {S,{error,timeout}}; + timeout -> {S,{error,timeout}}; % Bailout timeout {ok,_} -> Reply; {error,{E,_}} when E =:= nxdomain; E =:= qfmterror -> Reply; {error,E} when E =:= fmt; E =:= enetunreach; E =:= econnrefused -> @@ -653,48 +851,66 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I, PSz) -> case UseVC orelse iolist_size(Buffer) > PSz of true -> - {S0,query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose)}; + TcpTimeout = inet:timeout(Tm*5, Timer), + {S0,query_tcp(TcpTimeout, Id, Buffer, IP, Port, Verbose)}; false -> case udp_open(S0, IP) of {ok,S} -> - {S,case query_udp(S, Id, Buffer, IP, Port, Timer, - Retry, I, Tm, Verbose) of - {ok,#dns_rec{header=H}} when H#dns_header.tc -> - query_tcp(Tm, Id, Buffer, - IP, Port, Timer, Verbose); - Reply -> Reply - end}; + Timeout = + inet:timeout( (Tm * (1 bsl I)) div Retry, Timer), + {S, + case query_udp( + S, Id, Buffer, IP, Port, Timeout, Verbose) of + {ok,#dns_rec{header=H}} when H#dns_header.tc -> + TcpTimeout = inet:timeout(Tm*5, Timer), + query_tcp( + TcpTimeout, Id, Buffer, IP, Port, Verbose); + Reply -> Reply + end}; Error -> {S0,Error} end end. -query_udp(S, Id, Buffer, IP, Port, Timer, Retry, I, Tm, Verbose) -> - Timeout = inet:timeout( (Tm * (1 bsl I)) div Retry, Timer), +query_udp(_S, _Id, _Buffer, _IP, _Port, 0, _Verbose) -> + timeout; +query_udp(S, Id, Buffer, IP, Port, Timeout, Verbose) -> ?verbose(Verbose, "Try UDP server : ~p:~p (timeout=~w)\n", - [IP, Port, Timeout]), - udp_connect(S, IP, Port), - udp_send(S, IP, Port, Buffer), - query_udp_recv(S, IP, Port, Id, Timeout, Verbose). - -query_udp_recv(S, IP, Port, Id, Timeout, Verbose) -> - case udp_recv(S, IP, Port, Timeout) of - {ok,Answer,T} -> - case decode_answer(Answer, Id, Verbose) of - {error, badid} -> - query_udp_recv(S, IP, Port, Id, T, Verbose); - Reply -> Reply + [IP,Port,Timeout]), + case + case udp_connect(S, IP, Port) of + ok -> + udp_send(S, IP, Port, Buffer); + E1 -> + E1 end of + ok -> + Decode = + fun ({RecIP,RecPort,Answer}) + when RecIP =:= IP, RecPort =:= Port -> + case decode_answer(Answer, Id, Verbose) of + {error,badid} -> + false; + Reply -> + Reply + end; + ({_,_,_}) -> + false + end, + case udp_recv(S, IP, Port, Timeout, Decode) of + {ok,_}=Result -> + Result; + E2 -> + ?verbose(Verbose, "UDP server error: ~p\n", [E2]), + E2 end; - {error, timeout} when Timeout =:= 0 -> - ?verbose(Verbose, "UDP server timeout\n", []), - timeout; - Error -> - ?verbose(Verbose, "UDP server error: ~p\n", [Error]), - Error + E3 -> + ?verbose(Verbose, "UDP send failed: ~p\n", [E3]), + {error,econnrefused} end. -query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose) -> - Timeout = inet:timeout(Tm*5, Timer), +query_tcp(0, _Id, _Buffer, _IP, _Port, _Verbose) -> + timeout; +query_tcp(Timeout, Id, Buffer, IP, Port, Verbose) -> ?verbose(Verbose, "Try TCP server : ~p:~p (timeout=~w)\n", [IP, Port, Timeout]), Family = case IP of @@ -716,19 +932,10 @@ query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose) -> end; Error -> gen_tcp:close(S), - case Error of - {error, timeout} when Timeout =:= 0 -> - ?verbose(Verbose, "TCP server recv timeout\n", []), - timeout; - _ -> - ?verbose(Verbose, "TCP server recv error: ~p\n", - [Error]), - Error - end + ?verbose(Verbose, "TCP server recv error: ~p\n", + [Error]), + Error end; - {error, timeout} when Timeout =:= 0 -> - ?verbose(Verbose, "TCP server connect timeout\n", []), - timeout; Error -> ?verbose(Verbose, "TCP server error: ~p\n", [Error]), Error diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl index 9a4089ab19..60bd96f332 100644 --- a/lib/kernel/src/inet_udp.erl +++ b/lib/kernel/src/inet_udp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -39,8 +39,10 @@ getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,udp). getaddr(Address) -> inet:getaddr(Address, inet). getaddr(Address,Timer) -> inet:getaddr_tm(Address, inet, Timer). +-spec open(_) -> {ok, inet:socket()} | {error, atom()}. open(Port) -> open(Port, []). +-spec open(_, _) -> {ok, inet:socket()} | {error, atom()}. open(Port, Opts) -> case inet:udp_options( [{port,Port}, {recbuf, ?RECBUF} | Opts], @@ -69,6 +71,8 @@ recv(S,Len) -> recv(S,Len,Time) -> prim_inet:recvfrom(S, Len, Time). +-spec close(inet:socket()) -> ok. + close(S) -> inet:udp_close(S). diff --git a/lib/kernel/src/net_adm.erl b/lib/kernel/src/net_adm.erl index 737b1ecee9..9b2dac9544 100644 --- a/lib/kernel/src/net_adm.erl +++ b/lib/kernel/src/net_adm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -35,7 +35,11 @@ %% Try to read .hosts.erlang file in %% 1. cwd , 2. $HOME 3. init:root_dir() --spec host_file() -> [atom()] | {'error',atom() | {integer(),atom(),_}}. +-spec host_file() -> Hosts | {error, Reason} when + Hosts :: [Host :: atom()], + %% Copied from file:path_consult/2: + Reason :: file:posix() | badarg | terminated | system_limit + | {Line :: integer(), Mod :: module(), Term :: term()}. host_file() -> Home = case init:get_argument(home) of @@ -50,7 +54,8 @@ host_file() -> %% Check whether a node is up or down %% side effect: set up a connection to Node if there not yet is one. --spec ping(atom()) -> 'pang' | 'pong'. +-spec ping(Node) -> pong | pang when + Node :: atom(). ping(Node) when is_atom(Node) -> case catch gen:call({net_kernel, Node}, @@ -63,7 +68,8 @@ ping(Node) when is_atom(Node) -> pang end. --spec localhost() -> string(). +-spec localhost() -> Name when + Name :: string(). localhost() -> {ok, Host} = inet:gethostname(), @@ -73,12 +79,20 @@ localhost() -> end. --spec names() -> {'ok', [{string(), integer()}]} | {'error', _}. +-spec names() -> {ok, [{Name, Port}]} | {error, Reason} when + Name :: string(), + Port :: non_neg_integer(), + Reason :: address | file:posix(). names() -> names(localhost()). --spec names(atom() | string()) -> {'ok', [{string(), integer()}]} | {'error', _}. + +-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason} when + Host :: atom() | string(), + Name :: string(), + Port :: non_neg_integer(), + Reason :: address | file:posix(). names(Hostname) -> case inet:gethostbyname(Hostname) of @@ -88,8 +102,9 @@ names(Hostname) -> Else end. --spec dns_hostname(atom() | string()) -> - {'ok', string()} | {'error', atom() | string()}. +-spec dns_hostname(Host) -> {ok, Name} | {error, Host} when + Host :: atom() | string(), + Name :: string(). dns_hostname(Hostname) -> case inet:gethostbyname(Hostname) of @@ -164,7 +179,8 @@ collect_new(Sofar, Nodelist) -> world() -> world(silent). --spec world(verbosity()) -> [node()]. +-spec world(Arg) -> [node()] when + Arg :: verbosity(). world(Verbose) -> case net_adm:host_file() of @@ -172,12 +188,15 @@ world(Verbose) -> Hosts -> expand_hosts(Hosts, Verbose) end. --spec world_list([atom()]) -> [node()]. +-spec world_list(Hosts) -> [node()] when + Hosts :: [atom()]. world_list(Hosts) when is_list(Hosts) -> expand_hosts(Hosts, silent). --spec world_list([atom()], verbosity()) -> [node()]. +-spec world_list(Hosts, Arg) -> [node()] when + Hosts :: [atom()], + Arg :: verbosity(). world_list(Hosts, Verbose) when is_list(Hosts) -> expand_hosts(Hosts, Verbose). diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index 49a02359b0..9e3d730cee 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -145,8 +145,15 @@ %% Interface functions kernel_apply(M,F,A) -> request({apply,M,F,A}). + +-spec allow(Nodes) -> ok | error when + Nodes :: [node()]. allow(Nodes) -> request({allow, Nodes}). + longnames() -> request(longnames). + +-spec stop() -> ok | {error, Reason} when + Reason :: not_allowed | not_found. stop() -> erl_distribution:stop(). node_info(Node) -> get_node_info(Node). @@ -158,10 +165,28 @@ i(Node) -> print_info(Node). verbose(Level) when is_integer(Level) -> request({verbose, Level}). +-spec set_net_ticktime(NetTicktime, TransitionPeriod) -> Res when + NetTicktime :: pos_integer(), + TransitionPeriod :: non_neg_integer(), + Res :: unchanged + | change_initiated + | {ongoing_change_to, NewNetTicktime}, + NewNetTicktime :: pos_integer(). set_net_ticktime(T, TP) when is_integer(T), T > 0, is_integer(TP), TP >= 0 -> ticktime_res(request({new_ticktime, T*250, TP*1000})). + +-spec set_net_ticktime(NetTicktime) -> Res when + NetTicktime :: pos_integer(), + Res :: unchanged + | change_initiated + | {ongoing_change_to, NewNetTicktime}, + NewNetTicktime :: pos_integer(). set_net_ticktime(T) when is_integer(T) -> set_net_ticktime(T, ?DEFAULT_TRANSITION_PERIOD). + +-spec get_net_ticktime() -> Res when + Res :: NetTicktime | {ongoing_change_to, NetTicktime} | ignored, + NetTicktime :: pos_integer(). get_net_ticktime() -> ticktime_res(request(ticktime)). @@ -171,6 +196,9 @@ get_net_ticktime() -> %% flags (we may want to move it elsewhere later). In order to easily %% be backward compatible, errors are created here when process_flag() %% fails. +-spec monitor_nodes(Flag) -> ok | Error when + Flag :: boolean(), + Error :: error | {error, term()}. monitor_nodes(Flag) -> case catch process_flag(monitor_nodes, Flag) of true -> ok; @@ -178,6 +206,13 @@ monitor_nodes(Flag) -> _ -> mk_monitor_nodes_error(Flag, []) end. +-spec monitor_nodes(Flag, Options) -> ok | Error when + Flag :: boolean(), + Options :: [Option], + Option :: {node_type, NodeType} + | nodedown_reason, + NodeType :: visible | hidden | all, + Error :: error | {error, term()}. monitor_nodes(Flag, Opts) -> case catch process_flag({monitor_nodes, Opts}, Flag) of true -> ok; @@ -209,6 +244,8 @@ publish_on_node(Node) when is_atom(Node) -> update_publish_nodes(Ns) -> request({update_publish_nodes, Ns}). +-spec connect_node(Node) -> boolean() | ignored when + Node :: node(). %% explicit connects connect_node(Node) when is_atom(Node) -> request({connect, normal, Node}). @@ -1249,7 +1286,7 @@ protocol_childspecs([H|T]) -> epmd_module() -> case init:get_argument(epmd_module) of {ok,[[Module]]} -> - Module; + list_to_atom(Module); _ -> erl_epmd end. diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index d1feae771d..f6769df585 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -24,7 +24,10 @@ -include("file.hrl"). --spec type() -> 'vxworks' | {'unix',atom()} | {'win32',atom()} | {'ose',atom()}. +-spec type() -> vxworks | {Osfamily, Osname} when + Osfamily :: unix | win32, + Osname :: atom(). + type() -> case erlang:system_info(os_type) of {vxworks, _} -> @@ -32,18 +35,27 @@ type() -> Else -> Else end. --spec version() -> string() | {non_neg_integer(),non_neg_integer(),non_neg_integer()}. +-spec version() -> VersionString | {Major, Minor, Release} when + VersionString :: string(), + Major :: non_neg_integer(), + Minor :: non_neg_integer(), + Release :: non_neg_integer(). version() -> erlang:system_info(os_version). --spec find_executable(string()) -> string() | 'false'. +-spec find_executable(Name) -> Filename | 'false' when + Name :: string(), + Filename :: string(). find_executable(Name) -> case os:getenv("PATH") of false -> find_executable(Name, []); Path -> find_executable(Name, Path) end. --spec find_executable(string(), string()) -> string() | 'false'. +-spec find_executable(Name, Path) -> Filename | 'false' when + Name :: string(), + Path :: string(), + Filename :: string(). find_executable(Name, Path) -> Extensions = extensions(), case filename:pathtype(Name) of @@ -147,7 +159,8 @@ extensions() -> end. %% Executes the given command in the default shell for the operating system. --spec cmd(atom() | string() | [string()]) -> string(). +-spec cmd(Command) -> string() when + Command :: atom() | io_lib:chars(). cmd(Cmd) -> validate(Cmd), case type() of diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl index 956a900adc..0d5838716e 100644 --- a/lib/kernel/src/pg2.erl +++ b/lib/kernel/src/pg2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -30,17 +30,19 @@ %%% Exported functions %%% --spec start_link() -> {'ok', pid()} | {'error', term()}. +-spec start_link() -> {'ok', pid()} | {'error', any()}. start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). --spec start() -> {'ok', pid()} | {'error', term()}. +-spec start() -> {'ok', pid()} | {'error', any()}. start() -> ensure_started(). --spec create(term()) -> 'ok'. +-type name() :: any(). + +-spec create(Name :: name()) -> 'ok'. create(Name) -> ensure_started(), @@ -55,9 +57,7 @@ create(Name) -> ok end. --type name() :: term(). - --spec delete(name()) -> 'ok'. +-spec delete(Name :: name()) -> 'ok'. delete(Name) -> ensure_started(), @@ -67,7 +67,8 @@ delete(Name) -> end), ok. --spec join(name(), pid()) -> 'ok' | {'error', {'no_such_group', term()}}. +-spec join(Name, Pid :: pid()) -> 'ok' | {'error', {'no_such_group', Name}} + when Name :: name(). join(Name, Pid) when is_pid(Pid) -> ensure_started(), @@ -83,7 +84,8 @@ join(Name, Pid) when is_pid(Pid) -> ok end. --spec leave(name(), pid()) -> 'ok' | {'error', {'no_such_group', name()}}. +-spec leave(Name, Pid :: pid()) -> 'ok' | {'error', {'no_such_group', Name}} + when Name :: name(). leave(Name, Pid) when is_pid(Pid) -> ensure_started(), @@ -99,10 +101,9 @@ leave(Name, Pid) when is_pid(Pid) -> ok end. --type get_members_ret() :: [pid()] | {'error', {'no_such_group', name()}}. +-spec get_members(Name) -> [pid()] | {'error', {'no_such_group', Name}} + when Name :: name(). --spec get_members(name()) -> get_members_ret(). - get_members(Name) -> ensure_started(), case ets:member(pg2_table, {group, Name}) of @@ -112,7 +113,8 @@ get_members(Name) -> {error, {no_such_group, Name}} end. --spec get_local_members(name()) -> get_members_ret(). +-spec get_local_members(Name) -> [pid()] | {'error', {'no_such_group', Name}} + when Name :: name(). get_local_members(Name) -> ensure_started(), @@ -123,15 +125,15 @@ get_local_members(Name) -> {error, {no_such_group, Name}} end. --spec which_groups() -> [name()]. +-spec which_groups() -> [Name :: name()]. which_groups() -> ensure_started(), all_groups(). --type gcp_error_reason() :: {'no_process', term()} | {'no_such_group', term()}. - --spec get_closest_pid(term()) -> pid() | {'error', gcp_error_reason()}. +-spec get_closest_pid(Name) -> pid() | {'error', Reason} when + Name :: name(), + Reason :: {'no_process', Name} | {'no_such_group', Name}. get_closest_pid(Name) -> case get_local_members(Name) of @@ -157,7 +159,9 @@ get_closest_pid(Name) -> -record(state, {}). --spec init([]) -> {'ok', #state{}}. +-opaque state() :: #state{}. + +-spec init(Arg :: []) -> {'ok', state()}. init([]) -> Ns = nodes(), @@ -169,13 +173,13 @@ init([]) -> pg2_table = ets:new(pg2_table, [ordered_set, protected, named_table]), {ok, #state{}}. --type call() :: {'create', name()} - | {'delete', name()} - | {'join', name(), pid()} - | {'leave', name(), pid()}. - --spec handle_call(call(), _, #state{}) -> - {'reply', 'ok', #state{}}. +-spec handle_call(Call :: {'create', Name} + | {'delete', Name} + | {'join', Name, Pid :: pid()} + | {'leave', Name, Pid :: pid()}, + From :: {pid(),Tag :: any()}, + State :: state()) -> {'reply', 'ok', state()} + when Name :: name(). handle_call({create, Name}, _From, S) -> assure_group(Name), @@ -195,11 +199,10 @@ handle_call(Request, From, S) -> [Request, From]), {noreply, S}. --type all_members() :: [[name(),...]]. --type cast() :: {'exchange', node(), all_members()} - | {'del_member', name(), pid()}. - --spec handle_cast(cast(), #state{}) -> {'noreply', #state{}}. +-spec handle_cast(Cast :: {'exchange', node(), Names :: [[Name,...]]} + | {'del_member', Name, Pid :: pid()}, + State :: state()) -> {'noreply', state()} + when Name :: name(). handle_cast({exchange, _Node, List}, S) -> store(List), @@ -208,7 +211,8 @@ handle_cast(_, S) -> %% Ignore {del_member, Name, Pid}. {noreply, S}. --spec handle_info(tuple(), #state{}) -> {'noreply', #state{}}. +-spec handle_info(Tuple :: tuple(), State :: state()) -> + {'noreply', state()}. handle_info({'DOWN', MonitorRef, process, _Pid, _Info}, S) -> member_died(MonitorRef), @@ -222,7 +226,7 @@ handle_info({new_pg2, Node}, S) -> handle_info(_, S) -> {noreply, S}. --spec terminate(term(), #state{}) -> 'ok'. +-spec terminate(Reason :: any(), State :: state()) -> 'ok'. terminate(_Reason, _S) -> true = ets:delete(pg2_table), diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index e09acb5024..be35f99ed2 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -263,14 +263,28 @@ proxy_user_flush() -> %% THE rpc client interface --spec call(node(), atom(), atom(), [term()]) -> term(). +-spec call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()], + Res :: term(), + Reason :: term(). call(N,M,F,A) when node() =:= N -> %% Optimize local call local_call(M, F, A); call(N,M,F,A) -> do_call(N, {call,M,F,A,group_leader()}, infinity). --spec call(node(), atom(), atom(), [term()], timeout()) -> term(). +-spec call(Node, Module, Function, Args, Timeout) -> + Res | {badrpc, Reason} when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()], + Res :: term(), + Reason :: term(), + Timeout :: timeout(). call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call local_call(M,F,A); @@ -279,14 +293,28 @@ call(N,M,F,A,infinity) -> call(N,M,F,A,Timeout) when is_integer(Timeout), Timeout >= 0 -> do_call(N, {call,M,F,A,group_leader()}, Timeout). --spec block_call(node(), atom(), atom(), [term()]) -> term(). +-spec block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()], + Res :: term(), + Reason :: term(). block_call(N,M,F,A) when node() =:= N -> %% Optimize local call local_call(M,F,A); block_call(N,M,F,A) -> do_call(N, {block_call,M,F,A,group_leader()}, infinity). --spec block_call(node(), atom(), atom(), [term()], timeout()) -> term(). +-spec block_call(Node, Module, Function, Args, Timeout) -> + Res | {badrpc, Reason} when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()], + Res :: term(), + Reason :: term(), + Timeout :: timeout(). block_call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call local_call(M, F, A); @@ -339,7 +367,13 @@ rpc_check(X) -> X. %% The entire call is packed into an atomic transaction which %% either succeeds or fails, i.e. never hangs (unless the server itself hangs). --spec server_call(node(), atom(), term(), term()) -> term() | {'error', 'nodedown'}. +-spec server_call(Node, Name, ReplyWrapper, Msg) -> Reply | {error, Reason} when + Node :: node(), + Name :: atom(), + ReplyWrapper :: term(), + Msg :: term(), + Reply :: term(), + Reason :: nodedown. server_call(Node, Name, ReplyWrapper, Msg) when is_atom(Node), is_atom(Name) -> @@ -362,7 +396,11 @@ server_call(Node, Name, ReplyWrapper, Msg) end end. --spec cast(node(), atom(), atom(), [term()]) -> 'true'. +-spec cast(Node, Module, Function, Args) -> true when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()]. cast(Node, Mod, Fun, Args) when Node =:= node() -> catch spawn(Mod, Fun, Args), @@ -373,12 +411,17 @@ cast(Node, Mod, Fun, Args) -> %% Asynchronous broadcast, returns nothing, it's just send'n prey --spec abcast(atom(), term()) -> 'abcast'. +-spec abcast(Name, Msg) -> abcast when + Name :: atom(), + Msg :: term(). abcast(Name, Mess) -> abcast([node() | nodes()], Name, Mess). --spec abcast([node()], atom(), term()) -> 'abcast'. +-spec abcast(Nodes, Name, Msg) -> abcast when + Nodes :: [node()], + Name :: atom(), + Msg :: term(). abcast([Node|Tail], Name, Mess) -> Dest = {Name,Node}, @@ -396,23 +439,39 @@ abcast([], _,_) -> abcast. %% message when we return from the call, we can't know that they have %% processed the message though. --spec sbcast(atom(), term()) -> {[node()], [node()]}. +-spec sbcast(Name, Msg) -> {GoodNodes, BadNodes} when + Name :: atom(), + Msg :: term(), + GoodNodes :: [node()], + BadNodes :: [node()]. sbcast(Name, Mess) -> sbcast([node() | nodes()], Name, Mess). --spec sbcast([node()], atom(), term()) -> {[node()], [node()]}. +-spec sbcast(Nodes, Name, Msg) -> {GoodNodes, BadNodes} when + Name :: atom(), + Msg :: term(), + Nodes :: [node()], + GoodNodes :: [node()], + BadNodes :: [node()]. sbcast(Nodes, Name, Mess) -> Monitors = send_nodes(Nodes, ?NAME, {sbcast, Name, Mess}, []), rec_nodes(?NAME, Monitors). --spec eval_everywhere(atom(), atom(), [term()]) -> 'abcast'. +-spec eval_everywhere(Module, Function, Args) -> abcast when + Module :: module(), + Function :: atom(), + Args :: [term()]. eval_everywhere(Mod, Fun, Args) -> eval_everywhere([node() | nodes()] , Mod, Fun, Args). --spec eval_everywhere([node()], atom(), atom(), [term()]) -> 'abcast'. +-spec eval_everywhere(Nodes, Module, Function, Args) -> abcast when + Nodes :: [node()], + Module :: module(), + Function :: atom(), + Args :: [term()]. eval_everywhere(Nodes, Mod, Fun, Args) -> gen_server:abcast(Nodes, ?NAME, {cast,Mod,Fun,Args,group_leader()}). @@ -453,20 +512,45 @@ unmonitor(Ref) when is_reference(Ref) -> %% Call apply(M,F,A) on all nodes in parallel --spec multicall(atom(), atom(), [term()]) -> {[_], [node()]}. +-spec multicall(Module, Function, Args) -> {ResL, BadNodes} when + Module :: module(), + Function :: atom(), + Args :: [term()], + ResL :: [term()], + BadNodes :: [node()]. multicall(M, F, A) -> multicall(M, F, A, infinity). --spec multicall([node()], atom(), atom(), [term()]) -> {[_], [node()]} - ; (atom(), atom(), [term()], timeout()) -> {[_], [node()]}. +-spec multicall(Nodes, Module, Function, Args) -> {ResL, BadNodes} when + Nodes :: [node()], + Module :: module(), + Function :: atom(), + Args :: [term()], + ResL :: [term()], + BadNodes :: [node()]; + (Module, Function, Args, Timeout) -> {ResL, BadNodes} when + Module :: module(), + Function :: atom(), + Args :: [term()], + Timeout :: timeout(), + ResL :: [term()], + BadNodes :: [node()]. multicall(Nodes, M, F, A) when is_list(Nodes) -> multicall(Nodes, M, F, A, infinity); multicall(M, F, A, Timeout) -> multicall([node() | nodes()], M, F, A, Timeout). --spec multicall([node()], atom(), atom(), [term()], timeout()) -> {[_], [node()]}. +-spec multicall(Nodes, Module, Function, Args, Timeout) -> + {ResL, BadNodes} when + Nodes :: [node()], + Module :: module(), + Function :: atom(), + Args :: [term()], + Timeout :: timeout(), + ResL :: [term()], + BadNodes :: [node()]. multicall(Nodes, M, F, A, infinity) when is_list(Nodes), is_atom(M), is_atom(F), is_list(A) -> @@ -495,12 +579,21 @@ do_multicall(Nodes, M, F, A, Timeout) -> %% %% There is no apparent order among the replies. --spec multi_server_call(atom(), term()) -> {[_], [node()]}. +-spec multi_server_call(Name, Msg) -> {Replies, BadNodes} when + Name :: atom(), + Msg :: term(), + Replies :: [Reply :: term()], + BadNodes :: [node()]. multi_server_call(Name, Msg) -> multi_server_call([node() | nodes()], Name, Msg). --spec multi_server_call([node()], atom(), term()) -> {[_], [node()]}. +-spec multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes} when + Nodes :: [node()], + Name :: atom(), + Msg :: term(), + Replies :: [Reply :: term()], + BadNodes :: [node()]. multi_server_call(Nodes, Name, Msg) when is_list(Nodes), is_atom(Name) -> @@ -509,9 +602,22 @@ multi_server_call(Nodes, Name, Msg) %% Deprecated functions. Were only needed when communicating with R6 nodes. +-spec safe_multi_server_call(Name, Msg) -> {Replies, BadNodes} when + Name :: atom(), + Msg :: term(), + Replies :: [Reply :: term()], + BadNodes :: [node()]. + safe_multi_server_call(Name, Msg) -> multi_server_call(Name, Msg). +-spec safe_multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes} when + Nodes :: [node()], + Name :: atom(), + Msg :: term(), + Replies :: [Reply :: term()], + BadNodes :: [node()]. + safe_multi_server_call(Nodes, Name, Msg) -> multi_server_call(Nodes, Name, Msg). @@ -539,7 +645,14 @@ rec_nodes(Name, [{N,R} | Tail], Badnodes, Replies) -> %% rpc's towards the same node. I.e. it returns immediately and %% it returns a Key that can be used in a subsequent yield(Key). --spec async_call(node(), atom(), atom(), [term()]) -> pid(). +-opaque key() :: pid(). + +-spec async_call(Node, Module, Function, Args) -> Key when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()], + Key :: key(). async_call(Node, Mod, Fun, Args) -> ReplyTo = self(), @@ -549,20 +662,27 @@ async_call(Node, Mod, Fun, Args) -> ReplyTo ! {self(), {promise_reply, R}} %% self() is key end). --spec yield(pid()) -> term(). +-spec yield(Key) -> {value, Val} | timeout when + Key :: key(), + Val :: (Res :: term()) | {badrpc, Reason :: term()}. yield(Key) when is_pid(Key) -> {value,R} = do_yield(Key, infinity), R. --spec nb_yield(pid(), timeout()) -> {'value', _} | 'timeout'. +-spec nb_yield(Key, Timeout) -> {value, Val} | timeout when + Key :: key(), + Timeout :: timeout(), + Val :: (Res :: term()) | {badrpc, Reason :: term()}. nb_yield(Key, infinity=Inf) when is_pid(Key) -> do_yield(Key, Inf); nb_yield(Key, Timeout) when is_pid(Key), is_integer(Timeout), Timeout >= 0 -> do_yield(Key, Timeout). --spec nb_yield(pid()) -> {'value', _} | 'timeout'. +-spec nb_yield(Key) -> {value, Val} | timeout when + Key :: key(), + Val :: (Res :: term()) | {badrpc, Reason :: term()}. nb_yield(Key) when is_pid(Key) -> do_yield(Key, 0). @@ -582,7 +702,12 @@ do_yield(Key, Timeout) -> %% ArgL === [{M,F,Args},........] %% Returns a lists of the evaluations in the same order as %% given to ArgL --spec parallel_eval([{atom(), atom(), [_]}]) -> [_]. +-spec parallel_eval(FuncCalls) -> ResL when + FuncCalls :: [{Module, Function, Args}], + Module :: module(), + Function :: atom(), + Args :: [term()], + ResL :: [term()]. parallel_eval(ArgL) -> Nodes = [node() | nodes()], @@ -599,7 +724,13 @@ map_nodes([{M,F,A}|Tail],[Node|MoreNodes], Original) -> %% Parallel version of lists:map/3 with exactly the same %% arguments and return value as lists:map/3, %% except that it calls exit/1 if a network error occurs. --spec pmap({atom(),atom()}, [term()], [term()]) -> [term()]. +-spec pmap(FuncSpec, ExtraArgs, List1) -> List2 when + FuncSpec :: {Module,Function}, + Module :: module(), + Function :: atom(), + ExtraArgs :: [term()], + List1 :: [Elem :: term()], + List2 :: [term()]. pmap({M,F}, As, List) -> check(parallel_eval(build_args(M,F,As, List, [])), []). @@ -616,15 +747,20 @@ check([], Ack) -> Ack. %% location transparent version of process_info --spec pinfo(pid()) -> [{atom(), _}] | 'undefined'. +-spec pinfo(Pid) -> [{Item, Info}] | undefined when + Pid :: pid(), + Item :: atom(), + Info :: term(). pinfo(Pid) when node(Pid) =:= node() -> process_info(Pid); pinfo(Pid) -> call(node(Pid), erlang, process_info, [Pid]). --spec pinfo(pid(), Item) -> {Item, _} | 'undefined' | [] - when is_subtype(Item, atom()). +-spec pinfo(Pid, Item) -> {Item, Info} | undefined | [] when + Pid :: pid(), + Item :: atom(), + Info :: term(). pinfo(Pid, Item) when node(Pid) =:= node() -> process_info(Pid, Item); diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl index 78c3040f21..ea5da2de1c 100644 --- a/lib/kernel/src/seq_trace.erl +++ b/lib/kernel/src/seq_trace.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. 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 @@ -38,15 +38,17 @@ -type flag() :: 'send' | 'receive' | 'print' | 'timestamp'. -type component() :: 'label' | 'serial' | flag(). --type value() :: non_neg_integer() - | {non_neg_integer(), non_neg_integer()} - | boolean(). --type token_pair() :: {component(), value()}. +-type value() :: (Integer :: non_neg_integer()) + | {Previous :: non_neg_integer(), + Current :: non_neg_integer()} + | (Bool :: boolean()). %%--------------------------------------------------------------------------- --type token() :: [] | {integer(), boolean(), _, _, _}. --spec set_token(token()) -> token() | 'ok'. +-opaque token() :: {integer(), boolean(), _, _, _}. +-spec set_token(Token) -> PreviousToken | 'ok' when + Token :: [] | token(), + PreviousToken :: [] | token(). set_token([]) -> erlang:seq_trace(sequential_trace_token,[]); @@ -58,28 +60,35 @@ set_token({Flags,Label,Serial,_From,Lastcnt}) -> %% expects that, the BIF can however "unofficially" handle atoms as well, and %% atoms can be used if only Erlang nodes are involved --spec set_token(component(), value()) -> token_pair(). +-spec set_token(Component, Val) -> {Component, OldVal} when + Component :: component(), + Val :: value(), + OldVal :: value(). set_token(Type, Val) -> erlang:seq_trace(Type, Val). --spec get_token() -> term(). +-spec get_token() -> [] | token(). get_token() -> element(2,process_info(self(),sequential_trace_token)). --spec get_token(component()) -> token_pair(). - +-spec get_token(Component) -> {Component, Val} when + Component :: component(), + Val :: value(). get_token(Type) -> erlang:seq_trace_info(Type). --spec print(term()) -> 'ok'. +-spec print(TraceInfo) -> 'ok' when + TraceInfo :: term(). print(Term) -> erlang:seq_trace_print(Term), ok. --spec print(integer(), term()) -> 'ok'. +-spec print(Label, TraceInfo) -> 'ok' when + Label :: integer(), + TraceInfo :: term(). print(Label, Term) when is_atom(Label) -> erlang:error(badarg, [Label, Term]); @@ -94,14 +103,17 @@ reset_trace() -> %% reset_trace(Pid) -> % this might be a useful function too --type tracer() :: pid() | port() | 'false'. +-type tracer() :: (Pid :: pid()) | port() | 'false'. --spec set_system_tracer(tracer()) -> tracer(). +-spec set_system_tracer(Tracer) -> OldTracer when + Tracer :: tracer(), + OldTracer :: tracer(). set_system_tracer(Pid) -> erlang:system_flag(sequential_tracer, Pid). --spec get_system_tracer() -> tracer(). +-spec get_system_tracer() -> Tracer when + Tracer :: tracer(). get_system_tracer() -> element(2, erlang:system_info(sequential_tracer)). diff --git a/lib/kernel/src/wrap_log_reader.erl b/lib/kernel/src/wrap_log_reader.erl index fabaa07752..c41e0091e4 100644 --- a/lib/kernel/src/wrap_log_reader.erl +++ b/lib/kernel/src/wrap_log_reader.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. 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 @@ -41,6 +41,8 @@ first_no :: non_neg_integer() | 'one' % first read file number }). +-opaque continuation() :: #wrap_reader{}. + %% %% Exported functions %% @@ -50,9 +52,11 @@ %% is not yet reached, we are on the first 'round' of filling the wrap %% files. --type open_ret() :: {'ok', #wrap_reader{}} | {'error', tuple()}. +-type open_ret() :: {'ok', Continuation :: continuation()} + | {'error', Reason :: tuple()}. --spec open(atom() | string()) -> open_ret(). +-spec open(Filename) -> open_ret() when + Filename :: string() | atom(). open(File) when is_atom(File) -> open(atom_to_list(File)); @@ -77,7 +81,9 @@ open(File) when is_list(File) -> Error end. --spec open(atom() | string(), integer()) -> open_ret(). +-spec open(Filename, N) -> open_ret() when + Filename :: string() | atom(), + N :: integer(). open(File, FileNo) when is_atom(File), is_integer(FileNo) -> open(atom_to_list(File), FileNo); @@ -100,22 +106,29 @@ open(File, FileNo) when is_list(File), is_integer(FileNo) -> Error end. --spec close(#wrap_reader{}) -> 'ok' | {'error', atom()}. +-spec close(Continuation) -> 'ok' | {'error', Reason} when + Continuation :: continuation(), + Reason :: file:posix(). close(#wrap_reader{fd = FD}) -> file:close(FD). --type chunk_ret() :: {#wrap_reader{}, [term()]} - | {#wrap_reader{}, [term()], non_neg_integer()} - | {#wrap_reader{}, 'eof'} - | {'error', term()}. +-type chunk_ret() :: {Continuation2, Terms :: [term()]} + | {Continuation2, + Terms :: [term()], + Badbytes :: non_neg_integer()} + | {Continuation2, 'eof'} + | {'error', Reason :: term()}. --spec chunk(#wrap_reader{}) -> chunk_ret(). +-spec chunk(Continuation) -> chunk_ret() when + Continuation :: continuation(). chunk(WR = #wrap_reader{}) -> chunk(WR, ?MAX_CHUNK_SIZE, 0). --spec chunk(#wrap_reader{}, 'infinity' | pos_integer()) -> chunk_ret(). +-spec chunk(Continuation, N) -> chunk_ret() when + Continuation :: continuation(), + N :: infinity | pos_integer(). chunk(WR = #wrap_reader{}, infinity) -> chunk(WR, ?MAX_CHUNK_SIZE, 0); diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 5f8f3a6bf6..95517ffd6a 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -144,7 +144,7 @@ release_tests_spec: make_emakefile $(INSTALL_DATA) $(APP_FILES) $(RELSYSDIR) $(INSTALL_DATA) kernel.spec $(EMAKEFILE)\ $(COVERFILE) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) release_docs_spec: diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 8078c7d021..2f73394c4e 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -2055,6 +2055,10 @@ try_read_file_list(Fd) -> ?line Title = "Real Programmers Don't Use PASCAL</TITLE>\n", ?line Title = io:get_line(Fd, ''), + %% Seek past the end of the file. + + ?line {ok, _} = ?FILE_MODULE:position(Fd, 25000), + %% Done. ?line ?FILE_MODULE:close(Fd), diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 3b313a6c21..b1ef8826d5 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -39,7 +39,7 @@ accept_timeouts_in_order/1,accept_timeouts_in_order2/1, accept_timeouts_in_order3/1,accept_timeouts_mixed/1, killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1, - several_accepts_in_one_go/1,active_once_closed/1, send_timeout/1, + several_accepts_in_one_go/1,active_once_closed/1, send_timeout/1, send_timeout_active/1, otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1]). %% Internal exports. @@ -71,7 +71,7 @@ all() -> accept_timeouts_in_order3, accept_timeouts_mixed, killing_acceptor, killing_multi_acceptors, killing_multi_acceptors2, several_accepts_in_one_go, - active_once_closed, send_timeout, otp_7731, + active_once_closed, send_timeout, send_timeout_active, otp_7731, zombie_sockets, otp_7816, otp_8102]. groups() -> @@ -1957,6 +1957,60 @@ send_timeout(Config) when is_list(Config) -> ParaFun(false), ParaFun(true), ok. +mad_sender(S) -> + {_, _, USec} = now(), + case gen_tcp:send(S, integer_to_list(USec)) of + ok -> + mad_sender(S); + Err -> + Err + end. + + +flush() -> + receive + _X -> + %erlang:display(_X), + flush() + after 0 -> + ok + end. + +send_timeout_active(suite) -> + []; +send_timeout_active(doc) -> + ["Test the send_timeout socket option for active sockets"]; +send_timeout_active(Config) when is_list(Config) -> + Dog = test_server:timetrap(test_server:seconds(20)), + %% Basic + BasicFun = + fun(AutoClose) -> + ?line {Loop,A,RNode,C} = setup_active_timeout_sink(1, AutoClose), + inet:setopts(A, [{active, once}]), + ?line Mad = spawn_link(RNode,fun() -> mad_sender(C) end), + ?line {error,timeout} = + Loop(fun() -> + receive + {tcp, Sock, _Data} -> + inet:setopts(A, [{active, once}]), + Res = gen_tcp:send(A,lists:duplicate(1000, $a)), + %erlang:display(Res), + Res; + Err -> + io:format("sock closed: ~p~n", [Err]), + Err + end + end), + unlink(Mad), + exit(Mad,kill), + ?line test_server:stop_node(RNode) + end, + BasicFun(false), + flush(), + BasicFun(true), + flush(), + test_server:timetrap_cancel(Dog), + ok. after_send_timeout(AutoClose) -> case AutoClose of @@ -2039,35 +2093,35 @@ setup_closed_ao() -> {Loop,A}. setup_timeout_sink(Timeout, AutoClose) -> - Dir = filename:dirname(code:which(?MODULE)), - {ok,R} = test_server:start_node(test_default_options_slave,slave, + ?line Dir = filename:dirname(code:which(?MODULE)), + ?line {ok,R} = test_server:start_node(test_default_options_slave,slave, [{args,"-pa " ++ Dir}]), - Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))), - {ok, L} = gen_tcp:listen(0, [{active,false},{packet,2}, + ?line Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))), + ?line {ok, L} = gen_tcp:listen(0, [{active,false},{packet,2}, {send_timeout,Timeout}, {send_timeout_close,AutoClose}]), - Fun = fun(F) -> + ?line Fun = fun(F) -> receive {From,X} when is_function(X) -> From ! {self(),X()}, F(F); die -> ok end end, - Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]), - {ok, Port} = inet:port(L), - Remote = fun(Fu) -> + ?line Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]), + ?line {ok, Port} = inet:port(L), + ?line Remote = fun(Fu) -> Pid ! {self(), Fu}, receive {Pid,X} -> X end end, - {ok, C} = Remote(fun() -> + ?line {ok, C} = Remote(fun() -> gen_tcp:connect(Host,Port, [{active,false},{packet,2}]) end), - {ok,A} = gen_tcp:accept(L), - gen_tcp:send(A,"Hello"), - {ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end), - Loop2 = fun(_,_,0) -> + ?line {ok,A} = gen_tcp:accept(L), + ?line gen_tcp:send(A,"Hello"), + ?line {ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end), + ?line Loop2 = fun(_,_,0) -> {failure, timeout}; (L2,F2,N) -> Ret = F2(), @@ -2078,9 +2132,53 @@ setup_timeout_sink(Timeout, AutoClose) -> Other -> Other end end, - Loop = fun(F3) -> Loop2(Loop2,F3,1000) end, + ?line Loop = fun(F3) -> Loop2(Loop2,F3,1000) end, {Loop,A,R}. - + +setup_active_timeout_sink(Timeout, AutoClose) -> + ?line Dir = filename:dirname(code:which(?MODULE)), + ?line {ok,R} = test_server:start_node(test_default_options_slave,slave, + [{args,"-pa " ++ Dir}]), + ?line Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))), + ?line {ok, L} = gen_tcp:listen(0, [binary,{active,false},{packet,0},{nodelay, true},{keepalive, true}, + {send_timeout,Timeout}, + {send_timeout_close,AutoClose}]), + ?line Fun = fun(F) -> + receive + {From,X} when is_function(X) -> + From ! {self(),X()}, F(F); + die -> ok + end + end, + ?line Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]), + ?line {ok, Port} = inet:port(L), + ?line Remote = fun(Fu) -> + Pid ! {self(), Fu}, + receive {Pid,X} -> X + end + end, + ?line {ok, C} = Remote(fun() -> + gen_tcp:connect(Host,Port, + [{active,false}]) + end), + ?line {ok,A} = gen_tcp:accept(L), + ?line gen_tcp:send(A,"Hello"), + ?line {ok, "H"++_} = Remote(fun() -> gen_tcp:recv(C,0) end), + ?line Loop2 = fun(_,_,0) -> + {failure, timeout}; + (L2,F2,N) -> + Ret = F2(), + io:format("~p~n",[Ret]), + case Ret of + ok -> receive after 1 -> ok end, + L2(L2,F2,N-1); + Other -> Other + end + end, + ?line Loop = fun(F3) -> Loop2(Loop2,F3,1000) end, + {Loop,A,R,C}. + + millistamp() -> {Mega, Secs, Micros} = erlang:now(), (Micros div 1000) + Secs * 1000 + Mega * 1000000000. diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl index 043c753cf8..233e438dc9 100644 --- a/lib/kernel/test/heart_SUITE.erl +++ b/lib/kernel/test/heart_SUITE.erl @@ -22,7 +22,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, start/1, restart/1, - reboot/1, set_cmd/1, clear_cmd/1, + reboot/1, set_cmd/1, clear_cmd/1, get_cmd/1, dont_drop/1, kill_pid/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -58,7 +58,7 @@ end_per_testcase(_Func, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [start, restart, reboot, set_cmd, clear_cmd, kill_pid]. + [start, restart, reboot, set_cmd, clear_cmd, get_cmd, kill_pid]. groups() -> []. @@ -246,6 +246,15 @@ clear_cmd(Config) when is_list(Config) -> end, ok. +get_cmd(suite) -> []; +get_cmd(Config) when is_list(Config) -> + ?line {ok, Node} = start_check(slave, heart_test), + Cmd = "test", + ?line ok = rpc:call(Node, heart, set_cmd, [Cmd]), + ?line {ok, Cmd} = rpc:call(Node, heart, get_cmd, []), + stop_node(Node), + ok. + dont_drop(suite) -> %%% Removed as it may crash epmd/distribution in colourful %%% ways. While we ARE finding out WHY, it would diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl index 5fc8df475d..6064a9b2d9 100644 --- a/lib/kernel/test/inet_res_SUITE.erl +++ b/lib/kernel/test/inet_res_SUITE.erl @@ -27,7 +27,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). --export([basic/1, resolve/1, edns0/1, txt_record/1, files_monitor/1]). +-export([basic/1, resolve/1, edns0/1, txt_record/1, files_monitor/1, + last_ms_answer/1]). -export([ gethostbyaddr/0, gethostbyaddr/1, gethostbyaddr_v6/0, gethostbyaddr_v6/1, @@ -45,6 +46,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [basic, resolve, edns0, txt_record, files_monitor, + last_ms_answer, gethostbyaddr, gethostbyaddr_v6, gethostbyname, gethostbyname_v6, getaddr, getaddr_v6, ipv4_to_ipv6, host_and_addr]. @@ -64,16 +66,15 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. -zone_dir(basic) -> - otptest; -zone_dir(resolve) -> - otptest; -zone_dir(edns0) -> - otptest; -zone_dir(files_monitor) -> - otptest; -zone_dir(_) -> - undefined. +zone_dir(TC) -> + case TC of + basic -> otptest; + resolve -> otptest; + edns0 -> otptest; + files_monitor -> otptest; + last_ms_answer -> otptest; + _ -> undefined + end. init_per_testcase(Func, Config) -> PrivDir = ?config(priv_dir, Config), @@ -184,6 +185,88 @@ ns_printlog(Fname) -> ok end. +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Behaviour modifying nameserver proxy + +proxy_start(TC, {NS,P}) -> + Tag = make_ref(), + Parent = self(), + Pid = + spawn_link( + fun () -> + try proxy_start(TC, NS, P, Parent, Tag) + catch C:X -> + io:format( + "~w: ~w:~p ~p~n", + [self(),C,X,erlang:get_stacktrace()]) + end + end), + receive {started,Tag,Port} -> + ProxyNS = {{127,0,0,1},Port}, + {proxy,Pid,Tag,ProxyNS} + end. + +proxy_start(TC, NS, P, Parent, Tag) -> + {ok,Outbound} = gen_udp:open(0, [binary]), + ok = gen_udp:connect(Outbound, NS, P), + {ok,Inbound} = gen_udp:open(0, [binary]), + {ok,Port} = inet:port(Inbound), + Parent ! {started,Tag,Port}, + proxy(TC, Outbound, NS, P, Inbound). + + +%% To provoke the last_ms_answer bug (OTP-9221) the proxy +%% * Relays the query to the right nameserver +%% * Intercepts the reply but holds it until the timer that +%% was started when receiving the query fires. +%% * Repeats the reply with incorrect query ID a number of +%% times with a short interval. +%% * Sends the correct reply, to give a correct test result +%% after bug correction. +%% +%% The repetition of an incorrect answer with tight interval will keep +%% inet_res in an inner loop in the code that decrements the remaining +%% time until it hits 0 which triggers a crash, if the outer timeout +%% parameter to inet_res:resolve is so short that it runs out during +%% these repetitions. +proxy(last_ms_answer, Outbound, NS, P, Inbound) -> + receive + {udp,Inbound,SrcIP,SrcPort,Data} -> + Time = + inet_db:res_option(timeout) div inet_db:res_option(retry), + Tag = erlang:make_ref(), + erlang:send_after(Time - 10, self(), {time,Tag}), + ok = gen_udp:send(Outbound, NS, P, Data), + receive + {udp,Outbound,NS,P,Reply} -> + {ok,Msg} = inet_dns:decode(Reply), + Hdr = inet_dns:msg(Msg, header), + Id = inet_dns:header(Hdr, id), + BadHdr = + inet_dns:make_header(Hdr, id, (Id+1) band 16#ffff), + BadMsg = inet_dns:make_msg(Msg, header, BadHdr), + BadReply = inet_dns:encode(BadMsg), + receive + {time,Tag} -> + proxy__last_ms_answer( + Inbound, SrcIP, SrcPort, BadReply, Reply, 30) + end + end + end. + +proxy__last_ms_answer(Socket, IP, Port, _, Reply, 0) -> + ok = gen_udp:send(Socket, IP, Port, Reply); +proxy__last_ms_answer(Socket, IP, Port, BadReply, Reply, N) -> + ok = gen_udp:send(Socket, IP, Port, BadReply), + receive after 1 -> ok end, + proxy__last_ms_answer(Socket, IP, Port, BadReply, Reply, N-1). + +proxy_wait({proxy,Pid,_,_}) -> + Mref = erlang:monitor(process, Pid), + receive {'DOWN',Mref,_,_,_} -> ok end. + +proxy_ns({proxy,_,_,ProxyNS}) -> ProxyNS. + %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -204,7 +287,7 @@ basic(Config) when is_list(Config) -> {ok,Msg1} = inet_dns:decode(Bin1), %% %% resolve - {ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]}]), + {ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]},verbose]), io:format("~p~n", [Msg2]), [RR2] = inet_dns:msg(Msg2, anlist), IP = inet_dns:rr(RR2, data), @@ -474,6 +557,26 @@ do_files_monitor(Config) -> ok. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +last_ms_answer(doc) -> + ["Answer just when timeout is triggered (OTP-9221)"]; +last_ms_answer(Config) when is_list(Config) -> + NS = ns(Config), + Name = "ns.otptest", + %%IP = {127,0,0,254}, + Time = inet_db:res_option(timeout) div inet_db:res_option(retry), + PSpec = proxy_start(last_ms_answer, NS), + ProxyNS = proxy_ns(PSpec), + %% + %% resolve; whith short timeout to trigger Timeout =:= 0 in inet_res + {error,timeout} = + inet_res:resolve( + Name, in, a, [{nameservers,[ProxyNS]},verbose], Time + 10), + %% + proxy_wait(PSpec), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Compatibility tests. Call the inet_SUITE tests, but with %% lookup = [file,dns] instead of [native] diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index 06bfe97bc4..2db0f7dcb8 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -24,6 +24,7 @@ init_per_group/2,end_per_group/2]). -export([get_arguments/1, get_argument/1, boot_var/1, restart/1, + many_restarts/1, get_plain_arguments/1, reboot/1, stop/1, get_status/1, script_id/1]). -export([boot1/1, boot2/1]). @@ -43,6 +44,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [get_arguments, get_argument, boot_var, + many_restarts, get_plain_arguments, restart, get_status, script_id, {group, boot}]. @@ -317,6 +319,73 @@ is_real_system(KernelVsn, StdlibVsn) -> %% Therefore the slave process must be killed %% before restart. %% ------------------------------------------------ +many_restarts(doc) -> []; +many_restarts(suite) -> + case ?t:os_type() of + {Fam, _} when Fam == unix; Fam == win32 -> + {req, [distribution, {local_slave_nodes, 1}, {time, 5}]}; + _ -> + {skip, "Only run on unix and win32"} + end; + +many_restarts(Config) when is_list(Config) -> + ?line Dog = ?t:timetrap(?t:seconds(480)), + ?line {ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC), + ?line loop_restart(30,Node,rpc:call(Node,erlang,whereis,[error_logger])), + ?line loose_node:stop(Node), + ?line ?t:timetrap_cancel(Dog), + ok. + +loop_restart(0,_,_) -> + ok; +loop_restart(N,Node,EHPid) -> + ?line erlang:monitor_node(Node, true), + ?line ok = rpc:call(Node, init, restart, []), + ?line receive + {nodedown, Node} -> + ok + after 10000 -> + loose_node:stop(Node), + ?t:fail(not_stopping) + end, + ?line ok = wait_for(30, Node, EHPid), + ?line loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[error_logger])). + +wait_for(0,Node,_) -> + loose_node:stop(Node), + error; +wait_for(N,Node,EHPid) -> + ?line case rpc:call(Node, erlang, whereis, [error_logger]) of + Pid when is_pid(Pid), Pid =/= EHPid -> + %% ?line erlang:display(ok), + ?line ok; + _X -> + %% ?line erlang:display(_X), + %% ?line Procs = rpc:call(Node, erlang, processes, []), + %% ?line erlang:display(Procs), + %% case is_list(Procs) of + %% true -> + %% ?line [(catch erlang:display( + %% rpc:call(Node, + %% erlang, + %% process_info, + %% [Y,registered_name]))) + %% || Y <- Procs]; + %% _ -> + %% ok + %% end, + receive + after 100 -> + ok + end, + ?line wait_for(N-1,Node,EHPid) + end. + +%% ------------------------------------------------ +%% Slave executes erlang:halt() on master nodedown. +%% Therefore the slave process must be killed +%% before restart. +%% ------------------------------------------------ restart(doc) -> []; restart(suite) -> case ?t:os_type() of diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index e33b90a274..e7b71cc168 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 2.14.3 +KERNEL_VSN = 2.14.4 |