Feng 9 лет назад
Родитель
Сommit
3406137433
7 измененных файлов с 1049 добавлено и 9 удалено
  1. 1 0
      .gitignore
  2. 19 8
      Makefile
  3. 252 0
      etc/emqttd.2.0.conf
  4. 192 0
      etc/emqttd.conf
  5. 210 0
      etc/emqttd.conf.3
  6. 374 0
      priv/emqttd.schema
  7. 1 1
      rebar.config

+ 1 - 0
.gitignore

@@ -27,3 +27,4 @@ ct.coverdata
 .idea/
 emqttd.iml
 _rel/
+data/

+ 19 - 8
Makefile

@@ -1,15 +1,23 @@
 PROJECT = emqttd
 PROJECT_DESCRIPTION = Erlang MQTT Broker
-PROJECT_VERSION = 2.0
+PROJECT_VERSION = 3.0
 
-DEPS = gproc lager gen_logger gen_conf esockd mochiweb
+DEPS = gproc lager gen_logger esockd mochiweb getopt pbkdf2 \
+	   clique time_compat rand_compat
 
-dep_gproc      = git https://github.com/uwiger/gproc
-dep_lager      = git https://github.com/basho/lager
-dep_gen_conf   = git https://github.com/emqtt/gen_conf
-dep_gen_logger = git https://github.com/emqtt/gen_logger
-dep_esockd     = git https://github.com/emqtt/esockd emq20
-dep_mochiweb   = git https://github.com/emqtt/mochiweb
+dep_gproc       = git https://github.com/uwiger/gproc
+dep_getopt      = git https://github.com/jcomellas/getopt v0.8.2
+dep_lager       = git https://github.com/basho/lager master
+dep_gen_logger  = git https://github.com/emqtt/gen_logger
+dep_esockd      = git https://github.com/emqtt/esockd emq20
+dep_mochiweb    = git https://github.com/emqtt/mochiweb
+dep_clique      = git https://github.com/basho/clique
+dep_pbkdf2	    = git https://github.com/basho/erlang-pbkdf2 2.0.0
+dep_time_compat = git https://github.com/lasp-lang/time_compat
+dep_rand_compat = git https://github.com/lasp-lang/rand_compat
+
+BUILD_DEPS = cuttlefish
+dep_cuttlefish = git https://github.com/basho/cuttlefish master
 
 ERLC_OPTS += +'{parse_transform, lager_transform}'
 
@@ -29,3 +37,6 @@ include erlang.mk
 
 app:: rebar.config
 
+app.config::
+	cuttlefish -l info -e etc/ -c etc/emqttd.conf -i priv/emqttd.schema -d data
+

+ 252 - 0
etc/emqttd.2.0.conf

@@ -0,0 +1,252 @@
+
+%%--------------------------------------------------------------------
+%% MQTT Protocol
+%%--------------------------------------------------------------------
+
+%% Max ClientId Length Allowed.
+{mqtt_max_clientid_len, 512}.
+
+%% Max Packet Size Allowed, 64K by default.
+{mqtt_max_packet_size, 65536}.
+
+%% Client Idle Timeout.
+{mqtt_client_idle_timeout, 30}. % Second
+
+%%--------------------------------------------------------------------
+%% Authentication
+%%--------------------------------------------------------------------
+
+%% Anonymous: Allow all
+{auth, anonymous, []}.
+
+%% Authentication with username, password
+{auth, username, [{passwd, "etc/modules/passwd.conf"}]}.
+
+%% Authentication with clientId
+{auth, clientid, [{config, "etc/modules/client.conf"}, {password, no}]}.
+
+%%--------------------------------------------------------------------
+%% ACL
+%%--------------------------------------------------------------------
+
+{acl, anonymous, []}.
+
+{acl, internal, [{config, "etc/modules/acl.conf"}, {nomatch, allow}]}.
+
+%% Cache ACL result for PUBLISH
+{cache_acl, true}.
+
+
+%%--------------------------------------------------------------------
+%% Session
+%%--------------------------------------------------------------------
+
+%% Max number of QoS 1 and 2 messages that can be “inflight” at one time.
+%% 0 means no limit
+{session_max_inflight, 100}.
+
+%% Retry interval for redelivering QoS1/2 messages.
+{session_unack_retry_interval, 60}.
+
+%% Awaiting PUBREL Timeout
+{session_await_rel_timeout, 20}.
+
+%% Max Packets that Awaiting PUBREL, 0 means no limit
+{session_max_awaiting_rel, 0}.
+
+%% Statistics Collection Interval(seconds)
+{session_collect_interval, 0}.
+
+%% Expired after 2 day (unit: minute)
+{session_expired_after, 2880}.
+
+%%--------------------------------------------------------------------
+%% Queue
+%%--------------------------------------------------------------------
+
+%% Type: simple | priority
+{queue_type, simple}.
+
+%% Topic Priority: 0~255, Default is 0
+%% {queue_priority, [{"topic/1", 10}, {"topic/2", 8}]}.
+
+%% Max queue length. Enqueued messages when persistent client disconnected,
+%% or inflight window is full.
+{queue_max_length, infinity}.
+
+%% Low-water mark of queued messages
+{queue_low_watermark, 0.2}.
+
+%% High-water mark of queued messages
+{queue_high_watermark, 0.6}.
+
+%% Queue Qos0 messages?
+{queue_qos0, true}.
+
+%%--------------------------------------------------------------------
+%% Listener
+%%--------------------------------------------------------------------
+
+%% Plain MQTT
+{listener, mqtt, 1883, [
+    %% Size of acceptor pool
+    {acceptors, 16},
+
+    %% Maximum number of concurrent clients
+    {max_clients, 512},
+
+    %% Mount point prefix
+    %% {mount_point, "prefix/"},
+
+    %% Socket Access Control
+    {access, [{allow, all}]},
+
+    %% Connection Options
+    {connopts, [
+        %% Rate Limit. Format is 'burst, rate', Unit is KB/Sec
+        %% {rate_limit, "100,10"} %% 100K burst, 10K rate
+    ]},
+
+    %% Socket Options
+    {sockopts, [
+        %Set buffer if hight thoughtput
+        %{recbuf, 4096},
+        %{sndbuf, 4096},
+        %{buffer, 4096},
+        %{nodelay, true},
+        {backlog, 1024}
+    ]}
+]}.
+
+%% MQTT/SSL
+{listener, mqtts, 8883, [
+    %% Size of acceptor pool
+    {acceptors, 4},
+
+    %% Maximum number of concurrent clients
+    {max_clients, 512},
+
+    %% Mount point prefix
+    %% {mount_point, "secure/"},
+
+    %% Socket Access Control
+    {access, [{allow, all}]},
+
+    %% SSL certificate and key files
+    {ssl, [{handshake_timeout, 10000},
+           %% Mutual SSL Authentication option
+           %% {verify, verify_peer},
+           %% {cacertfile, "etc/ssl/ca.pem"},
+           {certfile, "etc/ssl/ssl.crt"},
+           {keyfile,  "etc/ssl/ssl.key"}]},
+
+    %% Socket Options
+    {sockopts, [
+        {backlog, 1024}
+        %{buffer, 4096},
+    ]}
+]}.
+
+%% HTTP and WebSocket Listener
+{listener, http, 8083, [
+    %% Size of acceptor pool
+    {acceptors, 4},
+
+    %% Maximum number of concurrent clients
+    {max_clients, 64},
+
+    %% Socket Access Control
+    {access, [{allow, all}]},
+
+    %% Socket Options
+    {sockopts, [
+        {backlog, 1024}
+        %{buffer, 4096},
+    ]}
+]}.
+
+%%--------------------------------------------------------------------
+%% PubSub
+%%--------------------------------------------------------------------
+
+%% PubSub Pool Size. Default should be scheduler numbers.
+{pubsub_pool_size, 8}.
+
+{pubsub_by_clientid, true}.
+
+%% Subscribe Asynchronously
+{pubsub_async, true}.
+
+%%--------------------------------------------------------------------
+%% Bridge
+%%--------------------------------------------------------------------
+
+%% TODO: Bridge Queue Size
+{bridge_max_queue_len, 10000}.
+
+%% Ping Interval of bridge node
+{bridge_ping_down_interval, 1}. % second
+
+%%-------------------------------------------------------------------
+%% Plugins
+%%-------------------------------------------------------------------
+
+%% Dir of plugins' config
+{plugins_etc_dir, "etc/plugins/"}.
+
+%% File to store loaded plugin names.
+{plugins_loaded_file, "data/loaded_plugins"}.
+
+%%--------------------------------------------------------------------
+%% Modules
+%%--------------------------------------------------------------------
+
+%% Retainer Module
+{module, retainer, [
+
+    %% disc: disc_copies, ram: ram_copies
+    {storage_type, disc},
+
+    %% Max number of retained messages
+    {max_message_num, 100000},
+
+    %% Max Payload Size of retained message
+    {max_playload_size, 65536},
+
+    %% Expired after seconds, never expired if 0
+    {expired_after, 0}
+
+]}.
+
+%% Client presence management module. Publish presence messages when 
+%% client connected or disconnected.
+{module, presence, [{qos, 0}]}.
+
+%% Subscribe topics automatically when client connected
+{module, subscription, [{"$client/%c", 1}]}.
+
+%% [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite)
+%% {module, rewrite, [{config, "etc/modules/rewrite.conf"}]}.
+
+%%-------------------------------------------------------------------
+%% Erlang System Monitor
+%%-------------------------------------------------------------------
+
+%% Long GC, don't monitor in production mode for:
+%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
+
+{sysmon_long_gc, false}.
+
+%% Long Schedule(ms)
+{sysmon_long_schedule, 240}.
+
+%% 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM.
+%% 8 * 1024 * 1024
+{sysmon_large_heap, 8388608}.
+
+%% Busy Port
+{sysmon_busy_port, false}.
+
+%% Busy Dist Port
+{sysmon_busy_dist_port, true}.
+

+ 192 - 0
etc/emqttd.conf

@@ -0,0 +1,192 @@
+##====================================================================
+##
+## Config File for EMQ 3.0
+##
+##====================================================================
+
+##--------------------------------------------------------------------
+## Erlang VM Args
+##--------------------------------------------------------------------
+
+## Erlang Node Name
+vm.nodename = emqttd@127.0.0.1
+
+## Cookie for distributed erlang
+vm.setcookie = emqttdsecretcookie
+
+## SMP support: enable, auto, disable
+vm.smp = auto
+
+## Enable kernel poll
+vm.kernel_poll = on
+
+## async thread pool
+vm.async_threads = 32
+
+## Erlang Process Limit
+vm.process_limit = 256000
+
+## Sets the maximum number of simultaneously existing ports for this system
+vm.max_ports = 262144
+
+## Set the distribution buffer busy limit (dist_buf_busy_limit)
+vm.dist_buffer_size = 32MB
+
+## Max ETS Tables.
+## Note that mnesia and SSL will create temporary ets tables.
+vm.max_ets_tables = 256000
+
+## Tweak GC to run more often
+vm.fullsweep_after = 1000
+
+vm.crash_dump = log/emqttd_crash.dump
+
+##--------------------------------------------------------------------
+## MQTT Protocol
+##--------------------------------------------------------------------
+
+## Max ClientId Length Allowed.
+mqtt.max_clientid_len = 1024
+
+## Max Packet Size Allowed, 64K by default.
+mqtt.max_packet_size = 64KB
+
+## Client Idle Timeout (Second)
+mqtt.client_idle_timeout = 30
+
+##--------------------------------------------------------------------
+## MQTT Listeners
+##--------------------------------------------------------------------
+
+## {listener, mqtt, 1883, [
+##    %% Size of acceptor pool
+##    {acceptors, 16},
+##   %% Maximum number of concurrent clients
+##    {max_clients, 512},
+##    %% Mount point prefix
+##    %% {mount_point, "prefix/"},
+##    %% Socket Access Control
+##    {access, [{allow, all}]},
+##    %% Connection Options
+##    {connopts, [
+##        %% Rate Limit. Format is 'burst, rate', Unit is KB/Sec
+##        %% {rate_limit, "100,10"} %% 100K burst, 10K rate
+##    ]},
+##    %% Socket Options
+##    {sockopts, [
+##        %Set buffer if hight thoughtput
+##        %{recbuf, 4096},
+##        %{sndbuf, 4096},
+##        %{buffer, 4096},
+##        %{nodelay, true},
+##        {backlog, 1024}
+##    ]}
+## ]}.
+
+listener.mqtt.plain = 1883
+## IPv6
+## listener.mqtt = 127.0.0.1:1883
+## IPv6
+## listener.mqtt = ::1:1883
+listener.mqtt.plain.acceptors = 16
+listener.mqtt.plain.max_clients = 512
+listener.mqtt.plain.rate_limit = 100,10
+listener.mqtt.plain.mount_point = prefix/
+
+listener.mqtts = 8883
+listener.mqtts.acceptors = 4
+listener.mqtts.max_clients = 512
+listener.mqtts.ssl.
+
+    %% SSL certificate and key files
+    {ssl, [{handshake_timeout, 10000},
+           %% Mutual SSL Authentication option
+           %% {verify, verify_peer},
+           %% {cacertfile, "etc/ssl/ca.pem"},
+           {certfile, "etc/ssl/ssl.crt"},
+           {keyfile,  "etc/ssl/ssl.key"}]},
+
+listener.http = 8083
+
+##--------------------------------------------------------------------
+## MQTT Session
+##--------------------------------------------------------------------
+
+## Max number of QoS 1 and 2 messages that can be “inflight” at one time.
+## 0 means no limit
+mqtt.session.max_inflight = 100
+
+## Retry interval for redelivering QoS1/2 messages.
+mqtt.session.unack_retry_interval = 60
+
+## Awaiting PUBREL Timeout
+mqtt.session.await_rel_timeout = 20
+
+## Max Packets that Awaiting PUBREL, 0 means no limit
+mqtt.session.max_awaiting_rel = 0
+
+## Statistics Collection Interval(seconds)
+mqtt.session.collect_interval = 0
+
+## Expired after 2 day (unit: minute)
+mqtt.session.expired_after = 2880
+
+##--------------------------------------------------------------------
+## MQTT Queue Parameters
+##--------------------------------------------------------------------
+
+## Type: simple | priority
+mqtt.queue_type = simple
+
+## Topic Priority: 0~255, Default is 0
+## mqtt.queue_priority = topic/1=10,topic/2=8
+
+## Max queue length. Enqueued messages when persistent client disconnected,
+## or inflight window is full.
+mqtt.queue_max_length = infinity
+
+## Low-water mark of queued messages
+mqtt.queue_low_watermark = 0.2
+
+## High-water mark of queued messages
+mqtt.queue_high_watermark = 0.6
+
+## Queue Qos0 messages?
+mqtt.queue_qos0 = true
+
+##--------------------------------------------------------------------
+## Broker
+##--------------------------------------------------------------------
+
+## System Interval of publishing broker $SYS Messages
+broker.sys_interval = 60
+
+
+##-------------------------------------------------------------------
+## Log
+##-------------------------------------------------------------------
+
+
+
+##-------------------------------------------------------------------
+## System Monitor
+##-------------------------------------------------------------------
+
+## Long GC, don't monitor in production mode for:
+## https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
+
+sysmon.long_gc = false
+
+## Long Schedule(ms)
+sysmon.long_schedule = 240
+
+## 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM.
+## 8 * 1024 * 1024
+sysmon.large_heap = 8388608
+
+## Busy Port
+sysmon.busy_port = false
+
+## Busy Dist Port
+sysmon.busy_dist_port = true
+

+ 210 - 0
etc/emqttd.conf.3

@@ -0,0 +1,210 @@
+##===================================================================
+##
+## Config file for EMQ 3.0
+##
+##===================================================================
+
+##--------------------------------------------------------------------
+## Authentication
+##--------------------------------------------------------------------
+
+%% Anonymous: Allow all
+{auth, anonymous, []}.
+
+%% Authentication with username, password
+{auth, username, [{passwd, "etc/modules/passwd.conf"}]}.
+
+%% Authentication with clientId
+{auth, clientid, [{config, "etc/modules/client.conf"}, {password, no}]}.
+
+%%--------------------------------------------------------------------
+%% ACL
+%%--------------------------------------------------------------------
+
+{acl, anonymous, []}.
+
+{acl, internal, [{config, "etc/modules/acl.conf"}, {nomatch, allow}]}.
+
+%% Cache ACL result for PUBLISH
+{cache_acl, true}.
+
+##--------------------------------------------------------------------
+## Broker
+##--------------------------------------------------------------------
+
+## System interval of publishing broker $SYS messages
+broker.sys_interval = 60.
+
+##--------------------------------------------------------------------
+## Session
+##--------------------------------------------------------------------
+
+
+
+%%--------------------------------------------------------------------
+%% Listener
+%%--------------------------------------------------------------------
+
+%% Plain MQTT
+{listener, mqtt, 1883, [
+    %% Size of acceptor pool
+    {acceptors, 16},
+
+    %% Maximum number of concurrent clients
+    {max_clients, 512},
+
+    %% Mount point prefix
+    %% {mount_point, "prefix/"},
+
+    %% Socket Access Control
+    {access, [{allow, all}]},
+
+    %% Connection Options
+    {connopts, [
+        %% Rate Limit. Format is 'burst, rate', Unit is KB/Sec
+        %% {rate_limit, "100,10"} %% 100K burst, 10K rate
+    ]},
+
+    %% Socket Options
+    {sockopts, [
+        %Set buffer if hight thoughtput
+        %{recbuf, 4096},
+        %{sndbuf, 4096},
+        %{buffer, 4096},
+        %{nodelay, true},
+        {backlog, 1024}
+    ]}
+]}.
+
+%% MQTT/SSL
+{listener, mqtts, 8883, [
+    %% Size of acceptor pool
+    {acceptors, 4},
+
+    %% Maximum number of concurrent clients
+    {max_clients, 512},
+
+    %% Mount point prefix
+    %% {mount_point, "secure/"},
+
+    %% Socket Access Control
+    {access, [{allow, all}]},
+
+    %% SSL certificate and key files
+    {ssl, [{handshake_timeout, 10000},
+           %% Mutual SSL Authentication option
+           %% {verify, verify_peer},
+           %% {cacertfile, "etc/ssl/ca.pem"},
+           {certfile, "etc/ssl/ssl.crt"},
+           {keyfile,  "etc/ssl/ssl.key"}]},
+
+    %% Socket Options
+    {sockopts, [
+        {backlog, 1024}
+        %{buffer, 4096},
+    ]}
+]}.
+
+%% HTTP and WebSocket Listener
+{listener, http, 8083, [
+    %% Size of acceptor pool
+    {acceptors, 4},
+
+    %% Maximum number of concurrent clients
+    {max_clients, 64},
+
+    %% Socket Access Control
+    {access, [{allow, all}]},
+
+    %% Socket Options
+    {sockopts, [
+        {backlog, 1024}
+        %{buffer, 4096},
+    ]}
+]}.
+
+%%--------------------------------------------------------------------
+%% PubSub
+%%--------------------------------------------------------------------
+
+%% PubSub Pool Size. Default should be scheduler numbers.
+{pubsub_pool_size, 8}.
+
+{pubsub_by_clientid, true}.
+
+%% Subscribe Asynchronously
+{pubsub_async, true}.
+
+%%--------------------------------------------------------------------
+%% Bridge
+%%--------------------------------------------------------------------
+
+%% TODO: Bridge Queue Size
+{bridge_max_queue_len, 10000}.
+
+%% Ping Interval of bridge node
+{bridge_ping_down_interval, 1}. % second
+
+%%-------------------------------------------------------------------
+%% Plugins
+%%-------------------------------------------------------------------
+
+%% Dir of plugins' config
+{plugins_etc_dir, "etc/plugins/"}.
+
+%% File to store loaded plugin names.
+{plugins_loaded_file, "data/loaded_plugins"}.
+
+%%--------------------------------------------------------------------
+%% Modules
+%%--------------------------------------------------------------------
+
+%% Retainer Module
+{module, retainer, [
+
+    %% disc: disc_copies, ram: ram_copies
+    {storage_type, disc},
+
+    %% Max number of retained messages
+    {max_message_num, 100000},
+
+    %% Max Payload Size of retained message
+    {max_playload_size, 65536},
+
+    %% Expired after seconds, never expired if 0
+    {expired_after, 0}
+
+]}.
+
+%% Client presence management module. Publish presence messages when 
+%% client connected or disconnected.
+{module, presence, [{qos, 0}]}.
+
+%% Subscribe topics automatically when client connected
+{module, subscription, [{"$client/%c", 1}]}.
+
+%% [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite)
+%% {module, rewrite, [{config, "etc/modules/rewrite.conf"}]}.
+
+%%-------------------------------------------------------------------
+%% Erlang System Monitor
+%%-------------------------------------------------------------------
+
+%% Long GC, don't monitor in production mode for:
+%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
+
+sysmon.long_gc = false
+
+%% Long Schedule(ms)
+sysmon.long_schedule = 240
+
+%% 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM.
+%% 8 * 1024 * 1024
+sysmon.large_heap = 8388608
+
+%% Busy Port
+sysmon.busy_port = false
+
+%% Busy Dist Port
+sysmon.busy_dist_port = true
+

+ 374 - 0
priv/emqttd.schema

@@ -0,0 +1,374 @@
+%%-*- mode: erlang -*-
+%% EMQ 3.0 Config Mapping
+
+%%--------------------------------------------------------------------
+%% Erlang VM Args
+%%--------------------------------------------------------------------
+
+{mapping, "vm.nodename", "vm_args.-name", [
+  {default, "{{node}}"}
+]}.
+
+{mapping, "vm.setcookie", "vm_args.-setcookie", [
+  {default, "emqttd"}
+]}.
+
+{mapping, "vm.smp", "vm_args.-smp", [
+  {default, enable},
+  {datatype, {enum, [enable, auto, disable]}},
+  hidden
+]}.
+
+{mapping, "vm.kernel_poll", "vm_args.+K", [
+  {default, on},
+  {datatype, flag},
+  hidden
+]}.
+
+%% More information at: http://erlang.org/doc/man/erl.html
+{mapping, "vm.async_threads", "vm_args.+A", [
+  {default, 64},
+  {datatype, integer},
+  {validators, ["range:0-1024"]}
+]}.
+
+%% @doc Erlang Process Limit
+{mapping, "vm.process_limit", "vm_args.+P", [
+  {datatype, integer},
+  {default, 256000},
+  hidden
+]}.
+
+%% Note: OTP R15 and earlier uses -env ERL_MAX_PORTS, R16+ uses +Q
+%% @doc The number of concurrent ports/sockets
+%% Valid range is 1024-134217727
+{mapping, "vm.max_ports",
+  cuttlefish:otp("R16", "vm_args.+Q", "vm_args.-env ERL_MAX_PORTS"), [
+  {default, 262144},
+  {datatype, integer},
+  {validators, ["range4ports"]}
+]}.
+
+{validator, "range4ports", "must be 1024 to 134217727",
+ fun(X) -> X >= 1024 andalso X =< 134217727 end}.
+
+%% @doc For nodes with many busy_dist_port events, Basho recommends
+%% raising the sender-side network distribution buffer size.
+%% 32MB may not be sufficient for some workloads and is a suggested
+%% starting point. Erlangers may know this as +zdbbl.
+%% The Erlang/OTP default is 1024 (1 megabyte).
+%% See: http://www.erlang.org/doc/man/erl.html#%2bzdbbl
+{mapping, "vm.dist_buffer_size", "vm_args.+zdbbl", [
+  {datatype, bytesize},
+  {commented, "32MB"},
+  hidden,
+  {validators, ["zdbbl_range"]}
+]}.
+
+{translation, "vm_args.+zdbbl",
+ fun(Conf) ->
+  ZDBBL = cuttlefish:conf_get("vm.dist_buffer_size", Conf, undefined),
+  case ZDBBL of
+    undefined -> undefined;
+    X when is_integer(X) -> cuttlefish_util:ceiling(X / 1024); %% Bytes to Kilobytes;
+    _ -> undefined
+  end
+ end
+}.
+
+{validator, "zdbbl_range", "must be between 1KB and 2097151KB",
+ fun(ZDBBL) ->
+  %% 2097151KB = 2147482624
+  ZDBBL >= 1024 andalso ZDBBL =< 2147482624
+ end
+}.
+
+%% @doc A non-negative integer which indicates how many times
+%% generational garbage collections can be done without forcing a
+%% fullsweep collection. In low-memory systems (especially without
+%% virtual memory), setting the value to 0 can help to conserve
+%% memory.
+%%
+%% More information at:
+%% http://www.erlang.org/doc/man/erlang.html#system_flag-2
+{mapping, "vm.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [
+  {default, 1000},
+  {datatype, integer},
+  hidden,
+  {validators, ["positive_integer"]}
+]}.
+
+{validator, "positive_integer", "must be a positive integer",
+  fun(X) -> X >= 0 end}.
+
+%% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES,
+%% R16+ uses +e
+%% @doc Raise the ETS table limit
+{mapping, "vm.max_ets_tables",
+  cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [
+  {default, 256000},
+  {datatype, integer},
+  hidden
+]}.
+
+%% @doc Set the location of crash dumps
+{mapping, "vm.crash_dump", "vm_args.-env ERL_CRASH_DUMP", [
+  {default, "{{crash_dump}}"},
+  {datatype, file},
+  hidden
+]}.
+
+{mapping, "mqtt.max_clientid_len", "emqttd.mqtt_max_clientid_len", [
+  {default, 1024},
+  {datatype, integer}
+]}.
+
+{mapping, "mqtt.max_packet_size", "emqttd.mqtt_max_packet_size", [
+  {datatype, bytesize}
+]}.
+
+{mapping, "mqtt.client_idle_timeout", "emqttd.mqtt_client_idle_timeout", [
+  {datatype, integer}
+]}.
+
+{mapping, "sysmon.long_gc", "emqttd.sysmon", [
+  {default, false},
+  {datatype, {enum, [true, false]}}
+]}.
+
+{mapping, "sysmon.long_schedule", "emqttd.sysmon", [
+  {default, 1000},
+  {datatype, integer}
+]}.
+
+{mapping, "sysmon.large_heap", "emqttd.sysmon", [
+  {datatype, integer}
+]}.
+
+{mapping, "sysmon.busy_port", "emqttd.sysmon", [
+  {default, false},
+  {datatype, {enum, [true, false]}}
+]}.
+
+{mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [
+  {default, true},
+  {datatype, {enum, [true, false]}}
+]}.
+
+{translation, "emqttd.sysmon", fun(Conf) ->
+    [{long_gc, cuttlefish:conf_get("sysmon.long_gc", Conf)},
+     {long_schedule, cuttlefish:conf_get("sysmon.long_schedule", Conf)},
+     {large_heap, cuttlefish:conf_get("sysmon.large_heap", Conf)},
+     {busy_port, cuttlefish:conf_get("sysmon.busy_port", Conf)},
+     {busy_dist_port, cuttlefish:conf_get("sysmon.busy_dist_port", Conf)}]
+end}.
+
+%% @doc Where to emit the default log messages (typically at 'info'
+%% severity):
+%%     off: disabled
+%%    file: the file specified by log.console.file
+%% console: to standard output (seen when using `riak attach-direct`)
+%%    both: log.console.file and standard out.
+{mapping, "log.console", "lager.handlers", [
+  {default, file },
+  {datatype, {enum, [off, file, console, both]}}
+]}.
+
+%% @doc The severity level of the console log, default is 'info'.
+{mapping, "log.console.level", "lager.handlers", [
+  {default, info},
+  {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}}
+]}.
+
+%% @doc When 'log.console' is set to 'file' or 'both', the file where
+%% console messages will be logged.
+{mapping, "log.console.file", "lager.handlers", [
+  {default, "$(platform_log_dir)/console.log"},
+  {datatype, file}
+]}.
+
+%% @doc The file where error messages will be logged.
+{mapping, "log.error.file", "lager.handlers", [
+  {default, "$(platform_log_dir)/error.log"},
+  {datatype, file}
+]}.
+
+%% @doc When set to 'on', enables log output to syslog.
+{mapping, "log.syslog", "lager.handlers", [
+  {default, off},
+  {datatype, flag}
+]}.
+
+%% @doc When set to 'on', enables log output to syslog.
+{mapping, "log.syslog.ident", "lager.handlers", [
+  {default, "riak"},
+  hidden
+]}.
+
+%% @doc Syslog facility to log entries from Riak.
+{mapping, "log.syslog.facility", "lager.handlers", [
+  {default, daemon},
+  {datatype, {enum,[kern, user, mail, daemon, auth, syslog,
+                    lpr, news, uucp, clock, authpriv, ftp,
+                    cron, local0, local1, local2, local3,
+                    local4, local5, local6, local7]}},
+  hidden
+]}.
+
+%% @doc The severity level at which to log entries to syslog, default is 'info'.
+{mapping, "log.syslog.level", "lager.handlers", [
+  {default, info},
+  {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}},
+  hidden
+]}.
+
+{translation,
+ "lager.handlers",
+ fun(Conf) ->
+    SyslogHandler = case cuttlefish:conf_get("log.syslog", Conf) of
+      true ->
+        Ident = cuttlefish:conf_get("log.syslog.ident", Conf),
+        Facility = cuttlefish:conf_get("log.syslog.facility", Conf),
+        LogLevel = cuttlefish:conf_get("log.syslog.level", Conf),
+        [{lager_syslog_backend, [Ident, Facility, LogLevel]}];
+      _ -> []
+    end,
+    ErrorHandler = case cuttlefish:conf_get("log.error.file", Conf) of
+      undefined -> [];
+      ErrorFilename -> [{lager_file_backend, [{file, ErrorFilename},
+                                              {level, error},
+                                              {size, 10485760},
+                                              {date, "$D0"},
+                                              {count, 5}]}]
+    end,
+
+    ConsoleLogLevel = cuttlefish:conf_get("log.console.level", Conf),
+    ConsoleLogFile = cuttlefish:conf_get("log.console.file", Conf),
+
+    ConsoleHandler = {lager_console_backend, ConsoleLogLevel},
+    ConsoleFileHandler = {lager_file_backend, [{file, ConsoleLogFile},
+                                               {level, ConsoleLogLevel},
+                                               {size, 10485760},
+                                               {date, "$D0"},
+                                               {count, 5}]},
+
+    ConsoleHandlers = case cuttlefish:conf_get("log.console", Conf) of
+      off -> [];
+      file -> [ConsoleFileHandler];
+      console -> [ConsoleHandler];
+      both -> [ConsoleHandler, ConsoleFileHandler];
+      _ -> []
+    end,
+    SyslogHandler ++ ConsoleHandlers ++ ErrorHandler
+  end
+}.
+
+
+%% @doc Whether to enable Erlang's built-in error logger.
+{mapping, "sasl", "sasl.sasl_error_logger", [
+  {default, off},
+  {datatype, flag},
+  hidden
+]}.
+
+%% @doc Whether to enable the crash log.
+{mapping, "log.crash", "lager.crash_log", [
+  {default, on},
+  {datatype, flag}
+]}.
+
+%% @doc If the crash log is enabled, the file where its messages will
+%% be written.
+{mapping, "log.crash.file", "lager.crash_log", [
+  {default, "$(platform_log_dir)/crash.log"},
+  {datatype, file}
+]}.
+
+{translation,
+ "lager.crash_log",
+ fun(Conf) ->
+     case cuttlefish:conf_get("log.crash", Conf) of
+         false -> undefined;
+         _ ->
+             cuttlefish:conf_get("log.crash.file", Conf, "./log/crash.log")
+     end
+ end}.
+
+%% @doc Maximum size in bytes of individual messages in the crash log
+{mapping, "log.crash.maximum_message_size", "lager.crash_log_msg_size", [
+  {default, "64KB"},
+  {datatype, bytesize}
+]}.
+
+%% @doc Maximum size of the crash log in bytes, before it is rotated
+{mapping, "log.crash.size", "lager.crash_log_size", [
+  {default, "10MB"},
+  {datatype, bytesize}
+]}.
+
+%% @doc The schedule on which to rotate the crash log.  For more
+%% information see:
+%% https://github.com/basho/lager/blob/master/README.md#internal-log-rotation
+{mapping, "log.crash.rotation", "lager.crash_log_date", [
+  {default, "$D0"}
+]}.
+
+%% @doc The number of rotated crash logs to keep. When set to
+%% 'current', only the current open log file is kept.
+{mapping, "log.crash.rotation.keep", "lager.crash_log_count", [
+  {default, 5},
+  {datatype, [integer, {atom, current}]},
+  {validators, ["rotation_count"]}
+]}.
+
+{validator,
+ "rotation_count",
+ "must be 'current' or a positive integer",
+ fun(current) -> true;
+    (Int) when is_integer(Int) andalso Int >= 0 -> true;
+    (_) -> false
+ end}.
+
+{translation,
+ "lager.crash_log_count",
+ fun(Conf) ->
+    case cuttlefish:conf_get("log.crash.rotation.keep", Conf) of
+       current -> 0;
+       Int -> Int
+    end
+ end}.
+
+%% @doc Whether to redirect error_logger messages into lager -
+%% defaults to true
+{mapping, "log.error.redirect", "lager.error_logger_redirect", [
+  {default, on},
+  {datatype, flag},
+  hidden
+]}.
+
+%% @doc Maximum number of error_logger messages to handle in a second
+{mapping, "log.error.messages_per_second", "lager.error_logger_hwm", [
+  {default, 100},
+  {datatype, integer},
+  hidden
+]}.
+
+
+%% @doc Cookie for distributed node communication.  All nodes in the
+%% same cluster should use the same cookie or they will not be able to
+%% communicate.
+{mapping, "distributed_cookie", "vm_args.-setcookie", [
+  {default, "riak"}
+]}.
+
+%% @see platform_bin_dir
+{mapping, "platform_etc_dir", "emqttd.platform_etc_dir", [
+  {datatype, directory},
+  {default, "./etc"}
+]}.
+
+%% @see platform_bin_dir
+{mapping, "platform_log_dir", "emqttd.platform_log_dir", [
+  {datatype, directory},
+  {default, "./log"}
+]}.

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
rebar.config