Add ioq io_priority functions and system class
diff --git a/src/chttpd/src/chttpd.app.src b/src/chttpd/src/chttpd.app.src
index bc899b1..d48f02b 100644
--- a/src/chttpd/src/chttpd.app.src
+++ b/src/chttpd/src/chttpd.app.src
@@ -27,7 +27,8 @@
         config,
         couch,
         ets_lru,
-        fabric
+        fabric,
+        ioq
     ]},
     {mod, {chttpd_app, []}}
 ]}.
diff --git a/src/chttpd/src/chttpd_auth_cache.erl b/src/chttpd/src/chttpd_auth_cache.erl
index e47d02f..36157ed 100644
--- a/src/chttpd/src/chttpd_auth_cache.erl
+++ b/src/chttpd/src/chttpd_auth_cache.erl
@@ -156,7 +156,7 @@
 
 listen_for_changes(Since) ->
     DbName = dbname(),
-    erlang:put(io_priority, {system, DbName}),
+    ioq:set_io_priority({system, DbName}),
     ensure_auth_ddoc_exists(DbName, <<"_design/_auth">>),
     CBFun = fun ?MODULE:changes_callback/2,
     Args = #changes_args{
diff --git a/src/couch_index/src/couch_index.app.src b/src/couch_index/src/couch_index.app.src
index 834be3f..e452313 100644
--- a/src/couch_index/src/couch_index.app.src
+++ b/src/couch_index/src/couch_index.app.src
@@ -14,6 +14,6 @@
     {description, "CouchDB Secondary Index Manager"},
     {vsn, git},
     {registered, []},
-    {applications, [kernel, stdlib, couch_epi]},
+    {applications, [kernel, stdlib, couch_epi, ioq]},
     {mod, {couch_index_app, []}}
 ]}.
diff --git a/src/couch_index/src/couch_index.erl b/src/couch_index/src/couch_index.erl
index c67abc9..67a34e9 100644
--- a/src/couch_index/src/couch_index.erl
+++ b/src/couch_index/src/couch_index.erl
@@ -72,7 +72,7 @@
 
 init({Mod, IdxState}) ->
     DbName = Mod:get(db_name, IdxState),
-    erlang:put(io_priority, {view_update, DbName}),
+    ioq:set_io_priority({view_update, DbName}),
     erlang:send_after(?CHECK_INTERVAL, self(), maybe_close),
     Resp = couch_util:with_db(DbName, fun(Db) ->
         case Mod:open(Db, IdxState) of
diff --git a/src/couch_peruser/src/couch_peruser.app.src b/src/couch_peruser/src/couch_peruser.app.src
index 6cfaf44..fcdcb4f 100644
--- a/src/couch_peruser/src/couch_peruser.app.src
+++ b/src/couch_peruser/src/couch_peruser.app.src
@@ -14,7 +14,7 @@
     {description, "couch_peruser - maintains per-user databases in CouchDB"},
     {vsn, git},
     {registered, [couch_peruser, couch_peruser_sup]},
-    {applications, [kernel, stdlib, config, couch, fabric, mem3]},
+    {applications, [kernel, stdlib, config, couch, fabric, mem3, ioq]},
     {mod, {couch_peruser_app, []}},
     {env, []}
 ]}.
diff --git a/src/couch_peruser/src/couch_peruser.erl b/src/couch_peruser/src/couch_peruser.erl
index c87ffb2..7a6aec0 100644
--- a/src/couch_peruser/src/couch_peruser.erl
+++ b/src/couch_peruser/src/couch_peruser.erl
@@ -85,6 +85,7 @@
                     "couch_httpd_auth", "authentication_db", "_users"
                 )
             ),
+            ioq:set_io_priority({system, DbName}),
             DeleteDbs = config:get_boolean("couch_peruser", "delete_dbs", false),
             Q = config:get_integer("couch_peruser", "q", 1),
             Prefix = config:get("couch_peruser", "database_prefix", ?DEFAULT_USERDB_PREFIX),
@@ -186,6 +187,7 @@
 -spec init_changes_handler(ChangesState :: #changes_state{}) -> ok.
 init_changes_handler(#changes_state{db_name = DbName} = ChangesState) ->
     % couch_log:debug("peruser: init_changes_handler() on DbName ~p", [DbName]),
+    ioq:set_io_priority({system, DbName}),
     try
         {ok, Db} = couch_db:open_int(DbName, [?ADMIN_CTX, sys_db]),
         FunAcc = {fun ?MODULE:changes_handler/3, ChangesState},
diff --git a/src/couch_replicator/src/couch_replicator.app.src b/src/couch_replicator/src/couch_replicator.app.src
index 2e0e191..7cc0fd1 100644
--- a/src/couch_replicator/src/couch_replicator.app.src
+++ b/src/couch_replicator/src/couch_replicator.app.src
@@ -32,6 +32,7 @@
         config,
         couch,
         couch_event,
-        couch_stats
+        couch_stats,
+        ioq
     ]}
 ]}.
diff --git a/src/couch_replicator/src/couch_replicator_docs.erl b/src/couch_replicator/src/couch_replicator_docs.erl
index 7bdf00b..a80abe9 100644
--- a/src/couch_replicator/src/couch_replicator_docs.erl
+++ b/src/couch_replicator/src/couch_replicator_docs.erl
@@ -357,6 +357,7 @@
     end.
 
 open_rep_doc(DbName, DocId) ->
+    ioq:maybe_set_io_priority({system, DbName}),
     case couch_db:open_int(DbName, [?CTX, sys_db]) of
         {ok, Db} ->
             try
@@ -369,6 +370,7 @@
     end.
 
 save_rep_doc(DbName, Doc) ->
+    ioq:maybe_set_io_priority({system, DbName}),
     {ok, Db} = couch_db:open_int(DbName, [?CTX, sys_db]),
     try
         couch_db:update_doc(Db, Doc, [])
diff --git a/src/global_changes/src/global_changes.app.src b/src/global_changes/src/global_changes.app.src
index a1dc2f3..757387a 100644
--- a/src/global_changes/src/global_changes.app.src
+++ b/src/global_changes/src/global_changes.app.src
@@ -23,7 +23,8 @@
         couch_stats,
         couch,
         mem3,
-        fabric
+        fabric,
+        ioq
     ]},
     {mod, {global_changes_app, []}},
     {env, [
diff --git a/src/global_changes/src/global_changes_server.erl b/src/global_changes/src/global_changes_server.erl
index e4902e2..e9a9c5f 100644
--- a/src/global_changes/src/global_changes_server.erl
+++ b/src/global_changes/src/global_changes_server.erl
@@ -60,6 +60,9 @@
         end,
     MaxWriteDelay = list_to_integer(MaxWriteDelay0),
 
+    GlobalChangesDbName = global_changes_util:get_dbname(),
+    ioq:set_io_priority({system, GlobalChangesDbName}),
+
     % Start our write triggers
     erlang:send_after(MaxWriteDelay, self(), flush_updates),
 
@@ -68,7 +71,7 @@
         pending_update_count = 0,
         pending_updates = sets:new(),
         max_write_delay = MaxWriteDelay,
-        dbname = global_changes_util:get_dbname(),
+        dbname = GlobalChangesDbName,
         handler_ref = erlang:monitor(process, Handler)
     },
     {ok, State}.
diff --git a/src/ioq/src/ioq.erl b/src/ioq/src/ioq.erl
index 51934d5..945e455 100644
--- a/src/ioq/src/ioq.erl
+++ b/src/ioq/src/ioq.erl
@@ -16,6 +16,7 @@
 
 -export([start_link/0, call/3]).
 -export([get_queue_lengths/0]).
+-export([get_io_priority/0, set_io_priority/1, maybe_set_io_priority/1]).
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]).
 
 % config_listener api
@@ -39,6 +40,18 @@
     ref
 }).
 
+set_io_priority(Priority) ->
+    erlang:put(io_priority, Priority).
+
+get_io_priority() ->
+    erlang:get(io_priority).
+
+maybe_set_io_priority(Priority) ->
+    case get_io_priority() of
+        undefined -> set_io_priority(Priority);
+        _ -> ok
+    end.
+
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
@@ -81,6 +94,12 @@
     compaction;
 io_class(_, {view_compact, _, _}) ->
     compaction;
+io_class(_, {system, _}) ->
+    system;
+io_class(_, {search, _}) ->
+    search;
+io_class(_, {search, _, _}) ->
+    search;
 io_class(_, _) ->
     other.
 
diff --git a/src/mem3/src/mem3.app.src b/src/mem3/src/mem3.app.src
index 889ebf9..824ff99 100644
--- a/src/mem3/src/mem3.app.src
+++ b/src/mem3/src/mem3.app.src
@@ -35,6 +35,7 @@
         rexi,
         couch_log,
         couch_event,
-        couch_stats
+        couch_stats,
+        ioq
     ]}
 ]}.
diff --git a/src/mem3/src/mem3_nodes.erl b/src/mem3/src/mem3_nodes.erl
index b46b3bb..f39c71b 100644
--- a/src/mem3/src/mem3_nodes.erl
+++ b/src/mem3/src/mem3_nodes.erl
@@ -49,6 +49,8 @@
     end.
 
 init([]) ->
+    DbName = mem3_sync:nodes_db(),
+    ioq:set_io_priority({system, DbName}),
     ets:new(?MODULE, [named_table, {read_concurrency, true}]),
     UpdateSeq = initialize_nodelist(),
     {Pid, _} = spawn_monitor(fun() -> listen_for_changes(UpdateSeq) end),
@@ -104,7 +106,7 @@
 %% internal functions
 
 initialize_nodelist() ->
-    DbName = config:get("mem3", "nodes_db", "_nodes"),
+    DbName = mem3_sync:nodes_db(),
     {ok, Db} = mem3_util:ensure_exists(DbName),
     {ok, _} = couch_db:fold_docs(Db, fun first_fold/2, Db, []),
     insert_if_missing(Db, [node() | mem3_seeds:get_seeds()]),
@@ -122,7 +124,8 @@
     {ok, Db}.
 
 listen_for_changes(Since) ->
-    DbName = config:get("mem3", "nodes_db", "_nodes"),
+    DbName = mem3_sync:nodes_db(),
+    ioq:set_io_priority({system, DbName}),
     {ok, Db} = mem3_util:ensure_exists(DbName),
     Args = #changes_args{
         feed = "continuous",
diff --git a/src/mem3/src/mem3_shards.erl b/src/mem3/src/mem3_shards.erl
index 8bbc924..f48bfdb 100644
--- a/src/mem3/src/mem3_shards.erl
+++ b/src/mem3/src/mem3_shards.erl
@@ -220,6 +220,8 @@
     ok = config:listen_for_changes(?MODULE, nil),
     SizeList = config:get("mem3", "shard_cache_size", "25000"),
     WriteTimeout = config:get_integer("mem3", "shard_write_timeout", 1000),
+    DbName = mem3_sync:shards_db(),
+    ioq:set_io_priority({system, DbName}),
     UpdateSeq = get_update_seq(),
     {ok, #st{
         max_size = list_to_integer(SizeList),
@@ -341,7 +343,9 @@
     Seq.
 
 listen_for_changes(Since) ->
-    {ok, Db} = mem3_util:ensure_exists(mem3_sync:shards_db()),
+    DbName = mem3_sync:shards_db(),
+    ioq:set_io_priority({system, DbName}),
+    {ok, Db} = mem3_util:ensure_exists(DbName),
     Args = #changes_args{
         feed = "continuous",
         since = Since,
diff --git a/src/mem3/src/mem3_util.erl b/src/mem3/src/mem3_util.erl
index f454e3e..6a4ae13 100644
--- a/src/mem3/src/mem3_util.erl
+++ b/src/mem3/src/mem3_util.erl
@@ -119,6 +119,7 @@
     write_db_doc(mem3_sync:shards_db(), Doc, true).
 
 write_db_doc(DbName, #doc{id = Id, body = Body} = Doc, ShouldMutate) ->
+    ioq:maybe_set_io_priority({system, DbName}),
     {ok, Db} = couch_db:open(DbName, [?ADMIN_CTX]),
     try couch_db:open_doc(Db, Id, [ejson_body]) of
         {ok, #doc{body = Body}} ->
@@ -144,6 +145,7 @@
     update_db_doc(mem3_sync:shards_db(), Doc, true).
 
 update_db_doc(DbName, #doc{id = Id, body = Body} = Doc, ShouldMutate) ->
+    ioq:maybe_set_io_priority({system, DbName}),
     {ok, Db} = couch_db:open(DbName, [?ADMIN_CTX]),
     try couch_db:open_doc(Db, Id, [ejson_body]) of
         {ok, #doc{body = Body}} ->
@@ -174,6 +176,7 @@
     delete_db_doc(mem3_sync:shards_db(), DocId, true).
 
 delete_db_doc(DbName, DocId, ShouldMutate) ->
+    ioq:maybe_set_io_priority({system, DbName}),
     {ok, Db} = couch_db:open(DbName, [?ADMIN_CTX]),
     {ok, Revs} = couch_db:open_doc_revs(Db, DocId, all, []),
     try [Doc#doc{deleted = true} || {ok, #doc{deleted = false} = Doc} <- Revs] of