Skip to content

Instantly share code, notes, and snippets.

@221V
Created February 15, 2022 19:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 221V/17046ff1cd942d4a1dee207764ff8b9d to your computer and use it in GitHub Desktop.
Save 221V/17046ff1cd942d4a1dee207764ff8b9d to your computer and use it in GitHub Desktop.
O_o erl 19.3.6.5 diff O_o
$ diff -r otp-OTP-19.3.6.5 erlang-otp-6356f67
diff -r otp-OTP-19.3.6.5/lib/inets/examples/httpd_load_test/hdlt_ssl_client_cert.pem erlang-otp-6356f67/lib/inets/examples/httpd_load_test/hdlt_ssl_client_cert.pem
1c1,31
< ../../test/httpc_SUITE_data/ssl_client_cert.pem
\ Наприкінці файла немає нового рядка
---
> -----BEGIN RSA PRIVATE KEY-----
> MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n
> 0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr
> 3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB
> AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB
> I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna
> QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f
> eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws
> /LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI
> ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV
> LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj
> 40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6
> UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80
> t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J
> -----END RSA PRIVATE KEY-----
> -----BEGIN CERTIFICATE-----
> MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
> BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
> BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
> VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
> MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
> cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
> VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
> AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV
> wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53
> h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID
> AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A
> PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD
> 4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ
> S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5
> -----END CERTIFICATE-----
diff -r otp-OTP-19.3.6.5/lib/inets/examples/httpd_load_test/hdlt_ssl_server_cert.pem erlang-otp-6356f67/lib/inets/examples/httpd_load_test/hdlt_ssl_server_cert.pem
1c1,31
< ../../test/httpc_SUITE_data/ssl_client_cert.pem
\ Наприкінці файла немає нового рядка
---
> -----BEGIN RSA PRIVATE KEY-----
> MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n
> 0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr
> 3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB
> AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB
> I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna
> QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f
> eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws
> /LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI
> ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV
> LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj
> 40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6
> UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80
> t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J
> -----END RSA PRIVATE KEY-----
> -----BEGIN CERTIFICATE-----
> MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
> BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
> BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
> VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
> MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
> cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
> VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
> AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV
> wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53
> h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID
> AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A
> PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD
> 4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ
> S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5
> -----END CERTIFICATE-----
diff -r otp-OTP-19.3.6.5/lib/inets/test/ftp_internal.hrl erlang-otp-6356f67/lib/inets/test/ftp_internal.hrl
1c1,33
< ../src/ftp/ftp_internal.hrl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 2005-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> %%
>
> -ifndef(ftp_internal_hrl).
> -define(ftp_internal_hrl, true).
>
> -include_lib("inets/src/inets_app/inets_internal.hrl").
>
> -define(SERVICE, ftpc).
> -define(fcri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
> -define(fcrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
> -define(fcrd(Label, Content), ?report_debug(Label, ?SERVICE, Content)).
> -define(fcrt(Label, Content), ?report_trace(Label, ?SERVICE, Content)).
>
> -endif. % -ifdef(ftp_internal_hrl).
diff -r otp-OTP-19.3.6.5/lib/inets/test/httpc_internal.hrl erlang-otp-6356f67/lib/inets/test/httpc_internal.hrl
1c1,177
< ../src/http_client/httpc_internal.hrl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 2005-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> %%
>
> -ifndef(httpc_internal_hrl).
> -define(httpc_internal_hrl, true).
>
> -include_lib("inets/src/inets_app/inets_internal.hrl").
>
> -define(SERVICE, httpc).
> -define(hcri(Label, Data), ?report_important(Label, ?SERVICE, Data)).
> -define(hcrv(Label, Data), ?report_verbose(Label, ?SERVICE, Data)).
> -define(hcrd(Label, Data), ?report_debug(Label, ?SERVICE, Data)).
> -define(hcrt(Label, Data), ?report_trace(Label, ?SERVICE, Data)).
>
> -define(HTTP_REQUEST_TIMEOUT, infinity).
> -define(HTTP_REQUEST_CTIMEOUT, ?HTTP_REQUEST_TIMEOUT).
> -define(HTTP_PIPELINE_TIMEOUT, 0).
> -define(HTTP_PIPELINE_LENGTH, 2).
> -define(HTTP_MAX_TCP_SESSIONS, 2).
> -define(HTTP_MAX_REDIRECTS, 4).
> -define(HTTP_KEEP_ALIVE_TIMEOUT, 120000).
> -define(HTTP_KEEP_ALIVE_LENGTH, 5).
> -define(TLS_UPGRADE_TOKEN, "TLS/1.0").
>
> %%% HTTP Client per request settings
> -record(http_options,
> {
> %% "HTTP/1.1" | "HTTP/1.0" | "HTTP/0.9"
> version :: 'undefined' | string(),
>
> %% ms before a request times out
> timeout = ?HTTP_REQUEST_TIMEOUT :: timeout(),
>
> %% true if auto redirect on 30x response
> autoredirect = true :: boolean(),
>
> %% ssl socket options
> ssl = [],
>
> %% {User, Password} = {string(), string()}
> proxy_auth,
>
> %% true if not strictly std compliant
> relaxed = false :: boolean(),
>
> %% integer() - ms before a connect times out
> connect_timeout = ?HTTP_REQUEST_CTIMEOUT :: timeout(),
>
> %% Use %-encoding rfc 2396
> url_encode :: 'undefined' | boolean()
> }
> ).
> -type http_options() :: #http_options{}.
>
> %%% HTTP Client per profile setting.
> -record(options,
> {
> proxy = {undefined, []}, % {{ProxyHost, ProxyPort}, [NoProxy]},
> https_proxy = {undefined, []}, % {{ProxyHost, ProxyPort}, [NoProxy]}
> %% 0 means persistent connections are used without pipelining
> pipeline_timeout = ?HTTP_PIPELINE_TIMEOUT,
> max_pipeline_length = ?HTTP_PIPELINE_LENGTH,
> max_keep_alive_length = ?HTTP_KEEP_ALIVE_LENGTH,
> keep_alive_timeout = ?HTTP_KEEP_ALIVE_TIMEOUT, % Used when pipeline_timeout = 0
> max_sessions = ?HTTP_MAX_TCP_SESSIONS,
> cookies = disabled, % enabled | disabled | verify
> verbose = false, % boolean(),
> ipfamily = inet, % inet | inet6 | inet6fb4
> ip = default, % specify local interface
> port = default, % specify local port
> socket_opts = [] % other socket options
> }
> ).
> -type options() :: #options{}.
>
> %%% All data associated to a specific HTTP request
> -record(request,
> {
> id :: 'undefined' | reference(), % Request Id
> from, % pid() - Caller
> redircount = 0,% Number of redirects made for this request
> scheme, % http | https
> address, % ({Host,Port}) Destination Host and Port
> path, % string() - Path of parsed URL
> pquery, % string() - Rest of parsed URL
> method, % atom() - HTTP request Method
> headers, % #http_request_h{}
> content, % {ContentType, Body} - Current HTTP request
> settings :: http_options(), % User defined settings
> abs_uri, % string() ex: "http://www.erlang.org"
> userinfo, % string() - optinal "<userinfo>@<host>:<port>"
> stream, % boolean() - stream async reply?
> headers_as_is, % boolean() - workaround for servers that does
> % not honor the http standard, can also be used
> % for testing purposes.
> started, % integer() > 0 - When we started processing the
> % request
> timer :: undefined | reference(),
> socket_opts, % undefined | [socket_option()]
> ipv6_host_with_brackets % boolean()
> }
> ).
> -type request() :: #request{}.
>
> -record(session,
> {
> %% {{Host, Port}, HandlerPid}
> id,
>
> client_close :: 'undefined' | boolean(),
>
> %% http (HTTP/TCP) | https (HTTP/SSL/TCP)
> scheme,
>
> %% Open socket, used by connection
> socket,
>
> %% socket-type, used by connection
> socket_type,
>
> %% Current length of pipeline or keep-alive queue
> queue_length = 1,
>
> %% pipeline | keep_alive (wait for response before sending new request)
> type :: 'undefined' | 'pipeline' | 'keep_alive',
>
> %% This will be true, when a response has been received for
> %% the first request. See type above.
> available = false :: boolean()
> }).
> -type session() :: #session{}.
>
> -record(http_cookie,
> {
> domain,
> domain_default = false,
> name,
> value,
> comment,
> max_age = session,
> path,
> path_default = false,
> secure = false,
> version = "0"
> }).
> -type http_cookie() :: #http_cookie{}.
>
> %% -record(parsed_uri,
> %% {
> %% scheme, % http | https
> %% uinfo, % string()
> %% host, % string()
> %% port, % integer()
> %% path, % string()
> %% q % query: string()
> %% }).
>
>
> -endif. % -ifdef(httpc_internal_hrl).
diff -r otp-OTP-19.3.6.5/lib/inets/test/httpc_SUITE_data/cgi_echo.c erlang-otp-6356f67/lib/inets/test/httpc_SUITE_data/cgi_echo.c
1c1,97
< ../httpd_SUITE_data/cgi_echo.c
\ Наприкінці файла немає нового рядка
---
> #include <stdlib.h>
> #include <stdio.h>
>
> #if defined __WIN32__
> #include <windows.h>
> #include <fcntl.h>
> #endif
>
> static int read_exact(char *buffer, int len);
> static int write_exact(char *buffer, int len);
>
> int main(void)
> {
> char msg[100];
> int msg_len;
> #ifdef __WIN32__
> _setmode(_fileno( stdin), _O_BINARY);
> _setmode(_fileno( stdout), _O_BINARY);
> #endif
> msg_len = read_exact(msg, 100);
>
> write_exact("Content-type: text/plain\r\n\r\n", 28);
> write_exact(msg, msg_len);
> exit(EXIT_SUCCESS);
> }
>
>
> /* read from stdin */
> #ifdef __WIN32__
> static int read_exact(char *buffer, int len)
> {
> HANDLE standard_input = GetStdHandle(STD_INPUT_HANDLE);
>
> unsigned read_result;
> unsigned sofar = 0;
>
> if (!len) { /* Happens for "empty packages */
> return 0;
> }
> for (;;) {
> if (!ReadFile(standard_input, buffer + sofar,
> len - sofar, &read_result, NULL)) {
> return -1; /* EOF */
> }
> if (!read_result) {
> return -2; /* Interrupted while reading? */
> }
> sofar += read_result;
> if (sofar == len) {
> return len;
> }
> }
> }
> #else
> static int read_exact(char *buffer, int len) {
> int i, got = 0;
>
> do {
> if ((i = read(0, buffer + got, len - got)) <= 0)
> return(i);
> got += i;
> } while (got < len);
> return len;
>
> }
> #endif
>
> /* write to stdout */
> #ifdef __WIN32__
> static int write_exact(char *buffer, int len)
> {
> HANDLE standard_output = GetStdHandle(STD_OUTPUT_HANDLE);
> unsigned written;
>
> if (!WriteFile(standard_output, buffer, len, &written, NULL)) {
> return -1; /* Broken Pipe */
> }
> if (written < ((unsigned) len)) {
> /* This should not happen, standard output is not blocking? */
> return -2;
> }
>
> return (int) written;
> }
>
> #else
> static int write_exact(char *buffer, int len) {
> int i, wrote = 0;
>
> do {
> if ((i = write(1, buffer + wrote, len - wrote)) <= 0)
> return i;
> wrote += i;
> } while (wrote < len);
> return len;
> }
> #endif
diff -r otp-OTP-19.3.6.5/lib/inets/test/httpc_SUITE_data/Makefile.src erlang-otp-6356f67/lib/inets/test/httpc_SUITE_data/Makefile.src
1c1,19
< ../httpd_SUITE_data/Makefile.src
\ Наприкінці файла немає нового рядка
---
> CC = @CC@
> LD = @LD@
> CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
> CROSSLDFLAGS = @CROSSLDFLAGS@
>
> PROGS = cgi_echo@exe@
>
> all: $(PROGS)
>
> cgi_echo@exe@: cgi_echo@obj@
> $(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@
>
> @IFEQ@ (@CC@, cl -nologo)
> cgi_echo@obj@: cgi_echo.c
> $(CC) /c /Focgi_echo@obj@ $(CFLAGS) cgi_echo.c
> @ELSE@
> cgi_echo@obj@: cgi_echo.c
> $(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c
> @ENDIF@
diff -r otp-OTP-19.3.6.5/lib/inets/test/httpd_basic_SUITE_data/printenv.bat erlang-otp-6356f67/lib/inets/test/httpd_basic_SUITE_data/printenv.bat
1c1,9
< ../httpd_SUITE_data/server_root/cgi-bin/printenv.bat
\ Наприкінці файла немає нового рядка
---
> @echo off
> echo tomrad > c:\cygwin\tmp\hej
> echo Content-type: text/html
> echo.
> echo ^<HTML^> ^<HEAD^> ^<TITLE^>OS Environment^</TITLE^> ^</HEAD^> ^<BODY^>^<PRE^>
> set
> echo ^</PRE^>^</BODY^>^</HTML^>
>
>
diff -r otp-OTP-19.3.6.5/lib/inets/test/httpd_basic_SUITE_data/printenv.sh erlang-otp-6356f67/lib/inets/test/httpd_basic_SUITE_data/printenv.sh
1c1,6
< ../httpd_SUITE_data/server_root/cgi-bin/printenv.sh
\ Наприкінці файла немає нового рядка
---
> #!/bin/sh
> echo "Content-type: text/html"
> echo ""
> echo "<HTML> <HEAD> <TITLE>OS Environment</TITLE> </HEAD> <BODY><PRE>"
> env
> echo "</PRE></BODY></HTML>"
\ Наприкінці файла немає нового рядка
diff -r otp-OTP-19.3.6.5/lib/inets/test/http_internal.hrl erlang-otp-6356f67/lib/inets/test/http_internal.hrl
1c1,123
< ../src/http_lib/http_internal.hrl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 2002-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> %%
>
> -ifndef(http_internal_hrl).
> -define(http_internal_hrl, true).
>
> -include_lib("inets/src/inets_app/inets_internal.hrl").
>
> -define(HTTP_MAX_BODY_SIZE, nolimit).
> -define(HTTP_MAX_HEADER_SIZE, 10240).
> -define(HTTP_MAX_URI_SIZE, nolimit).
> -define(HTTP_MAX_VERSION_STRING, 8).
> -define(HTTP_MAX_METHOD_STRING, 20).
> -define(HTTP_MAX_CONTENT_LENGTH, 100000000).
>
> -ifndef(HTTP_DEFAULT_SSL_KIND).
> -define(HTTP_DEFAULT_SSL_KIND, essl).
> -endif. % -ifdef(HTTP_DEFAULT_SSL_KIND).
>
>
> %%% Response headers
> -record(http_response_h,{
> %%% --- Standard "General" headers
> 'cache-control',
> connection,
> date,
> pragma,
> trailer,
> 'transfer-encoding',
> upgrade,
> via,
> warning,
> %%% --- Standard "Response" headers
> 'accept-ranges',
> age,
> etag,
> location,
> 'proxy-authenticate',
> 'retry-after',
> server,
> vary,
> 'www-authenticate',
> %%% --- Standard "Entity" headers
> allow,
> 'content-encoding',
> 'content-language',
> 'content-length' = "-1",
> 'content-location',
> 'content-md5',
> 'content-range',
> 'content-type',
> expires,
> 'last-modified',
> other=[] % list() - Key/Value list with other headers
> }).
> -type http_response_h() :: #http_response_h{}.
>
> %%% Request headers
> -record(http_request_h,{
> %%% --- Standard "General" headers
> 'cache-control',
> connection = "keep-alive",
> date,
> pragma,
> trailer,
> 'transfer-encoding',
> upgrade,
> via,
> warning,
> %%% --- Standard "Request" headers
> accept,
> 'accept-charset',
> 'accept-encoding',
> 'accept-language',
> authorization,
> expect,
> from,
> host,
> 'if-match',
> 'if-modified-since',
> 'if-none-match',
> 'if-range',
> 'if-unmodified-since',
> 'max-forwards',
> 'proxy-authorization',
> range,
> referer,
> te,
> 'user-agent',
> %%% --- Standard "Entity" headers
> allow,
> 'content-encoding',
> 'content-language',
> 'content-length' = "0",
> 'content-location',
> 'content-md5',
> 'content-range',
> 'content-type',
> expires,
> 'last-modified',
> other=[] % list() - Key/Value list with other headers
> }).
> -type http_request_h() :: #http_request_h{}.
>
> -endif. % -ifdef(http_internal_hrl).
diff -r otp-OTP-19.3.6.5/lib/inets/test/inets_internal.hrl erlang-otp-6356f67/lib/inets/test/inets_internal.hrl
1c1,52
< ../src/inets_app/inets_internal.hrl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 2005-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> %%
>
> -ifndef(inets_internal_hrl).
> -define(inets_internal_hrl, true).
>
> -define(STACK(), erlang:get_stacktrace()).
>
> %% Various trace macros
>
> -define(report(Severity, Label, Service, Content),
> inets_trace:report_event(Severity, Label, Service,
> [{module, ?MODULE}, {line, ?LINE} | Content])).
> -define(report_important(Label, Service, Content),
> ?report(20, Label, Service, Content)).
> -define(report_verbose(Label, Service, Content),
> ?report(40, Label, Service, Content)).
> -define(report_debug(Label, Service, Content),
> ?report(60, Label, Service, Content)).
> -define(report_trace(Label, Service, Content),
> ?report(80, Label, Service, Content)).
>
>
> -define(CR, $\r).
> -define(LF, $\n).
> -define(CRLF, [$\r,$\n]).
> -define(SP, $\s).
> -define(TAB, $\t).
> -define(LEFT_PAREN, $().
> -define(RIGHT_PAREN, $)).
> -define(WHITE_SPACE, $ ).
> -define(DOUBLE_QUOTE, $").
>
> -endif. % -ifdef(inets_internal_hrl).
diff -r otp-OTP-19.3.6.5/lib/mnesia/examples/bup.erl erlang-otp-6356f67/lib/mnesia/examples/bup.erl
1c1,240
< ../doc/src/bup.erl
\ Наприкінці файла немає нового рядка
---
> %% ``Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions 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$
> %%
> -module(bup).
> -export([
> change_node_name/5,
> view/2,
> test/0,
> test/1
> ]).
>
> -export([
> count/1,
> display/1
> ]).
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Management of backups, a few demos
>
> %0
> change_node_name(Mod, From, To, Source, Target) ->
> Switch =
> fun(Node) when Node == From -> To;
> (Node) when Node == To -> throw({error, already_exists});
> (Node) -> Node
> end,
> Convert =
> fun({schema, db_nodes, Nodes}, Acc) ->
> {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};
> ({schema, version, Version}, Acc) ->
> {[{schema, version, Version}], Acc};
> ({schema, cookie, Cookie}, Acc) ->
> {[{schema, cookie, Cookie}], Acc};
> ({schema, Tab, CreateList}, Acc) ->
> Keys = [ram_copies, disc_copies, disc_only_copies],
> OptSwitch =
> fun({Key, Val}) ->
> case lists:member(Key, Keys) of
> true -> {Key, lists:map(Switch, Val)};
> false-> {Key, Val}
> end
> end,
> {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
> (Other, Acc) ->
> {[Other], Acc}
> end,
> mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched).
>
> view(Source, Mod) ->
> View = fun(Item, Acc) ->
> io:format("~p.~n",[Item]),
> {[Item], Acc + 1}
> end,
> mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).
> %0
>
> -record(bup_rec, {key, val}).
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Test change of node name
> %%
> %% Assume db_nodes to be current node and on all other nodes but one
> %% Create new schema, start Mnesia on all db_nodes
> %% Create a table of disc_copies type which is replicated to all db_nodes
> %% Perform a backup and change current node to unused node in backup
> %% Start Mnesia on all nodes according to the new set of db_nodes
> test() ->
> test(nodes()).
>
> test(Nodes)->
> AllNodes = (Nodes -- [node()]) ++ [node()],
> case length(AllNodes) of
> Length when Length > 1 ->
> OldBup = "old.BUP",
> NewBup = "new.BUP",
> Res = (catch test2(AllNodes, OldBup, NewBup)),
> case Res of
> {'EXIT', Reason} ->
> file:delete(OldBup),
> file:delete(NewBup),
> {error, Reason};
> ok ->
> ok = count(NewBup),
> file:delete(OldBup),
> file:delete(NewBup),
> ok
> end;
> _ ->
> {error,{"Must run on at least one other node",AllNodes}}
> end.
>
> test2(AllNodes, OldBup, NewBup) ->
> ThisNode = node(),
> OtherNode = hd(AllNodes -- [ThisNode]),
> OldNodes = AllNodes -- [OtherNode],
> NewNodes = AllNodes -- [ThisNode],
> Mod = mnesia_backup, % Assume local files
> file:delete(OldBup),
> file:delete(NewBup),
>
> %% Create old backup
> rpc:multicall(AllNodes, mnesia, lkill, []),
> ok = mnesia:delete_schema(AllNodes),
> ok = mnesia:create_schema(OldNodes),
> rpc:multicall(OldNodes, mnesia, start, []),
> rpc:multicall(OldNodes, mnesia, wait_for_tables, [[schema], infinity]),
>
> CreateList = [{disc_copies, OldNodes},
> {attributes, record_info(fields, bup_rec)}],
> {atomic, ok} = mnesia:create_table(bup_rec, CreateList),
> rpc:multicall(OldNodes, mnesia, wait_for_tables, [[bup_rec], infinity]),
> OldRecs = [#bup_rec{key = I, val = I * I} || I <- lists:seq(1, 10)],
> lists:foreach(fun(R) -> ok = mnesia:dirty_write(R) end,OldRecs),
> ok = mnesia:backup(OldBup, Mod),
> ok = mnesia:dirty_write(#bup_rec{key = 4711, val = 4711}),
> rpc:multicall(OldNodes, mnesia, stop, []),
> {ok,_} = view(OldBup, Mod),
>
> %% Change node name
> {ok,_} = change_node_name(Mod, ThisNode, OtherNode, OldBup, NewBup),
> ok = rpc:call(OtherNode, mnesia, install_fallback, [NewBup, Mod]),
> {_NewStartRes,[]} = rpc:multicall(NewNodes, mnesia, start, []),
> rpc:call(OtherNode, mnesia, wait_for_tables, [[bup_rec], infinity]),
> Wild = rpc:call(OtherNode, mnesia, table_info, [bup_rec, wild_pattern]),
> NewRecs = rpc:call(OtherNode, mnesia, dirty_match_object, [Wild]),
> rpc:multicall(NewNodes, mnesia, stop, []),
> {ok,_} = view(NewBup, Mod),
>
> %% Sanity test
> case {lists:sort(OldRecs), lists:sort(NewRecs)} of
> {Same, Same} -> ok
> end.
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> -record(state, {counter_tab, size_tab, acc_size = 0, n_records = 0}).
>
>
> %% Iterates over a backup file and shows some statistics
> %% The identity of ets table containing the counters is not removed
> count(BupFile) ->
> CounterTab = ets:new(?MODULE, [set, public]),
> SizeTab = ets:new(?MODULE, [set, public]),
> Mod = mnesia:system_info(backup_module),
> State = #state{counter_tab = CounterTab, size_tab = SizeTab},
> case mnesia:traverse_backup(BupFile, Mod, dummy, read_only, fun incr/2, State) of
> {ok, State2} ->
> Res = display(State2),
> ets:delete(CounterTab),
> ets:delete(SizeTab),
> Res;
> {error, Reason} ->
> ets:delete(CounterTab),
> ets:delete(SizeTab),
> {error, Reason}
> end.
>
> incr(Rec, State) ->
> Tab = element(1, Rec),
> Key = element(2, Rec),
> Oid = {Tab, Key},
> incr_counter(State#state.counter_tab, Oid),
> Size = size(term_to_binary(Rec)),
> max_size(State#state.size_tab, Tab, Key, Size),
> AccSize = State#state.acc_size,
> N = State#state.n_records,
> State2 = State#state{acc_size = AccSize + Size, n_records = N + 1},
> {[Rec], State2}.
>
> incr_counter(T, Counter) ->
> case catch ets:update_counter(T, Counter, 1) of
> {'EXIT', _} ->
> ets:insert(T, {Counter, 1});
> _ ->
> ignore
> end.
>
> max_size(T, Tab, Key, Size) ->
> case catch ets:lookup_element(T, Tab, 2) of
> {'EXIT', _} ->
> ets:insert(T, {Tab, Size, Key});
> OldSize when OldSize < Size ->
> ets:insert(T, {Tab, Size, Key});
> _ ->
> ignore
> end.
>
> %% Displays the statistics found in the ets table
> display(State) ->
> CounterTab = State#state.counter_tab,
> Tabs = [T || {{_, T}, _} <- match_tab(CounterTab, schema)],
> io:format("~w tables with totally: ~w records, ~w keys, ~w bytes~n",
> [length(Tabs),
> State#state.n_records,
> ets:info(CounterTab, size),
> State#state.acc_size]),
> display(State, lists:sort(Tabs)).
>
> display(State, [Tab | Tabs]) ->
> Counters = match_tab(State#state.counter_tab, Tab),
> io:format("~-10w records in table ~w~n", [length(Counters), Tab]),
> Fun = fun({_Oid, Val}) when Val < 5 ->
> ignore;
> ({Oid, Val}) ->
> io:format("~-10w *** records with key ~w~n", [Val, Oid])
> end,
> lists:foreach(Fun, Counters),
> display_size(State#state.size_tab, Tab),
> display(State, Tabs);
> display(_CounterTab, []) ->
> ok.
>
> match_tab(T, Tab) ->
> ets:match_object(T, {{Tab, '_'}, '_'}).
>
> display_size(T, Tab) ->
> case catch ets:lookup(T, Tab) of
> [] ->
> ignore;
> [{_, Size, Key}] when Size > 1000 ->
> io:format("~-10w --- bytes occupied by largest record ~w~n",
> [Size, {Tab, Key}]);
> [{_, _, _}] ->
> ignore
> end.
diff -r otp-OTP-19.3.6.5/lib/mnesia/examples/company.erl erlang-otp-6356f67/lib/mnesia/examples/company.erl
1c1,383
< ../doc/src/company.erl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 1999-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> -module(company).
>
> -compile(export_all).
>
> %0
>
> -include_lib("stdlib/include/qlc.hrl").
> -include("company.hrl").
>
> init() ->
> mnesia:create_table(employee,
> [{attributes, record_info(fields, employee)}]),
> mnesia:create_table(dept,
> [{attributes, record_info(fields, dept)}]),
> mnesia:create_table(project,
> [{attributes, record_info(fields, project)}]),
> mnesia:create_table(manager, [{type, bag},
> {attributes, record_info(fields, manager)}]),
> mnesia:create_table(at_dep,
> [{attributes, record_info(fields, at_dep)}]),
> mnesia:create_table(in_proj, [{type, bag},
> {attributes, record_info(fields, in_proj)}]).
>
> %0
>
> %1
>
> insert_emp(Emp, DeptId, ProjNames) ->
> Ename = Emp#employee.name,
> Fun = fun() ->
> mnesia:write(Emp),
> AtDep = #at_dep{emp = Ename, dept_id = DeptId},
> mnesia:write(AtDep),
> mk_projs(Ename, ProjNames)
> end,
> mnesia:transaction(Fun).
>
>
> mk_projs(Ename, [ProjName|Tail]) ->
> mnesia:write(#in_proj{emp = Ename, proj_name = ProjName}),
> mk_projs(Ename, Tail);
> mk_projs(_, []) -> ok.
>
>
> %1
>
> %2
> females() ->
> F = fun() ->
> Q = qlc:q([E#employee.name || E <- mnesia:table(employee),
> E#employee.sex == female]),
> qlc:e(Q)
> end,
> mnesia:transaction(F).
> %2
> %20
> all_females() ->
> F = fun() ->
> Female = #employee{sex = female, name = '$1', _ = '_'},
> mnesia:select(employee, [{Female, [], ['$1']}])
> end,
> mnesia:transaction(F).
> %20
>
> g() -> l.
>
> %3
> female_bosses() ->
> H1 = qlc:q( [{Atdep#at_dep.dept_id,E} ||
> E <- mnesia:table(employee),
> E#employee.sex == female,
> Atdep <- mnesia:table(at_dep),
> Atdep#at_dep.emp == E#employee.emp_no]
> ),
>
> H2 = qlc:q( [{Mgr#manager.emp,E} ||
> {AtdepDeptId, E} <- H1,
> Mgr <- mnesia:table(manager),
> AtdepDeptId == Mgr#manager.dept]
> ),
>
> Q = qlc:q( [{E#employee.name, Boss#employee.name} ||
> {MgrEmp,E} <- H2,
> Boss <- mnesia:table(employee),
> MgrEmp == Boss#employee.emp_no]
> ),
> mnesia:transaction(fun() -> qlc:e(Q) end).
> %3
>
> %4
> raise_females(Amount) ->
> F = fun() ->
> Q = qlc:q([E || E <- mnesia:table(employee),
> E#employee.sex == female]),
> Fs = qlc:e(Q),
> over_write(Fs, Amount)
> end,
> mnesia:transaction(F).
>
> over_write([E|Tail], Amount) ->
> Salary = E#employee.salary + Amount,
> New = E#employee{salary = Salary},
> mnesia:write(New),
> 1 + over_write(Tail, Amount);
> over_write([], _) ->
> 0.
> %4
>
> %5
> raise(Eno, Raise) ->
> F = fun() ->
> [E] = mnesia:read(employee, Eno, write),
> Salary = E#employee.salary + Raise,
> New = E#employee{salary = Salary},
> mnesia:write(New)
> end,
> mnesia:transaction(F).
> %5
>
>
> %6
> bad_raise(Eno, Raise) ->
> F = fun() ->
> [E] = mnesia:read({employee, Eno}),
> Salary = E#employee.salary + Raise,
> New = E#employee{salary = Salary},
> io:format("Trying to write ... ~n", []),
> mnesia:write(New)
> end,
> mnesia:transaction(F).
> %6
>
> %9
> get_emps(Salary, Dep) ->
> Q = qlc:q(
> [E || E <- mnesia:table(employee),
> At <- mnesia:table(at_dep),
> E#employee.salary > Salary,
> E#employee.emp_no == At#at_dep.emp,
> At#at_dep.dept_id == Dep]
> ),
> F = fun() -> qlc:e(Q) end,
> mnesia:transaction(F).
> %9
> %10
> get_emps2(Salary, Dep) ->
> Epat = mnesia:table_info(employee, wild_pattern),
> Apat = mnesia:table_info(at_dep, wild_pattern),
> F = fun() ->
> All = mnesia:match_object(Epat),
> High = filter(All, Salary),
> Alldeps = mnesia:match_object(Apat),
> filter_deps(High, Alldeps, Dep)
> end,
> mnesia:transaction(F).
>
>
> filter([E|Tail], Salary) ->
> if
> E#employee.salary > Salary ->
> [E | filter(Tail, Salary)];
> true ->
> filter(Tail, Salary)
> end;
> filter([], _) ->
> [].
>
> filter_deps([E|Tail], Deps, Dep) ->
> case search_deps(E#employee.name, Deps, Dep) of
> true ->
> [E | filter_deps(Tail, Deps, Dep)];
> false ->
> filter_deps(Tail, Deps, Dep)
> end;
> filter_deps([], _,_) ->
> [].
>
>
> search_deps(Name, [D|Tail], Dep) ->
> if
> D#at_dep.emp == Name,
> D#at_dep.dept_id == Dep -> true;
> true -> search_deps(Name, Tail, Dep)
> end;
> search_deps(_Name, _Tail, _Dep) ->
> false.
>
> %10
>
>
>
> %11
> bench1() ->
> Me = #employee{emp_no= 104732,
> name = klacke,
> salary = 7,
> sex = male,
> phone = 99586,
> room_no = {221, 015}},
>
> F = fun() -> insert_emp(Me, 'B/DUR', [erlang, mnesia, otp]) end,
> T1 = timer:tc(company, dotimes, [1000, F]),
> mnesia:add_table_copy(employee, b@skeppet, ram_copies),
> mnesia:add_table_copy(at_dep, b@skeppet, ram_copies),
> mnesia:add_table_copy(in_proj, b@skeppet, ram_copies),
> T2 = timer:tc(company, dotimes, [1000, F]),
> {T1, T2}.
>
> dotimes(0, _) ->
> ok;
> dotimes(I, F) ->
> F(), dotimes(I-1, F).
>
> %11
>
>
>
>
>
> %12
>
> dist_init() ->
> mnesia:create_table(employee,
> [{ram_copies, [a@gin, b@skeppet]},
> {attributes, record_info(fields,
> employee)}]),
> mnesia:create_table(dept,
> [{ram_copies, [a@gin, b@skeppet]},
> {attributes, record_info(fields, dept)}]),
> mnesia:create_table(project,
> [{ram_copies, [a@gin, b@skeppet]},
> {attributes, record_info(fields, project)}]),
> mnesia:create_table(manager, [{type, bag},
> {ram_copies, [a@gin, b@skeppet]},
> {attributes, record_info(fields,
> manager)}]),
> mnesia:create_table(at_dep,
> [{ram_copies, [a@gin, b@skeppet]},
> {attributes, record_info(fields, at_dep)}]),
> mnesia:create_table(in_proj,
> [{type, bag},
> {ram_copies, [a@gin, b@skeppet]},
> {attributes, record_info(fields, in_proj)}]).
> %12
>
> %13
> remove_proj(ProjName) ->
> F = fun() ->
> Ip = qlc:e(qlc:q([X || X <- mnesia:table(in_proj),
> X#in_proj.proj_name == ProjName]
> )),
> mnesia:delete({project, ProjName}),
> del_in_projs(Ip)
> end,
> mnesia:transaction(F).
>
> del_in_projs([Ip|Tail]) ->
> mnesia:delete_object(Ip),
> del_in_projs(Tail);
> del_in_projs([]) ->
> done.
> %13
>
> %14
> sync() ->
> case mnesia:wait_for_tables(tabs(), 10000) of
> {timeout, RemainingTabs} ->
> panic(RemainingTabs);
> ok ->
> synced
> end.
>
> tabs() -> [employee, dept, project, at_dep, in_proj, manager].
>
> %14
>
>
> find_male_on_second_floor() ->
> Select = fun() ->
> %21
> MatchHead = #employee{name='$1', sex=male, room_no={'$2', '_'}, _='_'},
> Guard = [{'>=', '$2', 220},{'<', '$2', 230}],
> Result = '$1',
> mnesia:select(employee,[{MatchHead, Guard, [Result]}])
> %21
> end,
> mnesia:transaction(Select).
>
> panic(X) -> exit({panic, X}).
>
>
> fill_tables() ->
> Emps =
> [
> {employee, 104465, "Johnson Torbjorn", 1, male, 99184, {242,038}},
> {employee, 107912, "Carlsson Tuula", 2, female,94556, {242,056}},
> {employee, 114872, "Dacker Bjarne", 3, male, 99415, {221,035}},
> {employee, 104531, "Nilsson Hans", 3, male, 99495, {222,026}},
> {employee, 104659, "Tornkvist Torbjorn", 2, male, 99514, {222,022}},
> {employee, 104732, "Wikstrom Claes", 2, male, 99586, {221,015}},
> {employee, 117716, "Fedoriw Anna", 1, female,99143, {221,031}},
> {employee, 115018, "Mattsson Hakan", 3, male, 99251, {203,348}}
> ],
>
> Dept = [
> {dept, 'B/SF', "Open Telecom Platform"},
> {dept, 'B/SFP', "OTP - Product Development"},
> {dept, 'B/SFR', "Computer Science Laboratory"}
> ],
>
> Projects = [
> {project, erlang, 1},
> {project, otp, 2},
> {project, beam, 3},
> {project, mnesia, 5},
> {project, wolf, 6},
> {project, documentation, 7},
> {project, www, 8}
> ],
>
> Manager = [
> {manager, 104465, 'B/SF'},
> {manager, 104465, 'B/SFP'},
> {manager, 114872, 'B/SFR'}
> ],
>
> At_dep = [
> {at_dep, 104465, 'B/SF'},
> {at_dep, 107912, 'B/SF'},
> {at_dep, 114872, 'B/SFR'},
> {at_dep, 104531, 'B/SFR'},
> {at_dep, 104659, 'B/SFR'},
> {at_dep, 104732, 'B/SFR'},
> {at_dep, 117716, 'B/SFP'},
> {at_dep, 115018, 'B/SFP'}
> ],
>
> In_proj = [
> {in_proj, 104465, otp},
> {in_proj, 107912, otp},
> {in_proj, 114872, otp},
> {in_proj, 104531, otp},
> {in_proj, 104531, mnesia},
> {in_proj, 104545, wolf},
> {in_proj, 104659, otp},
> {in_proj, 104659, wolf},
> {in_proj, 104732, otp},
> {in_proj, 104732, mnesia},
> {in_proj, 104732, erlang},
> {in_proj, 117716, otp},
> {in_proj, 117716, documentation},
> {in_proj, 115018, otp},
> {in_proj, 115018, mnesia}
> ],
>
> [mnesia:dirty_write(W) || W <- Emps],
> [mnesia:dirty_write(W) || W <- Dept],
> [mnesia:dirty_write(W) || W <- Projects],
> %% Relations
> [mnesia:dirty_write(W) || W <- Manager],
> [mnesia:dirty_write(W) || W <- At_dep],
> [mnesia:dirty_write(W) || W <- In_proj],
>
> ok.
diff -r otp-OTP-19.3.6.5/lib/mnesia/examples/company.hrl erlang-otp-6356f67/lib/mnesia/examples/company.hrl
1c1,51
< ../doc/src/company.hrl
\ Наприкінці файла немає нового рядка
---
> %% ``Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions 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$
> %%
>
>
> %0
> -record(employee, {emp_no,
> name,
> salary,
> sex,
> phone,
> room_no}).
>
> -record(dept, {id,
> name}).
>
> -record(project, {name,
> number}).
>
>
> -record(manager, {emp,
> dept}).
>
> -record(at_dep, {emp,
> dept_id}).
>
> -record(in_proj, {emp,
> proj_name}).
>
> %0
>
>
>
>
>
>
diff -r otp-OTP-19.3.6.5/lib/mnesia/examples/company_o.erl erlang-otp-6356f67/lib/mnesia/examples/company_o.erl
1c1,147
< ../doc/src/company_o.erl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 1999-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
>
> -module(company_o).
> -compile(export_all).
>
> -import(mnesia, [transaction/1]).
>
> %0
> -include_lib("stdlib/include/qlc.hrl").
> -include("company_o.hrl").
>
>
> sinit() ->
> mnesia:create_schema([node()]).
>
> init() ->
> mnesia:create_table(employee,
> [{attributes, record_info(fields, employee)}]),
> mnesia:create_table(dept,
> [{attributes, record_info(fields, dept)}]),
> mnesia:create_table(project,
> [{attributes, record_info(fields, project)}]).
>
> %0
>
>
>
> %1
>
> insert_emp(Emp, DeptId, ProjNames) ->
> Fun = fun() ->
> mnesia:write(Emp#employee{dept = DeptId,
> projects = ProjNames})
> end,
> mnesia:transaction(Fun).
>
>
> %1
>
> %2
> females() ->
> F = fun() ->
> Q = qlc:q([E#employee.name || E <- mnesia:table(employee),
> E#employee.sex == female]),
> qlc:e(Q)
> end,
> mnesia:transaction(F).
> %2
>
> %3
> female_bosses() ->
> F = fun() -> qlc:e(qlc:q(
> [{E#employee.name, Boss#employee.name} ||
> E <- mnesia:table(employee),
> Boss <- mnesia:table(employee),
> Boss#employee.emp_no == E#employee.manager,
> E#employee.sex == female]
> ))
> end,
> mnesia:transaction(F).
>
>
> %4
> raise_females(Amount) ->
> F = fun() ->
> Q = qlc:q([E || E <- mnesia:table(employee),
> E#employee.sex == female]),
> Fs = qlc:e(Q),
> over_write(Fs, Amount)
> end,
> mnesia:transaction(F).
>
> over_write([E|Tail], Amount) ->
> Salary = E#employee.salary + Amount,
> New = E#employee{salary = Salary},
> mnesia:write(New),
> 1 + over_write(Tail, Amount);
> over_write([], _) ->
> 0.
> %4
>
> %5
> raise(Eno, Raise) ->
> F = fun() ->
> [E] = mnesia:read({employee, Eno}),
> Salary = E#employee.salary + Raise,
> New = E#employee{salary = Salary},
> mnesia:write(New)
> end,
> mnesia:transaction(F).
> %5
>
>
> %6
> bad_raise(Eno, Raise) ->
> F = fun() ->
> [E] = mnesia:read({employee, Eno}),
> Salary = E#employee.salary + Raise,
> New = E#employee{salary = Salary},
> io:format("Trying to write ... ~n", []),
> mnesia:write(New)
> end,
> mnesia:transaction(F).
> %6
>
> %9
> get_emps(Salary, Dep) ->
> Q = qlc:q(
> [E || E <- mnesia:table(employee),
> E#employee.salary > Salary,
> E#employee.dept == Dep]
> ),
> F = fun() -> qlc:e(Q) end,
> transaction(F).
> %9
>
> %10
> get_emps2(Salary, Dep) ->
> Epat0 = mnesia:table_info(employee, wild_pattern),
> Epat = Epat0#employee{dept = Dep},
> F = fun() ->
> All = mnesia:match_object(Epat),
> [E || E <-All, E#employee.salary > Salary ]
> end,
> mnesia:transaction(F).
>
>
> %10
>
diff -r otp-OTP-19.3.6.5/lib/mnesia/examples/company_o.hrl erlang-otp-6356f67/lib/mnesia/examples/company_o.hrl
1c1,39
< ../doc/src/company_o.hrl
\ Наприкінці файла немає нового рядка
---
> %% ``Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions 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$
> %%
>
> %0
> -record(employee, {emp_no,
> name,
> salary,
> sex,
> phone,
> room_no,
> dept,
> projects,
> manager}).
>
>
> -record(dept, {id,
> name}).
>
> -record(project, {name,
> number,
> location}).
>
> %0
diff -r otp-OTP-19.3.6.5/lib/mnesia/examples/DATA erlang-otp-6356f67/lib/mnesia/examples/DATA
1c1,100
< ../doc/src/DATA
\ Наприкінці файла немає нового рядка
---
> %S0
> {tables,
> [{employee, [{attributes, [emp_no,name,salary,sex, phone,room_no]}]},
> {dept, [{attributes, [id, name]}]},
> {project, [{attributes, [name, number]}]},
> {manager, [{attributes, [emp, dept]},
> {type, bag}]},
> {at_dep, [{attributes, [emp, dept_id]}]},
> {in_proj, [{attributes, [emp, proj_name]},
> {type, bag}]}
> ]
> }.
>
> %E0
>
>
> %S1
> {employee, 104465, "Johnson Torbjorn", 1, male, 99184, {242,038}}.
> {employee, 107912, "Carlsson Tuula", 2, female, 94556, {242,056}}.
> {employee, 114872, "Dacker Bjarne", 3, male, 99415, {221,035}}.
> {employee, 114849, "Armstrong Josef", 3, male, 99452, {221,023}}.
> {employee, 114952, "Froberg Magnus", 5, male, 99469, {222,018}}.
> {employee, 104531, "Nilsson Hans", 3, male, 99495, {222,026}}.
> {employee, 104659, "Tornkvist Torbjorn", 2, male, 99514, {222,022}}.
> {employee, 104732, "Wikstrom Claes", 2, male, 99586, {221,015}}.
> {employee, 117716, "Fedoriw Anna", 1, female, 99143, {221,031}}.
> {employee, 115020, "Hansson Catrin", 6, female, 99129, {222,072}}.
> {employee, 115018, "Mattsson Hakan", 3, male, 99251, {203,348}}.
> {employee, 113069, "Eriksson Morgan", 6, male, 99186, {241,543}}.
> %E1
>
> %S2
> %% departments
> {dept, 'B/SF', "Open Telecom Platform"}.
> {dept, 'B/SFP', "OTP - Product Development"}.
> {dept, 'B/SFR', "Computer Science Laboratory"}.
> %E2
>
>
> %% projects
> %S3
> {project, erlang, 1}.
> {project, otp, 2}.
> {project, beam, 3}.
> {project, mnesia, 5}.
> {project, wolf, 6}.
> {project, documentation, 7}.
> {project, www, 8}.
>
> %E3
>
>
>
> %% manager
> %S4
> {manager, 104465, 'B/SF'}.
> {manager, 104465, 'B/SFP'}.
> {manager, 114872, 'B/SFR'}.
>
> %E4
> %S5
> {at_dep, 104465, 'B/SF'}.
> {at_dep, 107912, 'B/SF'}.
> {at_dep, 114872, 'B/SFR'}.
> {at_dep, 114849, 'B/SFR'}.
> {at_dep, 114952, 'B/SFR'}.
> {at_dep, 104531, 'B/SFR'}.
> {at_dep, 104659, 'B/SFR'}.
> {at_dep, 104732, 'B/SFR'}.
> {at_dep, 117716, 'B/SFP'}.
> {at_dep, 115020, 'B/SFP'}.
> {at_dep, 115018, 'B/SFP'}.
> {at_dep, 113069, 'B/SFP'}.
>
>
> %E5
> %S6
> {in_proj, 104465, otp}.
> {in_proj, 107912, otp}.
> {in_proj, 114872, otp}.
> {in_proj, 114849, otp}.
> {in_proj, 114849, erlang}.
> {in_proj, 114952, otp}.
> {in_proj, 104531, otp}.
> {in_proj, 104531, mnesia}.
> {in_proj, 104545, wolf}.
> {in_proj, 104659, otp}.
> {in_proj, 104659, wolf}.
> {in_proj, 104732, otp}.
> {in_proj, 104732, mnesia}.
> {in_proj, 104732, erlang}.
> {in_proj, 117716, otp}.
> {in_proj, 117716, documentation}.
> {in_proj, 115020, otp}.
> {in_proj, 115018, otp}.
> {in_proj, 115018, mnesia}.
> {in_proj, 113069, otp}.
>
> %E6
>
diff -r otp-OTP-19.3.6.5/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/src/installer.erl erlang-otp-6356f67/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/src/installer.erl
1c1,1124
< ../../../../installer.erl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 2011-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
>
> -module(installer).
>
> -include("test_lib.hrl").
>
> %%-compile(export_all).
> -export([install_1/2]).
> -export([install_2/1]).
> -export([install_3/2]).
> -export([install_6a/1]).
> -export([install_4/1]).
> -export([install_5/1]).
> -export([install_5a/1]).
> -export([install_6/1]).
> -export([install_7/1]).
> -export([install_7a/1]).
> -export([install_8/1]).
> -export([install_8a/1]).
> -export([install_9/1]).
> -export([install_10/1]).
> -export([install_11/1]).
> -export([install_12/1]).
> -export([install_13/1]).
> -export([install_14/1]).
> -export([upgrade_restart_1/2]).
> -export([upgrade_restart_1a/1]).
> -export([upgrade_restart_2/1]).
> -export([upgrade_restart_2a/1]).
> -export([upgrade_restart_2b/1]).
> -export([upgrade_restart_3/1]).
> -export([client1_1/4]).
> -export([client2/3]).
> -export([stop/1]).
> -export([unpack_p1h/2]).
> -export([permanent_p1h/1]).
> -export([reg_proc/1]).
> -export([registered_loop/1]).
>
> -define(print(List),
> io:format(user,"(~w:~w) ~tp~n",[?MODULE,?LINE,List]),
> {rh_print, TestNode} ! {print, {?MODULE, ?LINE}, List}).
> -define(print_line(Line,List),
> io:format(user,"(~w:~w) ~tp~n",[?MODULE,Line,List]),
> {rh_print, TestNode} ! {print, {?MODULE, Line}, List}).
> -define(fail(Term), exit({?MODULE, ?LINE, Term})).
> -define(fail_line(Line,Term), exit({?MODULE, Line, Term})).
>
> -define(check_release_states(States),
> check_release_states(TestNode,node(),States,?LINE)).
> -define(check_release_states_client(Node,States),
> check_release_states(TestNode,Node,States,?LINE)).
>
> -define(check_release_lib(Vsn,Apps),
> check_release_lib(TestNode,node(),Vsn,Apps,?LINE)).
> -define(check_release_lib_client(Node,Vsn,Apps),
> check_release_lib(TestNode,Node,Vsn,Apps,?LINE)).
>
> -define(check_running_app(App,Vsn),
> check_running_app(TestNode,node(),App,Vsn,?LINE)).
> -define(check_running_app_client(Node,App,Vsn),
> check_running_app(TestNode,Node,App,Vsn,?LINE)).
>
> -define(check_disallowed_calls,check_disallowed_calls(TestNode,?LINE)).
>
>
> install_1(TestNode,PrivDir) ->
> ?print([TestNode]),
> ?print(["install_1 start"]),
> ?check_release_states([permanent]),
>
> % Unpack and install P1H
> {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
> ?check_release_states([permanent,unpacked]),
> ?check_release_lib("P1H",["a-1.0"]),
> {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
> ?check_release_states([permanent,current]),
> ?check_running_app(a,"1.0"),
> X = a:a(),
> ?print(["X", X]),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> ?print(["install_1 end OK"]),
> ok.
> % release_handler_SUITE will reboot this node now!
>
> install_2(TestNode) ->
> ?print(["install_2 start"]),
>
> % Check that P1H is still unpacked, install it and make_permanent
> ?check_release_states([permanent,unpacked]),
> {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
> ?print(["install_2 install_release ok"]),
> ?check_release_states([permanent,current]),
> ?check_running_app(a,"1.0"),
> ok = release_handler:make_permanent("P1H"),
> ?print(["install_2 make permanent P1H ok"]),
> ?check_release_states([old,permanent]),
> ?check_running_app(a,"1.0"),
> ok.
> % release_handler_SUITE will reboot this node now!
>
> install_3(TestNode,PrivDir) ->
> ?print(["install_3 start"]),
>
> % Check that P1H is permanent
> ?check_release_states([old,permanent]),
> ?check_running_app(a,"1.0"),
> X = a:a(),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
>
> % Unpack and install P1I
> {ok, "P1I"} = unpack_release(PrivDir,"rel2"),
> ?check_release_states([old,permanent,unpacked]),
> ?check_release_lib("P1I",["a-1.1"]),
> {ok,"P1H",[{extra, gott}]} = release_handler:check_install_release("P1I"),
> ?print(["install_3 check_install_release P1I ok"]),
> {error,_} = release_handler:check_install_release("P1J"),
> ?print(["install_3 check_install_release P1J fails - ok"]),
> {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
> ?check_release_states([old,permanent,current]),
> ?check_running_app(a,"1.1"),
> X2 = a:a(),
> {key2, newval2} = lists:keyfind(key2, 1, X2),
> {key1, val1} = lists:keyfind(key1, 1, X2),
> {ok, bval} = a:b(),
> ?print(["install_3 env ok"]),
>
> % Unpack P2A
> {ok, "P2A"} = unpack_release(PrivDir,"rel3"),
> ?check_release_states([old,permanent,current,unpacked]),
> ?check_release_lib("P2A",["a-1.1"]),
> {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"),
> ?print(["install_3 check_install_release P2A ok"]),
> ok.
> % release_handler_SUITE will reboot this node now!
>
> install_4(TestNode) ->
> ?print(["install_4 start"]),
>
> %% Check that P1H is the one that is used
> ?check_release_states([old,permanent,unpacked,unpacked]),
> ?check_running_app(a,"1.0"),
>
> %% Install P2A
> {continue_after_restart, "P1H", [new_emu,new_appl]} =
> release_handler:install_release("P2A"),
> %% Node is rebooted by the release_handler:install_release
> %% (init:reboot) because P2A includes a new erts vsn and the relup
> %% file contains a 'restart_new_emulator' instruction.
> ?print(["install_4 P2A installed"]),
> ok.
>
>
> install_5(TestNode) ->
> ?print(["install_5 start"]),
>
> %% Check that the upgrade was done via a temporary release due to
> %% new emulator version.
> {"SASL-test","__new_emulator__P1H"} = init:script_id(),
>
> %% Check that P2A is in use.
> ?check_release_states([old,permanent,unpacked,current]),
> ?check_running_app(a,"1.1"),
> X = a:a(),
> {key2, newval2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> {ok, bval} = a:b(),
> ?print(["install_5 check env ok"]),
> ok.
>
> install_5a(TestNode) ->
> ?print(["install_5a start"]),
>
> %% Install P1I (this will be a downgrade)
> {ok, "P1I", [old_emu]} = release_handler:install_release("P1I"),
> %% Node is rebooted by the release_handler:install_release
> %% (init:reboot) because P2A includes a new erts vsn and the relup
> %% file contains a 'restart_new_emulator' instruction.
> ?print(["install_5a P1I installed"]),
> ok.
>
> install_6(TestNode) ->
> ?print(["install_6 start"]),
>
> %% Check that P1I is used
> ?check_release_states([old,permanent,current,old]),
> ?check_running_app(a,"1.1"),
>
> %% Make P1I permanent
> ok = release_handler:make_permanent("P1I"),
> ?check_release_states([old,old,permanent,old]),
> ?check_running_app(a,"1.1"),
> ok.
>
> install_6a(TestNode) ->
> %% Install P2A
> {continue_after_restart, "P1I", [new_emu]} =
> release_handler:install_release("P2A"),
> %% Node is rebooted by the release_handler:install_release
> %% (init:reboot) because P2A includes a new erts vsn and the relup
> %% file contains a 'restart_new_emulator' instruction.
> ?print(["install_6a P2A installed"]),
> ok.
>
> install_7(TestNode) ->
> ?print(["install_7 start"]),
>
> %% Check that the upgrade was done via a temporary release due to
> %% new emulator version.
> {"SASL-test","__new_emulator__P1I"} = init:script_id(),
>
> % Check that P2A is in use.
> ?check_release_states([old,old,permanent,current]),
> ?check_running_app(a,"1.1"),
> X = a:a(),
> {key2, newval2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> {ok, bval} = a:b(),
> ?print(["install_7 check env ok"]),
> ok.
>
> install_7a(TestNode) ->
> %% Install P1H (this will be a downgrade)
> {ok, "P1H", [old_emu,old_appl]} = release_handler:install_release("P1H"),
> %% Node is rebooted by the release_handler:install_release
> %% (init:reboot) because P2A includes a new erts vsn and the relup
> %% file contains a 'restart_new_emulator' instruction.
> ?print(["install_7a P1H installed"]),
> ok.
>
> install_8(TestNode) ->
> ?print(["install_8 start"]),
>
> %% Check that P1H is used
> ?check_release_states([old,current,permanent,old]),
> ?check_running_app(a,"1.0"),
> {ok,"P1H",[new_emu,new_appl]} = release_handler:check_install_release("P2A"),
> ?print(["install_8 check_install_release P2A ok"]),
>
> %% Install P1I and check that it is permanent
> {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
> ?check_release_states([old,old,permanent,old]),
> ?check_running_app(a,"1.1"),
> ok.
>
> install_8a(TestNode) ->
> % Install P2A again
> {continue_after_restart, "P1I", [new_emu]} =
> release_handler:install_release("P2A"),
> %% Node is rebooted by the release_handler:install_release
> %% (init:reboot) because P2A includes a new erts vsn and the relup
> %% file contains a 'restart_new_emulator' instruction.
> ?print(["install_8a P2A installed"]),
> ok.
>
> install_9(TestNode) ->
> ?print(["install_9 start"]),
>
> %% Check that the upgrade was done via a temporary release due to
> %% new emulator version.
> {"SASL-test","__new_emulator__P1I"} = init:script_id(),
>
> % Check that P2A is used
> ?check_release_states([old,old,permanent,current]),
> ?check_running_app(a,"1.1"),
> X = a:a(),
> {key2, newval2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> {ok, bval} = a:b(),
> ?print(["install_9 check env ok"]),
> ok = release_handler:make_permanent("P2A"),
> ?check_release_states([old,old,old,permanent]),
> ?check_running_app(a,"1.1"),
> ok.
> % release_handler_SUITE will reboot this node now!
>
>
> install_10(TestNode) ->
> ?print(["install_10 start"]),
>
> % Check that P2A is used
> ?check_release_states([old,old,old,permanent]),
> ?check_running_app(a,"1.1"),
>
> % Install old P1H
> ok = release_handler:reboot_old_release("P1H"),
> ?print(["install_10 reboot_old ok"]),
> ok.
>
>
> install_11(TestNode) ->
> ?print(["install_11 start"]),
>
> % Check that P1H is permanent
> ?check_release_states([old,permanent,old,old]),
> ?check_running_app(a,"1.0"),
> X = a:a(),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> ?print(["install_11 check env ok"]),
>
> %% Remove P1I and P2A and check that a-1.1 and erts-<latest> are removed
> ok = release_handler:remove_release("P2A"),
> ?check_release_states([old,permanent,old]),
> ok = release_handler:remove_release("P1I"),
> ?check_release_states([old,permanent]),
> {ok, Libs} = file:list_dir(code:lib_dir()),
> {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()),
> true = lists:member("stdlib-"++StdlibVsn, Libs),
> true = lists:member("a-1.0", Libs),
> false = lists:member("a-1.1", Libs),
> {ok, Dirs} = file:list_dir(code:root_dir()),
> ErtsDir = "erts-"++?ertsvsn,
> [ErtsDir] = lists:filter(fun(Dir) -> lists:prefix("erts-",Dir) end, Dirs),
> ?print(["install_11 file checks ok"]),
> ok.
> % release_handler_SUITE will reboot this node now!
>
> install_12(TestNode) ->
> ?print(["install_12 start"]),
>
> % Check that P1H is permanent
> ?check_release_states([old,permanent]),
> ?check_running_app(a,"1.0"),
> X = a:a(),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> ?print(["install_12 check env ok"]),
>
> % Install old P1G
> ok = release_handler:reboot_old_release("P1G"),
> ?print(["install_12 reboot_old ok"]),
> ok.
>
> install_13(TestNode) ->
> ?print(["install_13 start"]),
>
> % Check that P1G is permanent
> ?check_release_states([permanent,old]),
> false = lists:keysearch(a,1,application:loaded_applications()),
> ?print(["install_13 no a application found - ok"]),
>
> %% Remove P1H and check that both versions of application a is removed
> ok = release_handler:remove_release("P1H"),
> ?check_release_states([permanent]),
> {ok, Libs} = file:list_dir(code:lib_dir()),
> {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()),
> true = lists:member("stdlib-"++StdlibVsn, Libs),
> false = lists:member("a-1.0", Libs),
> false = lists:member("a-1.1", Libs),
> ?print(["install_13 file checks ok"]),
> ok.
> % release_handler_SUITE will reboot this node now!
>
> install_14(TestNode) ->
> ?print(["install_14 start"]),
>
> % Check that P1G is permanent
> ?check_release_states([permanent]),
> false = lists:keysearch(a,1,application:loaded_applications()),
> ?print(["install_13 no a application found - ok"]),
> ok.
>
>
> %%%-----------------------------------------------------------------
> %%% Ths test checks that an upgrade which both upgrades to a new
> %%% emulator version, and had a restart_emulator option to
> %%% systools:make_relup will be restarted twice on upgrade.
> %%% (On downgrade it will happen only once.)
> upgrade_restart_1(TestNode,PrivDir) ->
> ?print([TestNode]),
> ?print(["upgrade_restart_1 start"]),
> ?check_release_states([permanent]),
>
> {ok, "P2B"} = unpack_release(PrivDir,"rel4"),
> ?check_release_states([permanent,unpacked]),
> ?check_release_lib("P2B",["a-1.1"]),
> ok.
>
> upgrade_restart_1a(TestNode) ->
> ?print(["upgrade_restart_1a start"]),
>
> {continue_after_restart,"P1G",[new_emu,add_appl]} =
> release_handler:install_release("P2B"),
> ?print(["upgrade_restart_1a P2B installed"]),
> ok.
>
> upgrade_restart_2(TestNode) ->
> ?print(["upgrade_restart_2 start"]),
>
> %% Check that the node has been restarted once more after the tmp release
> case init:script_id() of
> {"SASL-test","P2B"} ->
> upgrade_restart_2a(TestNode);
> {"SASL-test","__new_emulator__P1G"} ->
> %% catched the node too early - give it another try
> {wait,whereis(init)}
> end.
>
> upgrade_restart_2a(TestNode) ->
> ?print(["upgrade_restart_2a start"]),
>
> %% This time we must be there, else something is definitely wrong
> {"SASL-test","P2B"} = init:script_id(),
>
> ?check_release_states([permanent,current]),
> ?check_running_app(a,"1.1"),
>
> ok = release_handler:make_permanent("P2B"),
> ?check_release_states([old,permanent]),
>
> ok.
>
> upgrade_restart_2b(TestNode) ->
> ?print(["upgrade_restart_2b start"]),
>
> {ok,"P1G",[old_emu,rm_appl]} = release_handler:install_release("P1G"),
> ?print(["upgrade_restart_2b P1G installed"]),
> ok.
>
> upgrade_restart_3(TestNode) ->
> ?print(["upgrade_restart_3 start"]),
>
> %% Ideally we should test that the node has only been restarted
> %% once... but that's not so easy. Let's just check that P1G is running.
> ?check_release_states([current,permanent]),
> false = lists:keysearch(a,1,application:loaded_applications()),
> ?print(["upgrade_restart_3 no a application found - ok"]),
>
> ok.
>
>
>
>
> %%-----------------------------------------------------------------
> %% This test starts a client node which uses this node as master
> %% for the release_handler.
> %% The client node runs all tests as in installer/1 test case.
> %% Thus, the client node will be rebooted several times.
> %% The to_erl /tmp/NODENAME@HOSTNAME/ command can be used to connect
> %% to the client node.
> %% run_erl logs for the client can be found in the directory:
> %% code:root_dir() ++ "/clients/type1/NODENAME@HOSTNAME/log
> %%-----------------------------------------------------------------
>
>
> client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
> TestHost = test_host(),
> ?print(["client1_1 start"]),
>
> {ok,IP} = inet:getaddr(TestHost,inet),
> erl_boot_server:start([IP]),
>
> ok = net_kernel:monitor_nodes(true),
> Node = start_client(TestNode,client1,ClientSname),
> trace_disallowed_calls(Node),
>
> ?check_release_states_client(Node,[permanent]),
>
> %% Check env var for SASL on client node
> SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
> ?print([{client1_1,sasl_env},SaslEnv]),
> {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
> {_,[Master]} = lists:keyfind(masters,1,SaslEnv),
> {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
> NodeStr = atom_to_list(Node),
> [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
> true = (Master =:= node()),
> case os:type() of
> {unix,_} ->
> true = (StartCli =:= filename:join([CliDir,"bin","start"]));
> _ ->
> ok
> end,
>
> %% Unpack P1H on master
> {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
>
> %% Unpack and install P1H on client
> Root = code:root_dir(),
> P1HDir = filename:join([Root, "releases", "P1H"]),
>
> %% The AppDirs argument (last arg to set_unpacked) below is really
> %% not necessary, it could just be [] since the path is the same
> %% as default. But it is given here in order to force hitting the
> %% release_handler:check_path function so it can be checked that
> %% it does not use file:read_file_info on the client node, see
> %% trace_disallowed_calls/1 and check_disallowed_calls/2 below.
> %% (OTP-9142)
> {ok, "P1H"} = rpc:call(Node, release_handler, set_unpacked,
> [filename:join(P1HDir, "rel1.rel"),
> [{a,"1.0",filename:join(MasterDir,lib)}]]),
>
> ?check_release_states_client(Node,[permanent,unpacked]),
> ?check_release_lib_client(Node,"P1H",["a-1.0"]),
>
> ok = rpc:call(Node, release_handler, install_file,
> ["P1H", filename:join(P1HDir, "start.boot")]),
> ok = rpc:call(Node, release_handler, install_file,
> ["P1H", filename:join(P1HDir, "sys.config")]),
> ok = rpc:call(Node, release_handler, install_file,
> ["P1H", filename:join(P1HDir, "relup")]),
> ?print([{release_handler_state, Node},
> rpc:call(Node, sys, get_status, [release_handler])]),
>
> {ok,"P1G",[new_appl]} =
> rpc:call(Node, release_handler, check_install_release, ["P1H"]),
>
> {ok,"P1G",[new_appl]} =
> rpc:call(Node, release_handler, install_release, ["P1H"]),
>
> ?check_release_states_client(Node,[permanent,current]),
> ?check_running_app_client(Node,a,"1.0"),
>
> Apps = rpc:call(Node, application, which_applications, []),
> {a,"A CXC 138 11","1.0"} = lists:keyfind(a, 1, Apps),
> X = rpc:call(Node, a, a, []),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
>
> ?check_disallowed_calls,
> reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_2(TestNode,PrivDir,Node).
>
> client1_2(TestNode,PrivDir,Node) ->
> ?print(["client1_2 start"]),
>
> %% Check that P1H is still unpacked, install it and make_permanent
> ?check_release_states_client(Node,[permanent,unpacked]),
>
> {ok,"P1G",[new_appl]} =
> rpc:call(Node, release_handler, install_release, ["P1H"]),
> ?check_release_states_client(Node,[permanent,current]),
> ?check_running_app_client(Node,a,"1.0"),
>
> ok = rpc:call(Node, release_handler, make_permanent, ["P1H"]),
> ?check_release_states_client(Node,[old,permanent]),
>
> ?check_disallowed_calls,
> reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_3(TestNode,PrivDir,Node).
>
> client1_3(TestNode,PrivDir,Node) ->
> ?print(["client1_3 start"]),
>
> %% Check that P1H is permanent
> ?check_release_states_client(Node,[old,permanent]),
> ?check_running_app_client(Node,a,"1.0"),
>
> %% Unpack P1I on master
> {ok, "P1I"} = unpack_release(PrivDir,"rel2"),
>
> MasterRoot = code:root_dir(),
>
> %% Unpack and install P1I on client
> P1IDir = filename:join([MasterRoot, "releases", "P1I"]),
> {ok, "P1I"} = rpc:call(Node, release_handler, set_unpacked,
> [filename:join(P1IDir, "rel2.rel"),[]]),
>
> ?check_release_states_client(Node,[old,permanent,unpacked]),
> ?check_release_lib_client(Node,"P1I",["a-1.1"]),
>
> ok = rpc:call(Node, release_handler, install_file,
> ["P1I", filename:join(P1IDir, "start.boot")]),
> ok = rpc:call(Node, release_handler, install_file,
> ["P1I", filename:join(P1IDir, "sys.config")]),
> ok = rpc:call(Node, release_handler, install_file,
> ["P1I", filename:join(P1IDir, "relup")]),
>
> {ok,"P1H",[{extra, gott}]} =
> rpc:call(Node, release_handler, check_install_release, ["P1I"]),
> {error,_} = rpc:call(Node, release_handler, check_install_release, ["P1J"]),
> {ok,"P1H",[{extra, gott}]} =
> rpc:call(Node, release_handler, install_release, ["P1I"]),
>
> ?check_release_states_client(Node,[old,permanent,current]),
> ?check_running_app_client(Node,a,"1.1"),
> X2 = rpc:call(Node, a, a, []),
> {key2, newval2} = lists:keyfind(key2, 1, X2),
> {key1, val1} = lists:keyfind(key1, 1, X2),
> {ok, bval} = rpc:call(Node, a, b, []),
>
> %% Unpack P2A on master
> {ok, "P2A"} = unpack_release(PrivDir,"rel3"),
>
> %% Unpack and install P2A on client
> P2ADir = filename:join([MasterRoot, "releases", "P2A"]),
> {ok, "P2A"} =
> rpc:call(Node, release_handler, set_unpacked,
> [filename:join(P2ADir, "rel3.rel"),[]]),
>
> ?check_release_states_client(Node,[old,permanent,current,unpacked]),
> ?check_release_lib_client(Node,"P2A",["a-1.1"]),
>
> ok = rpc:call(Node, release_handler, install_file,
> ["P2A", filename:join(P2ADir, "start.boot")]),
> ok = rpc:call(Node, release_handler, install_file,
> ["P2A", filename:join(P2ADir, "sys.config")]),
> ok = rpc:call(Node, release_handler, install_file,
> ["P2A", filename:join(P2ADir, "relup")]),
>
> {ok, "P1I", [new_emu]} =
> rpc:call(Node, release_handler, check_install_release, ["P2A"]),
>
> %% Reboot from P1H
> ?check_disallowed_calls,
> reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_4(TestNode,Node).
>
> client1_4(TestNode,Node) ->
> ?print(["client1_4 start"]),
>
> %% check that P1H is used
> ?check_release_states_client(Node,[old,permanent,unpacked,unpacked]),
>
> %% since the install_release below reboot the node...
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> {continue_after_restart, "P1H", [new_emu,new_appl]} =
> rpc:call(Node, release_handler, install_release, ["P2A"]),
> %% Reboots the client !
>
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_5(TestNode,Node).
>
> client1_5(TestNode,Node) ->
> ?print(["client1_5 start"]),
>
> %% Check that P2A is in use.
> ?check_release_states_client(Node,[old,permanent,unpacked,current]),
> ?check_running_app_client(Node,a,"1.1"),
> X = rpc:call(Node, a, a, []),
> {key2, newval2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> {ok, bval} = rpc:call(Node, a, b, []),
>
> %% since the install_release below reboot the node...
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> {ok,"P1I",[old_emu]} =
> rpc:call(Node, release_handler, install_release, ["P1I"]),
>
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_6(TestNode,Node).
>
> client1_6(TestNode,Node) ->
> ?print(["client1_6 start"]),
>
> ?check_release_states_client(Node,[old,permanent,current,old]),
> ?check_running_app_client(Node,a,"1.1"),
>
> ok = rpc:call(Node, release_handler, make_permanent, ["P1I"]),
> ?check_release_states_client(Node,[old,old,permanent,old]),
>
> %% since the install_release below reboot the node...
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> {continue_after_restart, "P1I", [new_emu]} =
> rpc:call(Node, release_handler, install_release, ["P2A"]),
> %% Reboots the client !
>
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_7(TestNode,Node).
>
> client1_7(TestNode,Node) ->
> ?print(["client1_7 start"]),
>
> %% Check that P2A is in use.
> ?check_release_states_client(Node,[old,old,permanent,current]),
> ?check_running_app_client(Node,a,"1.1"),
> X = rpc:call(Node, a, a, []),
> {key2, newval2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> {ok, bval} = rpc:call(Node, a, b, []),
>
> %% since the install_release below reboot the node...
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> {ok,"P1H",[old_emu,old_appl]} =
> rpc:call(Node, release_handler, install_release, ["P1H"]),
>
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_8(TestNode,Node).
>
> client1_8(TestNode,Node) ->
> ?print(["client1_8 start"]),
>
> %% Check that P1H is used
> ?check_release_states_client(Node,[old,current,permanent,old]),
> ?check_running_app_client(Node,a,"1.0"),
> {ok, "P1H", [new_emu,new_appl]} =
> rpc:call(Node, release_handler, check_install_release, ["P2A"]),
>
>
> {ok,"P1H",[{extra, gott}]} =
> rpc:call(Node, release_handler, install_release, ["P1I"]),
> ?check_release_states_client(Node,[old,old,permanent,old]),
> ?check_running_app_client(Node,a,"1.1"),
>
>
> %% since the install_release below will reboot the node...
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> %% Install P2A again
> {continue_after_restart, "P1I", [new_emu]} =
> rpc:call(Node, release_handler, install_release, ["P2A"]),
>
> %% We are rebooted again.
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_9(TestNode,Node).
>
> client1_9(TestNode,Node) ->
> ?print(["client1_9 start"]),
>
> %% Check that P2A is used
> ?check_release_states_client(Node,[old,old,permanent,current]),
> ?check_running_app_client(Node,a,"1.1"),
> X = rpc:call(Node, a, a, []),
> {key2, newval2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
> {ok, bval} = rpc:call(Node, a, b, []),
>
> %% Make P2A permanent
> ok = rpc:call(Node, release_handler, make_permanent, ["P2A"]),
> ?check_release_states_client(Node,[old,old,old,permanent]),
>
> %% Reboot from P2A
> ?check_disallowed_calls,
> reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_10(TestNode,Node).
>
> client1_10(TestNode,Node) ->
> ?print(["client1_10 start"]),
>
> %% Check that P2A is used
> ?check_release_states_client(Node,[old,old,old,permanent]),
>
> %% since the reboot_old_release below will reboot the node
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> %% Install old P1H
> rpc:call(Node, release_handler, reboot_old_release, ["P1H"]),
> %% We are rebooted.
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_11(TestNode,Node).
>
> client1_11(TestNode,Node) ->
> ?print(["client1_11 start"]),
>
> %% Check that P1H is permanent
> ?check_release_states_client(Node,[old,permanent,old,old]),
> ?check_running_app_client(Node,a,"1.0"),
> X = rpc:call(Node, a, a, []),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
>
> %% Remove P1I and P2A from client
> ok = rpc:call(Node, release_handler, set_removed, ["P2A"]),
> ?check_release_states_client(Node,[old,permanent,old]),
> ok = rpc:call(Node, release_handler, set_removed, ["P1I"]),
> ?check_release_states_client(Node,[old,permanent]),
>
> %% Check that P2A and P1I does not exists
> Rels = rpc:call(Node, release_handler, which_releases, []),
> false = lists:keysearch("P2A", 2, Rels),
> false = lists:keysearch("P1I", 2, Rels),
> X = rpc:call(Node, a, a, []),
> {key2, val2} = lists:keyfind(key2, 1, X),
> {key1, val1} = lists:keyfind(key1, 1, X),
>
> ?check_disallowed_calls,
> reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_12(TestNode,Node).
>
> client1_12(TestNode,Node) ->
> ?print(["client1_12 start"]),
>
> ?check_release_states_client(Node,[old,permanent]),
>
> %% since the reboot_old_release below will reboot the node
> ?check_disallowed_calls,
> cover_client(TestNode,Node,stop_cover),
>
> %% Install old P1G
> rpc:call(Node, release_handler, reboot_old_release, ["P1G"]),
> %% We are rebooted.
> check_reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_13(TestNode,Node).
>
> client1_13(TestNode,Node) ->
> ?print(["client1_13 start"]),
>
> %% Check that P1G is permanent
> ?check_release_states_client(Node,[permanent,old]),
> {error,client_node} = rpc:call(Node,release_handler,remove_release,["P1H"]),
> ok = rpc:call(Node, release_handler, set_removed, ["P1H"]),
> ?check_release_states_client(Node,[permanent]),
>
> ?check_disallowed_calls,
> reboot(TestNode,Node),
> trace_disallowed_calls(Node),
>
> client1_14(TestNode,Node).
>
> client1_14(TestNode,Node) ->
> ?print(["client1_14 start"]),
>
> %% Check that P1G is permanent
> ?check_release_states_client(Node,[permanent]),
>
> ?check_disallowed_calls,
> stop_client(TestNode,Node), %% TEST IS OK !!
> net_kernel:monitor_nodes(false),
>
> %% Remove releases from master
> ok = release_handler:remove_release("P2A"),
> ok = release_handler:remove_release("P1I"),
> ok = release_handler:remove_release("P1H"),
> ok.
>
> %% Start tracing of the file module on the client node. This module
> %% shall never be called, since
> %% 1) the node is a client from the release_handler's point of view,
> %% so all file access should be done via rpc calls to the master
> %% 2) it is started with erl_prim_loader loader set to 'inet' so all
> %% code loading should be done via the inet to the master
> %% (OTP-9142)
> %% This function is called each time the client node is started and to
> %% check if a call has been made, call check_disallowed_node/0
> trace_disallowed_calls(Node) ->
> MasterProc = self(),
> rpc:call(Node,dbg,tracer,[process,{fun(T,_) -> MasterProc ! T end,[]}]),
> rpc:call(Node,dbg,p,[all,call]),
> rpc:call(Node,dbg,tp,[file,[{'_',[],[{message,{caller}}]}]]),
> %% File:native_name_encoding/0 is a BIF and OK to use
> rpc:call(Node,dbg,ctp,[file,native_name_encoding,0]).
>
> check_disallowed_calls(TestNode,Line) ->
> receive
> Trace when element(1,Trace)==trace ->
> ?print_line(Line,["Disallowed function called",Trace]),
> exit({disallowed_function_call,Trace})
> after 0 ->
> ok
> end.
>
> start_client(TestNode,Client,Sname) ->
> Node = list_to_atom(lists:concat([Sname,"@",test_host()])),
> case os:type() of
> {unix,_} -> start_client_unix(TestNode,Sname,Node);
> {win32,_} -> start_client_win32(TestNode,Client,Sname)
> end,
> receive
> {nodeup, Node} ->
> wait_started(TestNode,Node)
> after 30000 ->
> ?print([{start_client,failed,Node},net_adm:ping(Node)]),
> ?fail({"can not start", Node})
> end.
>
> start_client_unix(TestNode,Sname,Node) ->
> Start = filename:join(["clients", "type1", Node, "bin", "start"]),
> Cmd = filename:join(code:root_dir(), Start),
> ?print([{start_client,Sname},Cmd]),
> Res = rh_test_lib:cmd(Cmd,[],[{"NODENAME",atom_to_list(Sname)}]),
> ?print([{start_client,result},Res]).
>
> start_client_win32(TestNode,Client,ClientSname) ->
> Name = atom_to_list(ClientSname) ++ "_P1G",
> RootDir = code:root_dir(),
> ErtsBinDir = filename:join([RootDir,"erts-"++?ertsvsn,"bin"]),
>
> {ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname,
> RootDir),
> StartErlArgs = rh_test_lib:get_start_erl_args(RootDir,RelClientDir,
> ClientArgs),
> ServiceArgs = rh_test_lib:get_service_args(RootDir, RelClientDir,
> ClientSname, StartErlArgs),
>
> ?print([{start_client,ClientSname},ServiceArgs]),
> Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")),
> rh_test_lib:erlsrv(Erlsrv,stop,Name),
> rh_test_lib:erlsrv(Erlsrv,remove,Name),
> ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs),
> ok = rh_test_lib:erlsrv(Erlsrv,start,Name),
> ?print([{start_client,result},ok]),
> ok.
>
> reboot(TestNode,Node) ->
> cover_client(TestNode,Node,stop_cover),
> rpc:call(Node, init, reboot, []),
> check_reboot(TestNode,Node).
>
> %% This way of checking that the node is rebooted will only work if
> %% the nodes are automatically re-connected after the reboot. This
> %% happens for master/client (when sasl is started on the client).
> check_reboot(TestNode,Node) ->
> receive
> {nodedown, Node} ->
> receive
> {nodeup, Node} -> wait_started(TestNode,Node)
> after 30000 ->
> ?fail({Node, "not rebooted",net_adm:ping(Node)})
> end
> after 30000 ->
> ?fail({Node, "not closing down",net_adm:ping(Node)})
> end.
>
> stop_client(TestNode,Node) ->
> cover_client(TestNode,Node,stop_cover),
> rpc:call(Node, init, stop, []),
> receive
> {nodedown, Node} -> ok
> after 30000 ->
> ?fail({Node, "not stopping"})
> end.
>
> wait_started(TestNode,Node) ->
> case rpc:call(Node, init, get_status, []) of
> {started, _} ->
> cover_client(TestNode,Node,start_cover),
> Node;
> _ ->
> timer:sleep(1000),
> wait_started(TestNode,Node)
> end.
>
> cover_client(TestNode,Node,Func) ->
> R = rpc:call(TestNode,release_handler_SUITE,Func,[Node]),
> ?print([{Func,Node,R}]).
>
>
> %%-----------------------------------------------------------------
> %% This test starts a client node which uses this node as master
> %% for the release_handler.
> %% The client node has the name cli2@HOSTNAME.
> %% The client node is not allowed to do ANY release updates
> %% as it also have another (non-existing) master node.
> %%
> %% The to_erl /tmp/cli2@HOSTNAME/ command can be used to connect
> %% to the client node.
> %% run_erl logs for the client can be found in the directory:
> %% code:root_dir() ++ "/clients/type1/cli2@HOSTNAME/log
> %%-----------------------------------------------------------------
> client2(TestNode,PrivDir,ClientSname) ->
> TestHost = test_host(),
> ?print(["client2 start"]),
>
> %% Clean up if previous test case failed
> release_handler:remove_release("P1H"),
>
> ok = net_kernel:monitor_nodes(true),
> Node = start_client(TestNode,client2,ClientSname),
>
> %% Check env var for SASL on client node
> SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
> ?print([{client1_1,sasl_env},SaslEnv]),
> {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
> {_,[Master,Master2]} = lists:keyfind(masters,1,SaslEnv),
> {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
> NodeStr = atom_to_list(Node),
> [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
> true = (Master =:= node()),
> true = (Master2 =:= list_to_atom("master2@"++TestHost)),
> case os:type() of
> {unix,_} ->
> true = (StartCli =:= filename:join([CliDir,"bin","start"]));
> _ ->
> ok
> end,
>
> %% Unpack P1H on master
> {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
>
> %% Try to set P1H unpacked on client
> Root = code:root_dir(),
> {error,{bad_masters,[Master2]}} =
> rpc:call(Node, release_handler, set_unpacked,
> [filename:join([Root, "releases", "P1H", "rel1.rel"]),[]]),
>
> {error,{no_such_release,"P1H"}} =
> rpc:call(Node, release_handler, check_install_release, ["P1H"]),
>
> stop_client(TestNode,Node), %% TEST IS OK !!
> net_kernel:monitor_nodes(false),
>
> release_handler:remove_release("P1H"),
> ok.
>
>
> stop(Now) ->
> %% The timestamp is only used for debugging. It is printed by
> %% release_handler_SUITE also.
> R = init:stop(),
> erlang:display({init_stop,Now,R}),
> R.
>
> unpack_p1h(TestNode,PrivDir) ->
> {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
> ?check_release_states([permanent,unpacked]),
> ?check_release_lib("P1H",["a-1.0"]),
> ok.
>
> permanent_p1h(TestNode) ->
> ?check_release_states([permanent,unpacked]),
> ?check_release_lib("P1H",["a-1.0"]),
> {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
> ?check_release_states([permanent,current]),
> ok = release_handler:make_permanent("P1H"),
> ?check_release_states([old,permanent]),
> ok.
>
>
> reg_proc(Name) ->
> catch unregister(Name),
> Pid = spawn_link(?MODULE, registered_loop, [Name]),
> global:register_name(Name, Pid),
> ok.
>
> registered_loop(_Name) ->
> receive
> kill ->
> exit(killed)
> end.
>
> %% Checks that the list of states for all releases (sorted on vsn)
> %% equals the input States
> check_release_states(TestNode,Node,States,Line) ->
> case rpc:call(Node,release_handler,which_releases,[]) of
> {badrpc,_}=Error ->
> ?fail_line(Line,{check_release_states,Node,States,Error});
> Rels ->
> ?print_line(Line,["check_release_states:", Rels]),
> States = [Status || {_,_,_,Status} <- lists:keysort(2,Rels)],
> ok
> end.
>
> %% Check that the given release (Vsn) sees the correct vsn of App.
> check_release_lib(TestNode,Node,Vsn,Apps,Line) ->
> case rpc:call(Node,release_handler,which_releases,[]) of
> {badrpc,_}=Error ->
> ?fail_line(Line,{check_release_lib,Node,Vsn,Apps,Error});
> Rels ->
> ?print_line(Line,["check_release_lib:", Rels]),
> {"SASL-test", Vsn, Libs, _Status} = lists:keyfind(Vsn, 2, Rels),
> true = lists:all(fun(App) -> lists:member(App,Libs) end,Apps),
> ok
> end.
>
> %% Check that the given Vsn of App is executed
> check_running_app(TestNode,Node,App,Vsn,Line) ->
> case rpc:call(Node,application,which_applications,[]) of
> {badrpc,_}=Error ->
> ?fail_line(Line,{check_running_app,Node,App,Vsn,Error});
> Apps ->
> ?print_line(Line,["check_running_app:", Apps]),
> {App, _, Vsn} = lists:keyfind(App, 1, Apps),
> ok
> end.
>
> test_host() ->
> {ok,Host} = inet:gethostname(),
> Host.
>
> unpack_release(PrivDir,Rel) ->
> copy(filename:join([PrivDir,Rel,Rel++".tar.gz"]),
> filename:join(code:root_dir(),releases)),
> release_handler:unpack_release(Rel).
>
> copy(Src, DestDir) ->
> Dest = filename:join(DestDir, filename:basename(Src)),
> {ok,_} = file:copy(Src, Dest),
> ok.
>
diff -r otp-OTP-19.3.6.5/lib/sasl/test/release_handler_SUITE_data/target_system.erl erlang-otp-6356f67/lib/sasl/test/release_handler_SUITE_data/target_system.erl
1c1,275
< ../../examples/src/target_system.erl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 2011-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> %module
> -module(target_system).
> -export([create/1, create/2, install/2]).
>
> %% Note: RelFileName below is the *stem* without trailing .rel,
> %% .script etc.
> %%
>
> %% create(RelFileName)
> %%
> create(RelFileName) ->
> create(RelFileName,[]).
>
> create(RelFileName,SystoolsOpts) ->
> RelFile = RelFileName ++ ".rel",
> Dir = filename:dirname(RelFileName),
> PlainRelFileName = filename:join(Dir,"plain"),
> PlainRelFile = PlainRelFileName ++ ".rel",
> io:fwrite("Reading file: ~tp ...~n", [RelFile]),
> {ok, [RelSpec]} = file:consult(RelFile),
> io:fwrite("Creating file: ~tp from ~tp ...~n",
> [PlainRelFile, RelFile]),
> {release,
> {RelName, RelVsn},
> {erts, ErtsVsn},
> AppVsns} = RelSpec,
> PlainRelSpec = {release,
> {RelName, RelVsn},
> {erts, ErtsVsn},
> lists:filter(fun({kernel, _}) ->
> true;
> ({stdlib, _}) ->
> true;
> (_) ->
> false
> end, AppVsns)
> },
> {ok, Fd} = file:open(PlainRelFile, [write]),
> io:fwrite(Fd, "~p.~n", [PlainRelSpec]),
> file:close(Fd),
>
> io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n",
> [PlainRelFileName,PlainRelFileName]),
> make_script(PlainRelFileName,SystoolsOpts),
>
> io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n",
> [RelFileName, RelFileName]),
> make_script(RelFileName,SystoolsOpts),
>
> TarFileName = RelFileName ++ ".tar.gz",
> io:fwrite("Creating tar file ~tp ...~n", [TarFileName]),
> make_tar(RelFileName,SystoolsOpts),
>
> TmpDir = filename:join(Dir,"tmp"),
> io:fwrite("Creating directory ~tp ...~n",[TmpDir]),
> file:make_dir(TmpDir),
>
> io:fwrite("Extracting ~tp into directory ~tp ...~n", [TarFileName,TmpDir]),
> extract_tar(TarFileName, TmpDir),
>
> TmpBinDir = filename:join([TmpDir, "bin"]),
> ErtsBinDir = filename:join([TmpDir, "erts-" ++ ErtsVsn, "bin"]),
> io:fwrite("Deleting \"erl\" and \"start\" in directory ~tp ...~n",
> [ErtsBinDir]),
> file:delete(filename:join([ErtsBinDir, "erl"])),
> file:delete(filename:join([ErtsBinDir, "start"])),
>
> io:fwrite("Creating temporary directory ~tp ...~n", [TmpBinDir]),
> file:make_dir(TmpBinDir),
>
> io:fwrite("Copying file \"~ts.boot\" to ~tp ...~n",
> [PlainRelFileName, filename:join([TmpBinDir, "start.boot"])]),
> copy_file(PlainRelFileName++".boot",filename:join([TmpBinDir, "start.boot"])),
>
> io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n"
> "~tp to ~tp ...~n",
> [ErtsBinDir, TmpBinDir]),
> copy_file(filename:join([ErtsBinDir, "epmd"]),
> filename:join([TmpBinDir, "epmd"]), [preserve]),
> copy_file(filename:join([ErtsBinDir, "run_erl"]),
> filename:join([TmpBinDir, "run_erl"]), [preserve]),
> copy_file(filename:join([ErtsBinDir, "to_erl"]),
> filename:join([TmpBinDir, "to_erl"]), [preserve]),
>
> %% This is needed if 'start' script created from 'start.src' shall
> %% be used as it points out this directory as log dir for 'run_erl'
> TmpLogDir = filename:join([TmpDir, "log"]),
> io:fwrite("Creating temporary directory ~tp ...~n", [TmpLogDir]),
> ok = file:make_dir(TmpLogDir),
>
> StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]),
> io:fwrite("Creating ~tp ...~n", [StartErlDataFile]),
> StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]),
> write_file(StartErlDataFile, StartErlData),
>
> io:fwrite("Recreating tar file ~tp from contents in directory ~tp ...~n",
> [TarFileName,TmpDir]),
> {ok, Tar} = erl_tar:open(TarFileName, [write, compressed]),
> %% {ok, Cwd} = file:get_cwd(),
> %% file:set_cwd("tmp"),
> ErtsDir = "erts-"++ErtsVsn,
> erl_tar:add(Tar, filename:join(TmpDir,"bin"), "bin", []),
> erl_tar:add(Tar, filename:join(TmpDir,ErtsDir), ErtsDir, []),
> erl_tar:add(Tar, filename:join(TmpDir,"releases"), "releases", []),
> erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []),
> erl_tar:add(Tar, filename:join(TmpDir,"log"), "log", []),
> erl_tar:close(Tar),
> %% file:set_cwd(Cwd),
> io:fwrite("Removing directory ~tp ...~n",[TmpDir]),
> remove_dir_tree(TmpDir),
> ok.
>
>
> install(RelFileName, RootDir) ->
> TarFile = RelFileName ++ ".tar.gz",
> io:fwrite("Extracting ~tp ...~n", [TarFile]),
> extract_tar(TarFile, RootDir),
> StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]),
> {ok, StartErlData} = read_txt_file(StartErlDataFile),
> [ErlVsn, _RelVsn| _] = string:tokens(StartErlData, " \n"),
> ErtsBinDir = filename:join([RootDir, "erts-" ++ ErlVsn, "bin"]),
> BinDir = filename:join([RootDir, "bin"]),
> io:fwrite("Substituting in erl.src, start.src and start_erl.src to "
> "form erl, start and start_erl ...\n"),
> subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir,
> [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}],
> [preserve]),
> %%! Workaround for pre OTP 17.0: start.src and start_erl.src did
> %%! not have correct permissions, so the above 'preserve' option did not help
> ok = file:change_mode(filename:join(BinDir,"start"),8#0755),
> ok = file:change_mode(filename:join(BinDir,"start_erl"),8#0755),
>
> io:fwrite("Creating the RELEASES file ...\n"),
> create_RELEASES(RootDir, filename:join([RootDir, "releases",
> filename:basename(RelFileName)])).
>
> %% LOCALS
>
> %% make_script(RelFileName,Opts)
> %%
> make_script(RelFileName,Opts) ->
> systools:make_script(RelFileName, [no_module_tests,
> {outdir,filename:dirname(RelFileName)}
> |Opts]).
>
> %% make_tar(RelFileName,Opts)
> %%
> make_tar(RelFileName,Opts) ->
> RootDir = code:root_dir(),
> systools:make_tar(RelFileName, [{erts, RootDir},
> {outdir,filename:dirname(RelFileName)}
> |Opts]).
>
> %% extract_tar(TarFile, DestDir)
> %%
> extract_tar(TarFile, DestDir) ->
> erl_tar:extract(TarFile, [{cwd, DestDir}, compressed]).
>
> create_RELEASES(DestDir, RelFileName) ->
> release_handler:create_RELEASES(DestDir, RelFileName ++ ".rel").
>
> subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) ->
> lists:foreach(fun(Script) ->
> subst_src_script(Script, SrcDir, DestDir,
> Vars, Opts)
> end, Scripts).
>
> subst_src_script(Script, SrcDir, DestDir, Vars, Opts) ->
> subst_file(filename:join([SrcDir, Script ++ ".src"]),
> filename:join([DestDir, Script]),
> Vars, Opts).
>
> subst_file(Src, Dest, Vars, Opts) ->
> {ok, Conts} = read_txt_file(Src),
> NConts = subst(Conts, Vars),
> write_file(Dest, NConts),
> case lists:member(preserve, Opts) of
> true ->
> {ok, FileInfo} = file:read_file_info(Src),
> file:write_file_info(Dest, FileInfo);
> false ->
> ok
> end.
>
> %% subst(Str, Vars)
> %% Vars = [{Var, Val}]
> %% Var = Val = string()
> %% Substitute all occurrences of %Var% for Val in Str, using the list
> %% of variables in Vars.
> %%
> subst(Str, Vars) ->
> subst(Str, Vars, []).
>
> subst([$%, C| Rest], Vars, Result) when $A =< C, C =< $Z ->
> subst_var([C| Rest], Vars, Result, []);
> subst([$%, C| Rest], Vars, Result) when $a =< C, C =< $z ->
> subst_var([C| Rest], Vars, Result, []);
> subst([$%, C| Rest], Vars, Result) when C == $_ ->
> subst_var([C| Rest], Vars, Result, []);
> subst([C| Rest], Vars, Result) ->
> subst(Rest, Vars, [C| Result]);
> subst([], _Vars, Result) ->
> lists:reverse(Result).
>
> subst_var([$%| Rest], Vars, Result, VarAcc) ->
> Key = lists:reverse(VarAcc),
> case lists:keysearch(Key, 1, Vars) of
> {value, {Key, Value}} ->
> subst(Rest, Vars, lists:reverse(Value, Result));
> false ->
> subst(Rest, Vars, [$%| VarAcc ++ [$%| Result]])
> end;
> subst_var([C| Rest], Vars, Result, VarAcc) ->
> subst_var(Rest, Vars, Result, [C| VarAcc]);
> subst_var([], Vars, Result, VarAcc) ->
> subst([], Vars, [VarAcc ++ [$%| Result]]).
>
> copy_file(Src, Dest) ->
> copy_file(Src, Dest, []).
>
> copy_file(Src, Dest, Opts) ->
> {ok,_} = file:copy(Src, Dest),
> case lists:member(preserve, Opts) of
> true ->
> {ok, FileInfo} = file:read_file_info(Src),
> file:write_file_info(Dest, FileInfo);
> false ->
> ok
> end.
>
> write_file(FName, Conts) ->
> Enc = file:native_name_encoding(),
> {ok, Fd} = file:open(FName, [write]),
> file:write(Fd, unicode:characters_to_binary(Conts,Enc,Enc)),
> file:close(Fd).
>
> read_txt_file(File) ->
> {ok, Bin} = file:read_file(File),
> {ok, binary_to_list(Bin)}.
>
> remove_dir_tree(Dir) ->
> remove_all_files(".", [Dir]).
>
> remove_all_files(Dir, Files) ->
> lists:foreach(fun(File) ->
> FilePath = filename:join([Dir, File]),
> case filelib:is_dir(FilePath) of
> true ->
> {ok, DirFiles} = file:list_dir(FilePath),
> remove_all_files(FilePath, DirFiles),
> file:del_dir(FilePath);
> _ ->
> file:delete(FilePath)
> end
> end, Files).
> %module
diff -r otp-OTP-19.3.6.5/lib/tools/emacs/tags.erl erlang-otp-6356f67/lib/tools/emacs/tags.erl
1c1,346
< ../src/tags.erl
\ Наприкінці файла немає нового рядка
---
> %%
> %% %CopyrightBegin%
> %%
> %% Copyright Ericsson AB 1996-2016. All Rights Reserved.
> %%
> %% Licensed under the Apache License, Version 2.0 (the "License");
> %% you may not use this file except in compliance with the License.
> %% You may obtain a copy of the License at
> %%
> %% http://www.apache.org/licenses/LICENSE-2.0
> %%
> %% Unless required by applicable law or agreed to in writing, software
> %% distributed under the License is distributed on an "AS IS" BASIS,
> %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> %% See the License for the specific language governing permissions and
> %% limitations under the License.
> %%
> %% %CopyrightEnd%
> %%
> %%%----------------------------------------------------------------------
> %%% File : tags.erl
> %%% Author : Anders Lindgren
> %%% Purpose : Generate an Emacs TAGS file from programs written in Erlang.
> %%% Date : 1998-03-16
> %%% Version : 1.1
> %%%----------------------------------------------------------------------
>
> -module(tags).
>
> -export([file/1, file/2, files/1, files/2, dir/1, dir/2,
> dirs/1, dirs/2, subdir/1, subdir/2, subdirs/1, subdirs/2,
> root/0, root/1]).
>
>
> %% `Tags' is a part of the editor Emacs. It is used for warp-speed
> %% jumps between different source files in a project. When Using
> %% `Tags', a function in any source file can be found by few a simple
> %% keystrokes, just press M-. (in normal terms: Press Escape and dot).
> %%
> %% In order to work, the `Tags' system needs a list of all functions
> %% in all source files in the project. This list is denoted the "TAGS
> %% file". This purpose of this module is to create the TAGS file for
> %% programs written in Erlang.
> %%
> %% In addition to functions, both records and macros (`define's) are
> %% added to the TAGS file.
>
>
> %% Usage:
> %% root([Options]) -- Create a TAGS file covering all files in
> %% the Erlang distribution.
> %%
> %% file(File [, Options]) -- Create a TAGS file for the file `File'.
> %% files(FileList [, Options])
> %% -- Dito for all files in `FileList'.
> %%
> %% dir(Dir [, Options]) -- Create a TAGS file for all files in `Dir'.
> %% dirs(DirList [, Options]) -- Dito for all files in all
> %% directories in `DirList'.
> %%
> %% subdir(Dir [, Options]) -- Descend recursively down `Dir' and create
> %% a TAGS file convering all files found.
> %% subdirs(DirList [, Options])
> %% -- Dito, for all directories in `DirList'.
> %%
> %% The default is to create a file named "TAGS" in the current directory.
> %%
> %% Options is a list of tuples, where the following tuples are
> %% recognised:
> %% {outfile, NameOfTAGSFile}
> %% {outdir, NameOfDirectory}
> %%
> %% Note, should both `outfile' and `outdir' options be given, `outfile'
> %% take precedence.
>
>
> %%% External interface
>
> root() -> root([]).
> root(Options) -> subdir(code:root_dir(), Options).
>
> dir(Dir) -> dir(Dir, []).
> dir(Dir, Options) -> dirs([Dir], Options).
>
> dirs(Dirs) -> dirs(Dirs, []).
> dirs(Dirs, Options) ->
> files(collect_dirs(Dirs, false), Options).
>
> subdir(Dir) -> subdir(Dir, []).
> subdir(Dir, Options) -> subdirs([Dir], Options).
>
> subdirs(Dirs) -> subdirs(Dirs, []).
> subdirs(Dirs, Options) ->
> files(collect_dirs(Dirs, true), Options).
>
> file(Name) -> file(Name, []).
> file(Name, Options) -> files([Name], Options).
>
> files(Files) -> files(Files, []).
> files(Files, Options) ->
> case open_out(Options) of
> {ok, Os} ->
> files_loop(Files, Os),
> ok = close_out(Os),
> ok;
> _ ->
> error
> end.
>
>
>
> %%% Internal functions.
>
> %% Find all files in a directory list. Should the second argument be
> %% the atom `true' the functions will descend into subdirectories.
> collect_dirs(Dirs, Recursive) ->
> collect_dirs(Dirs, Recursive, []).
>
> collect_dirs([], _Recursive, Acc) -> Acc;
> collect_dirs([Dir | Dirs], Recursive, Acc) ->
> NewAcc = case file:list_dir(Dir) of
> {ok, Entries} ->
> collect_files(Dir, Entries, Recursive, Acc);
> _ ->
> Acc
> end,
> collect_dirs(Dirs, Recursive, NewAcc).
>
> collect_files(_Dir,[],_Recursive, Acc) -> Acc;
> collect_files(Dir, [File | Files], Recursive, Acc) ->
> FullFile = filename:join(Dir, File),
> NewAcc = case filelib:is_dir(FullFile) of
> true when Recursive ->
> collect_dirs([FullFile], Recursive, Acc);
> true ->
> Acc;
> false ->
> case filelib:is_regular(FullFile) of
> true ->
> case filename:extension(File) of
> ".erl" ->
> [FullFile | Acc];
> ".hrl" ->
> [FullFile | Acc];
> _ ->
> Acc
> end;
> false ->
> Acc
> end
> end,
> collect_files(Dir, Files, Recursive, NewAcc).
>
>
> files_loop([],_Os) -> true;
> files_loop([F | Fs], Os) ->
> case filename(F, Os) of
> ok ->
> ok;
> error ->
> %% io:format("Could not open ~ts~n", [F]),
> error
> end,
> files_loop(Fs, Os).
>
>
> %% Generate tags for one file.
> filename(Name, Os) ->
> case file:open(Name, [read]) of
> {ok, Desc} ->
> Acc = module(Desc, [], [], {1, 0}),
> ok = file:close(Desc),
> genout(Os, Name, Acc),
> ok;
> _ ->
> error
> end.
>
>
> module(In, Last, Acc, {LineNo, CharNo}) ->
> case io:get_line(In, []) of
> eof ->
> Acc;
> Line ->
> {NewLast, NewAcc} = line(Line, Last, Acc, {LineNo, CharNo}),
> module(In, NewLast, NewAcc, {LineNo+1, CharNo+length(Line)})
> end.
>
>
> %% Handle one line. Return the last added function name.
> line([], Last, Acc, _) -> {Last, Acc};
> line(Line, _, Acc, Nos) when hd(Line) =:= $- ->
> case attribute(Line, Nos) of
> false -> {[], Acc};
> New -> {[], [New | Acc]}
> end;
> line(Line, Last, Acc, Nos) ->
> %% to be OR not to be?
> case case {hd(Line), word_char(hd(Line))} of
> {$', _} -> true;
> {_, true} -> true;
> _ -> false
> end of
> true ->
> case func(Line, Last, Nos) of
> false ->
> {Last, Acc};
> {NewLast, NewEntry} ->
> {NewLast, [NewEntry | Acc]}
> end;
> false ->
> {Last, Acc}
> end.
>
> %% Handle one function. Will only add the first clause. (i.e.
> %% if the function name doesn't match `Last').
> %% Return `false' or {NewLast, GeneratedLine}.
> func(Line, Last, Nos) ->
> {Name, Line1} = word(Line),
> case Name of
> [] -> false;
> Last -> false;
> _ ->
> {Space, Line2} = white(Line1),
> case Line2 of
> [$( | _] ->
> {Name, pfnote([$(, Space, Name], Nos)};
> _ ->
> false
> end
> end.
>
>
> %% Return `false' or generated line.
> attribute([$- | Line], Nos) ->
> {Attr, Line1} = word(Line),
> case case Attr of
> "drocer" -> true;
> "enifed" -> true;
> _ -> false
> end of
> false ->
> false;
> true ->
> {Space2, Line2} = white(Line1),
> case Line2 of
> [$( | Line3] ->
> {Space4, Line4} = white(Line3),
> {Name,_Line5} = word(Line4),
> case Name of
> [] -> false;
> _ ->
> pfnote([Name, Space4, $(, Space2, Attr, $-], Nos)
> end;
> _ ->
> false
> end
> end.
>
>
> %% Removes whitespace from the head of the line.
> %% Returns {ReveredSpace, Rest}
> white(Line) -> white(Line, []).
>
> white([], Acc) -> {Acc, []};
> white([32 | Rest], Acc) -> white(Rest, [32 | Acc]);
> white([9 | Rest], Acc) -> white(Rest, [9 | Acc]);
> white(Line, Acc) -> {Acc, Line}.
>
>
> %% Returns {ReversedWord, Rest}
> word([$' | Rest]) ->
> quoted(Rest, [$']);
> word(Line) ->
> unquoted(Line, []).
>
> quoted([$' | Rest], Acc) -> {[$' | Acc], Rest};
> quoted([$\\ , C | Rest], Acc) ->
> quoted(Rest, [C, $\\ | Acc]);
> quoted([C | Rest], Acc) ->
> quoted(Rest, [C | Acc]).
>
> unquoted([], Word) -> {Word, []};
> unquoted([C | Cs], Acc) ->
> case word_char(C) of
> true -> unquoted(Cs, [C | Acc]);
> false -> {Acc, [C | Cs]}
> end.
>
> word_char(C) when C >= $a, C =< $z -> true;
> word_char(C) when C >= $A, C =< $Z -> true;
> word_char(C) when C >= $0, C =< $9 -> true;
> word_char($_) -> true;
> word_char(_) -> false.
>
>
> %%% Output routines
>
> %% Check the options `outfile' and `outdir'.
> open_out(Options) ->
> Opts = [write, {encoding, unicode}],
> case lists:keysearch(outfile, 1, Options) of
> {value, {outfile, File}} ->
> file:open(File, Opts);
> _ ->
> case lists:keysearch(outdir, 1, Options) of
> {value, {outdir, Dir}} ->
> file:open(filename:join(Dir, "TAGS"), Opts);
> _ ->
> file:open("TAGS", Opts)
> end
> end.
>
>
> close_out(Os) ->
> file:close(Os).
>
>
> pfnote(Str, {LineNo, CharNo}) ->
> io_lib:format("~ts\177~w,~w~n", [flatrev(Str), LineNo, CharNo]).
>
>
> genout(Os, Name, Entries) ->
> io:format(Os, "\^l~n~ts,~w~n", [Name, reclength(Entries)]),
> io:put_chars(Os, lists:reverse(Entries)).
>
>
>
> %%% help routines
>
> %% Flatten and reverse a nested list.
> flatrev(Ls) -> flatrev(Ls, []).
>
> flatrev([C | Ls], Acc) when is_integer(C) -> flatrev(Ls, [C | Acc]);
> flatrev([L | Ls], Acc) -> flatrev(Ls, flatrev(L, Acc));
> flatrev([], Acc) -> Acc.
>
>
> %% Count the number of elements in a nested list.
> reclength([L | Ls]) when is_list(L) ->
> reclength(L) + reclength(Ls);
> reclength([_ | Ls]) ->
> reclength(Ls) + 1;
> reclength([]) -> 0.
>
> %%% tags.erl ends here.
otp-OTP-19.3.6.5 = from otp-OTP-19.3.6.5.zip
page https://github.com/erlang/otp/releases/tag/OTP-19.3.6.5
link https://github.com/erlang/otp/archive/refs/tags/OTP-19.3.6.5.zip ("Source code (zip)" - bottom)
erlang-otp-6356f67 = from erlang-otp-OTP-19.3.6.5-0-g2e7160f.tar.gz
page https://www.erlang.org/patches/otp-19.3.6.5
link https://api.github.com/repos/erlang/otp/tarball/refs/tags/OTP-19.3.6.5 (red button "Download source" - right top)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment