couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From iil...@apache.org
Subject [1/3] couch commit: updated refs/heads/master to b8b4982
Date Tue, 23 Aug 2016 22:03:58 GMT
Repository: couchdb-couch
Updated Branches:
  refs/heads/master 8bd756e60 -> b8b4982f4


Update handle_config_terminate API

COUCHDB-3102


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/608942f9
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/608942f9
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/608942f9

Branch: refs/heads/master
Commit: 608942f9ac7c5b2b225ec9598363228583f70f92
Parents: 8bd756e
Author: ILYA Khlopotov <iilyak@ca.ibm.com>
Authored: Wed Aug 17 11:24:08 2016 -0700
Committer: ILYA Khlopotov <iilyak@ca.ibm.com>
Committed: Tue Aug 23 12:23:45 2016 -0700

----------------------------------------------------------------------
 src/couch_auth_cache.erl        | 20 +++++++-----
 src/couch_compaction_daemon.erl | 18 ++++++-----
 src/couch_external_manager.erl  | 22 +++++++++-----
 src/couch_external_server.erl   | 59 +++++++++++++++++++-----------------
 src/couch_httpd_vhost.erl       | 15 +++++----
 src/couch_os_daemons.erl        | 16 ++++++----
 src/couch_proc_manager.erl      | 22 ++++++++------
 src/couch_server.erl            | 17 ++++++-----
 src/couch_sup.erl               | 18 ++++++-----
 src/couch_uuids.erl             | 21 +++++++------
 10 files changed, 130 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_auth_cache.erl
----------------------------------------------------------------------
diff --git a/src/couch_auth_cache.erl b/src/couch_auth_cache.erl
index 32d706d..9b00a9d 100644
--- a/src/couch_auth_cache.erl
+++ b/src/couch_auth_cache.erl
@@ -12,7 +12,7 @@
 
 -module(couch_auth_cache).
 -behaviour(gen_server).
--vsn(2).
+-vsn(3).
 -behaviour(config_listener).
 
 % public API
@@ -33,6 +33,8 @@
 -define(BY_USER, auth_by_user_ets).
 -define(BY_ATIME, auth_by_atime_ets).
 
+-define(RELISTEN_DELAY, 5000).
+
 -record(state, {
     max_cache_size = 0,
     cache_size = 0,
@@ -242,7 +244,11 @@ handle_info({'DOWN', Ref, _, _, Reason}, #state{closed = Closed} = State)
->
             {stop, Reason, State};
         NewClosed ->
             {noreply, reinit_cache(State#state{closed = NewClosed})}
-    end.
+    end;
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State}.
+
 
 
 terminate(_Reason, #state{event_listener = Listener}) ->
@@ -265,12 +271,10 @@ handle_config_change("couch_httpd_auth", "authentication_db", _DbName,
_, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
 
 clear_cache(State) ->
     exec_if_auth_db(fun(AuthDb) -> catch couch_db:close(AuthDb) end),

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_compaction_daemon.erl
----------------------------------------------------------------------
diff --git a/src/couch_compaction_daemon.erl b/src/couch_compaction_daemon.erl
index 7888eb4..8f95eb2 100644
--- a/src/couch_compaction_daemon.erl
+++ b/src/couch_compaction_daemon.erl
@@ -12,6 +12,7 @@
 
 -module(couch_compaction_daemon).
 -behaviour(gen_server).
+-vsn(1).
 -behaviour(config_listener).
 
 % public API
@@ -29,6 +30,8 @@
 
 -define(CONFIG_ETS, couch_compaction_daemon_config).
 
+-define(RELISTEN_DELAY, 5000).
+
 -record(state, {
     loop_pid,
     in_progress = []
@@ -98,7 +101,10 @@ handle_call(Msg, _From, State) ->
 
 
 handle_info({'EXIT', Pid, Reason}, #state{loop_pid = Pid} = State) ->
-    {stop, {compaction_loop_died, Reason}, State}.
+    {stop, {compaction_loop_died, Reason}, State};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State}.
 
 
 terminate(_Reason, _State) ->
@@ -114,12 +120,10 @@ handle_config_change("compactions", DbName, Value, _, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
 
 compact_loop(Parent) ->
     {ok, _} = couch_server:all_databases(

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_external_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_external_manager.erl b/src/couch_external_manager.erl
index 1aeb39a..f131342 100644
--- a/src/couch_external_manager.erl
+++ b/src/couch_external_manager.erl
@@ -12,7 +12,7 @@
 
 -module(couch_external_manager).
 -behaviour(gen_server).
--vsn(2).
+-vsn(3).
 -behaviour(config_listener).
 
 -export([start_link/0, execute/2]).
@@ -23,6 +23,8 @@
 
 -include_lib("couch/include/couch_db.hrl").
 
+-define(RELISTEN_DELAY, 5000).
+
 start_link() ->
     gen_server:start_link({local, couch_external_manager},
         couch_external_manager, [], []).
@@ -41,12 +43,11 @@ handle_config_change("external", UrlName, _, _, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
+
 
 % gen_server API
 
@@ -108,7 +109,12 @@ handle_info({'EXIT', Pid, Reason}, Handlers) ->
     % Remove Pid from the handlers table so we don't try closing
     % it a second time in terminate/2.
     ets:match_delete(Handlers, {'_', Pid}),
-    {stop, normal, Handlers}.
+    {stop, normal, Handlers};
+
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State}.
+
 
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_external_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_external_server.erl b/src/couch_external_server.erl
index ff2e185..0e01cf3 100644
--- a/src/couch_external_server.erl
+++ b/src/couch_external_server.erl
@@ -12,17 +12,15 @@
 
 -module(couch_external_server).
 -behaviour(gen_server).
--vsn(2).
--behaviour(config_listener).
+-vsn(3).
 
 -export([start_link/2, stop/1, execute/2]).
 -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
 
-% config_listener api
--export([handle_config_change/5, handle_config_terminate/3]).
-
 -include_lib("couch/include/couch_db.hrl").
 
+-define(RELISTEN_DELAY, 5000).
+
 % External API
 
 start_link(Name, Command) ->
@@ -40,47 +38,52 @@ execute(Pid, JsonReq) ->
 init([Name, Command]) ->
     couch_log:info("EXTERNAL: Starting process for: ~s", [Name]),
     couch_log:info("COMMAND: ~s", [Command]),
+    ok = config:subscribe_for_changes([{"couchdb", "os_process_timeout"}]),
     process_flag(trap_exit, true),
     Timeout = list_to_integer(config:get("couchdb", "os_process_timeout",
         "5000")),
     {ok, Pid} = couch_os_process:start_link(Command, [{timeout, Timeout}]),
-    ok = config:listen_for_changes(?MODULE, Pid),
-    {ok, {Name, Command, Pid}}.
+    {ok, {Name, Command, Pid, whereis(config_event)}}.
 
-terminate(_Reason, {_Name, _Command, Pid}) ->
+terminate(_Reason, {_Name, _Command, Pid, _}) ->
     couch_os_process:stop(Pid),
     ok.
 
-handle_call({execute, JsonReq}, _From, {Name, Command, Pid}) ->
+handle_call({execute, JsonReq}, _From, {Name, Command, Pid, _}) ->
     {reply, couch_os_process:prompt(Pid, JsonReq), {Name, Command, Pid}}.
 
 handle_info({'EXIT', _Pid, normal}, State) ->
     {noreply, State};
-handle_info({'EXIT', Pid, Reason}, {Name, Command, Pid}) ->
+handle_info({'EXIT', Pid, Reason}, {Name, Command, Pid, _}) ->
     couch_log:info("EXTERNAL: Process for ~s exiting. (reason: ~w)",
                    [Name, Reason]),
-    {stop, Reason, {Name, Command, Pid}}.
-
-handle_cast(stop, {Name, Command, Pid}) ->
+    {stop, Reason, {Name, Command, Pid}};
+handle_info({config_change, "couchdb", "os_process_timeout", NewTimeout, _},
+        {_Name, _Command, Pid, _} = State) ->
+    couch_os_process:set_timeout(Pid, list_to_integer(NewTimeout)),
+    {noreply, State};
+handle_info({gen_event_EXIT, _Handler, _Reason}, State) ->
+    erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
+    {noreply, State};
+handle_info({'EXIT', Pid, _Reason}, {_, _, _, Pid} = State) ->
+    erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
+    {noreply, State};
+handle_info(restart_config_listener, {Name, Command, Pid, _} = State) ->
+    case whereis(config_event) of
+        undefined ->
+            erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
+            {noreply, State};
+        EventMgr ->
+            ok = config:subscribe_for_changes([{"couchdb", "os_process_timeout"}]),
+            {noreply, {Name, Command, Pid, EventMgr}}
+    end.
+
+handle_cast(stop, {Name, _Command, Pid, _} = State) ->
     couch_log:info("EXTERNAL: Shutting down ~s", [Name]),
     exit(Pid, normal),
-    {stop, normal, {Name, Command, Pid}};
+    {stop, normal, State};
 handle_cast(_Whatever, State) ->
     {noreply, State}.
 
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
-
-
-handle_config_change("couchdb", "os_process_timeout", NewTimeout, _, Pid) ->
-    couch_os_process:set_timeout(Pid, list_to_integer(NewTimeout)),
-    {ok, Pid};
-handle_config_change(_, _, _, _, Pid) ->
-    {ok, Pid}.
-
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_httpd_vhost.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_vhost.erl b/src/couch_httpd_vhost.erl
index 05fc874..91a2476 100644
--- a/src/couch_httpd_vhost.erl
+++ b/src/couch_httpd_vhost.erl
@@ -12,6 +12,7 @@
 
 -module(couch_httpd_vhost).
 -behaviour(gen_server).
+-vsn(1).
 -behaviour(config_listener).
 
 -export([start_link/0, reload/0, get_state/0, dispatch_host/1]).
@@ -27,6 +28,7 @@
 
 -define(SEPARATOR, $\/).
 -define(MATCH_ALL, {bind, '*'}).
+-define(RELISTEN_DELAY, 5000).
 
 -record(vhosts_state, {
         vhosts,
@@ -355,6 +357,9 @@ handle_call(_Msg, _From, State) ->
 handle_cast(_Msg, State) ->
     {noreply, State}.
 
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(_Info, State) ->
     {noreply, State}.
 
@@ -374,12 +379,10 @@ handle_config_change("vhosts", _, _, _, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
 
 load_conf() ->
     %% get vhost globals

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_os_daemons.erl
----------------------------------------------------------------------
diff --git a/src/couch_os_daemons.erl b/src/couch_os_daemons.erl
index 409ba02..2c2c1a2 100644
--- a/src/couch_os_daemons.erl
+++ b/src/couch_os_daemons.erl
@@ -11,6 +11,7 @@
 % the License.
 -module(couch_os_daemons).
 -behaviour(gen_server).
+-vsn(1).
 -behaviour(config_listener).
 
 -export([start_link/0, info/0, info/1]).
@@ -36,6 +37,7 @@
 
 -define(PORT_OPTIONS, [stream, {line, 1024}, binary, exit_status, hide]).
 -define(TIMEOUT, 5000).
+-define(RELISTEN_DELAY, 5000).
 
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
@@ -183,6 +185,9 @@ handle_info({Port, Error}, Table) ->
     [D] = ets:lookup(Table, Port),
     true = ets:insert(Table, D#daemon{status=restarting, buf=nil}),
     {noreply, Table};
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(Msg, Table) ->
     couch_log:error("Unexpected info message to ~p: ~p", [?MODULE, Msg]),
     {stop, error, Table}.
@@ -195,12 +200,11 @@ handle_config_change(Section, Key, _, _, _) ->
     gen_server:cast(?MODULE, {config_change, Section, Key}),
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
+
 
 % Internal API
 

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index a6790b4..04101f2 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -13,7 +13,7 @@
 -module(couch_proc_manager).
 -behaviour(gen_server).
 -behaviour(config_listener).
--vsn(2).
+-vsn(3).
 
 -export([
     start_link/0,
@@ -43,6 +43,7 @@
 -define(PROCS, couch_proc_manager_procs).
 -define(WAITERS, couch_proc_manager_waiters).
 -define(OPENING, couch_proc_manager_opening).
+-define(RELISTEN_DELAY, 5000).
 
 -record(state, {
     config,
@@ -248,6 +249,11 @@ handle_info({'DOWN', Ref, _, _, _Reason}, State0) ->
             {noreply, State0}
     end;
 
+
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
+
 handle_info(_Msg, State) ->
     {noreply, State}.
 
@@ -255,15 +261,11 @@ handle_info(_Msg, State) ->
 code_change(_OldVsn, #state{}=State, _Extra) ->
     {ok, State}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, undefined),
-        % Reload our config in case it changed in the last
-        % five seconds.
-        gen_server:cast(?MODULE, reload_config)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    gen_server:cast(?MODULE, reload_config),
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
 
 handle_config_change("query_server_config", _, _, _, _) ->
     gen_server:cast(?MODULE, reload_config),

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 2634bbf..d7adf33 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -13,7 +13,7 @@
 -module(couch_server).
 -behaviour(gen_server).
 -behaviour(config_listener).
--vsn(2).
+-vsn(3).
 
 -export([open/2,create/2,delete/2,get_version/0,get_version/1,get_uuid/0]).
 -export([all_databases/0, all_databases/2]).
@@ -28,6 +28,7 @@
 -include_lib("couch/include/couch_db.hrl").
 
 -define(MAX_DBS_OPEN, 100).
+-define(RELISTEN_DELAY, 5000).
 
 -record(server,{
     root_dir = [],
@@ -233,13 +234,10 @@ handle_config_change("httpd_db_handlers", _, _, _, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, nil)
-    end).
-
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
 
 
 all_databases() ->
@@ -527,6 +525,9 @@ handle_info({'EXIT', Pid, Reason}, Server) ->
     [] ->
         {noreply, Server}
     end;
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(Info, Server) ->
     {stop, {unknown_message, Info}, Server}.
 

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_sup.erl b/src/couch_sup.erl
index f7a4344..8dcaf1d 100644
--- a/src/couch_sup.erl
+++ b/src/couch_sup.erl
@@ -12,6 +12,7 @@
 
 -module(couch_sup).
 -behaviour(supervisor).
+-vsn(1).
 -behaviour(config_listener).
 
 
@@ -35,7 +36,6 @@ start_link() ->
             notify_started(),
             notify_uris(),
             write_uris(),
-            ok = config:listen_for_changes(?MODULE, nil),
             Resp;
         Else ->
             notify_error(Else),
@@ -47,6 +47,14 @@ init(_Args) ->
     couch_log:info("Starting ~s", [?MODULE]),
     {ok, {{one_for_one,10, 60}, [
         {
+            config_listener_mon,
+            {config_listener_mon, start_link, [?MODULE, nil]},
+            permanent,
+            5000,
+            worker,
+            [config_listener_mon]
+        },
+        {
             couch_primary_services,
             {couch_primary_sup, start_link, []},
             permanent,
@@ -76,12 +84,8 @@ handle_config_change("couchdb", "util_driver_dir", _, _, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, undefined)
-    end).
+handle_config_terminate(_Server, _Reason, _State) ->
+    ok.
 
 notify_starting() ->
     couch_log:info("Apache CouchDB ~s is starting.~n", [

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/608942f9/src/couch_uuids.erl
----------------------------------------------------------------------
diff --git a/src/couch_uuids.erl b/src/couch_uuids.erl
index 5e1fda9..0553243 100644
--- a/src/couch_uuids.erl
+++ b/src/couch_uuids.erl
@@ -13,7 +13,7 @@
 -include_lib("couch/include/couch_db.hrl").
 
 -behaviour(gen_server).
--vsn(2).
+-vsn(3).
 -behaviour(config_listener).
 
 -export([start/0, stop/0]).
@@ -25,6 +25,8 @@
 % config_listener api
 -export([handle_config_change/5, handle_config_terminate/3]).
 
+-define(RELISTEN_DELAY, 5000).
+
 start() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
@@ -77,6 +79,9 @@ handle_cast(stop, State) ->
 handle_cast(_Msg, State) ->
     {noreply, State}.
 
+handle_info(restart_config_listener, State) ->
+    ok = config:listen_for_changes(?MODULE, nil),
+    {noreply, State};
 handle_info(_Info, State) ->
     {noreply, State}.
 
@@ -88,15 +93,11 @@ handle_config_change("uuids", _, _, _, _) ->
 handle_config_change(_, _, _, _, _) ->
     {ok, nil}.
 
-handle_config_terminate(_, stop, _) -> ok;
-handle_config_terminate(_, _, _) ->
-    spawn(fun() ->
-        timer:sleep(5000),
-        config:listen_for_changes(?MODULE, undefined),
-        % Reload our config in case it changed in the last
-        % five seconds.
-        gen_server:cast(?MODULE, change)
-    end).
+handle_config_terminate(_, stop, _) ->
+    ok;
+handle_config_terminate(_Server, _Reason, _State) ->
+    gen_server:cast(?MODULE, change),
+    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
 
 new_prefix() ->
     couch_util:to_hex((crypto:rand_bytes(13))).


Mime
View raw message