From 5a8efd9d2070711257d80399efd61d02db2c08c1 Mon Sep 17 00:00:00 2001 From: terry-xiaoyu <506895667@qq.com> Date: Sat, 31 Oct 2020 09:19:28 +0800 Subject: [PATCH 01/48] feature(project): move src to apps/emqx/src --- {src => apps/emqx/src}/emqx.app.src | 0 {src => apps/emqx/src}/emqx.app.src.script | 0 {src => apps/emqx/src}/emqx.appup.src | 0 {src => apps/emqx/src}/emqx.erl | 0 {src => apps/emqx/src}/emqx_access_control.erl | 0 {src => apps/emqx/src}/emqx_access_rule.erl | 0 {src => apps/emqx/src}/emqx_acl_cache.erl | 0 {src => apps/emqx/src}/emqx_alarm.erl | 0 {src => apps/emqx/src}/emqx_alarm_handler.erl | 0 {src => apps/emqx/src}/emqx_app.erl | 0 {src => apps/emqx/src}/emqx_banned.erl | 0 {src => apps/emqx/src}/emqx_base62.erl | 0 {src => apps/emqx/src}/emqx_batch.erl | 0 {src => apps/emqx/src}/emqx_boot.erl | 0 {src => apps/emqx/src}/emqx_broker.erl | 0 {src => apps/emqx/src}/emqx_broker_helper.erl | 0 {src => apps/emqx/src}/emqx_broker_sup.erl | 0 {src => apps/emqx/src}/emqx_channel.erl | 0 {src => apps/emqx/src}/emqx_cm.erl | 0 {src => apps/emqx/src}/emqx_cm_locker.erl | 0 {src => apps/emqx/src}/emqx_cm_registry.erl | 0 {src => apps/emqx/src}/emqx_cm_sup.erl | 0 {src => apps/emqx/src}/emqx_connection.erl | 0 {src => apps/emqx/src}/emqx_ctl.erl | 0 {src => apps/emqx/src}/emqx_flapping.erl | 0 {src => apps/emqx/src}/emqx_frame.erl | 0 {src => apps/emqx/src}/emqx_gc.erl | 0 {src => apps/emqx/src}/emqx_gen_mod.erl | 0 {src => apps/emqx/src}/emqx_global_gc.erl | 0 {src => apps/emqx/src}/emqx_guid.erl | 0 {src => apps/emqx/src}/emqx_hooks.erl | 0 {src => apps/emqx/src}/emqx_inflight.erl | 0 {src => apps/emqx/src}/emqx_json.erl | 0 {src => apps/emqx/src}/emqx_keepalive.erl | 0 {src => apps/emqx/src}/emqx_kernel_sup.erl | 0 {src => apps/emqx/src}/emqx_limiter.erl | 0 {src => apps/emqx/src}/emqx_listeners.erl | 0 {src => apps/emqx/src}/emqx_logger.erl | 0 {src => apps/emqx/src}/emqx_logger_formatter.erl | 0 {src => apps/emqx/src}/emqx_message.erl | 0 {src => apps/emqx/src}/emqx_metrics.erl | 0 {src => apps/emqx/src}/emqx_misc.erl | 0 {src => apps/emqx/src}/emqx_mod_acl_internal.erl | 0 {src => apps/emqx/src}/emqx_mod_delayed.erl | 0 {src => apps/emqx/src}/emqx_mod_presence.erl | 0 {src => apps/emqx/src}/emqx_mod_rewrite.erl | 0 {src => apps/emqx/src}/emqx_mod_subscription.erl | 0 {src => apps/emqx/src}/emqx_mod_sup.erl | 0 {src => apps/emqx/src}/emqx_mod_topic_metrics.erl | 0 {src => apps/emqx/src}/emqx_modules.erl | 0 {src => apps/emqx/src}/emqx_mountpoint.erl | 0 {src => apps/emqx/src}/emqx_mqtt_caps.erl | 0 {src => apps/emqx/src}/emqx_mqtt_props.erl | 0 {src => apps/emqx/src}/emqx_mqueue.erl | 0 {src => apps/emqx/src}/emqx_os_mon.erl | 0 {src => apps/emqx/src}/emqx_packet.erl | 0 {src => apps/emqx/src}/emqx_pd.erl | 0 {src => apps/emqx/src}/emqx_plugins.erl | 0 {src => apps/emqx/src}/emqx_pmon.erl | 0 {src => apps/emqx/src}/emqx_pool.erl | 0 {src => apps/emqx/src}/emqx_pool_sup.erl | 0 {src => apps/emqx/src}/emqx_pqueue.erl | 0 {src => apps/emqx/src}/emqx_psk.erl | 0 {src => apps/emqx/src}/emqx_reason_codes.erl | 0 {src => apps/emqx/src}/emqx_router.erl | 0 {src => apps/emqx/src}/emqx_router_helper.erl | 0 {src => apps/emqx/src}/emqx_router_sup.erl | 0 {src => apps/emqx/src}/emqx_rpc.erl | 0 {src => apps/emqx/src}/emqx_sequence.erl | 0 {src => apps/emqx/src}/emqx_session.erl | 0 {src => apps/emqx/src}/emqx_shared_sub.erl | 0 {src => apps/emqx/src}/emqx_stats.erl | 0 {src => apps/emqx/src}/emqx_sup.erl | 0 {src => apps/emqx/src}/emqx_sys.erl | 0 {src => apps/emqx/src}/emqx_sys_mon.erl | 0 {src => apps/emqx/src}/emqx_sys_sup.erl | 0 {src => apps/emqx/src}/emqx_tables.erl | 0 {src => apps/emqx/src}/emqx_topic.erl | 0 {src => apps/emqx/src}/emqx_tracer.erl | 0 {src => apps/emqx/src}/emqx_trie.erl | 0 {src => apps/emqx/src}/emqx_types.erl | 0 {src => apps/emqx/src}/emqx_vm.erl | 0 {src => apps/emqx/src}/emqx_vm_mon.erl | 0 {src => apps/emqx/src}/emqx_ws_connection.erl | 0 {src => apps/emqx/src}/emqx_zone.erl | 0 85 files changed, 0 insertions(+), 0 deletions(-) rename {src => apps/emqx/src}/emqx.app.src (100%) rename {src => apps/emqx/src}/emqx.app.src.script (100%) rename {src => apps/emqx/src}/emqx.appup.src (100%) rename {src => apps/emqx/src}/emqx.erl (100%) rename {src => apps/emqx/src}/emqx_access_control.erl (100%) rename {src => apps/emqx/src}/emqx_access_rule.erl (100%) rename {src => apps/emqx/src}/emqx_acl_cache.erl (100%) rename {src => apps/emqx/src}/emqx_alarm.erl (100%) rename {src => apps/emqx/src}/emqx_alarm_handler.erl (100%) rename {src => apps/emqx/src}/emqx_app.erl (100%) rename {src => apps/emqx/src}/emqx_banned.erl (100%) rename {src => apps/emqx/src}/emqx_base62.erl (100%) rename {src => apps/emqx/src}/emqx_batch.erl (100%) rename {src => apps/emqx/src}/emqx_boot.erl (100%) rename {src => apps/emqx/src}/emqx_broker.erl (100%) rename {src => apps/emqx/src}/emqx_broker_helper.erl (100%) rename {src => apps/emqx/src}/emqx_broker_sup.erl (100%) rename {src => apps/emqx/src}/emqx_channel.erl (100%) rename {src => apps/emqx/src}/emqx_cm.erl (100%) rename {src => apps/emqx/src}/emqx_cm_locker.erl (100%) rename {src => apps/emqx/src}/emqx_cm_registry.erl (100%) rename {src => apps/emqx/src}/emqx_cm_sup.erl (100%) rename {src => apps/emqx/src}/emqx_connection.erl (100%) rename {src => apps/emqx/src}/emqx_ctl.erl (100%) rename {src => apps/emqx/src}/emqx_flapping.erl (100%) rename {src => apps/emqx/src}/emqx_frame.erl (100%) rename {src => apps/emqx/src}/emqx_gc.erl (100%) rename {src => apps/emqx/src}/emqx_gen_mod.erl (100%) rename {src => apps/emqx/src}/emqx_global_gc.erl (100%) rename {src => apps/emqx/src}/emqx_guid.erl (100%) rename {src => apps/emqx/src}/emqx_hooks.erl (100%) rename {src => apps/emqx/src}/emqx_inflight.erl (100%) rename {src => apps/emqx/src}/emqx_json.erl (100%) rename {src => apps/emqx/src}/emqx_keepalive.erl (100%) rename {src => apps/emqx/src}/emqx_kernel_sup.erl (100%) rename {src => apps/emqx/src}/emqx_limiter.erl (100%) rename {src => apps/emqx/src}/emqx_listeners.erl (100%) rename {src => apps/emqx/src}/emqx_logger.erl (100%) rename {src => apps/emqx/src}/emqx_logger_formatter.erl (100%) rename {src => apps/emqx/src}/emqx_message.erl (100%) rename {src => apps/emqx/src}/emqx_metrics.erl (100%) rename {src => apps/emqx/src}/emqx_misc.erl (100%) rename {src => apps/emqx/src}/emqx_mod_acl_internal.erl (100%) rename {src => apps/emqx/src}/emqx_mod_delayed.erl (100%) rename {src => apps/emqx/src}/emqx_mod_presence.erl (100%) rename {src => apps/emqx/src}/emqx_mod_rewrite.erl (100%) rename {src => apps/emqx/src}/emqx_mod_subscription.erl (100%) rename {src => apps/emqx/src}/emqx_mod_sup.erl (100%) rename {src => apps/emqx/src}/emqx_mod_topic_metrics.erl (100%) rename {src => apps/emqx/src}/emqx_modules.erl (100%) rename {src => apps/emqx/src}/emqx_mountpoint.erl (100%) rename {src => apps/emqx/src}/emqx_mqtt_caps.erl (100%) rename {src => apps/emqx/src}/emqx_mqtt_props.erl (100%) rename {src => apps/emqx/src}/emqx_mqueue.erl (100%) rename {src => apps/emqx/src}/emqx_os_mon.erl (100%) rename {src => apps/emqx/src}/emqx_packet.erl (100%) rename {src => apps/emqx/src}/emqx_pd.erl (100%) rename {src => apps/emqx/src}/emqx_plugins.erl (100%) rename {src => apps/emqx/src}/emqx_pmon.erl (100%) rename {src => apps/emqx/src}/emqx_pool.erl (100%) rename {src => apps/emqx/src}/emqx_pool_sup.erl (100%) rename {src => apps/emqx/src}/emqx_pqueue.erl (100%) rename {src => apps/emqx/src}/emqx_psk.erl (100%) rename {src => apps/emqx/src}/emqx_reason_codes.erl (100%) rename {src => apps/emqx/src}/emqx_router.erl (100%) rename {src => apps/emqx/src}/emqx_router_helper.erl (100%) rename {src => apps/emqx/src}/emqx_router_sup.erl (100%) rename {src => apps/emqx/src}/emqx_rpc.erl (100%) rename {src => apps/emqx/src}/emqx_sequence.erl (100%) rename {src => apps/emqx/src}/emqx_session.erl (100%) rename {src => apps/emqx/src}/emqx_shared_sub.erl (100%) rename {src => apps/emqx/src}/emqx_stats.erl (100%) rename {src => apps/emqx/src}/emqx_sup.erl (100%) rename {src => apps/emqx/src}/emqx_sys.erl (100%) rename {src => apps/emqx/src}/emqx_sys_mon.erl (100%) rename {src => apps/emqx/src}/emqx_sys_sup.erl (100%) rename {src => apps/emqx/src}/emqx_tables.erl (100%) rename {src => apps/emqx/src}/emqx_topic.erl (100%) rename {src => apps/emqx/src}/emqx_tracer.erl (100%) rename {src => apps/emqx/src}/emqx_trie.erl (100%) rename {src => apps/emqx/src}/emqx_types.erl (100%) rename {src => apps/emqx/src}/emqx_vm.erl (100%) rename {src => apps/emqx/src}/emqx_vm_mon.erl (100%) rename {src => apps/emqx/src}/emqx_ws_connection.erl (100%) rename {src => apps/emqx/src}/emqx_zone.erl (100%) diff --git a/src/emqx.app.src b/apps/emqx/src/emqx.app.src similarity index 100% rename from src/emqx.app.src rename to apps/emqx/src/emqx.app.src diff --git a/src/emqx.app.src.script b/apps/emqx/src/emqx.app.src.script similarity index 100% rename from src/emqx.app.src.script rename to apps/emqx/src/emqx.app.src.script diff --git a/src/emqx.appup.src b/apps/emqx/src/emqx.appup.src similarity index 100% rename from src/emqx.appup.src rename to apps/emqx/src/emqx.appup.src diff --git a/src/emqx.erl b/apps/emqx/src/emqx.erl similarity index 100% rename from src/emqx.erl rename to apps/emqx/src/emqx.erl diff --git a/src/emqx_access_control.erl b/apps/emqx/src/emqx_access_control.erl similarity index 100% rename from src/emqx_access_control.erl rename to apps/emqx/src/emqx_access_control.erl diff --git a/src/emqx_access_rule.erl b/apps/emqx/src/emqx_access_rule.erl similarity index 100% rename from src/emqx_access_rule.erl rename to apps/emqx/src/emqx_access_rule.erl diff --git a/src/emqx_acl_cache.erl b/apps/emqx/src/emqx_acl_cache.erl similarity index 100% rename from src/emqx_acl_cache.erl rename to apps/emqx/src/emqx_acl_cache.erl diff --git a/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl similarity index 100% rename from src/emqx_alarm.erl rename to apps/emqx/src/emqx_alarm.erl diff --git a/src/emqx_alarm_handler.erl b/apps/emqx/src/emqx_alarm_handler.erl similarity index 100% rename from src/emqx_alarm_handler.erl rename to apps/emqx/src/emqx_alarm_handler.erl diff --git a/src/emqx_app.erl b/apps/emqx/src/emqx_app.erl similarity index 100% rename from src/emqx_app.erl rename to apps/emqx/src/emqx_app.erl diff --git a/src/emqx_banned.erl b/apps/emqx/src/emqx_banned.erl similarity index 100% rename from src/emqx_banned.erl rename to apps/emqx/src/emqx_banned.erl diff --git a/src/emqx_base62.erl b/apps/emqx/src/emqx_base62.erl similarity index 100% rename from src/emqx_base62.erl rename to apps/emqx/src/emqx_base62.erl diff --git a/src/emqx_batch.erl b/apps/emqx/src/emqx_batch.erl similarity index 100% rename from src/emqx_batch.erl rename to apps/emqx/src/emqx_batch.erl diff --git a/src/emqx_boot.erl b/apps/emqx/src/emqx_boot.erl similarity index 100% rename from src/emqx_boot.erl rename to apps/emqx/src/emqx_boot.erl diff --git a/src/emqx_broker.erl b/apps/emqx/src/emqx_broker.erl similarity index 100% rename from src/emqx_broker.erl rename to apps/emqx/src/emqx_broker.erl diff --git a/src/emqx_broker_helper.erl b/apps/emqx/src/emqx_broker_helper.erl similarity index 100% rename from src/emqx_broker_helper.erl rename to apps/emqx/src/emqx_broker_helper.erl diff --git a/src/emqx_broker_sup.erl b/apps/emqx/src/emqx_broker_sup.erl similarity index 100% rename from src/emqx_broker_sup.erl rename to apps/emqx/src/emqx_broker_sup.erl diff --git a/src/emqx_channel.erl b/apps/emqx/src/emqx_channel.erl similarity index 100% rename from src/emqx_channel.erl rename to apps/emqx/src/emqx_channel.erl diff --git a/src/emqx_cm.erl b/apps/emqx/src/emqx_cm.erl similarity index 100% rename from src/emqx_cm.erl rename to apps/emqx/src/emqx_cm.erl diff --git a/src/emqx_cm_locker.erl b/apps/emqx/src/emqx_cm_locker.erl similarity index 100% rename from src/emqx_cm_locker.erl rename to apps/emqx/src/emqx_cm_locker.erl diff --git a/src/emqx_cm_registry.erl b/apps/emqx/src/emqx_cm_registry.erl similarity index 100% rename from src/emqx_cm_registry.erl rename to apps/emqx/src/emqx_cm_registry.erl diff --git a/src/emqx_cm_sup.erl b/apps/emqx/src/emqx_cm_sup.erl similarity index 100% rename from src/emqx_cm_sup.erl rename to apps/emqx/src/emqx_cm_sup.erl diff --git a/src/emqx_connection.erl b/apps/emqx/src/emqx_connection.erl similarity index 100% rename from src/emqx_connection.erl rename to apps/emqx/src/emqx_connection.erl diff --git a/src/emqx_ctl.erl b/apps/emqx/src/emqx_ctl.erl similarity index 100% rename from src/emqx_ctl.erl rename to apps/emqx/src/emqx_ctl.erl diff --git a/src/emqx_flapping.erl b/apps/emqx/src/emqx_flapping.erl similarity index 100% rename from src/emqx_flapping.erl rename to apps/emqx/src/emqx_flapping.erl diff --git a/src/emqx_frame.erl b/apps/emqx/src/emqx_frame.erl similarity index 100% rename from src/emqx_frame.erl rename to apps/emqx/src/emqx_frame.erl diff --git a/src/emqx_gc.erl b/apps/emqx/src/emqx_gc.erl similarity index 100% rename from src/emqx_gc.erl rename to apps/emqx/src/emqx_gc.erl diff --git a/src/emqx_gen_mod.erl b/apps/emqx/src/emqx_gen_mod.erl similarity index 100% rename from src/emqx_gen_mod.erl rename to apps/emqx/src/emqx_gen_mod.erl diff --git a/src/emqx_global_gc.erl b/apps/emqx/src/emqx_global_gc.erl similarity index 100% rename from src/emqx_global_gc.erl rename to apps/emqx/src/emqx_global_gc.erl diff --git a/src/emqx_guid.erl b/apps/emqx/src/emqx_guid.erl similarity index 100% rename from src/emqx_guid.erl rename to apps/emqx/src/emqx_guid.erl diff --git a/src/emqx_hooks.erl b/apps/emqx/src/emqx_hooks.erl similarity index 100% rename from src/emqx_hooks.erl rename to apps/emqx/src/emqx_hooks.erl diff --git a/src/emqx_inflight.erl b/apps/emqx/src/emqx_inflight.erl similarity index 100% rename from src/emqx_inflight.erl rename to apps/emqx/src/emqx_inflight.erl diff --git a/src/emqx_json.erl b/apps/emqx/src/emqx_json.erl similarity index 100% rename from src/emqx_json.erl rename to apps/emqx/src/emqx_json.erl diff --git a/src/emqx_keepalive.erl b/apps/emqx/src/emqx_keepalive.erl similarity index 100% rename from src/emqx_keepalive.erl rename to apps/emqx/src/emqx_keepalive.erl diff --git a/src/emqx_kernel_sup.erl b/apps/emqx/src/emqx_kernel_sup.erl similarity index 100% rename from src/emqx_kernel_sup.erl rename to apps/emqx/src/emqx_kernel_sup.erl diff --git a/src/emqx_limiter.erl b/apps/emqx/src/emqx_limiter.erl similarity index 100% rename from src/emqx_limiter.erl rename to apps/emqx/src/emqx_limiter.erl diff --git a/src/emqx_listeners.erl b/apps/emqx/src/emqx_listeners.erl similarity index 100% rename from src/emqx_listeners.erl rename to apps/emqx/src/emqx_listeners.erl diff --git a/src/emqx_logger.erl b/apps/emqx/src/emqx_logger.erl similarity index 100% rename from src/emqx_logger.erl rename to apps/emqx/src/emqx_logger.erl diff --git a/src/emqx_logger_formatter.erl b/apps/emqx/src/emqx_logger_formatter.erl similarity index 100% rename from src/emqx_logger_formatter.erl rename to apps/emqx/src/emqx_logger_formatter.erl diff --git a/src/emqx_message.erl b/apps/emqx/src/emqx_message.erl similarity index 100% rename from src/emqx_message.erl rename to apps/emqx/src/emqx_message.erl diff --git a/src/emqx_metrics.erl b/apps/emqx/src/emqx_metrics.erl similarity index 100% rename from src/emqx_metrics.erl rename to apps/emqx/src/emqx_metrics.erl diff --git a/src/emqx_misc.erl b/apps/emqx/src/emqx_misc.erl similarity index 100% rename from src/emqx_misc.erl rename to apps/emqx/src/emqx_misc.erl diff --git a/src/emqx_mod_acl_internal.erl b/apps/emqx/src/emqx_mod_acl_internal.erl similarity index 100% rename from src/emqx_mod_acl_internal.erl rename to apps/emqx/src/emqx_mod_acl_internal.erl diff --git a/src/emqx_mod_delayed.erl b/apps/emqx/src/emqx_mod_delayed.erl similarity index 100% rename from src/emqx_mod_delayed.erl rename to apps/emqx/src/emqx_mod_delayed.erl diff --git a/src/emqx_mod_presence.erl b/apps/emqx/src/emqx_mod_presence.erl similarity index 100% rename from src/emqx_mod_presence.erl rename to apps/emqx/src/emqx_mod_presence.erl diff --git a/src/emqx_mod_rewrite.erl b/apps/emqx/src/emqx_mod_rewrite.erl similarity index 100% rename from src/emqx_mod_rewrite.erl rename to apps/emqx/src/emqx_mod_rewrite.erl diff --git a/src/emqx_mod_subscription.erl b/apps/emqx/src/emqx_mod_subscription.erl similarity index 100% rename from src/emqx_mod_subscription.erl rename to apps/emqx/src/emqx_mod_subscription.erl diff --git a/src/emqx_mod_sup.erl b/apps/emqx/src/emqx_mod_sup.erl similarity index 100% rename from src/emqx_mod_sup.erl rename to apps/emqx/src/emqx_mod_sup.erl diff --git a/src/emqx_mod_topic_metrics.erl b/apps/emqx/src/emqx_mod_topic_metrics.erl similarity index 100% rename from src/emqx_mod_topic_metrics.erl rename to apps/emqx/src/emqx_mod_topic_metrics.erl diff --git a/src/emqx_modules.erl b/apps/emqx/src/emqx_modules.erl similarity index 100% rename from src/emqx_modules.erl rename to apps/emqx/src/emqx_modules.erl diff --git a/src/emqx_mountpoint.erl b/apps/emqx/src/emqx_mountpoint.erl similarity index 100% rename from src/emqx_mountpoint.erl rename to apps/emqx/src/emqx_mountpoint.erl diff --git a/src/emqx_mqtt_caps.erl b/apps/emqx/src/emqx_mqtt_caps.erl similarity index 100% rename from src/emqx_mqtt_caps.erl rename to apps/emqx/src/emqx_mqtt_caps.erl diff --git a/src/emqx_mqtt_props.erl b/apps/emqx/src/emqx_mqtt_props.erl similarity index 100% rename from src/emqx_mqtt_props.erl rename to apps/emqx/src/emqx_mqtt_props.erl diff --git a/src/emqx_mqueue.erl b/apps/emqx/src/emqx_mqueue.erl similarity index 100% rename from src/emqx_mqueue.erl rename to apps/emqx/src/emqx_mqueue.erl diff --git a/src/emqx_os_mon.erl b/apps/emqx/src/emqx_os_mon.erl similarity index 100% rename from src/emqx_os_mon.erl rename to apps/emqx/src/emqx_os_mon.erl diff --git a/src/emqx_packet.erl b/apps/emqx/src/emqx_packet.erl similarity index 100% rename from src/emqx_packet.erl rename to apps/emqx/src/emqx_packet.erl diff --git a/src/emqx_pd.erl b/apps/emqx/src/emqx_pd.erl similarity index 100% rename from src/emqx_pd.erl rename to apps/emqx/src/emqx_pd.erl diff --git a/src/emqx_plugins.erl b/apps/emqx/src/emqx_plugins.erl similarity index 100% rename from src/emqx_plugins.erl rename to apps/emqx/src/emqx_plugins.erl diff --git a/src/emqx_pmon.erl b/apps/emqx/src/emqx_pmon.erl similarity index 100% rename from src/emqx_pmon.erl rename to apps/emqx/src/emqx_pmon.erl diff --git a/src/emqx_pool.erl b/apps/emqx/src/emqx_pool.erl similarity index 100% rename from src/emqx_pool.erl rename to apps/emqx/src/emqx_pool.erl diff --git a/src/emqx_pool_sup.erl b/apps/emqx/src/emqx_pool_sup.erl similarity index 100% rename from src/emqx_pool_sup.erl rename to apps/emqx/src/emqx_pool_sup.erl diff --git a/src/emqx_pqueue.erl b/apps/emqx/src/emqx_pqueue.erl similarity index 100% rename from src/emqx_pqueue.erl rename to apps/emqx/src/emqx_pqueue.erl diff --git a/src/emqx_psk.erl b/apps/emqx/src/emqx_psk.erl similarity index 100% rename from src/emqx_psk.erl rename to apps/emqx/src/emqx_psk.erl diff --git a/src/emqx_reason_codes.erl b/apps/emqx/src/emqx_reason_codes.erl similarity index 100% rename from src/emqx_reason_codes.erl rename to apps/emqx/src/emqx_reason_codes.erl diff --git a/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl similarity index 100% rename from src/emqx_router.erl rename to apps/emqx/src/emqx_router.erl diff --git a/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl similarity index 100% rename from src/emqx_router_helper.erl rename to apps/emqx/src/emqx_router_helper.erl diff --git a/src/emqx_router_sup.erl b/apps/emqx/src/emqx_router_sup.erl similarity index 100% rename from src/emqx_router_sup.erl rename to apps/emqx/src/emqx_router_sup.erl diff --git a/src/emqx_rpc.erl b/apps/emqx/src/emqx_rpc.erl similarity index 100% rename from src/emqx_rpc.erl rename to apps/emqx/src/emqx_rpc.erl diff --git a/src/emqx_sequence.erl b/apps/emqx/src/emqx_sequence.erl similarity index 100% rename from src/emqx_sequence.erl rename to apps/emqx/src/emqx_sequence.erl diff --git a/src/emqx_session.erl b/apps/emqx/src/emqx_session.erl similarity index 100% rename from src/emqx_session.erl rename to apps/emqx/src/emqx_session.erl diff --git a/src/emqx_shared_sub.erl b/apps/emqx/src/emqx_shared_sub.erl similarity index 100% rename from src/emqx_shared_sub.erl rename to apps/emqx/src/emqx_shared_sub.erl diff --git a/src/emqx_stats.erl b/apps/emqx/src/emqx_stats.erl similarity index 100% rename from src/emqx_stats.erl rename to apps/emqx/src/emqx_stats.erl diff --git a/src/emqx_sup.erl b/apps/emqx/src/emqx_sup.erl similarity index 100% rename from src/emqx_sup.erl rename to apps/emqx/src/emqx_sup.erl diff --git a/src/emqx_sys.erl b/apps/emqx/src/emqx_sys.erl similarity index 100% rename from src/emqx_sys.erl rename to apps/emqx/src/emqx_sys.erl diff --git a/src/emqx_sys_mon.erl b/apps/emqx/src/emqx_sys_mon.erl similarity index 100% rename from src/emqx_sys_mon.erl rename to apps/emqx/src/emqx_sys_mon.erl diff --git a/src/emqx_sys_sup.erl b/apps/emqx/src/emqx_sys_sup.erl similarity index 100% rename from src/emqx_sys_sup.erl rename to apps/emqx/src/emqx_sys_sup.erl diff --git a/src/emqx_tables.erl b/apps/emqx/src/emqx_tables.erl similarity index 100% rename from src/emqx_tables.erl rename to apps/emqx/src/emqx_tables.erl diff --git a/src/emqx_topic.erl b/apps/emqx/src/emqx_topic.erl similarity index 100% rename from src/emqx_topic.erl rename to apps/emqx/src/emqx_topic.erl diff --git a/src/emqx_tracer.erl b/apps/emqx/src/emqx_tracer.erl similarity index 100% rename from src/emqx_tracer.erl rename to apps/emqx/src/emqx_tracer.erl diff --git a/src/emqx_trie.erl b/apps/emqx/src/emqx_trie.erl similarity index 100% rename from src/emqx_trie.erl rename to apps/emqx/src/emqx_trie.erl diff --git a/src/emqx_types.erl b/apps/emqx/src/emqx_types.erl similarity index 100% rename from src/emqx_types.erl rename to apps/emqx/src/emqx_types.erl diff --git a/src/emqx_vm.erl b/apps/emqx/src/emqx_vm.erl similarity index 100% rename from src/emqx_vm.erl rename to apps/emqx/src/emqx_vm.erl diff --git a/src/emqx_vm_mon.erl b/apps/emqx/src/emqx_vm_mon.erl similarity index 100% rename from src/emqx_vm_mon.erl rename to apps/emqx/src/emqx_vm_mon.erl diff --git a/src/emqx_ws_connection.erl b/apps/emqx/src/emqx_ws_connection.erl similarity index 100% rename from src/emqx_ws_connection.erl rename to apps/emqx/src/emqx_ws_connection.erl diff --git a/src/emqx_zone.erl b/apps/emqx/src/emqx_zone.erl similarity index 100% rename from src/emqx_zone.erl rename to apps/emqx/src/emqx_zone.erl From d90c0dacb1dccff23cfb62f42c1c79dd80460388 Mon Sep 17 00:00:00 2001 From: terry-xiaoyu <506895667@qq.com> Date: Sat, 31 Oct 2020 09:33:50 +0800 Subject: [PATCH 02/48] feature(project): move hrl files and emqx_logger.erl to apps/emqx_libs --- {include => apps/emqx_libs/include}/emqx.hrl | 0 {include => apps/emqx_libs/include}/emqx_mqtt.hrl | 0 {include => apps/emqx_libs/include}/logger.hrl | 0 {include => apps/emqx_libs/include}/types.hrl | 0 apps/{emqx => emqx_libs}/src/emqx_logger.erl | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {include => apps/emqx_libs/include}/emqx.hrl (100%) rename {include => apps/emqx_libs/include}/emqx_mqtt.hrl (100%) rename {include => apps/emqx_libs/include}/logger.hrl (100%) rename {include => apps/emqx_libs/include}/types.hrl (100%) rename apps/{emqx => emqx_libs}/src/emqx_logger.erl (100%) diff --git a/include/emqx.hrl b/apps/emqx_libs/include/emqx.hrl similarity index 100% rename from include/emqx.hrl rename to apps/emqx_libs/include/emqx.hrl diff --git a/include/emqx_mqtt.hrl b/apps/emqx_libs/include/emqx_mqtt.hrl similarity index 100% rename from include/emqx_mqtt.hrl rename to apps/emqx_libs/include/emqx_mqtt.hrl diff --git a/include/logger.hrl b/apps/emqx_libs/include/logger.hrl similarity index 100% rename from include/logger.hrl rename to apps/emqx_libs/include/logger.hrl diff --git a/include/types.hrl b/apps/emqx_libs/include/types.hrl similarity index 100% rename from include/types.hrl rename to apps/emqx_libs/include/types.hrl diff --git a/apps/emqx/src/emqx_logger.erl b/apps/emqx_libs/src/emqx_logger.erl similarity index 100% rename from apps/emqx/src/emqx_logger.erl rename to apps/emqx_libs/src/emqx_logger.erl From 496a805aef3c3b68178e0b4b3fc349e002678e48 Mon Sep 17 00:00:00 2001 From: terry-xiaoyu <506895667@qq.com> Date: Sat, 31 Oct 2020 10:15:25 +0800 Subject: [PATCH 03/48] feature(project): move priv to apps/emqx/priv --- {priv => apps/emqx/priv}/emqx.schema | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {priv => apps/emqx/priv}/emqx.schema (100%) diff --git a/priv/emqx.schema b/apps/emqx/priv/emqx.schema similarity index 100% rename from priv/emqx.schema rename to apps/emqx/priv/emqx.schema From 18d6647b037f731246f0f66c81c91f6689746ab6 Mon Sep 17 00:00:00 2001 From: terry-xiaoyu <506895667@qq.com> Date: Sat, 31 Oct 2020 10:17:47 +0800 Subject: [PATCH 04/48] feature(project): move test to apps/emqx/test --- {test => apps/emqx/test}/emqx_SUITE.erl | 0 {test => apps/emqx/test}/emqx_SUITE_data/acl.conf | 0 {test => apps/emqx/test}/emqx_SUITE_data/loaded_modules | 0 {test => apps/emqx/test}/emqx_SUITE_data/loaded_plugins | 0 {test => apps/emqx/test}/emqx_access_SUITE_data/acl.conf | 0 .../emqx/test}/emqx_access_SUITE_data/acl_deny_action.conf | 0 {test => apps/emqx/test}/emqx_access_control_SUITE.erl | 0 {test => apps/emqx/test}/emqx_access_rule_SUITE.erl | 0 {test => apps/emqx/test}/emqx_acl_cache_SUITE.erl | 0 {test => apps/emqx/test}/emqx_acl_test_mod.erl | 0 {test => apps/emqx/test}/emqx_alarm_SUITE.erl | 0 {test => apps/emqx/test}/emqx_banned_SUITE.erl | 0 {test => apps/emqx/test}/emqx_batch_SUITE.erl | 0 {test => apps/emqx/test}/emqx_boot_SUITE.erl | 0 {test => apps/emqx/test}/emqx_broker_SUITE.erl | 0 {test => apps/emqx/test}/emqx_broker_helper_SUITE.erl | 0 {test => apps/emqx/test}/emqx_channel_SUITE.erl | 0 {test => apps/emqx/test}/emqx_client_SUITE.erl | 0 {test => apps/emqx/test}/emqx_cm_SUITE.erl | 0 {test => apps/emqx/test}/emqx_cm_locker_SUITE.erl | 0 {test => apps/emqx/test}/emqx_cm_registry_SUITE.erl | 0 {test => apps/emqx/test}/emqx_connection_SUITE.erl | 0 {test => apps/emqx/test}/emqx_ctl_SUITE.erl | 0 {test => apps/emqx/test}/emqx_flapping_SUITE.erl | 0 {test => apps/emqx/test}/emqx_frame_SUITE.erl | 0 {test => apps/emqx/test}/emqx_gc_SUITE.erl | 0 {test => apps/emqx/test}/emqx_global_gc_SUITE.erl | 0 {test => apps/emqx/test}/emqx_guid_SUITE.erl | 0 {test => apps/emqx/test}/emqx_hooks_SUITE.erl | 0 {test => apps/emqx/test}/emqx_inflight_SUITE.erl | 0 {test => apps/emqx/test}/emqx_json_SUITE.erl | 0 {test => apps/emqx/test}/emqx_keepalive_SUITE.erl | 0 {test => apps/emqx/test}/emqx_limiter_SUITE.erl | 0 {test => apps/emqx/test}/emqx_listeners_SUITE.erl | 0 {test => apps/emqx/test}/emqx_logger_SUITE.erl | 0 {test => apps/emqx/test}/emqx_logger_formatter_SUITE.erl | 0 {test => apps/emqx/test}/emqx_message_SUITE.erl | 0 {test => apps/emqx/test}/emqx_metrics_SUITE.erl | 0 {test => apps/emqx/test}/emqx_misc_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_acl_internal_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_delayed_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_presence_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_rewrite_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_subscription_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_sup_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mod_topic_metrics_SUITE.erl | 0 {test => apps/emqx/test}/emqx_modules_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mountpoint_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mqtt_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mqtt_caps_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mqtt_props_SUITE.erl | 0 {test => apps/emqx/test}/emqx_mqueue_SUITE.erl | 0 {test => apps/emqx/test}/emqx_os_mon_SUITE.erl | 0 {test => apps/emqx/test}/emqx_packet_SUITE.erl | 0 {test => apps/emqx/test}/emqx_pd_SUITE.erl | 0 {test => apps/emqx/test}/emqx_plugins_SUITE.erl | 0 .../emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile | 0 .../emqx_mini_plugin/etc/emqx_mini_plugin.conf | 0 .../emqx_mini_plugin/priv/emqx_mini_plugin.schema | 0 .../test}/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config | 0 .../emqx_mini_plugin/src/emqx_mini_plugin.app.src | 0 .../emqx_mini_plugin/src/emqx_mini_plugin_app.erl | 0 {test => apps/emqx/test}/emqx_pmon_SUITE.erl | 0 {test => apps/emqx/test}/emqx_pool_SUITE.erl | 0 {test => apps/emqx/test}/emqx_pqueue_SUITE.erl | 0 {test => apps/emqx/test}/emqx_reason_codes_SUITE.erl | 0 {test => apps/emqx/test}/emqx_request_handler.erl | 0 {test => apps/emqx/test}/emqx_request_responser_SUITE.erl | 0 {test => apps/emqx/test}/emqx_request_sender.erl | 0 {test => apps/emqx/test}/emqx_router_SUITE.erl | 0 {test => apps/emqx/test}/emqx_router_helper_SUITE.erl | 0 {test => apps/emqx/test}/emqx_sequence_SUITE.erl | 0 {test => apps/emqx/test}/emqx_session_SUITE.erl | 0 {test => apps/emqx/test}/emqx_shared_sub_SUITE.erl | 0 {test => apps/emqx/test}/emqx_stats_SUITE.erl | 0 {test => apps/emqx/test}/emqx_sup_SUITE.erl | 0 {test => apps/emqx/test}/emqx_sys_SUITE.erl | 0 {test => apps/emqx/test}/emqx_sys_mon_SUITE.erl | 0 {test => apps/emqx/test}/emqx_tables_SUITE.erl | 0 {test => apps/emqx/test}/emqx_takeover_SUITE.erl | 0 {test => apps/emqx/test}/emqx_topic_SUITE.erl | 0 {test => apps/emqx/test}/emqx_tracer_SUITE.erl | 0 {test => apps/emqx/test}/emqx_trie_SUITE.erl | 0 {test => apps/emqx/test}/emqx_vm_SUITE.erl | 0 {test => apps/emqx/test}/emqx_vm_mon_SUITE.erl | 0 {test => apps/emqx/test}/emqx_ws_connection_SUITE.erl | 0 {test => apps/emqx/test}/emqx_zone_SUITE.erl | 0 {test => apps/emqx/test}/mqtt_protocol_v5_SUITE.erl | 0 {test => apps/emqx/test}/props/prop_emqx_base62.erl | 0 {test => apps/emqx/test}/props/prop_emqx_frame.erl | 0 {test => apps/emqx/test}/props/prop_emqx_json.erl | 0 {test => apps/emqx/test}/props/prop_emqx_psk.erl | 0 {test => apps/emqx/test}/props/prop_emqx_reason_codes.erl | 0 {test => apps/emqx/test}/props/prop_emqx_rpc.erl | 0 {test => apps/emqx/test}/props/prop_emqx_sys.erl | 0 95 files changed, 0 insertions(+), 0 deletions(-) rename {test => apps/emqx/test}/emqx_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_SUITE_data/acl.conf (100%) rename {test => apps/emqx/test}/emqx_SUITE_data/loaded_modules (100%) rename {test => apps/emqx/test}/emqx_SUITE_data/loaded_plugins (100%) rename {test => apps/emqx/test}/emqx_access_SUITE_data/acl.conf (100%) rename {test => apps/emqx/test}/emqx_access_SUITE_data/acl_deny_action.conf (100%) rename {test => apps/emqx/test}/emqx_access_control_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_access_rule_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_acl_cache_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_acl_test_mod.erl (100%) rename {test => apps/emqx/test}/emqx_alarm_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_banned_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_batch_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_boot_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_broker_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_broker_helper_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_channel_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_client_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_cm_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_cm_locker_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_cm_registry_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_connection_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_ctl_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_flapping_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_frame_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_gc_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_global_gc_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_guid_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_hooks_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_inflight_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_json_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_keepalive_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_limiter_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_listeners_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_logger_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_logger_formatter_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_message_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_metrics_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_misc_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_acl_internal_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_delayed_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_presence_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_rewrite_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_subscription_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_sup_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mod_topic_metrics_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_modules_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mountpoint_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mqtt_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mqtt_caps_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mqtt_props_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_mqueue_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_os_mon_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_packet_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_pd_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src (100%) rename {test => apps/emqx/test}/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl (100%) rename {test => apps/emqx/test}/emqx_pmon_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_pool_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_pqueue_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_reason_codes_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_request_handler.erl (100%) rename {test => apps/emqx/test}/emqx_request_responser_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_request_sender.erl (100%) rename {test => apps/emqx/test}/emqx_router_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_router_helper_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_sequence_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_session_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_shared_sub_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_stats_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_sup_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_sys_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_sys_mon_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_tables_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_takeover_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_topic_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_tracer_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_trie_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_vm_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_vm_mon_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_ws_connection_SUITE.erl (100%) rename {test => apps/emqx/test}/emqx_zone_SUITE.erl (100%) rename {test => apps/emqx/test}/mqtt_protocol_v5_SUITE.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_base62.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_frame.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_json.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_psk.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_reason_codes.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_rpc.erl (100%) rename {test => apps/emqx/test}/props/prop_emqx_sys.erl (100%) diff --git a/test/emqx_SUITE.erl b/apps/emqx/test/emqx_SUITE.erl similarity index 100% rename from test/emqx_SUITE.erl rename to apps/emqx/test/emqx_SUITE.erl diff --git a/test/emqx_SUITE_data/acl.conf b/apps/emqx/test/emqx_SUITE_data/acl.conf similarity index 100% rename from test/emqx_SUITE_data/acl.conf rename to apps/emqx/test/emqx_SUITE_data/acl.conf diff --git a/test/emqx_SUITE_data/loaded_modules b/apps/emqx/test/emqx_SUITE_data/loaded_modules similarity index 100% rename from test/emqx_SUITE_data/loaded_modules rename to apps/emqx/test/emqx_SUITE_data/loaded_modules diff --git a/test/emqx_SUITE_data/loaded_plugins b/apps/emqx/test/emqx_SUITE_data/loaded_plugins similarity index 100% rename from test/emqx_SUITE_data/loaded_plugins rename to apps/emqx/test/emqx_SUITE_data/loaded_plugins diff --git a/test/emqx_access_SUITE_data/acl.conf b/apps/emqx/test/emqx_access_SUITE_data/acl.conf similarity index 100% rename from test/emqx_access_SUITE_data/acl.conf rename to apps/emqx/test/emqx_access_SUITE_data/acl.conf diff --git a/test/emqx_access_SUITE_data/acl_deny_action.conf b/apps/emqx/test/emqx_access_SUITE_data/acl_deny_action.conf similarity index 100% rename from test/emqx_access_SUITE_data/acl_deny_action.conf rename to apps/emqx/test/emqx_access_SUITE_data/acl_deny_action.conf diff --git a/test/emqx_access_control_SUITE.erl b/apps/emqx/test/emqx_access_control_SUITE.erl similarity index 100% rename from test/emqx_access_control_SUITE.erl rename to apps/emqx/test/emqx_access_control_SUITE.erl diff --git a/test/emqx_access_rule_SUITE.erl b/apps/emqx/test/emqx_access_rule_SUITE.erl similarity index 100% rename from test/emqx_access_rule_SUITE.erl rename to apps/emqx/test/emqx_access_rule_SUITE.erl diff --git a/test/emqx_acl_cache_SUITE.erl b/apps/emqx/test/emqx_acl_cache_SUITE.erl similarity index 100% rename from test/emqx_acl_cache_SUITE.erl rename to apps/emqx/test/emqx_acl_cache_SUITE.erl diff --git a/test/emqx_acl_test_mod.erl b/apps/emqx/test/emqx_acl_test_mod.erl similarity index 100% rename from test/emqx_acl_test_mod.erl rename to apps/emqx/test/emqx_acl_test_mod.erl diff --git a/test/emqx_alarm_SUITE.erl b/apps/emqx/test/emqx_alarm_SUITE.erl similarity index 100% rename from test/emqx_alarm_SUITE.erl rename to apps/emqx/test/emqx_alarm_SUITE.erl diff --git a/test/emqx_banned_SUITE.erl b/apps/emqx/test/emqx_banned_SUITE.erl similarity index 100% rename from test/emqx_banned_SUITE.erl rename to apps/emqx/test/emqx_banned_SUITE.erl diff --git a/test/emqx_batch_SUITE.erl b/apps/emqx/test/emqx_batch_SUITE.erl similarity index 100% rename from test/emqx_batch_SUITE.erl rename to apps/emqx/test/emqx_batch_SUITE.erl diff --git a/test/emqx_boot_SUITE.erl b/apps/emqx/test/emqx_boot_SUITE.erl similarity index 100% rename from test/emqx_boot_SUITE.erl rename to apps/emqx/test/emqx_boot_SUITE.erl diff --git a/test/emqx_broker_SUITE.erl b/apps/emqx/test/emqx_broker_SUITE.erl similarity index 100% rename from test/emqx_broker_SUITE.erl rename to apps/emqx/test/emqx_broker_SUITE.erl diff --git a/test/emqx_broker_helper_SUITE.erl b/apps/emqx/test/emqx_broker_helper_SUITE.erl similarity index 100% rename from test/emqx_broker_helper_SUITE.erl rename to apps/emqx/test/emqx_broker_helper_SUITE.erl diff --git a/test/emqx_channel_SUITE.erl b/apps/emqx/test/emqx_channel_SUITE.erl similarity index 100% rename from test/emqx_channel_SUITE.erl rename to apps/emqx/test/emqx_channel_SUITE.erl diff --git a/test/emqx_client_SUITE.erl b/apps/emqx/test/emqx_client_SUITE.erl similarity index 100% rename from test/emqx_client_SUITE.erl rename to apps/emqx/test/emqx_client_SUITE.erl diff --git a/test/emqx_cm_SUITE.erl b/apps/emqx/test/emqx_cm_SUITE.erl similarity index 100% rename from test/emqx_cm_SUITE.erl rename to apps/emqx/test/emqx_cm_SUITE.erl diff --git a/test/emqx_cm_locker_SUITE.erl b/apps/emqx/test/emqx_cm_locker_SUITE.erl similarity index 100% rename from test/emqx_cm_locker_SUITE.erl rename to apps/emqx/test/emqx_cm_locker_SUITE.erl diff --git a/test/emqx_cm_registry_SUITE.erl b/apps/emqx/test/emqx_cm_registry_SUITE.erl similarity index 100% rename from test/emqx_cm_registry_SUITE.erl rename to apps/emqx/test/emqx_cm_registry_SUITE.erl diff --git a/test/emqx_connection_SUITE.erl b/apps/emqx/test/emqx_connection_SUITE.erl similarity index 100% rename from test/emqx_connection_SUITE.erl rename to apps/emqx/test/emqx_connection_SUITE.erl diff --git a/test/emqx_ctl_SUITE.erl b/apps/emqx/test/emqx_ctl_SUITE.erl similarity index 100% rename from test/emqx_ctl_SUITE.erl rename to apps/emqx/test/emqx_ctl_SUITE.erl diff --git a/test/emqx_flapping_SUITE.erl b/apps/emqx/test/emqx_flapping_SUITE.erl similarity index 100% rename from test/emqx_flapping_SUITE.erl rename to apps/emqx/test/emqx_flapping_SUITE.erl diff --git a/test/emqx_frame_SUITE.erl b/apps/emqx/test/emqx_frame_SUITE.erl similarity index 100% rename from test/emqx_frame_SUITE.erl rename to apps/emqx/test/emqx_frame_SUITE.erl diff --git a/test/emqx_gc_SUITE.erl b/apps/emqx/test/emqx_gc_SUITE.erl similarity index 100% rename from test/emqx_gc_SUITE.erl rename to apps/emqx/test/emqx_gc_SUITE.erl diff --git a/test/emqx_global_gc_SUITE.erl b/apps/emqx/test/emqx_global_gc_SUITE.erl similarity index 100% rename from test/emqx_global_gc_SUITE.erl rename to apps/emqx/test/emqx_global_gc_SUITE.erl diff --git a/test/emqx_guid_SUITE.erl b/apps/emqx/test/emqx_guid_SUITE.erl similarity index 100% rename from test/emqx_guid_SUITE.erl rename to apps/emqx/test/emqx_guid_SUITE.erl diff --git a/test/emqx_hooks_SUITE.erl b/apps/emqx/test/emqx_hooks_SUITE.erl similarity index 100% rename from test/emqx_hooks_SUITE.erl rename to apps/emqx/test/emqx_hooks_SUITE.erl diff --git a/test/emqx_inflight_SUITE.erl b/apps/emqx/test/emqx_inflight_SUITE.erl similarity index 100% rename from test/emqx_inflight_SUITE.erl rename to apps/emqx/test/emqx_inflight_SUITE.erl diff --git a/test/emqx_json_SUITE.erl b/apps/emqx/test/emqx_json_SUITE.erl similarity index 100% rename from test/emqx_json_SUITE.erl rename to apps/emqx/test/emqx_json_SUITE.erl diff --git a/test/emqx_keepalive_SUITE.erl b/apps/emqx/test/emqx_keepalive_SUITE.erl similarity index 100% rename from test/emqx_keepalive_SUITE.erl rename to apps/emqx/test/emqx_keepalive_SUITE.erl diff --git a/test/emqx_limiter_SUITE.erl b/apps/emqx/test/emqx_limiter_SUITE.erl similarity index 100% rename from test/emqx_limiter_SUITE.erl rename to apps/emqx/test/emqx_limiter_SUITE.erl diff --git a/test/emqx_listeners_SUITE.erl b/apps/emqx/test/emqx_listeners_SUITE.erl similarity index 100% rename from test/emqx_listeners_SUITE.erl rename to apps/emqx/test/emqx_listeners_SUITE.erl diff --git a/test/emqx_logger_SUITE.erl b/apps/emqx/test/emqx_logger_SUITE.erl similarity index 100% rename from test/emqx_logger_SUITE.erl rename to apps/emqx/test/emqx_logger_SUITE.erl diff --git a/test/emqx_logger_formatter_SUITE.erl b/apps/emqx/test/emqx_logger_formatter_SUITE.erl similarity index 100% rename from test/emqx_logger_formatter_SUITE.erl rename to apps/emqx/test/emqx_logger_formatter_SUITE.erl diff --git a/test/emqx_message_SUITE.erl b/apps/emqx/test/emqx_message_SUITE.erl similarity index 100% rename from test/emqx_message_SUITE.erl rename to apps/emqx/test/emqx_message_SUITE.erl diff --git a/test/emqx_metrics_SUITE.erl b/apps/emqx/test/emqx_metrics_SUITE.erl similarity index 100% rename from test/emqx_metrics_SUITE.erl rename to apps/emqx/test/emqx_metrics_SUITE.erl diff --git a/test/emqx_misc_SUITE.erl b/apps/emqx/test/emqx_misc_SUITE.erl similarity index 100% rename from test/emqx_misc_SUITE.erl rename to apps/emqx/test/emqx_misc_SUITE.erl diff --git a/test/emqx_mod_acl_internal_SUITE.erl b/apps/emqx/test/emqx_mod_acl_internal_SUITE.erl similarity index 100% rename from test/emqx_mod_acl_internal_SUITE.erl rename to apps/emqx/test/emqx_mod_acl_internal_SUITE.erl diff --git a/test/emqx_mod_delayed_SUITE.erl b/apps/emqx/test/emqx_mod_delayed_SUITE.erl similarity index 100% rename from test/emqx_mod_delayed_SUITE.erl rename to apps/emqx/test/emqx_mod_delayed_SUITE.erl diff --git a/test/emqx_mod_presence_SUITE.erl b/apps/emqx/test/emqx_mod_presence_SUITE.erl similarity index 100% rename from test/emqx_mod_presence_SUITE.erl rename to apps/emqx/test/emqx_mod_presence_SUITE.erl diff --git a/test/emqx_mod_rewrite_SUITE.erl b/apps/emqx/test/emqx_mod_rewrite_SUITE.erl similarity index 100% rename from test/emqx_mod_rewrite_SUITE.erl rename to apps/emqx/test/emqx_mod_rewrite_SUITE.erl diff --git a/test/emqx_mod_subscription_SUITE.erl b/apps/emqx/test/emqx_mod_subscription_SUITE.erl similarity index 100% rename from test/emqx_mod_subscription_SUITE.erl rename to apps/emqx/test/emqx_mod_subscription_SUITE.erl diff --git a/test/emqx_mod_sup_SUITE.erl b/apps/emqx/test/emqx_mod_sup_SUITE.erl similarity index 100% rename from test/emqx_mod_sup_SUITE.erl rename to apps/emqx/test/emqx_mod_sup_SUITE.erl diff --git a/test/emqx_mod_topic_metrics_SUITE.erl b/apps/emqx/test/emqx_mod_topic_metrics_SUITE.erl similarity index 100% rename from test/emqx_mod_topic_metrics_SUITE.erl rename to apps/emqx/test/emqx_mod_topic_metrics_SUITE.erl diff --git a/test/emqx_modules_SUITE.erl b/apps/emqx/test/emqx_modules_SUITE.erl similarity index 100% rename from test/emqx_modules_SUITE.erl rename to apps/emqx/test/emqx_modules_SUITE.erl diff --git a/test/emqx_mountpoint_SUITE.erl b/apps/emqx/test/emqx_mountpoint_SUITE.erl similarity index 100% rename from test/emqx_mountpoint_SUITE.erl rename to apps/emqx/test/emqx_mountpoint_SUITE.erl diff --git a/test/emqx_mqtt_SUITE.erl b/apps/emqx/test/emqx_mqtt_SUITE.erl similarity index 100% rename from test/emqx_mqtt_SUITE.erl rename to apps/emqx/test/emqx_mqtt_SUITE.erl diff --git a/test/emqx_mqtt_caps_SUITE.erl b/apps/emqx/test/emqx_mqtt_caps_SUITE.erl similarity index 100% rename from test/emqx_mqtt_caps_SUITE.erl rename to apps/emqx/test/emqx_mqtt_caps_SUITE.erl diff --git a/test/emqx_mqtt_props_SUITE.erl b/apps/emqx/test/emqx_mqtt_props_SUITE.erl similarity index 100% rename from test/emqx_mqtt_props_SUITE.erl rename to apps/emqx/test/emqx_mqtt_props_SUITE.erl diff --git a/test/emqx_mqueue_SUITE.erl b/apps/emqx/test/emqx_mqueue_SUITE.erl similarity index 100% rename from test/emqx_mqueue_SUITE.erl rename to apps/emqx/test/emqx_mqueue_SUITE.erl diff --git a/test/emqx_os_mon_SUITE.erl b/apps/emqx/test/emqx_os_mon_SUITE.erl similarity index 100% rename from test/emqx_os_mon_SUITE.erl rename to apps/emqx/test/emqx_os_mon_SUITE.erl diff --git a/test/emqx_packet_SUITE.erl b/apps/emqx/test/emqx_packet_SUITE.erl similarity index 100% rename from test/emqx_packet_SUITE.erl rename to apps/emqx/test/emqx_packet_SUITE.erl diff --git a/test/emqx_pd_SUITE.erl b/apps/emqx/test/emqx_pd_SUITE.erl similarity index 100% rename from test/emqx_pd_SUITE.erl rename to apps/emqx/test/emqx_pd_SUITE.erl diff --git a/test/emqx_plugins_SUITE.erl b/apps/emqx/test/emqx_plugins_SUITE.erl similarity index 100% rename from test/emqx_plugins_SUITE.erl rename to apps/emqx/test/emqx_plugins_SUITE.erl diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl diff --git a/test/emqx_pmon_SUITE.erl b/apps/emqx/test/emqx_pmon_SUITE.erl similarity index 100% rename from test/emqx_pmon_SUITE.erl rename to apps/emqx/test/emqx_pmon_SUITE.erl diff --git a/test/emqx_pool_SUITE.erl b/apps/emqx/test/emqx_pool_SUITE.erl similarity index 100% rename from test/emqx_pool_SUITE.erl rename to apps/emqx/test/emqx_pool_SUITE.erl diff --git a/test/emqx_pqueue_SUITE.erl b/apps/emqx/test/emqx_pqueue_SUITE.erl similarity index 100% rename from test/emqx_pqueue_SUITE.erl rename to apps/emqx/test/emqx_pqueue_SUITE.erl diff --git a/test/emqx_reason_codes_SUITE.erl b/apps/emqx/test/emqx_reason_codes_SUITE.erl similarity index 100% rename from test/emqx_reason_codes_SUITE.erl rename to apps/emqx/test/emqx_reason_codes_SUITE.erl diff --git a/test/emqx_request_handler.erl b/apps/emqx/test/emqx_request_handler.erl similarity index 100% rename from test/emqx_request_handler.erl rename to apps/emqx/test/emqx_request_handler.erl diff --git a/test/emqx_request_responser_SUITE.erl b/apps/emqx/test/emqx_request_responser_SUITE.erl similarity index 100% rename from test/emqx_request_responser_SUITE.erl rename to apps/emqx/test/emqx_request_responser_SUITE.erl diff --git a/test/emqx_request_sender.erl b/apps/emqx/test/emqx_request_sender.erl similarity index 100% rename from test/emqx_request_sender.erl rename to apps/emqx/test/emqx_request_sender.erl diff --git a/test/emqx_router_SUITE.erl b/apps/emqx/test/emqx_router_SUITE.erl similarity index 100% rename from test/emqx_router_SUITE.erl rename to apps/emqx/test/emqx_router_SUITE.erl diff --git a/test/emqx_router_helper_SUITE.erl b/apps/emqx/test/emqx_router_helper_SUITE.erl similarity index 100% rename from test/emqx_router_helper_SUITE.erl rename to apps/emqx/test/emqx_router_helper_SUITE.erl diff --git a/test/emqx_sequence_SUITE.erl b/apps/emqx/test/emqx_sequence_SUITE.erl similarity index 100% rename from test/emqx_sequence_SUITE.erl rename to apps/emqx/test/emqx_sequence_SUITE.erl diff --git a/test/emqx_session_SUITE.erl b/apps/emqx/test/emqx_session_SUITE.erl similarity index 100% rename from test/emqx_session_SUITE.erl rename to apps/emqx/test/emqx_session_SUITE.erl diff --git a/test/emqx_shared_sub_SUITE.erl b/apps/emqx/test/emqx_shared_sub_SUITE.erl similarity index 100% rename from test/emqx_shared_sub_SUITE.erl rename to apps/emqx/test/emqx_shared_sub_SUITE.erl diff --git a/test/emqx_stats_SUITE.erl b/apps/emqx/test/emqx_stats_SUITE.erl similarity index 100% rename from test/emqx_stats_SUITE.erl rename to apps/emqx/test/emqx_stats_SUITE.erl diff --git a/test/emqx_sup_SUITE.erl b/apps/emqx/test/emqx_sup_SUITE.erl similarity index 100% rename from test/emqx_sup_SUITE.erl rename to apps/emqx/test/emqx_sup_SUITE.erl diff --git a/test/emqx_sys_SUITE.erl b/apps/emqx/test/emqx_sys_SUITE.erl similarity index 100% rename from test/emqx_sys_SUITE.erl rename to apps/emqx/test/emqx_sys_SUITE.erl diff --git a/test/emqx_sys_mon_SUITE.erl b/apps/emqx/test/emqx_sys_mon_SUITE.erl similarity index 100% rename from test/emqx_sys_mon_SUITE.erl rename to apps/emqx/test/emqx_sys_mon_SUITE.erl diff --git a/test/emqx_tables_SUITE.erl b/apps/emqx/test/emqx_tables_SUITE.erl similarity index 100% rename from test/emqx_tables_SUITE.erl rename to apps/emqx/test/emqx_tables_SUITE.erl diff --git a/test/emqx_takeover_SUITE.erl b/apps/emqx/test/emqx_takeover_SUITE.erl similarity index 100% rename from test/emqx_takeover_SUITE.erl rename to apps/emqx/test/emqx_takeover_SUITE.erl diff --git a/test/emqx_topic_SUITE.erl b/apps/emqx/test/emqx_topic_SUITE.erl similarity index 100% rename from test/emqx_topic_SUITE.erl rename to apps/emqx/test/emqx_topic_SUITE.erl diff --git a/test/emqx_tracer_SUITE.erl b/apps/emqx/test/emqx_tracer_SUITE.erl similarity index 100% rename from test/emqx_tracer_SUITE.erl rename to apps/emqx/test/emqx_tracer_SUITE.erl diff --git a/test/emqx_trie_SUITE.erl b/apps/emqx/test/emqx_trie_SUITE.erl similarity index 100% rename from test/emqx_trie_SUITE.erl rename to apps/emqx/test/emqx_trie_SUITE.erl diff --git a/test/emqx_vm_SUITE.erl b/apps/emqx/test/emqx_vm_SUITE.erl similarity index 100% rename from test/emqx_vm_SUITE.erl rename to apps/emqx/test/emqx_vm_SUITE.erl diff --git a/test/emqx_vm_mon_SUITE.erl b/apps/emqx/test/emqx_vm_mon_SUITE.erl similarity index 100% rename from test/emqx_vm_mon_SUITE.erl rename to apps/emqx/test/emqx_vm_mon_SUITE.erl diff --git a/test/emqx_ws_connection_SUITE.erl b/apps/emqx/test/emqx_ws_connection_SUITE.erl similarity index 100% rename from test/emqx_ws_connection_SUITE.erl rename to apps/emqx/test/emqx_ws_connection_SUITE.erl diff --git a/test/emqx_zone_SUITE.erl b/apps/emqx/test/emqx_zone_SUITE.erl similarity index 100% rename from test/emqx_zone_SUITE.erl rename to apps/emqx/test/emqx_zone_SUITE.erl diff --git a/test/mqtt_protocol_v5_SUITE.erl b/apps/emqx/test/mqtt_protocol_v5_SUITE.erl similarity index 100% rename from test/mqtt_protocol_v5_SUITE.erl rename to apps/emqx/test/mqtt_protocol_v5_SUITE.erl diff --git a/test/props/prop_emqx_base62.erl b/apps/emqx/test/props/prop_emqx_base62.erl similarity index 100% rename from test/props/prop_emqx_base62.erl rename to apps/emqx/test/props/prop_emqx_base62.erl diff --git a/test/props/prop_emqx_frame.erl b/apps/emqx/test/props/prop_emqx_frame.erl similarity index 100% rename from test/props/prop_emqx_frame.erl rename to apps/emqx/test/props/prop_emqx_frame.erl diff --git a/test/props/prop_emqx_json.erl b/apps/emqx/test/props/prop_emqx_json.erl similarity index 100% rename from test/props/prop_emqx_json.erl rename to apps/emqx/test/props/prop_emqx_json.erl diff --git a/test/props/prop_emqx_psk.erl b/apps/emqx/test/props/prop_emqx_psk.erl similarity index 100% rename from test/props/prop_emqx_psk.erl rename to apps/emqx/test/props/prop_emqx_psk.erl diff --git a/test/props/prop_emqx_reason_codes.erl b/apps/emqx/test/props/prop_emqx_reason_codes.erl similarity index 100% rename from test/props/prop_emqx_reason_codes.erl rename to apps/emqx/test/props/prop_emqx_reason_codes.erl diff --git a/test/props/prop_emqx_rpc.erl b/apps/emqx/test/props/prop_emqx_rpc.erl similarity index 100% rename from test/props/prop_emqx_rpc.erl rename to apps/emqx/test/props/prop_emqx_rpc.erl diff --git a/test/props/prop_emqx_sys.erl b/apps/emqx/test/props/prop_emqx_sys.erl similarity index 100% rename from test/props/prop_emqx_sys.erl rename to apps/emqx/test/props/prop_emqx_sys.erl From d1a87d38ba6a7622cf537d828ac25702b7fe6442 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Fri, 16 Oct 2020 10:16:19 +0800 Subject: [PATCH 05/48] refactor(exproto): improve the exproto implementation --- .gitignore | 1 + apps/emqx_exproto/.gitignore | 5 + apps/emqx_exproto/README.md | 28 + apps/emqx_exproto/docs/design.md | 127 ++++ .../emqx_exproto/docs/images/exproto-arch.jpg | Bin 0 -> 72633 bytes .../docs/images/exproto-grpc-arch.jpg | Bin 0 -> 97464 bytes apps/emqx_exproto/include/emqx_exproto.hrl | 37 + apps/emqx_exproto/priv/emqx_exproto.schema | 364 ++++++++++ apps/emqx_exproto/priv/protos/exproto.proto | 259 +++++++ apps/emqx_exproto/rebar.config | 50 ++ apps/emqx_exproto/src/emqx_exproto.app.src | 12 + apps/emqx_exproto/src/emqx_exproto.erl | 183 +++++ apps/emqx_exproto/src/emqx_exproto_app.erl | 37 + .../emqx_exproto/src/emqx_exproto_channel.erl | 599 +++++++++++++++ apps/emqx_exproto/src/emqx_exproto_conn.erl | 685 ++++++++++++++++++ apps/emqx_exproto/src/emqx_exproto_gcli.erl | 110 +++ apps/emqx_exproto/src/emqx_exproto_gsvr.erl | 154 ++++ apps/emqx_exproto/src/emqx_exproto_sup.erl | 86 +++ apps/emqx_exproto/test/emqx_exproto_SUITE.erl | 454 ++++++++++++ .../test/emqx_exproto_echo_svr.erl | 238 ++++++ etc/emqx_cloud.d/emqx_exproto.conf | 252 +++++++ 21 files changed, 3681 insertions(+) create mode 100644 apps/emqx_exproto/.gitignore create mode 100644 apps/emqx_exproto/README.md create mode 100644 apps/emqx_exproto/docs/design.md create mode 100644 apps/emqx_exproto/docs/images/exproto-arch.jpg create mode 100644 apps/emqx_exproto/docs/images/exproto-grpc-arch.jpg create mode 100644 apps/emqx_exproto/include/emqx_exproto.hrl create mode 100644 apps/emqx_exproto/priv/emqx_exproto.schema create mode 100644 apps/emqx_exproto/priv/protos/exproto.proto create mode 100644 apps/emqx_exproto/rebar.config create mode 100644 apps/emqx_exproto/src/emqx_exproto.app.src create mode 100644 apps/emqx_exproto/src/emqx_exproto.erl create mode 100644 apps/emqx_exproto/src/emqx_exproto_app.erl create mode 100644 apps/emqx_exproto/src/emqx_exproto_channel.erl create mode 100644 apps/emqx_exproto/src/emqx_exproto_conn.erl create mode 100644 apps/emqx_exproto/src/emqx_exproto_gcli.erl create mode 100644 apps/emqx_exproto/src/emqx_exproto_gsvr.erl create mode 100644 apps/emqx_exproto/src/emqx_exproto_sup.erl create mode 100644 apps/emqx_exproto/test/emqx_exproto_SUITE.erl create mode 100644 apps/emqx_exproto/test/emqx_exproto_echo_svr.erl create mode 100644 etc/emqx_cloud.d/emqx_exproto.conf diff --git a/.gitignore b/.gitignore index aaec950d4..b23eeafe3 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ erlang.mk *.coverdata etc/emqx.conf.rendered Mnesia.*/ +*.DS_Store diff --git a/apps/emqx_exproto/.gitignore b/apps/emqx_exproto/.gitignore new file mode 100644 index 000000000..791a6e94e --- /dev/null +++ b/apps/emqx_exproto/.gitignore @@ -0,0 +1,5 @@ +src/emqx_exproto_pb.erl +src/emqx_exproto_v_1_connection_adapter_bhvr.erl +src/emqx_exproto_v_1_connection_adapter_client.erl +src/emqx_exproto_v_1_connection_handler_bhvr.erl +src/emqx_exproto_v_1_connection_handler_client.erl diff --git a/apps/emqx_exproto/README.md b/apps/emqx_exproto/README.md new file mode 100644 index 000000000..4b59dcae3 --- /dev/null +++ b/apps/emqx_exproto/README.md @@ -0,0 +1,28 @@ +# emqx-exproto + +The `emqx_exproto` extremly enhance the extensibility for EMQ X. It allow using an others programming language to **replace the protocol handling layer in EMQ X Broker**. + +## Feature + +- [x] Based on gRPC, it brings a very wide range of applicability +- [x] Allows you to use the return value to extend emqx behavior. + +## Architecture + +![EMQ X ExProto Arch](./docs/images/exproto-arch.jpg) + +## Usage + +### gRPC service + +See: `priv/protos/exproto.proto` + +## Example + +## Recommended gRPC Framework + +See: https://github.com/grpc-ecosystem/awesome-grpc + +## Thanks + +- [grpcbox](https://github.com/tsloughter/grpcbox) diff --git a/apps/emqx_exproto/docs/design.md b/apps/emqx_exproto/docs/design.md new file mode 100644 index 000000000..0a6a082e2 --- /dev/null +++ b/apps/emqx_exproto/docs/design.md @@ -0,0 +1,127 @@ +# 多语言 - 协议接入 + +`emqx-exproto` 插件用于协议解析的多语言支持。它能够允许其他编程语言(例如:Python,Java 等)直接处理数据流实现协议的解析,并提供 Pub/Sub 接口以实现与系统其它组件的通信。 + +该插件给 EMQ X 带来的扩展性十分的强大,它能以你熟悉语言处理任何的私有协议,并享受由 EMQ X 系统带来的高连接,和高并发的优点。 + +## 特性 + +- 极强的扩展能力。使用 gRPC 作为 RPC 通信框架,支持各个主流编程语言 +- 高吞吐。连接层以完全的异步非阻塞式 I/O 的方式实现 +- 连接层透明。完全的支持 TCP\TLS UDP\DTLS 类型的连接管理,并对上层提供统一个 API +- 连接层的管理能力。例如,最大连接数,连接和吞吐的速率限制,IP 黑名单 等 + +## 架构 + +![Extension-Protocol Arch](images/exproto-arch.jpg) + +该插件主要需要处理的内容包括: + +1. **连接层:** 该部分主要**维持 Socket 的生命周期,和数据的收发**。它的功能要求包括: + - 监听某个端口。当有新的 TCP/UDP 连接到达后,启动一个连接进程,来维持连接的状态。 + - 调用 `OnSocketCreated` 回调。用于通知外部模块**已新建立了一个连接**。 + - 调用 `OnScoektClosed` 回调。用于通知外部模块连接**已关闭**。 + - 调用 `OnReceivedBytes` 回调。用于通知外部模块**该连接新收到的数据包**。 + - 提供 `Send` 接口。供外部模块调用,**用于发送数据包**。 + - 提供 `Close` 接口。供外部模块调用,**用于主动关闭连接**。 + +2. **协议/会话层:**该部分主要**提供 PUB/SUB 接口**,以实现与 EMQ X Broker 系统的消息互通。包括: + + - 提供 `Authenticate` 接口。供外部模块调用,用于向集群注册客户端。 + - 提供 `StartTimer` 接口。供外部模块调用,用于为该连接进程启动心跳等定时器。 + - 提供 `Publish` 接口。供外部模块调用,用于发布消息 EMQ X Broker 中。 + - 提供 `Subscribe` 接口。供外部模块调用,用于订阅某主题,以实现从 EMQ X Broker 中接收某些下行消息。 + - 提供 `Unsubscribe` 接口。供外部模块调用,用于取消订阅某主题。 + - 调用 `OnTimerTimeout` 回调。用于处理定时器超时的事件。 + - 调用 `OnReceivedMessages` 回调。用于接收下行消息(在订阅主题成功后,如果主题上有消息,便会回调该方法) + +## 接口设计 + +从 gRPC 上的逻辑来说,emqx-exproto 会作为客户端向用户的 `ProtocolHandler` 服务发送回调请求。同时,它也会作为服务端向用户提供 `ConnectionAdapter` 服务,以提供 emqx-exproto 各个接口的访问。如图: + +![Extension Protocol gRPC Arch](images/exproto-grpc-arch.jpg) + + +详情参见:`priv/protos/exproto.proto`,例如接口的定义有: + +```protobuff +syntax = "proto3"; + +package emqx.exproto.v1; + +// The Broker side serivce. It provides a set of APIs to +// handle a protcol access +service ConnectionAdapter { + + // -- socket layer + + rpc Send(SendBytesRequest) returns (CodeResponse) {}; + + rpc Close(CloseSocketRequest) returns (CodeResponse) {}; + + // -- protocol layer + + rpc Authenticate(AuthenticateRequest) returns (CodeResponse) {}; + + rpc StartTimer(TimerRequest) returns (CodeResponse) {}; + + // -- pub/sub layer + + rpc Publish(PublishRequest) returns (CodeResponse) {}; + + rpc Subscribe(SubscribeRequest) returns (CodeResponse) {}; + + rpc Unsubscribe(UnsubscribeRequest) returns (CodeResponse) {}; +} + +service ConnectionHandler { + + // -- socket layer + + rpc OnSocketCreated(SocketCreatedRequest) returns (EmptySuccess) {}; + + rpc OnSocketClosed(SocketClosedRequest) returns (EmptySuccess) {}; + + rpc OnReceivedBytes(ReceivedBytesRequest) returns (EmptySuccess) {}; + + // -- pub/sub layer + + rpc OnTimerTimeout(TimerTimeoutRequest) returns (EmptySuccess) {}; + + rpc OnReceivedMessages(ReceivedMessagesRequest) returns (EmptySuccess) {}; +} +``` + +## 配置项设计 + +1. 以 **监听器( Listener)** 为基础,提供 TCP/UDP 的监听。 + - Listener 目前仅支持:TCP、TLS、UDP、DTLS。(ws、wss、quic 暂不支持) +2. 每个监听器,会指定一个 `ProtocolHandler` 的服务地址,用于调用外部模块的接口。 +3. emqx-exproto 还会监听一个 gRPC 端口用于提供对 `ConnectionAdapter` 服务的访问。 + +例如: + +``` properties +## gRPC 服务监听地址 (HTTP) +## +exproto.server.http.url = http://127.0.0.1:9002 + +## gRPC 服务监听地址 (HTTPS) +## +exproto.server.https.url = https://127.0.0.1:9002 +exproto.server.https.cacertfile = ca.pem +exproto.server.https.certfile = cert.pem +exproto.server.https.keyfile = key.pem + +## Listener 配置 +## 例如,名称为 protoname 协议的 TCP 监听器配置 +exproto.listener.protoname = tcp://0.0.0.0:7993 + +## ProtocolHandler 服务地址及 https 的证书配置 +exproto.listener.protoname.proto_handler_url = http://127.0.0.1:9001 +#exproto.listener.protoname.proto_handler_certfile = +#exproto.listener.protoname.proto_handler_cacertfile = +#exproto.listener.protoname.proto_handler_keyfile = + +# ... +``` diff --git a/apps/emqx_exproto/docs/images/exproto-arch.jpg b/apps/emqx_exproto/docs/images/exproto-arch.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dddf7996b98c61bf55f911a35e0f51e76c8e8728 GIT binary patch literal 72633 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