├── config
├── sys.config
├── vm.args
├── dev1_vm.args
├── dev2_vm.args
├── dev3_vm.args
├── vars.config
├── vars_dev1.config
├── vars_dev2.config
├── vars_dev3.config
├── advanced.config
├── config.schema
├── nodetool
├── admin_bin
├── erlang_vm.schema
└── riak_core.schema
├── .editorconfig
├── .gitignore
├── apps
└── tanodb
│ ├── src
│ ├── tanodb_json.erl
│ ├── tanodb.app.src
│ ├── tanodb_coverage_fsm_sup.erl
│ ├── tanodb_write_fsm_sup.erl
│ ├── tanodb_http_metrics.erl
│ ├── tanodb_http_ping.erl
│ ├── tanodb_sup.erl
│ ├── tanodb.erl
│ ├── tanodb_coverage_fsm.erl
│ ├── tanodb_metrics.erl
│ ├── tanodb_http_store.erl
│ ├── tanodb_console.erl
│ ├── tanodb_app.erl
│ ├── tanodb_write_fsm.erl
│ └── tanodb_vnode.erl
│ └── priv
│ └── ui
│ └── admin
│ ├── index.html
│ └── css
│ ├── iorioui_style.css
│ └── bootstrap.min.css
├── Makefile
├── rebar.config
├── README.rst
└── rebar.lock
/config/sys.config:
--------------------------------------------------------------------------------
1 | [
2 | { tanodb, []}
3 | ].
4 |
--------------------------------------------------------------------------------
/config/vm.args:
--------------------------------------------------------------------------------
1 | -name tanodb@127.0.0.1
2 |
3 | -setcookie tanodb_cookie
4 |
5 | +K true
6 | +A30
7 |
--------------------------------------------------------------------------------
/config/dev1_vm.args:
--------------------------------------------------------------------------------
1 | -name tanodb1@127.0.0.1
2 |
3 | -setcookie tanodb_cookie
4 |
5 | +K true
6 | +A30
7 |
--------------------------------------------------------------------------------
/config/dev2_vm.args:
--------------------------------------------------------------------------------
1 | -name tanodb2@127.0.0.1
2 |
3 | -setcookie tanodb_cookie
4 |
5 | +K true
6 | +A30
7 |
--------------------------------------------------------------------------------
/config/dev3_vm.args:
--------------------------------------------------------------------------------
1 | -name tanodb3@127.0.0.1
2 |
3 | -setcookie tanodb_cookie
4 |
5 | +K true
6 | +A30
7 |
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.fn]
2 | end_of_line = lf
3 | insert_final_newline = true
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .rebar3
2 | rebar3
3 | _*
4 | .eunit
5 | *.o
6 | *.beam
7 | *.plt
8 | *.swp
9 | *.swo
10 | .erlang.cookie
11 | ebin
12 | log
13 | erl_crash.dump
14 | .rebar
15 | _rel
16 | _deps
17 | _plugins
18 | _tdeps
19 | logs
20 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_json.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_json).
2 | -export([decode/1, encode/1, is_json/1]).
3 |
4 | decode(Obj) -> jsx:decode(Obj, [return_maps]).
5 | encode(Obj) -> jsx:encode(Obj).
6 | is_json(Obj) -> jsx:is_json(Obj).
7 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb.app.src:
--------------------------------------------------------------------------------
1 | %% -*- erlang -*-
2 | {application, tanodb,
3 | [
4 | {description, "A Riak Core Application"},
5 | {vsn, "1"},
6 | {registered, []},
7 | {applications, [
8 | kernel,
9 | stdlib,
10 | sasl,
11 | riak_core,
12 | setup,
13 | cowboy,
14 | jsx
15 | ]},
16 | {mod, { tanodb_app, []}},
17 | {env, []}
18 | ]}.
19 |
--------------------------------------------------------------------------------
/apps/tanodb/priv/ui/admin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Admin
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/config/vars.config:
--------------------------------------------------------------------------------
1 | {cuttlefish_conf, "tanodb.conf"}.
2 | {rel_name, "tanodb"}.
3 | {node, "tanodb@127.0.0.1"}.
4 |
5 | {web_ip, "127.0.0.1"}.
6 | {handoff_port, 8099}.
7 | {handoff_ip, "127.0.0.1"}.
8 | {sasl_error_log, "./log/sasl-error.log"}.
9 | {sasl_log_dir, "./log/sasl"}.
10 |
11 | {http_port, 8080}.
12 |
13 | {run_user_home, "$HOME"}.
14 | {platform_bin_dir, "./bin"}.
15 | {platform_data_dir, "../tanodb_data"}.
16 | {platform_etc_dir, "../tanodb_config"}.
17 | {platform_lib_dir, "./lib"}.
18 | {platform_log_dir, "./log"}.
19 |
20 | {crash_dump, "{{platform_log_dir}}/erl_crash.dump"}.
21 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_coverage_fsm_sup.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_coverage_fsm_sup).
2 | -behavior(supervisor).
3 |
4 | -export([start_link/0, start_fsm/1]).
5 | -export([init/1]).
6 |
7 | -ignore_xref([start_link/0, init/1]).
8 |
9 | start_link() ->
10 | supervisor:start_link({local, ?MODULE}, ?MODULE, []).
11 |
12 | init([]) ->
13 | CoverageFSM = {undefined,
14 | {tanodb_coverage_fsm, start_link, []},
15 | temporary, 5000, worker, [tanodb_coverage_fsm]},
16 |
17 | {ok, {{simple_one_for_one, 10, 10}, [CoverageFSM]}}.
18 |
19 | start_fsm(Args) ->
20 | supervisor:start_child(?MODULE, Args).
21 |
22 |
--------------------------------------------------------------------------------
/config/vars_dev1.config:
--------------------------------------------------------------------------------
1 | {cuttlefish_conf, "tanodb.conf"}.
2 | {rel_name, "tanodb"}.
3 | {node, "tanodb1@127.0.0.1"}.
4 |
5 | {web_ip, "127.0.0.1"}.
6 | {handoff_port, 8199}.
7 | {handoff_ip, "127.0.0.1"}.
8 | {sasl_error_log, "./log/sasl-error.log"}.
9 | {sasl_log_dir, "./log/sasl"}.
10 |
11 | {http_port, 8180}.
12 |
13 | {run_user_home, "$HOME"}.
14 | {platform_bin_dir, "./bin"}.
15 | {platform_data_dir, "../tanodb_data"}.
16 | {platform_etc_dir, "../tanodb_config"}.
17 | {platform_lib_dir, "./lib"}.
18 | {platform_log_dir, "./log"}.
19 |
20 | {crash_dump, "{{platform_log_dir}}/erl_crash.dump"}.
21 |
--------------------------------------------------------------------------------
/config/vars_dev2.config:
--------------------------------------------------------------------------------
1 | {cuttlefish_conf, "tanodb.conf"}.
2 | {rel_name, "tanodb"}.
3 | {node, "tanodb2@127.0.0.1"}.
4 |
5 | {web_ip, "127.0.0.1"}.
6 | {handoff_port, 8299}.
7 | {handoff_ip, "127.0.0.1"}.
8 | {sasl_error_log, "./log/sasl-error.log"}.
9 | {sasl_log_dir, "./log/sasl"}.
10 |
11 | {http_port, 8280}.
12 |
13 | {run_user_home, "$HOME"}.
14 | {platform_bin_dir, "./bin"}.
15 | {platform_data_dir, "../tanodb_data"}.
16 | {platform_etc_dir, "../tanodb_config"}.
17 | {platform_lib_dir, "./lib"}.
18 | {platform_log_dir, "./log"}.
19 |
20 | {crash_dump, "{{platform_log_dir}}/erl_crash.dump"}.
21 |
--------------------------------------------------------------------------------
/config/vars_dev3.config:
--------------------------------------------------------------------------------
1 | {cuttlefish_conf, "tanodb.conf"}.
2 | {rel_name, "tanodb"}.
3 | {node, "tanodb3@127.0.0.1"}.
4 |
5 | {web_ip, "127.0.0.1"}.
6 | {handoff_port, 8399}.
7 | {handoff_ip, "127.0.0.1"}.
8 | {sasl_error_log, "./log/sasl-error.log"}.
9 | {sasl_log_dir, "./log/sasl"}.
10 |
11 | {http_port, 8380}.
12 |
13 | {run_user_home, "$HOME"}.
14 | {platform_bin_dir, "./bin"}.
15 | {platform_data_dir, "../tanodb_data"}.
16 | {platform_etc_dir, "../tanodb_config"}.
17 | {platform_lib_dir, "./lib"}.
18 | {platform_log_dir, "./log"}.
19 |
20 | {crash_dump, "{{platform_log_dir}}/erl_crash.dump"}.
21 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_write_fsm_sup.erl:
--------------------------------------------------------------------------------
1 | %% @doc Supervise the tanodb_write FSM.
2 | -module(tanodb_write_fsm_sup).
3 | -behavior(supervisor).
4 |
5 | -export([start_write_fsm/1, start_link/0]).
6 | -export([init/1]).
7 |
8 | -ignore_xref([init/1, start_link/0]).
9 |
10 | start_write_fsm(Args) ->
11 | supervisor:start_child(?MODULE, Args).
12 |
13 | start_link() ->
14 | supervisor:start_link({local, ?MODULE}, ?MODULE, []).
15 |
16 | init([]) ->
17 | WriteFsm = {undefined,
18 | {tanodb_write_fsm, start_link, []},
19 | temporary, 5000, worker, [tanodb_write_fsm]},
20 | {ok, {{simple_one_for_one, 10, 10}, [WriteFsm]}}.
21 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_http_metrics.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_http_metrics).
2 |
3 | -export([init/3, terminate/3]).
4 |
5 | -ignore_xref([init/3, terminate/3]).
6 |
7 | -export([rest_init/2,
8 | rest_terminate/2,
9 | allowed_methods/2,
10 | content_types_provided/2,
11 | to_json/2]).
12 |
13 | -ignore_xref([rest_init/2,
14 | rest_terminate/2,
15 | allowed_methods/2,
16 | content_types_provided/2,
17 | to_json/2]).
18 |
19 | -record(state, {}).
20 |
21 | init(_, _Req, _Opts) -> {upgrade, protocol, cowboy_rest}.
22 | rest_init(Req, _Opts) -> {ok, Req, #state{}}.
23 |
24 | allowed_methods(Req, State) -> {[<<"GET">>], Req, State}.
25 |
26 | content_types_provided(Req, State) ->
27 | {[{{<<"application">>, <<"json">>, '*'}, to_json}], Req, State}.
28 |
29 | to_json(Req, State) ->
30 | Metrics = tanodb_metrics:all(),
31 | Response = tanodb_json:encode(Metrics),
32 | {Response, Req, State}.
33 |
34 | rest_terminate(_Req, _State) -> ok.
35 | terminate(_Reason, _Req, _State) -> ok.
36 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_http_ping.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_http_ping).
2 |
3 | -export([init/3, terminate/3]).
4 |
5 | -ignore_xref([init/3, terminate/3]).
6 |
7 | -export([rest_init/2,
8 | rest_terminate/2,
9 | allowed_methods/2,
10 | content_types_provided/2,
11 | to_json/2]).
12 |
13 | -ignore_xref([rest_init/2,
14 | rest_terminate/2,
15 | allowed_methods/2,
16 | content_types_provided/2,
17 | to_json/2]).
18 |
19 | -record(state, {}).
20 |
21 | init(_, _Req, _Opts) -> {upgrade, protocol, cowboy_rest}.
22 | rest_init(Req, _Opts) -> {ok, Req, #state{}}.
23 |
24 | allowed_methods(Req, State) -> {[<<"GET">>], Req, State}.
25 |
26 | content_types_provided(Req, State) ->
27 | {[{{<<"application">>, <<"json">>, '*'}, to_json}], Req, State}.
28 |
29 | to_json(Req, State) ->
30 | {pong, Partition} = tanodb:ping(),
31 | Response = tanodb_json:encode([{pong, integer_to_binary(Partition)}]),
32 | {Response, Req, State}.
33 |
34 | rest_terminate(_Req, _State) -> ok.
35 | terminate(_Reason, _Req, _State) -> ok.
36 |
--------------------------------------------------------------------------------
/config/advanced.config:
--------------------------------------------------------------------------------
1 | [
2 | { tanodb, []},
3 | {riak_core, [
4 | {schema_dirs, ["share/schema"]},
5 | %% tanodb valid permissions to grant
6 | {permissions, [{ tanodb, [put, get, delete]}]}
7 | ]},
8 | %% SASL config
9 | {sasl, [
10 | {sasl_error_logger, {file, "log/sasl-error.log"}},
11 | {errlog_type, error},
12 | {error_logger_mf_dir, "log/sasl"}, % Log directory
13 | {error_logger_mf_maxbytes, 10485760}, % 10 MB max file size
14 | {error_logger_mf_maxfiles, 5} % 5 files max
15 | ]
16 | },
17 |
18 | %% Lager config
19 | %% see https://github.com/basho/lager#configuration
20 | %% see https://github.com/basho/lager/blob/master/src/lager.app.src
21 | {lager, [
22 | {handlers, [
23 | {lager_console_backend, info},
24 | {lager_file_backend, [{file, "error.log"}, {level, error},
25 | {size, 10485760}, {date, "$D0"}, {count, 5}]},
26 | {lager_file_backend, [{file, "console.log"}, {level, info},
27 | {size, 10485760}, {date, "$D0"}, {count, 5}]}
28 | ]}
29 | ]}
30 | ].
31 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_sup.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_sup).
2 |
3 | -behaviour(supervisor).
4 |
5 | %% API
6 | -export([start_link/0]).
7 |
8 | %% Supervisor callbacks
9 | -export([init/1]).
10 |
11 | %% ===================================================================
12 | %% API functions
13 | %% ===================================================================
14 |
15 | start_link() ->
16 | supervisor:start_link({local, ?MODULE}, ?MODULE, []).
17 |
18 | %% ===================================================================
19 | %% Supervisor callbacks
20 | %% ===================================================================
21 |
22 | init(_Args) ->
23 | VMaster = { tanodb_vnode_master,
24 | {riak_core_vnode_master, start_link, [tanodb_vnode]},
25 | permanent, 5000, worker, [riak_core_vnode_master]},
26 |
27 | CoverageFSMs = {tanodb_coverage_fsm_sup,
28 | {tanodb_coverage_fsm_sup, start_link, []},
29 | permanent, infinity, supervisor, [tanodb_coverage_fsm_sup]},
30 |
31 | WriteFSMs = {tanodb_write_fsm_sup,
32 | {tanodb_write_fsm_sup, start_link, []},
33 | permanent, infinity, supervisor, [tanodb_write_fsm_sup]},
34 |
35 | {ok, {{one_for_one, 5, 10}, [VMaster, CoverageFSMs, WriteFSMs]}}.
36 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb).
2 | -include_lib("riak_core/include/riak_core_vnode.hrl").
3 |
4 | -export([ping/0, get/1, delete/1, put/2, keys/1]).
5 |
6 | -ignore_xref([ping/0, get/1, delete/1, put/2]).
7 |
8 | -define(N, 3).
9 | -define(W, 3).
10 |
11 | %% Public API
12 |
13 | %% @doc Pings a random vnode to make sure communication is functional
14 | ping() ->
15 | tanodb_metrics:core_ping(),
16 | send_to_one({<<"ping">>, term_to_binary(os:timestamp())}, ping).
17 |
18 | get(Key) ->
19 | tanodb_metrics:core_get(),
20 | send_to_one(Key, {get, Key}).
21 |
22 | delete(Key) ->
23 | tanodb_metrics:core_delete(),
24 | ReqID = make_ref(),
25 | Timeout = 5000,
26 | tanodb_write_fsm:delete(?N, Key, self(), ReqID),
27 | wait_for_reqid(ReqID, Timeout).
28 |
29 | put(Key, Value) ->
30 | tanodb_metrics:core_put(),
31 | ReqID = make_ref(),
32 | Timeout = 5000,
33 | tanodb_write_fsm:write(?N, ?W, Key, Value, self(), ReqID),
34 | wait_for_reqid(ReqID, Timeout).
35 |
36 | keys(Bucket) ->
37 | tanodb_metrics:core_keys(),
38 | Timeout = 5000,
39 | tanodb_coverage_fsm:start({keys, Bucket}, Timeout).
40 |
41 | % private functions
42 |
43 | send_to_one(Key, Cmd) ->
44 | DocIdx = riak_core_util:chash_key(Key),
45 | PrefList = riak_core_apl:get_primary_apl(DocIdx, 1, tanodb),
46 | [{IndexNode, _Type}] = PrefList,
47 | riak_core_vnode_master:sync_spawn_command(IndexNode, Cmd, tanodb_vnode_master).
48 |
49 | wait_for_reqid(ReqID, Timeout) ->
50 | receive
51 | {ReqID, {error, Reason}} -> {error, Reason};
52 | {ReqID, Val} -> Val
53 | after Timeout -> {error, timeout}
54 | end.
55 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_coverage_fsm.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_coverage_fsm).
2 |
3 | -export([start_link/4, start/2]).
4 | -export([init/2, process_results/2, finish/2]).
5 |
6 | -ignore_xref([start_link/4]).
7 |
8 | -behaviour(riak_core_coverage_fsm).
9 |
10 | -record(state, {req_id, from, request, accum=[]}).
11 |
12 | %% API
13 |
14 | start_link(ReqId, From, Request, Timeout) ->
15 | riak_core_coverage_fsm:start_link(?MODULE, {pid, ReqId, From},
16 | [ReqId, From, Request, Timeout]).
17 |
18 | start(Request, Timeout) ->
19 | ReqId = erlang:phash2(time_compat:monotonic_time()),
20 | {ok, _} = tanodb_coverage_fsm_sup:start_fsm([ReqId, self(), Request, Timeout]),
21 | receive
22 | {ReqId, Val} -> Val
23 | end.
24 |
25 | %% riak_core_coverage_fsm API
26 |
27 | init(_, [ReqId, From, Request, Timeout]) ->
28 | State = #state{req_id=ReqId, from=From, request=Request},
29 | {Request, allup, 1, 1, tanodb, tanodb_vnode_master, Timeout, State}.
30 |
31 | process_results({{_ReqId, {Partition, Node}}, Data},
32 | State=#state{accum=Accum}) ->
33 | NewAccum = [{Partition, Node, Data}|Accum],
34 | {done, State#state{accum=NewAccum}};
35 |
36 | process_results(Other, State=#state{}) ->
37 | lager:warning("unknown process_results message ~p", [Other]),
38 | {stop, {error, {unknown_msg, Other}}, State}.
39 |
40 | finish(clean, S=#state{req_id=ReqId, from=From, accum=Accum}) ->
41 | From ! {ReqId, {ok, Accum}},
42 | {stop, normal, S};
43 |
44 | finish({error, Reason}, S=#state{req_id=ReqId, from=From, accum=Accum}) ->
45 | lager:warning("Coverage query failed! Reason: ~p", [Reason]),
46 | From ! {ReqId, {partial, Reason, Accum}},
47 | {stop, normal, S}.
48 |
--------------------------------------------------------------------------------
/apps/tanodb/priv/ui/admin/css/iorioui_style.css:
--------------------------------------------------------------------------------
1 | /* iorioui CSS */
2 | /*
3 | * Base structure
4 | */
5 |
6 | /* Move down content because we have a fixed navbar that is 50px tall */
7 | body {
8 | padding-top: 50px;
9 | }
10 |
11 |
12 | /*
13 | * Global add-ons
14 | */
15 |
16 | .sub-header {
17 | padding-bottom: 10px;
18 | border-bottom: 1px solid #eee;
19 | }
20 |
21 | /*
22 | * Top navigation
23 | * Hide default border to remove 1px line.
24 | */
25 | .navbar-fixed-top {
26 | border: 0;
27 | }
28 |
29 | /*
30 | * Sidebar
31 | */
32 |
33 | /* Hide for mobile, show later */
34 | .sidebar {
35 | display: none;
36 | }
37 | @media (min-width: 768px) {
38 | .sidebar {
39 | position: fixed;
40 | top: 51px;
41 | bottom: 0;
42 | left: 0;
43 | z-index: 1000;
44 | display: block;
45 | padding: 20px;
46 | overflow-x: hidden;
47 | overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
48 | background-color: #f5f5f5;
49 | border-right: 1px solid #eee;
50 | }
51 | }
52 |
53 | /* Sidebar navigation */
54 | .nav-sidebar {
55 | margin-right: -21px; /* 20px padding + 1px border */
56 | margin-bottom: 20px;
57 | margin-left: -20px;
58 | }
59 | .nav-sidebar > li > a {
60 | padding-right: 20px;
61 | padding-left: 20px;
62 | }
63 | .nav-sidebar > .active > a,
64 | .nav-sidebar > .active > a:hover,
65 | .nav-sidebar > .active > a:focus {
66 | color: #fff;
67 | background-color: #428bca;
68 | }
69 |
70 |
71 | /*
72 | * Main content
73 | */
74 |
75 | .main {
76 | padding: 20px;
77 | }
78 | @media (min-width: 768px) {
79 | .main {
80 | padding-right: 40px;
81 | padding-left: 40px;
82 | }
83 | }
84 | .main .page-header {
85 | margin-top: 0;
86 | }
87 |
88 | .buttons{
89 | width: 100%;
90 | margin: 1em;
91 | text-align: center;
92 | }
93 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_metrics.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_metrics).
2 | -export([all/0, init/0]).
3 |
4 | -export([core_ping/0, core_put/0, core_get/0, core_delete/0, core_keys/0]).
5 |
6 | -define(ENDPOINTS, [<<"ping">>, <<"metrics">>]).
7 | -define(METRIC_CORE_PING, [tanodb, core, ping]).
8 | -define(METRIC_CORE_PUT, [tanodb, core, put]).
9 | -define(METRIC_CORE_GET, [tanodb, core, get]).
10 | -define(METRIC_CORE_DELETE, [tanodb, core, delete]).
11 | -define(METRIC_CORE_KEYS, [tanodb, core, keys]).
12 |
13 | all() ->
14 | [{tanodb, tanodb_stats()},
15 | {http, cowboy_exometer:stats(?ENDPOINTS)},
16 | {node, node_stats()},
17 | {core, core_stats()}].
18 |
19 | core_stats() ->
20 | [
21 | {ping, unwrap_metric_value(?METRIC_CORE_PING)},
22 | {put, unwrap_metric_value(?METRIC_CORE_PUT)},
23 | {get, unwrap_metric_value(?METRIC_CORE_GET)},
24 | {keys, unwrap_metric_value(?METRIC_CORE_KEYS)},
25 | {delete, unwrap_metric_value(?METRIC_CORE_DELETE)}
26 | ].
27 |
28 | core_ping() -> exometer:update(?METRIC_CORE_PING, 1).
29 | core_put() -> exometer:update(?METRIC_CORE_PUT, 1).
30 | core_get() -> exometer:update(?METRIC_CORE_GET, 1).
31 | core_keys() -> exometer:update(?METRIC_CORE_KEYS, 1).
32 | core_delete() -> exometer:update(?METRIC_CORE_DELETE, 1).
33 |
34 | init() ->
35 | cowboy_exometer:init(?ENDPOINTS),
36 | exometer:new(?METRIC_CORE_PING, spiral, [{time_span, 60000}]),
37 | exometer:new(?METRIC_CORE_PUT, spiral, [{time_span, 60000}]),
38 | exometer:new(?METRIC_CORE_GET, spiral, [{time_span, 60000}]),
39 | exometer:new(?METRIC_CORE_KEYS, spiral, [{time_span, 60000}]),
40 | exometer:new(?METRIC_CORE_DELETE, spiral, [{time_span, 60000}]).
41 |
42 | tanodb_stats() ->
43 | Stats = riak_core_stat:get_stats(),
44 | lists:map(fun metric_key_to_string/1, Stats).
45 |
46 | node_stats() ->
47 | [{Abs1, Inc1}] = recon:node_stats_list(1, 0),
48 | [{abs, Abs1}, {inc, Inc1}].
49 |
50 | metric_key_to_string({K, V}) ->
51 | StrKeyTokens = lists:map(fun to_string/1, tl(tl(K))),
52 | StrKey = string:join(StrKeyTokens, "_"),
53 | BinKey = list_to_binary(StrKey),
54 | {BinKey, V}.
55 |
56 | to_string(V) when is_atom(V) -> atom_to_list(V);
57 | to_string(V) when is_integer(V) -> integer_to_list(V);
58 | to_string(V) when is_binary(V) -> binary_to_list(V);
59 | to_string(V) when is_list(V) -> V.
60 |
61 | unwrap_metric_value(Key) ->
62 | case exometer:get_value(Key) of
63 | {ok, Val} -> Val;
64 | Other ->
65 | lager:warning("Error getting endpoint value ~p: ~p",
66 | [Key, Other]),
67 | []
68 | end.
69 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BASEDIR = $(shell pwd)
2 | REBAR = rebar3
3 | RELPATH = _build/default/rel/tanodb
4 | APPNAME = tanodb
5 | SHELL = /bin/bash
6 |
7 | release:
8 | $(REBAR) release
9 | mkdir -p _build/default/rel/tanodb_data/
10 | mkdir -p _build/default/rel/tanodb_config/
11 | cp _build/default/rel/tanodb/etc/* _build/default/rel/tanodb_config/
12 |
13 | compile:
14 | $(REBAR) compile
15 |
16 | clean:
17 | $(REBAR) clean
18 |
19 | test:
20 | $(REBAR) ct
21 |
22 | devrel1:
23 | $(REBAR) as dev1 release
24 | mkdir -p _build/dev1/rel/tanodb_data/
25 | mkdir -p _build/dev1/rel/tanodb_config/
26 | cp _build/dev1/rel/tanodb/etc/* _build/dev1/rel/tanodb_config/
27 |
28 | devrel2:
29 | $(REBAR) as dev2 release
30 | mkdir -p _build/dev2/rel/tanodb_data/
31 | mkdir -p _build/dev2/rel/tanodb_config/
32 | cp _build/dev2/rel/tanodb/etc/* _build/dev2/rel/tanodb_config/
33 |
34 | devrel3:
35 | $(REBAR) as dev3 release
36 | mkdir -p _build/dev3/rel/tanodb_data/
37 | mkdir -p _build/dev3/rel/tanodb_config/
38 | cp _build/dev3/rel/tanodb/etc/* _build/dev3/rel/tanodb_config/
39 |
40 | devrel: devrel1 devrel2 devrel3
41 |
42 | dev-attach1:
43 | $(BASEDIR)/_build/dev1/rel/tanodb/bin/$(APPNAME) attach
44 |
45 | dev-attach2:
46 | $(BASEDIR)/_build/dev2/rel/tanodb/bin/$(APPNAME) attach
47 |
48 | dev-attach3:
49 | $(BASEDIR)/_build/dev3/rel/tanodb/bin/$(APPNAME) attach
50 |
51 | dev-console1:
52 | $(BASEDIR)/_build/dev1/rel/tanodb/bin/$(APPNAME) console
53 |
54 | dev-console2:
55 | $(BASEDIR)/_build/dev2/rel/tanodb/bin/$(APPNAME) console
56 |
57 | dev-console3:
58 | $(BASEDIR)/_build/dev3/rel/tanodb/bin/$(APPNAME) console
59 |
60 | devrel-start:
61 | for d in $(BASEDIR)/_build/dev*; do $$d/rel/tanodb/bin/$(APPNAME) start; done
62 |
63 | devrel-join:
64 | for d in $(BASEDIR)/_build/dev{2,3}; do $$d/rel/tanodb/bin/$(APPNAME)-admin cluster join tanodb1@127.0.0.1; done
65 |
66 | devrel-cluster-plan:
67 | $(BASEDIR)/_build/dev1/rel/tanodb/bin/$(APPNAME)-admin cluster plan
68 |
69 | devrel-cluster-commit:
70 | $(BASEDIR)/_build/dev1/rel/tanodb/bin/$(APPNAME)-admin cluster commit
71 |
72 | devrel-status:
73 | $(BASEDIR)/_build/dev1/rel/tanodb/bin/$(APPNAME)-admin member-status
74 |
75 | devrel-ping:
76 | for d in $(BASEDIR)/_build/dev*; do $$d/rel/tanodb/bin/$(APPNAME) ping; true; done
77 |
78 | devrel-stop:
79 | for d in $(BASEDIR)/_build/dev*; do $$d/rel/tanodb/bin/$(APPNAME) stop; true; done
80 |
81 | start:
82 | $(BASEDIR)/$(RELPATH)/bin/$(APPNAME) start
83 |
84 | stop:
85 | $(BASEDIR)/$(RELPATH)/bin/$(APPNAME) stop
86 |
87 | console:
88 | $(BASEDIR)/$(RELPATH)/bin/$(APPNAME) console
89 |
90 | attach:
91 | $(BASEDIR)/$(RELPATH)/bin/$(APPNAME) attach
92 |
93 |
--------------------------------------------------------------------------------
/rebar.config:
--------------------------------------------------------------------------------
1 | %% -*- mode: erlang; -*-
2 | {erl_opts, [debug_info, {parse_transform, lager_transform}]}.
3 |
4 | {deps, [
5 | lager,
6 | {riak_core, "3.0.9", {pkg, riak_core_ng}},
7 | {cowboy, "1.0.3"},
8 | jsx,
9 | recon,
10 | {cowboy_exometer, {git, "git://github.com/marianoguerra/cowboy_exometer", {branch, "master"}}},
11 | {rcs_cowboy, {git, "git://github.com/marianoguerra/rcs_cowboy", {branch, "master"}}},
12 |
13 | time_compat,
14 | pbkdf2,
15 | exometer_core
16 | ]}.
17 |
18 | {relx, [{release, { tanodb , "0.1.0"},
19 | [tanodb,
20 | cowboy,
21 | jsx,
22 | recon,
23 | cowboy_exometer,
24 | rcs_cowboy,
25 | time_compat,
26 | cuttlefish,
27 | sasl]},
28 |
29 | {sys_config, "./config/sys.config"},
30 | {vm_args, "./config/vm.args"},
31 |
32 | {dev_mode, true},
33 | {include_erts, false},
34 |
35 | {overlay_vars, "config/vars.config"},
36 | {overlay, [
37 | {mkdir, "etc"},
38 | {mkdir, "bin"},
39 | {mkdir, "data/ring"},
40 | {mkdir, "log/sasl"},
41 | {template, "./config/erlang_vm.schema",
42 | "share/schema/11-erlang_vm.schema"},
43 | {template, "./config/riak_core.schema", "share/schema/12-riak_core.schema"},
44 | {template, "./_build/default/lib/riak_sysmon/priv/riak_sysmon.schema", "lib/15-riak_sysmon.schema"},
45 | {template, "./_build/default/lib/eleveldb/priv/eleveldb.schema", "share/schema/21-leveldb.schema"},
46 | {template, "config/config.schema", "share/schema/22-tanodb.schema"},
47 | {copy, "./config/admin_bin", "bin/tanodb-admin"},
48 | {template, "./config/advanced.config", "etc/advanced.config"}
49 | ]}
50 | ]}.
51 |
52 | {plugins, [rebar3_run]}.
53 | {project_plugins, [rebar3_cuttlefish]}.
54 |
55 | {cuttlefish,
56 | [{schema_discovery, false}]}.
57 |
58 | {profiles, [
59 | {prod, [{relx, [{dev_mode, false}, {include_erts, true}]}]},
60 | {dev1, [{relx, [{overlay_vars, "config/vars_dev1.config"},
61 | {vm_args, "./config/dev1_vm.args"}]}]},
62 | {dev2, [{relx, [{overlay_vars, "config/vars_dev2.config"},
63 | {vm_args, "./config/dev2_vm.args"}]}]},
64 | {dev3, [{relx, [{overlay_vars, "config/vars_dev3.config"},
65 | {vm_args, "./config/dev3_vm.args"}]}]}
66 | ]}.
67 |
68 |
69 | {overrides,
70 | [{override, riak_ensemble,
71 | [
72 | {erl_opts, [debug_info,
73 | warn_untyped_record,
74 | {parse_transform, lager_transform}]}
75 | ]},
76 | {override, poolboy,
77 | [{erl_opts, [debug_info, {platform_define, "^[0-9]+", namespaced_types}]}]},
78 | {override, cuttlefish,
79 | [{escript_emu_args, "%%! -escript main cuttlefish_escript +S 1 +A 0\n"}]},
80 | {override, riak_core,
81 | [
82 | {erl_opts, [debug_info,
83 | export_all,
84 | {parse_transform, lager_transform},
85 | {platform_define, "^[0-9]+", namespaced_types},
86 | {platform_define, "^R15", "old_hash"}]}
87 | ]}
88 | ]}.
89 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | tanodb
2 | ======
3 |
4 | A riak_core application used as example for `The Little Riak Core Book
5 | `_. Go read it for
6 | details on how it's built.
7 |
8 | Build
9 | -----
10 |
11 | ::
12 |
13 | make release
14 |
15 | Test
16 | ----
17 |
18 | ::
19 |
20 | rebar3 ct
21 |
22 | Run
23 | ---
24 |
25 | ::
26 |
27 | rebar3 run
28 |
29 | Try
30 | ---
31 |
32 | ::
33 |
34 | 1> tanodb:ping().
35 | {pong,753586781748746817198774991869333432010090217472}
36 |
37 | Quit
38 | ----
39 |
40 | ::
41 |
42 | 2> q().
43 |
44 | Play with Clustering
45 | --------------------
46 |
47 | Build 3 releases that can run on the same machine::
48 |
49 | make devrel
50 |
51 | Start them in different consoles::
52 |
53 | make dev1-console
54 | make dev2-console
55 | make dev3-console
56 |
57 | join 2 nodes to the first one::
58 |
59 | make devrel-join
60 |
61 | check the status of the cluster::
62 |
63 | make devrel-status
64 |
65 | you should see something like this::
66 |
67 | ================================= Membership ==================================
68 | Status Ring Pending Node
69 | -------------------------------------------------------------------------------
70 | joining 0.0% -- 'tanodb2@127.0.0.1'
71 | joining 0.0% -- 'tanodb3@127.0.0.1'
72 | valid 100.0% -- 'tanodb1@127.0.0.1'
73 | -------------------------------------------------------------------------------
74 | Valid:1 / Leaving:0 / Exiting:0 / Joining:2 / Down:0
75 |
76 | it should say that 3 nodes are joining, now check the cluster plan::
77 |
78 | make devrel-cluster-plan
79 |
80 | it should display the cluster plan, now we can commit the plan::
81 |
82 | make devrel-cluster-commit
83 |
84 | check the status of the cluster again::
85 |
86 | make devrel-status
87 |
88 | you could see the vnodes transfering::
89 |
90 | ================================= Membership ==================================
91 | Status Ring Pending Node
92 | -------------------------------------------------------------------------------
93 | valid 75.0% 25.0% 'tanodb1@127.0.0.1'
94 | valid 9.4% 25.0% 'tanodb2@127.0.0.1'
95 | valid 7.8% 25.0% 'tanodb3@127.0.0.1'
96 | -------------------------------------------------------------------------------
97 | Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0
98 |
99 | at some point you should see something like this::
100 |
101 | ================================= Membership ==================================
102 | Status Ring Pending Node
103 | -------------------------------------------------------------------------------
104 | valid 33.3% -- 'tanodb1@127.0.0.1'
105 | valid 33.3% -- 'tanodb2@127.0.0.1'
106 | valid 33.3% -- 'tanodb3@127.0.0.1'
107 | -------------------------------------------------------------------------------
108 | Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0
109 |
110 | when you are bored you can stop them::
111 |
112 | make devrel-stop
113 |
114 |
115 | TODO
116 | ----
117 |
118 | * define license and create LICENSE file
119 |
120 | License
121 | -------
122 |
123 | TODO
124 |
--------------------------------------------------------------------------------
/config/config.schema:
--------------------------------------------------------------------------------
1 | %%-*- mode: erlang -*-
2 | %% ex: ft=erlang ts=4 sw=4 et
3 |
4 | %% @doc Enable/Disable HTTP API
5 | {mapping, "http.enabled", "tanodb.http_enabled", [
6 | {datatype, {flag, yes, no}},
7 | {default, yes}
8 | ]}.
9 |
10 | %% @doc port to listen to for HTTP API
11 | {mapping, "http.port", "tanodb.http_port", [
12 | {datatype, integer},
13 | {default, {{http_port}} }
14 | ]}.
15 |
16 | %% @doc number of acceptors to user for HTTP API
17 | {mapping, "http.acceptors", "tanodb.http_acceptors", [
18 | {datatype, integer},
19 | {default, 100}
20 | ]}.
21 |
22 | %% @doc Enable/Disable HTTPS API
23 | {mapping, "https.enabled", "tanodb.https_enabled", [
24 | {datatype, {flag, yes, no}},
25 | {default, no}
26 | ]}.
27 |
28 | %% @doc port to listen to for HTTPS API
29 | {mapping, "https.port", "tanodb.https_port", [
30 | {datatype, integer},
31 | {default, 8443}
32 | ]}.
33 |
34 | %% @doc number of acceptors to use for HTTPS API
35 | {mapping, "https.acceptors", "tanodb.https_acceptors", [
36 | {datatype, integer},
37 | {default, 100}
38 | ]}.
39 |
40 | %% @doc Enable/Disable HTTP CORS API
41 | {mapping, "http.cors.enabled", "tanodb.cors_enabled", [
42 | {datatype, {flag, yes, no}},
43 | {default, no}
44 | ]}.
45 |
46 | %% @doc HTTP CORS API allowed origins, it can be a comma separated list of
47 | %% origins to accept or * to accept all
48 | {mapping, "http.cors.origins", "tanodb.cors_origins", [
49 | {default, "*"}
50 | ]}.
51 |
52 | {translation, "tanodb.cors_origins",
53 | fun(Conf) ->
54 | Setting = cuttlefish:conf_get("http.cors.origins", Conf),
55 | case Setting of
56 | "*" -> any;
57 | CSVs ->
58 | Tokens = string:tokens(CSVs, ","),
59 | Cleanup = fun (Token) ->
60 | CleanToken = string:strip(Token),
61 | list_to_binary(CleanToken)
62 | end,
63 | FilterEmptyStr = fun ("") -> false; (_) -> true end,
64 | lists:filter(FilterEmptyStr, lists:map(Cleanup, Tokens))
65 | end
66 | end}.
67 |
68 | %% @doc HTTP CORS API a comma separated list of allowed headers to accept
69 | {mapping, "http.cors.headers", "tanodb.cors_headers", []}.
70 |
71 | {translation, "tanodb.cors_headers",
72 | fun(Conf) ->
73 | CSVs = cuttlefish:conf_get("http.cors.headers", Conf),
74 | Tokens = string:tokens(CSVs, ","),
75 | Cleanup = fun (Token) ->
76 | CleanToken = string:strip(Token),
77 | list_to_binary(CleanToken)
78 | end,
79 | FilterEmptyStr = fun ("") -> false; (_) -> true end,
80 | lists:filter(FilterEmptyStr, lists:map(Cleanup, Tokens))
81 | end}.
82 |
83 | %% @doc HTTP CORS API indicates how long the results of a preflight request can
84 | %% be cached
85 | {mapping, "http.cors.maxage", "tanodb.cors_max_age_secs", [
86 | {datatype, {duration, s}},
87 | {default, "60s"}
88 | ]}.
89 |
90 | %% @doc secret used to encrypt the session token, IMPORTANT: change this
91 | {mapping, "auth.secret", "tanodb.auth_secret", [
92 | {default, "changeme"}
93 | ]}.
94 |
95 | {translation, "tanodb.auth_secret",
96 | fun(Conf) ->
97 | Setting = cuttlefish:conf_get("auth.secret", Conf),
98 | list_to_binary(Setting)
99 | end}.
100 |
101 | %% @doc time a session is valid after login
102 | {mapping, "auth.session.duration", "tanodb.session_duration_secs", [
103 | {datatype, {duration, s}},
104 | {default, "24h"}
105 | ]}.
106 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_http_store.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_http_store).
2 |
3 | -export([init/3, terminate/3]).
4 |
5 | -ignore_xref([init/3, terminate/3]).
6 |
7 | -export([rest_init/2,
8 | rest_terminate/2,
9 | allowed_methods/2,
10 | resource_exists/2,
11 | delete_resource/2,
12 | content_types_accepted/2,
13 | content_types_provided/2,
14 | from_json/2,
15 | to_json/2]).
16 |
17 | -ignore_xref([rest_init/2,
18 | rest_terminate/2,
19 | allowed_methods/2,
20 | resource_exists/2,
21 | delete_resource/2,
22 | content_types_accepted/2,
23 | content_types_provided/2,
24 | from_json/2,
25 | to_json/2]).
26 |
27 | -record(state, {bucket, key, method, value}).
28 |
29 | init(_, _Req, _Opts) -> {upgrade, protocol, cowboy_rest}.
30 | rest_init(Req, _Opts) ->
31 | {Bucket, Req1} = cowboy_req:binding(bucket, Req),
32 | {Key, Req2} = cowboy_req:binding(key, Req1),
33 | {Method, Req3} = method(Req2),
34 | {ok, Req3, #state{bucket=Bucket, key=Key, method=Method}}.
35 |
36 | allowed_methods(Req, State) ->
37 | {[<<"GET">>, <<"POST">>, <<"DELETE">>], Req, State}.
38 |
39 | add_keys([], Map) -> Map;
40 | add_keys(Keys, Map) ->
41 | lists:foldl(fun (Key, MapIn) -> maps:put(Key, true, MapIn) end, Map, Keys).
42 |
43 |
44 | resource_exists(Req, State=#state{bucket=Bucket, key=undefined, method=get}) ->
45 | {ok, Keys0} = tanodb:keys(Bucket),
46 | KM = lists:foldl(fun ({_Partition, _Node, VKeys}, CurKeys) ->
47 | add_keys(VKeys, CurKeys)
48 | end, #{}, Keys0),
49 | Keys = maps:keys(KM),
50 | {true, Req, State#state{value=Keys}};
51 | resource_exists(Req, State=#state{key=undefined, method=delete}) ->
52 | {false, Req, State};
53 | resource_exists(Req, State=#state{bucket=Bucket, key=Key, method=Method})
54 | when Method =:= get; Method =:= delete ->
55 | case tanodb:Method({Bucket, Key}) of
56 | {not_found, _Partition, _BK} ->
57 | {false, Req, State};
58 | {found, _Partition, {_BK, {_BK1, Value}}} ->
59 | {true, Req, State#state{value=Value}}
60 | end;
61 | resource_exists(Req, State=#state{}) ->
62 | {false, Req, State}.
63 |
64 | content_types_provided(Req, State) ->
65 | {[{{<<"application">>, <<"json">>, '*'}, to_json}], Req, State}.
66 |
67 | content_types_accepted(Req, State) ->
68 | {[{{<<"application">>, <<"json">>, '*'}, from_json}], Req, State}.
69 |
70 | to_json(Req, State=#state{value=Value}) ->
71 | Response = tanodb_json:encode(Value),
72 | {Response, Req, State}.
73 |
74 | from_json(Req, State=#state{bucket=Bucket, key=Key}) ->
75 | {ok, BodyRaw, Req1} = cowboy_req:body(Req),
76 | try
77 | Body = tanodb_json:decode(BodyRaw),
78 | {ok, _Partition} = tanodb:put({Bucket, Key}, Body),
79 | {true, Req1, State}
80 | catch
81 | _T:_E -> {false, Req1, State}
82 | end.
83 |
84 | delete_resource(Req, State=#state{}) -> {true, Req, State}.
85 |
86 | rest_terminate(_Req, _State) -> ok.
87 | terminate(_Reason, _Req, _State) -> ok.
88 |
89 | % private functions
90 |
91 | method(Req) ->
92 | {Method, Req1} = cowboy_req:method(Req),
93 | AMethod = case Method of
94 | <<"POST">> -> post;
95 | <<"GET">> -> get;
96 | <<"PUT">> -> put;
97 | <<"DELETE">> -> delete;
98 | <<"OPTIONS">> -> options;
99 | <<"HEAD">> -> head
100 | end,
101 | {AMethod, Req1}.
102 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_console.erl:
--------------------------------------------------------------------------------
1 | %% @doc Interface for riak_searchng-admin commands.
2 | -module(tanodb_console).
3 | -export([staged_join/1,
4 | down/1,
5 | ringready/1]).
6 | -ignore_xref([join/1,
7 | leave/1,
8 | remove/1,
9 | ringready/1]).
10 |
11 | staged_join([NodeStr]) ->
12 | Node = list_to_atom(NodeStr),
13 | join(NodeStr, fun riak_core:staged_join/1,
14 | "Success: staged join request for ~p to ~p~n", [node(), Node]).
15 |
16 | join(NodeStr, JoinFn, SuccessFmt, SuccessArgs) ->
17 | try
18 | case JoinFn(NodeStr) of
19 | ok ->
20 | io:format(SuccessFmt, SuccessArgs),
21 | ok;
22 | {error, not_reachable} ->
23 | io:format("Node ~s is not reachable!~n", [NodeStr]),
24 | error;
25 | {error, different_ring_sizes} ->
26 | io:format("Failed: ~s has a different ring_creation_size~n",
27 | [NodeStr]),
28 | error;
29 | {error, unable_to_get_join_ring} ->
30 | io:format("Failed: Unable to get ring from ~s~n", [NodeStr]),
31 | error;
32 | {error, not_single_node} ->
33 | io:format("Failed: This node is already a member of a "
34 | "cluster~n"),
35 | error;
36 | {error, self_join} ->
37 | io:format("Failed: This node cannot join itself in a "
38 | "cluster~n"),
39 | error;
40 | {error, _} ->
41 | io:format("Join failed. Try again in a few moments.~n", []),
42 | error
43 | end
44 | catch
45 | Exception:Reason ->
46 | lager:error("Join failed ~p:~p", [Exception, Reason]),
47 | io:format("Join failed, see log for details~n"),
48 | error
49 | end.
50 |
51 |
52 | down([Node]) ->
53 | try
54 | case riak_core:down(list_to_atom(Node)) of
55 | ok ->
56 | io:format("Success: ~p marked as down~n", [Node]),
57 | ok;
58 | {error, legacy_mode} ->
59 | io:format("Cluster is currently in legacy mode~n"),
60 | ok;
61 | {error, is_up} ->
62 | io:format("Failed: ~s is up~n", [Node]),
63 | error;
64 | {error, not_member} ->
65 | io:format("Failed: ~p is not a member of the cluster.~n",
66 | [Node]),
67 | error;
68 | {error, only_member} ->
69 | io:format("Failed: ~p is the only member.~n", [Node]),
70 | error
71 | end
72 | catch
73 | Exception:Reason ->
74 | lager:error("Down failed ~p:~p", [Exception, Reason]),
75 | io:format("Down failed, see log for details~n"),
76 | error
77 | end.
78 |
79 | ringready([]) ->
80 | try
81 | case riak_core_status:ringready() of
82 | {ok, Nodes} ->
83 | io:format("TRUE All nodes agree on the ring ~p\n", [Nodes]);
84 | {error, {different_owners, N1, N2}} ->
85 | io:format("FALSE Node ~p and ~p list different partition owners\n", [N1, N2]),
86 | error;
87 | {error, {nodes_down, Down}} ->
88 | io:format("FALSE ~p down. All nodes need to be up to check.\n", [Down]),
89 | error
90 | end
91 | catch
92 | Exception:Reason ->
93 | lager:error("Ringready failed ~p:~p", [Exception,
94 | Reason]),
95 | io:format("Ringready failed, see log for details~n"),
96 | error
97 | end.
98 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_app.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_app).
2 |
3 | -behaviour(application).
4 |
5 | %% Application callbacks
6 | -export([start/2, stop/1]).
7 |
8 | %% ===================================================================
9 | %% Application callbacks
10 | %% ===================================================================
11 |
12 | start(_StartType, _StartArgs) ->
13 | tanodb_metrics:init(),
14 | init_http(),
15 | case tanodb_sup:start_link() of
16 | {ok, Pid} ->
17 | ok = riak_core:register([{vnode_module, tanodb_vnode}]),
18 | ok = riak_core_node_watcher:service_up(tanodb, self()),
19 | setup_basic_users_and_groups(),
20 |
21 | {ok, Pid};
22 | {error, Reason} ->
23 | {error, Reason}
24 | end.
25 |
26 | stop(_State) ->
27 | ok.
28 |
29 | % private functions
30 |
31 | rcs_is_user_authorized(Req, #{user_ctx := _UserCtx}) ->
32 | ResultJson = [{token, <<"atoken">>}],
33 | ResultJsonBin = tanodb_json:encode(ResultJson),
34 | Req1 = cowboy_req:set_resp_body(ResultJsonBin, Req),
35 | {true, Req1}.
36 |
37 | add_user(Username, Password, Groups) ->
38 | R = case riak_core_security:add_user(Username, [{"password", Password},
39 | {"groups", [Groups]}]) of
40 | ok ->
41 | R0 = riak_core_security:add_source([Username],
42 | {{127, 0, 0, 1}, 32},
43 | password, []),
44 | lager:info("Add Source for ~p: ~p", [Username, R0]),
45 | ok;
46 | Other -> Other
47 | end,
48 | lager:info("Create user ~p: ~p", [Username, R]).
49 |
50 | add_group(Name, Groups) ->
51 | R = riak_core_security:add_group(Name, Groups),
52 | lager:info("Create Group ~p: ~p", [Name, R]).
53 |
54 | setup_basic_users_and_groups() ->
55 | add_group(<<"users">>, []),
56 | add_group(<<"admins">>, [{"groups", [<<"users">>]}]),
57 |
58 | add_user(<<"user">>, "secret", <<"users">>),
59 | add_user(<<"admin">>, "secret", <<"admins">>).
60 |
61 | routes() ->
62 | JsonEncoder = fun tanodb_json:encode/1,
63 | JsonDecoder = fun tanodb_json:decode/1,
64 | IsAuthorizedFun = fun (Req, _Info) -> {true, Req} end,
65 | IsUserAuthorizedFun = fun rcs_is_user_authorized/2,
66 | RcsOpts = #{env_keys => [tanodb],
67 | json_encoder => JsonEncoder, json_decoder => JsonDecoder,
68 | is_user_authorized => IsUserAuthorizedFun,
69 | base_uri => "/admin", is_authorized => IsAuthorizedFun},
70 |
71 | [
72 | {"/ping", tanodb_http_ping, []},
73 | {"/metrics", tanodb_http_metrics, []},
74 | {"/store/:bucket", tanodb_http_store, []},
75 | {"/store/:bucket/:key", tanodb_http_store, []},
76 | {"/admin/:action", rcs_cowboy_handler, RcsOpts},
77 | {"/admin/:action/:param1", rcs_cowboy_handler, RcsOpts},
78 | {"/ui/[...]", cowboy_static,
79 | {priv_dir, tanodb, "ui", [{mimetypes, cow_mimetypes, all}]}}
80 | ].
81 |
82 | init_http() ->
83 | DispatchRoutes = routes(),
84 | Dispatch = cowboy_router:compile([{'_', DispatchRoutes}]),
85 | ApiMiddlewares = [cowboy_exometer, cowboy_router, cowboy_handler],
86 |
87 | CowboyOpts = [{env, [{dispatch, Dispatch}]},
88 | {onresponse, fun cowboy_exometer:cowboy_response_hook/4},
89 | {middlewares, ApiMiddlewares}],
90 | ApiAcceptors = envd(http_acceptors, 100),
91 | ApiPort = envd(http_port, 8080),
92 |
93 | {ok, _} = cowboy:start_http(http, ApiAcceptors, [{port, ApiPort}],
94 | CowboyOpts).
95 |
96 | env(App, Par, Def) -> application:get_env(App, Par, Def).
97 | envd(Par, Def) -> env(tanodb, Par, Def).
98 |
99 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_write_fsm.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_write_fsm).
2 | -behavior(gen_fsm).
3 |
4 | %% API
5 | -export([start_link/7, write/6, delete/4]).
6 |
7 | %% Callbacks
8 | -export([init/1, code_change/4, handle_event/3, handle_info/3,
9 | handle_sync_event/4, terminate/3]).
10 |
11 | -ignore_xref([start_link/7, init/1, code_change/4, handle_event/3,
12 | handle_info/3, handle_sync_event/4, terminate/3, write/6,
13 | delete/4]).
14 |
15 | -export([prepare/2, execute/2, waiting/2]).
16 |
17 | -ignore_xref([prepare/2, execute/2, waiting/2]).
18 |
19 | %% req_id: The request id so the caller can verify the response.
20 | %% sender: The pid of the sender so a reply can be made.
21 | %% prelist: The preflist for the given {Bucket, Key} pair.
22 | %% num_w: The number of successful write replies.
23 | -record(state, {req_id :: pos_integer(),
24 | from :: pid(),
25 | n :: pos_integer(),
26 | w :: pos_integer(),
27 | key :: string(),
28 | accum = [],
29 | action :: write | delete,
30 | data = undefined :: term() | undefined,
31 | preflist :: riak_core_apl:preflist2(),
32 | num_w = 0 :: non_neg_integer()}).
33 |
34 | %%%===================================================================
35 | %%% API
36 | %%%===================================================================
37 |
38 | start_link(ReqID, From, Key, Data, N, W, Action) ->
39 | gen_fsm:start_link(?MODULE, [ReqID, From, Key, Data, N, W, Action],
40 | []).
41 |
42 | write(N, W, Key, Data, Pid, ReqID) ->
43 | tanodb_write_fsm_sup:start_write_fsm([ReqID, Pid, Key, Data, N, W, write]),
44 | {ok, ReqID}.
45 |
46 | delete(N, Key, Pid, ReqID) ->
47 | tanodb_write_fsm_sup:start_write_fsm([ReqID, Pid, Key, nil, N, N, delete]),
48 | {ok, ReqID}.
49 |
50 | %%%===================================================================
51 | %%% States
52 | %%%===================================================================
53 |
54 | %% @doc Initialize the state data.
55 | init([ReqID, From, Key, Data, N, W, Action]) ->
56 | SD = #state{req_id=ReqID, from=From, action=Action, key=Key, data=Data,
57 | n=N, w=W},
58 | {ok, prepare, SD, 0}.
59 |
60 | %% @doc Prepare the write by calculating the _preference list_.
61 | prepare(timeout, SD0=#state{n=N, key=Key}) ->
62 | DocIdx = riak_core_util:chash_key(Key),
63 | Preflist = riak_core_apl:get_apl(DocIdx, N, tanodb),
64 | SD = SD0#state{preflist=Preflist},
65 | {next_state, execute, SD, 0}.
66 |
67 | %% @doc Execute the write request and then go into waiting state to
68 | %% verify it has meets consistency requirements.
69 | execute(timeout, SD0=#state{req_id=ReqID, key=Key, action=Action, data=Data,
70 | preflist=Preflist}) ->
71 | Command = case Action of
72 | delete -> {delete, ReqID, Key};
73 | write -> {put, ReqID, Key, Data}
74 | end,
75 | riak_core_vnode_master:command(Preflist, Command, {fsm, undefined, self()},
76 | tanodb_vnode_master),
77 | {next_state, waiting, SD0}.
78 |
79 | %% @doc Wait for W write reqs to respond.
80 | waiting({ReqID, Result}, SD0=#state{from=From, num_w=NumW0, w=W, accum=Accum}) ->
81 | NumW = NumW0 + 1,
82 | Accum1 = [Result|Accum],
83 | SD = SD0#state{num_w=NumW, accum=Accum1},
84 | if NumW =:= W ->
85 | From ! {ReqID, {ok, Accum1}},
86 | {stop, normal, SD};
87 | true -> {next_state, waiting, SD}
88 | end.
89 |
90 | handle_info(Info, _StateName, StateData) ->
91 | lager:warning("got unexpected info ~p", [Info]),
92 | {stop, badmsg, StateData}.
93 |
94 | handle_event(Event, _StateName, StateData) ->
95 | lager:warning("got unexpected event ~p", [Event]),
96 | {stop, badmsg, StateData}.
97 |
98 | handle_sync_event(Event, _From, _StateName, StateData) ->
99 | lager:warning("got unexpected sync event ~p", [Event]),
100 | {stop, badmsg, StateData}.
101 |
102 | code_change(_OldVsn, StateName, State, _Extra) -> {ok, StateName, State}.
103 | terminate(_Reason, _SN, _SD) -> ok.
104 |
--------------------------------------------------------------------------------
/rebar.lock:
--------------------------------------------------------------------------------
1 | {"1.1.0",
2 | [{<<"basho_stats">>,{pkg,<<"basho_stats">>,<<"1.0.3">>},1},
3 | {<<"bear">>,{pkg,<<"bear">>,<<"0.8.3">>},2},
4 | {<<"blume">>,{pkg,<<"blume">>,<<"0.1.1">>},1},
5 | {<<"chash">>,{pkg,<<"chash">>,<<"0.1.2">>},1},
6 | {<<"clique">>,{pkg,<<"clique">>,<<"0.3.10">>},1},
7 | {<<"cowboy">>,{pkg,<<"cowboy">>,<<"1.0.3">>},0},
8 | {<<"cowboy_exometer">>,
9 | {git,"git://github.com/marianoguerra/cowboy_exometer",
10 | {ref,"52a419bf59b82aa166c4f075f496518c38c8fc54"}},
11 | 0},
12 | {<<"cowlib">>,{pkg,<<"cowlib">>,<<"1.0.2">>},1},
13 | {<<"cuttlefish">>,{pkg,<<"cuttlefish">>,<<"2.0.12">>},1},
14 | {<<"edown">>,{pkg,<<"edown">>,<<"0.7.0">>},1},
15 | {<<"eleveldb">>,{pkg,<<"eleveldb">>,<<"2.2.20">>},1},
16 | {<<"exometer_core">>,{pkg,<<"exometer_core">>,<<"1.4.0">>},0},
17 | {<<"folsom">>,{pkg,<<"folsom">>,<<"0.8.3">>},1},
18 | {<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},2},
19 | {<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1},
20 | {<<"jam">>,{pkg,<<"jam">>,<<"1.0.0">>},1},
21 | {<<"jsx">>,{pkg,<<"jsx">>,<<"2.8.2">>},0},
22 | {<<"lager">>,{pkg,<<"lager">>,<<"3.5.1">>},0},
23 | {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"2.9.0">>},1},
24 | {<<"pbkdf2">>,{pkg,<<"pbkdf2">>,<<"2.0.0">>},0},
25 | {<<"poolboy">>,{pkg,<<"basho_poolboy">>,<<"0.8.2">>},1},
26 | {<<"ranch">>,{pkg,<<"ranch">>,<<"1.4.0">>},1},
27 | {<<"rcs_cowboy">>,
28 | {git,"git://github.com/marianoguerra/rcs_cowboy",
29 | {ref,"be81d9efc88d07d83c9f6d0c5eeb24546c267ac7"}},
30 | 0},
31 | {<<"recon">>,{pkg,<<"recon">>,<<"2.3.2">>},0},
32 | {<<"riak_core">>,{pkg,<<"riak_core_ng">>,<<"3.0.9">>},0},
33 | {<<"riak_ensemble">>,{pkg,<<"riak_ensemble_ng">>,<<"2.4.0">>},1},
34 | {<<"riak_sysmon">>,{pkg,<<"riak_sysmon">>,<<"2.1.5">>},1},
35 | {<<"setup">>,{pkg,<<"setup">>,<<"1.7.0">>},1},
36 | {<<"time_compat">>,{pkg,<<"time_compat">>,<<"0.0.1">>},0}]}.
37 | [
38 | {pkg_hash,[
39 | {<<"basho_stats">>, <<"7E1174151509C64FCC1934120ED32295E14F84DAAE7F84926BA2C8D3700D146C">>},
40 | {<<"bear">>, <<"866002127A97932720A0D475D8582C98EC5FB78DB3A18DFE7EAF91594D9024B8">>},
41 | {<<"blume">>, <<"CFB4F43688690BA81C6A79F54E4678CFD5FDEDAB692F277AE740AE4A3897360D">>},
42 | {<<"chash">>, <<"AF02484F2640C653C4B9A8557A14CA0704989DBEDB27E7CCBC442F1903A3BCA7">>},
43 | {<<"clique">>, <<"29ECBA7EC61DED866197164D33F61D1CBF892ED85FC933673D7E50D0689D34FB">>},
44 | {<<"cowboy">>, <<"101A5F826CE9A1EBB2EA53A2CDFFFC74736E99807E9E492ECD5F26544C04082B">>},
45 | {<<"cowlib">>, <<"9D769A1D062C9C3AC753096F868CA121E2730B9A377DE23DEC0F7E08B1DF84EE">>},
46 | {<<"cuttlefish">>, <<"1441A12BCE207F7FC796A4DA50D47080D21E83E15309AD6496DE27840A54D5FC">>},
47 | {<<"edown">>, <<"6803599606B10F8E328D6D60C44CD16244CD2429908894C415FCE4211C3BFEFD">>},
48 | {<<"eleveldb">>, <<"1FFF63A5055BBF4BF821F797EF76065882B193F5E8095F95FCD9287187773B58">>},
49 | {<<"exometer_core">>, <<"A546CCD38BE910DE6EA75EA95B724B6B2DB513C26F02E30919B25EB19651815A">>},
50 | {<<"folsom">>, <<"71CFF146152FA95E6092E62119F9DC96888660111E7B61853C8FDCF80598A4E0">>},
51 | {<<"getopt">>, <<"B17556DB683000BA50370B16C0619DF1337E7AF7ECBF7D64FBF8D1D6BCE3109B">>},
52 | {<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>},
53 | {<<"jam">>, <<"ED9B180F2F3A775E6A47AC490954976802F0638C19A393F3E86D4BA4CF890582">>},
54 | {<<"jsx">>, <<"7ACC7D785B5ABE8A6E9ADBDE926A24E481F29956DD8B4DF49E3E4E7BCC92A018">>},
55 | {<<"lager">>, <<"63897A61AF646C59BB928FEE9756CE8BDD02D5A1A2F3551D4A5E38386C2CC071">>},
56 | {<<"parse_trans">>, <<"3F5F7B402928FB9FD200C891E635DE909045D1EFAC40CE3F924D3892898F85EB">>},
57 | {<<"pbkdf2">>, <<"11C23279FDED5C0027AB3996CFAE77805521D7EF4BABDE2BD7EC04A9086CF499">>},
58 | {<<"poolboy">>, <<"AD5524BF4B8D30EEE0E5386847B74DAD739BB6AE1893F3AF10F54D427ACC96E4">>},
59 | {<<"ranch">>, <<"10272F95DA79340FA7E8774BA7930B901713D272905D0012B06CA6D994F8826B">>},
60 | {<<"recon">>, <<"4444C879BE323B1B133EEC5241CB84BD3821EA194C740D75617E106BE4744318">>},
61 | {<<"riak_core">>, <<"F6E27FB67C9CB9A3FB7AEF38EC1BB5633624D7B78E32E73FE7A0045F3514F032">>},
62 | {<<"riak_ensemble">>, <<"6570463BF09F1200C003DE298C5D6615C418D3BF0A2DF5CAF469A9DF2558059A">>},
63 | {<<"riak_sysmon">>, <<"2331BBCAEBE73EA7B2449F4C765827142476CC73D7D86999B4209EE005694D6B">>},
64 | {<<"setup">>, <<"15DF8E57C6DF9755E22BFB1AEF0C640BD97E9889396FDFB2A85A5536A9043674">>},
65 | {<<"time_compat">>, <<"23FE0AD1FDF3B5B88821B2D04B4B5E865BF587AE66056D671FE0F53514ED8139">>}]}
66 | ].
67 |
--------------------------------------------------------------------------------
/apps/tanodb/src/tanodb_vnode.erl:
--------------------------------------------------------------------------------
1 | -module(tanodb_vnode).
2 | -behaviour(riak_core_vnode).
3 |
4 | -include_lib("riak_core/include/riak_core_vnode.hrl").
5 |
6 | -export([start_vnode/1,
7 | init/1,
8 | terminate/2,
9 | handle_command/3,
10 | is_empty/1,
11 | delete/1,
12 | handle_handoff_command/3,
13 | handoff_starting/2,
14 | handoff_cancelled/1,
15 | handoff_finished/2,
16 | handle_handoff_data/2,
17 | encode_handoff_item/2,
18 | handle_coverage/4,
19 | handle_exit/3]).
20 |
21 | -ignore_xref([
22 | start_vnode/1
23 | ]).
24 |
25 | -record(state, {partition, table_id, table_name}).
26 |
27 | %% API
28 | start_vnode(I) ->
29 | riak_core_vnode_master:get_vnode_pid(I, ?MODULE).
30 |
31 | init([Partition]) ->
32 | TableName = list_to_atom("tanodb_" ++ integer_to_list(Partition)),
33 | TableId = ets:new(TableName, [set, public, named_table,
34 | {write_concurrency, false},
35 | {read_concurrency, true}]),
36 |
37 | {ok, #state{partition=Partition, table_id=TableId,
38 | table_name=TableName}}.
39 |
40 | %% Sample command: respond to a ping
41 | handle_command(ping, _Sender, State) ->
42 | {reply, {pong, State#state.partition}, State};
43 | handle_command({put, ReqId, Key, Value}, _Sender,
44 | State=#state{table_name=TableName, partition=Partition}) ->
45 | ets:insert(TableName, {Key, Value}),
46 | {reply, {ReqId, {ok, Partition}}, State};
47 | handle_command({get, Key}, _Sender,
48 | State=#state{table_name=TableName, partition=Partition}) ->
49 | case ets:lookup(TableName, Key) of
50 | [] ->
51 | {reply, {not_found, Partition, Key}, State};
52 | [Value] ->
53 | {reply, {found, Partition, {Key, Value}}, State}
54 | end;
55 | handle_command({delete, ReqId, Key}, _Sender,
56 | State=#state{table_name=TableName, partition=Partition}) ->
57 | case ets:lookup(TableName, Key) of
58 | [] ->
59 | {reply, {ReqId, {not_found, Partition, Key}}, State};
60 | [Value] ->
61 | true = ets:delete(TableName, Key),
62 | {reply, {ReqId, {found, Partition, {Key, Value}}}, State}
63 | end;
64 | handle_command(Message, _Sender, State) ->
65 | lager:warning("unhandled_command ~p", [Message]),
66 | {noreply, State}.
67 |
68 | handle_handoff_command(?FOLD_REQ{foldfun=FoldFun, acc0=Acc0}, _Sender,
69 | State=#state{partition=Partition, table_name=TableName}) ->
70 | lager:info("fold req ~p", [Partition]),
71 | AccFinal = ets:foldl(fun ({Key, Val}, AccIn) ->
72 | lager:info("fold fun ~p: ~p", [Key, Val]),
73 | FoldFun(Key, Val, AccIn)
74 | end, Acc0, TableName),
75 | {reply, AccFinal, State};
76 |
77 | handle_handoff_command(Message, _Sender, State) ->
78 | lager:warning("handoff command ~p, ignoring", [Message]),
79 | {noreply, State}.
80 |
81 | handoff_starting(TargetNode, State=#state{partition=Partition}) ->
82 | lager:info("handoff starting ~p: ~p", [Partition, TargetNode]),
83 | {true, State}.
84 |
85 | handoff_cancelled(State=#state{partition=Partition}) ->
86 | lager:info("handoff cancelled ~p", [Partition]),
87 | {ok, State}.
88 |
89 | handoff_finished(TargetNode, State=#state{partition=Partition}) ->
90 | lager:info("handoff finished ~p: ~p", [Partition, TargetNode]),
91 | {ok, State}.
92 |
93 | handle_handoff_data(BinData, State=#state{table_name=TableName}) ->
94 | TermData = binary_to_term(BinData),
95 | lager:info("handoff data received ~p", [TermData]),
96 | {Key, Value} = TermData,
97 | ets:insert(TableName, {Key, Value}),
98 | {reply, ok, State}.
99 |
100 | encode_handoff_item(Key, Value) ->
101 | term_to_binary({Key, Value}).
102 |
103 | is_empty(State=#state{table_name=TableName, partition=Partition}) ->
104 | IsEmpty = (ets:first(TableName) =:= '$end_of_table'),
105 | lager:info("is_empty ~p: ~p", [Partition, IsEmpty]),
106 | {IsEmpty, State}.
107 |
108 | delete(State=#state{table_name=TableName, partition=Partition}) ->
109 | lager:info("delete ~p", [Partition]),
110 | ets:delete(TableName),
111 | {ok, State}.
112 |
113 | handle_coverage({keys, Bucket}, _KeySpaces, {_, RefId, _},
114 | State=#state{table_name=TableName}) ->
115 | Keys0 = ets:match(TableName, {{Bucket, '$1'}, '_'}),
116 | Keys = lists:map(fun first/1, Keys0),
117 | {reply, {RefId, Keys}, State};
118 | handle_coverage(_Req, _KeySpaces, _Sender, State) ->
119 | {stop, not_implemented, State}.
120 |
121 | handle_exit(_Pid, _Reason, State) ->
122 | {noreply, State}.
123 |
124 | terminate(_Reason, _State) ->
125 | ok.
126 |
127 | % private functions
128 | first([V|_]) -> V.
129 |
--------------------------------------------------------------------------------
/config/nodetool:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env escript
2 | %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
3 | %% ex: ft=erlang ts=4 sw=4 et
4 | %% -------------------------------------------------------------------
5 | %%
6 | %% nodetool: Helper Script for interacting with live nodes
7 | %%
8 | %% -------------------------------------------------------------------
9 |
10 | main(Args) ->
11 | ok = start_epmd(),
12 | %% Extract the args
13 | {RestArgs, TargetNode} = process_args(Args, [], undefined),
14 |
15 | %% See if the node is currently running -- if it's not, we'll bail
16 | case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
17 | {true, pong} ->
18 | ok;
19 | {_, pang} ->
20 | io:format("Node ~p not responding to pings.\n", [TargetNode]),
21 | halt(1)
22 | end,
23 |
24 | case RestArgs of
25 | ["ping"] ->
26 | %% If we got this far, the node already responsed to a ping, so just dump
27 | %% a "pong"
28 | io:format("pong\n");
29 | ["stop"] ->
30 | io:format("~p\n", [rpc:call(TargetNode, init, stop, [], 60000)]);
31 | ["restart"] ->
32 | io:format("~p\n", [rpc:call(TargetNode, init, restart, [], 60000)]);
33 | ["reboot"] ->
34 | io:format("~p\n", [rpc:call(TargetNode, init, reboot, [], 60000)]);
35 | ["rpc", Module, Function | RpcArgs] ->
36 | case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
37 | [RpcArgs], 60000) of
38 | ok ->
39 | ok;
40 | {badrpc, Reason} ->
41 | io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
42 | halt(1);
43 | _ ->
44 | halt(1)
45 | end;
46 | ["rpcterms", Module, Function | ArgsAsString] ->
47 | case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
48 | consult(lists:flatten(ArgsAsString)), 60000) of
49 | {badrpc, Reason} ->
50 | io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
51 | halt(1);
52 | Other ->
53 | io:format("~p\n", [Other])
54 | end;
55 | Other ->
56 | io:format("Other: ~p\n", [Other]),
57 | io:format("Usage: nodetool {ping|stop|restart|reboot|rpc|rpcterms} [RPC]\n")
58 | end,
59 | net_kernel:stop().
60 |
61 | process_args([], Acc, TargetNode) ->
62 | {lists:reverse(Acc), TargetNode};
63 | process_args(["-setcookie", Cookie | Rest], Acc, TargetNode) ->
64 | erlang:set_cookie(node(), list_to_atom(Cookie)),
65 | process_args(Rest, Acc, TargetNode);
66 | process_args(["-name", TargetName | Rest], Acc, _) ->
67 | ThisNode = append_node_suffix(TargetName, "_maint_"),
68 | {ok, _} = net_kernel:start([ThisNode, longnames]),
69 | process_args(Rest, Acc, nodename(TargetName));
70 | process_args(["-sname", TargetName | Rest], Acc, _) ->
71 | ThisNode = append_node_suffix(TargetName, "_maint_"),
72 | {ok, _} = net_kernel:start([ThisNode, shortnames]),
73 | process_args(Rest, Acc, nodename(TargetName));
74 | process_args([Arg | Rest], Acc, Opts) ->
75 | process_args(Rest, [Arg | Acc], Opts).
76 |
77 |
78 | start_epmd() ->
79 | [] = os:cmd("\"" ++ epmd_path() ++ "\" -daemon"),
80 | ok.
81 |
82 | epmd_path() ->
83 | ErtsBinDir = filename:dirname(escript:script_name()),
84 | Name = "epmd",
85 | case os:find_executable(Name, ErtsBinDir) of
86 | false ->
87 | case os:find_executable(Name) of
88 | false ->
89 | io:format("Could not find epmd.~n"),
90 | halt(1);
91 | GlobalEpmd ->
92 | GlobalEpmd
93 | end;
94 | Epmd ->
95 | Epmd
96 | end.
97 |
98 |
99 | nodename(Name) ->
100 | case string:tokens(Name, "@") of
101 | [_Node, _Host] ->
102 | list_to_atom(Name);
103 | [Node] ->
104 | [_, Host] = string:tokens(atom_to_list(node()), "@"),
105 | list_to_atom(lists:concat([Node, "@", Host]))
106 | end.
107 |
108 | append_node_suffix(Name, Suffix) ->
109 | case string:tokens(Name, "@") of
110 | [Node, Host] ->
111 | list_to_atom(lists:concat([Node, Suffix, os:getpid(), "@", Host]));
112 | [Node] ->
113 | list_to_atom(lists:concat([Node, Suffix, os:getpid()]))
114 | end.
115 |
116 | %%
117 | %% Given a string or binary, parse it into a list of terms, ala file:consult/0
118 | %%
119 | consult(Str) when is_list(Str) ->
120 | consult([], Str, []);
121 | consult(Bin) when is_binary(Bin)->
122 | consult([], binary_to_list(Bin), []).
123 |
124 | consult(Cont, Str, Acc) ->
125 | case erl_scan:tokens(Cont, Str, 0) of
126 | {done, Result, Remaining} ->
127 | case Result of
128 | {ok, Tokens, _} ->
129 | {ok, Term} = erl_parse:parse_term(Tokens),
130 | consult([], Remaining, [Term | Acc]);
131 | {eof, _Other} ->
132 | lists:reverse(Acc);
133 | {error, Info, _} ->
134 | {error, Info}
135 | end;
136 | {more, Cont1} ->
137 | consult(Cont1, eof, Acc)
138 | end.
139 |
--------------------------------------------------------------------------------
/config/admin_bin:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is.
4 | if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
5 | POSIX_SHELL="true"
6 | export POSIX_SHELL
7 | # To support 'whoami' add /usr/ucb to path
8 | PATH=/usr/ucb:$PATH
9 | export PATH
10 | exec /usr/bin/ksh $0 "$@"
11 | fi
12 | unset POSIX_SHELL # clear it so if we invoke other scripts, they run as ksh as well
13 |
14 |
15 | RUNNER_SCRIPT_DIR=$(cd ${0%/*} && pwd)
16 | RUNNER_SCRIPT=${0##*/}
17 |
18 | RUNNER_BASE_DIR=${RUNNER_SCRIPT_DIR%/*}
19 | RUNNER_ETC_DIR=$RUNNER_BASE_DIR/etc
20 | RUNNER_LOG_DIR=$RUNNER_BASE_DIR/log
21 |
22 | LAST_GENERATED_ARGS=$(ls ${RUNNER_BASE_DIR}/generated.conf/*.args | sort -n | tail -n1 )
23 | RUNNER_USER=
24 |
25 | WHOAMI=$(whoami)
26 |
27 | # Make sure this script is running as the appropriate user
28 | if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
29 | type sudo > /dev/null 2>&1
30 | if [ $? -ne 0 ]; then
31 | echo "sudo doesn't appear to be installed and your EUID isn't $RUNNER_USER" 1>&2
32 | exit 1
33 | fi
34 | echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2
35 | exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
36 | fi
37 |
38 | # Make sure CWD is set to runner base dir
39 | cd $RUNNER_BASE_DIR
40 |
41 | # Extract the target node name from node.args
42 | NAME_ARG=`egrep "^ *-s?name" ${LAST_GENERATED_ARGS}`
43 | if [ -z "$NAME_ARG" ]; then
44 | echo "${LAST_GENERATED_ARGS} needs to have either -name or -sname parameter."
45 | exit 1
46 | fi
47 |
48 | # Learn how to specify node name for connection from remote nodes
49 | echo "$NAME_ARG" | grep '^-sname' > /dev/null 2>&1
50 | if [ "X$?" = "X0" ]; then
51 | NAME_PARAM="-sname"
52 | NAME_HOST=""
53 | else
54 | NAME_PARAM="-name"
55 | echo "$NAME_ARG" | grep '@.*' > /dev/null 2>&1
56 | if [ "X$?" = "X0" ]; then
57 | NAME_HOST=`echo "${NAME_ARG}" | sed -e 's/.*\(@.*\)$/\1/'`
58 | else
59 | NAME_HOST=""
60 | fi
61 | fi
62 |
63 | # Extract the target cookie
64 | COOKIE_ARG=`grep '\-setcookie' ${LAST_GENERATED_ARGS}`
65 | if [ -z "$COOKIE_ARG" ]; then
66 | echo "${LAST_GENERATED_ARGS} args needs to have a -setcookie parameter."
67 | exit 1
68 | fi
69 |
70 | # Identify the script name
71 | SCRIPT=`basename $0`
72 |
73 | # Parse out release and erts info
74 | START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data`
75 | ERTS_VSN=${START_ERL% *}
76 | APP_VSN=${START_ERL#* }
77 |
78 | # TODO: look in the release otherwise use which
79 | ESCRIPT=escript
80 | NODETOOL_PATH=$RUNNER_BASE_DIR/bin
81 | NODETOOL=$NODETOOL_PATH/nodetool
82 | # Setup command to control the node
83 | NODETOOL="$ESCRIPT $NODETOOL $NAME_ARG $COOKIE_ARG"
84 |
85 | ensure_node_running()
86 | {
87 | # Make sure the local node IS running
88 | RES=`$NODETOOL ping`
89 | if [ "$RES" != "pong" ]; then
90 | echo "Node is not running!"
91 | exit 1
92 | fi
93 | }
94 |
95 | cluster_admin()
96 | {
97 | case "$1" in
98 | join)
99 | if [ $# -ne 2 ]; then
100 | echo "Usage: $SCRIPT cluster join "
101 | exit 1
102 | fi
103 | ensure_node_running
104 | $NODETOOL rpc tanodb_console staged_join "$2"
105 | ;;
106 | leave)
107 | if [ $# -eq 1 ]; then
108 | ensure_node_running
109 | $NODETOOL rpc riak_core_console stage_leave
110 | elif [ $# -eq 2 ]; then
111 | ensure_node_running
112 | $NODETOOL rpc riak_core_console stage_leave "$2"
113 | else
114 | echo "Usage: $SCRIPT cluster leave []"
115 | exit 1
116 | fi
117 | ;;
118 | force-remove)
119 | if [ $# -ne 2 ]; then
120 | echo "Usage: $SCRIPT cluster force-remove "
121 | exit 1
122 | fi
123 | ensure_node_running
124 | $NODETOOL rpc riak_core_console stage_remove "$2"
125 | ;;
126 | replace)
127 | if [ $# -ne 3 ]; then
128 | echo "Usage: $SCRIPT cluster replace "
129 | exit 1
130 | fi
131 | ensure_node_running
132 | $NODETOOL rpc riak_core_console stage_replace "$2" "$3"
133 | ;;
134 | force-replace)
135 | if [ $# -ne 3 ]; then
136 | echo "Usage: $SCRIPT cluster force-replace "
137 | exit 1
138 | fi
139 | ensure_node_running
140 | $NODETOOL rpc riak_core_console stage_force_replace "$2" "$3"
141 | ;;
142 | plan)
143 | ensure_node_running
144 | $NODETOOL rpc riak_core_console print_staged
145 | ;;
146 | commit)
147 | ensure_node_running
148 | $NODETOOL rpc riak_core_console commit_staged
149 | ;;
150 | clear)
151 | ensure_node_running
152 | $NODETOOL rpc riak_core_console clear_staged
153 | ;;
154 | *)
155 | echo "\
156 | Usage: $SCRIPT cluster
157 |
158 | The following commands stage changes to cluster membership. These commands
159 | do not take effect immediately. After staging a set of changes, the staged
160 | plan must be committed to take effect:
161 |
162 | join Join node to the cluster containing
163 | leave Have this node leave the cluster and shutdown
164 | leave Have leave the cluster and shutdown
165 |
166 | force-remove Remove from the cluster without
167 | first handing off data. Designed for
168 | crashed, unrecoverable nodes
169 |
170 | replace Have transfer all data to ,
171 | and then leave the cluster and shutdown
172 |
173 | force-replace Reassign all partitions owned by to
174 | without first handing off data, and
175 | remove from the cluster.
176 |
177 | Staging commands:
178 | plan Display the staged changes to the cluster
179 | commit Commit the staged changes
180 | clear Clear the staged changes
181 | "
182 | esac
183 | }
184 |
185 | # Check the first argument for instructions
186 | case "$1" in
187 | down)
188 | if [ $# -ne 2 ]; then
189 | echo "Usage: $SCRIPT down "
190 | exit 1
191 | fi
192 |
193 | RES=`$NODETOOL ping`
194 | if [ "$RES" != "pong" ]; then
195 | echo "Node is not running!"
196 | exit 1
197 | fi
198 |
199 | shift
200 | $NODETOOL rpc tanodb_console down $@
201 | ;;
202 |
203 | ringready)
204 | if [ $# -ne 1 ]; then
205 | echo "Usage: $SCRIPT ringready"
206 | exit 1
207 | fi
208 |
209 | # Make sure the local node IS running
210 | RES=`$NODETOOL ping`
211 | if [ "$RES" != "pong" ]; then
212 | echo "Node is not running!"
213 | exit 1
214 | fi
215 | shift
216 |
217 | $NODETOOL rpc tanodb_console ringready $@
218 | ;;
219 |
220 | member[_-]status)
221 | if [ $# -ne 1 ]; then
222 | echo "Usage: $SCRIPT $1"
223 | exit 1
224 | fi
225 |
226 | # Make sure the local node IS running
227 | RES=`$NODETOOL ping`
228 | if [ "$RES" != "pong" ]; then
229 | echo "Node is not running!"
230 | exit 1
231 | fi
232 | shift
233 |
234 | $NODETOOL rpc riak_core_console member_status $@
235 | ;;
236 |
237 | ring[_-]status)
238 | if [ $# -ne 1 ]; then
239 | echo "Usage: $SCRIPT $1"
240 | exit 1
241 | fi
242 |
243 | # Make sure the local node IS running
244 | RES=`$NODETOOL ping`
245 | if [ "$RES" != "pong" ]; then
246 | echo "Node is not running!"
247 | exit 1
248 | fi
249 | shift
250 |
251 | $NODETOOL rpc riak_core_console ring_status $@
252 | ;;
253 |
254 | services)
255 | $NODETOOL rpcterms riak_core_node_watcher services ''
256 | ;;
257 |
258 | wait[_-]for[_-]service)
259 | SVC=$2
260 | TARGETNODE=$3
261 | if [ $# -lt 3 ]; then
262 | echo "Usage: $SCRIPT $1 "
263 | exit 1
264 | fi
265 |
266 | while (true); do
267 | # Make sure riak_core_node_watcher is up and running locally before trying to query it
268 | # to avoid ugly (but harmless) error messages
269 | NODEWATCHER=`$NODETOOL rpcterms erlang whereis "'riak_core_node_watcher'."`
270 | if [ "$NODEWATCHER" = "undefined" ]; then
271 | echo "$SVC is not up: node watcher is not running"
272 | continue
273 | fi
274 |
275 | # Get the list of services that are available on the requested node
276 | SERVICES=`$NODETOOL rpcterms riak_core_node_watcher services "'${TARGETNODE}'."`
277 | echo "$SERVICES" | grep "[[,]$SVC[],]" > /dev/null 2>&1
278 | if [ "X$?" = "X0" ]; then
279 | echo "$SVC is up"
280 | exit 0
281 | else
282 | echo "$SVC is not up: $SERVICES"
283 | fi
284 | sleep 3
285 | done
286 | ;;
287 | cluster)
288 | shift
289 | cluster_admin "$@"
290 | ;;
291 | *)
292 | echo "Usage: $SCRIPT { cluster | down | ringready | member-status | "
293 | echo " ring-status | services | wait-for-service "
294 | exit 1
295 | ;;
296 | esac
297 |
--------------------------------------------------------------------------------
/config/erlang_vm.schema:
--------------------------------------------------------------------------------
1 | %%-*- mode: erlang -*-
2 |
3 | %% @doc Starts the Erlang runtime system with SMP support
4 | %% enabled. This may fail if no runtime system with SMP support is
5 | %% available. The 'auto' setting starts the Erlang runtime system with
6 | %% SMP support enabled if it is available and more than one logical
7 | %% processor are detected. -smp disable starts a runtime system
8 | %% without SMP support.
9 | %%
10 | %% NOTE: The runtime system with SMP support will not be available on
11 | %% all supported platforms. See also the erlang.schedulers settings.
12 | %%
13 | %% NOTE: Some native extensions (NIFs) require use of the SMP
14 | %% emulator.
15 | %%
16 | %% More information at: http://erlang.org/doc/man/erl.html
17 | % NOTE: disable this so it runs on erlang 20
18 | %{mapping, "erlang.smp", "vm_args.-smp", [
19 | % {default, enable},
20 | % {datatype, {enum, [enable, auto, disable]}},
21 | % hidden
22 | %]}.
23 |
24 | %% @doc Sets the mapping of warning messages for error_logger.
25 | %% Messages sent to the error logger using one of the warning
26 | %% routines can be mapped either to errors (default), warnings
27 | %% (w - default), or info reports (i).
28 | {mapping, "erlang.W", "vm_args.+W", [
29 | {default, "w"},
30 | hidden
31 | ]}.
32 |
33 | %% @doc Sets the number of scheduler threads to create and scheduler
34 | %% threads to set online when erlang.smp support has been enabled. The
35 | %% maximum for both values is 1024. If the Erlang runtime system is
36 | %% able to determine the amount of logical processors configured and
37 | %% logical processors available, schedulers.total will default to
38 | %% logical processors configured, and schedulers.online will default
39 | %% to logical processors available; otherwise, the default values will
40 | %% be 1. Schedulers may be omitted if schedulers.online is not and
41 | %% vice versa.
42 | %%
43 | %% If schedulers.total or schedulers.online is specified as a negative
44 | %% number, the value is subtracted from the default number of logical
45 | %% processors configured or logical processors available,
46 | %% respectively.
47 | %%
48 | %% Specifying the value 0 for Schedulers or SchedulersOnline resets
49 | %% the number of scheduler threads or scheduler threads online
50 | %% respectively to its default value.
51 | %%
52 | %% This option is ignored if the emulator doesn't have SMP support
53 | %% enabled (see the erlang.smp flag).
54 | %%
55 | %% More information at: http://erlang.org/doc/man/erl.html
56 | %% +S Schedulers:SchedulerOnline
57 | {mapping, "erlang.schedulers.total", "vm_args.+S", [
58 | {default, undefined},
59 | {datatype, integer},
60 | {validators, ["=<1024"]}
61 | ]}.
62 |
63 | %% @see erlang.schedulers.total
64 | {mapping, "erlang.schedulers.online", "vm_args.+S", [
65 | {default, undefined},
66 | {datatype, integer},
67 | {validators, ["=<1024"]}
68 | ]}.
69 |
70 | {translation, "vm_args.+S",
71 | fun(Conf) ->
72 | Total = cuttlefish:conf_get("erlang.schedulers.total", Conf, undefined),
73 | Online = cuttlefish:conf_get("erlang.schedulers.online", Conf, undefined),
74 | case {Total, Online} of
75 | {undefined, undefined} -> cuttlefish:unset();
76 | {undefined, O} -> ":" ++ integer_to_list(O);
77 | {T, undefined} -> integer_to_list(T);
78 | _ -> integer_to_list(Total) ++ ":" ++ integer_to_list(Online)
79 | end
80 | end
81 | }.
82 |
83 | {validator, "=<1024", "has a maximum value of 1024",
84 | fun(X) -> X =< 1024 end}.
85 |
86 | %% @doc Enables or disables the kernel poll functionality if the
87 | %% emulator supports it. If the emulator does not support kernel poll,
88 | %% and the K flag is passed to the emulator, a warning is issued at
89 | %% startup.
90 | %%
91 | %% Similar information at: http://erlang.org/doc/man/erl.html
92 | {mapping, "erlang.K", "vm_args.+K", [
93 | {default, on},
94 | {datatype, flag},
95 | hidden
96 | ]}.
97 |
98 | %%%% Tunables
99 | %% @doc Name of the Erlang node
100 | {mapping, "nodename", "vm_args.-name", [
101 | {default, "{{node}}"}
102 | ]}.
103 |
104 | %% @doc Cookie for distributed node communication. All nodes in the
105 | %% same cluster should use the same cookie or they will not be able to
106 | %% communicate.
107 | {mapping, "distributed_cookie", "vm_args.-setcookie", [
108 | {default, "erlang"}
109 | ]}.
110 |
111 | %% @doc Sets the number of threads in async thread pool, valid range
112 | %% is 0-1024. If thread support is available, the default is 64.
113 | %%
114 | %% More information at: http://erlang.org/doc/man/erl.html
115 | {mapping, "erlang.async_threads", "vm_args.+A", [
116 | {default, 64},
117 | {datatype, integer},
118 | {validators, ["range:0-1024"]}
119 | ]}.
120 |
121 | {validator, "range:0-1024", "must be 0 to 1024",
122 | fun(X) -> X >= 0 andalso X =< 1024 end}.
123 |
124 | %% @doc Suggested stack size, in bytes, for threads in the
125 | %% async-thread pool. Valid range is 16-8192 kilowords. The default
126 | %% suggested stack size is 16 kilowords, i.e, 64 kilobyte on 32-bit
127 | %% architectures. This small default size has been chosen since the
128 | %% amount of async-threads might be quite large. The default size is
129 | %% enough for drivers delivered with Erlang/OTP, but might not be
130 | %% sufficiently large for other dynamically linked in drivers that use
131 | %% the driver_async() functionality. Note that the value passed is
132 | %% only a suggestion, and it might even be ignored on some platforms.
133 | %%
134 | %% More information at: http://erlang.org/doc/man/erl.html
135 | {mapping, "erlang.async_threads.stack_size", "vm_args.+a", [
136 | {datatype, bytesize},
137 | {validators, [ "stack-size-divisible", "stack-size-range"]},
138 | hidden
139 | ]}.
140 |
141 | {validator, "stack-size-divisible", ("must be divisible by " ++ integer_to_list(erlang:system_info({wordsize,external}))),
142 | fun(X) -> X rem (erlang:system_info({wordsize, external})) == 0 end}.
143 |
144 | {validator, "stack-size-range",
145 | begin
146 | WordSize = erlang:system_info({wordsize, external}),
147 | ("must be in the range of " ++ cuttlefish_bytesize:to_string(16 * 1024 * WordSize)
148 | ++ " to " ++ cuttlefish_bytesize:to_string(8192 * 1024 * WordSize))
149 | end,
150 | fun(X) ->
151 | Scaled = X div (1024 * erlang:system_info({wordsize, external})),
152 | Scaled =< 8192 andalso Scaled >= 16
153 | end}.
154 |
155 | {translation, "vm_args.+a",
156 | fun(Conf) ->
157 | RawValue = cuttlefish:conf_get("erlang.async_threads.stack_size", Conf),
158 | RawValue div (1024 * erlang:system_info({wordsize, external}))
159 | end}.
160 |
161 | %% Note: OTP R15 and earlier uses -env ERL_MAX_PORTS, R16+ uses +Q
162 | %% @doc The number of concurrent ports/sockets
163 | %% Valid range is 1024-134217727
164 | {mapping, "erlang.max_ports",
165 | cuttlefish:otp("R16", "vm_args.+Q", "vm_args.-env ERL_MAX_PORTS"), [
166 | {default, 262144},
167 | {datatype, integer},
168 | {validators, ["range4ports"]}
169 | ]}.
170 |
171 | {validator, "range4ports", "must be 1024 to 134217727",
172 | fun(X) -> X >= 1024 andalso X =< 134217727 end}.
173 |
174 | %% @doc A non-negative integer which indicates how many times
175 | %% generational garbage collections can be done without forcing a
176 | %% fullsweep collection. In low-memory systems (especially without
177 | %% virtual memory), setting the value to 0 can help to conserve
178 | %% memory.
179 | %%
180 | %% More information at:
181 | %% http://www.erlang.org/doc/man/erlang.html#system_flag-2
182 | {mapping, "erlang.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [
183 | {default, 0},
184 | {datatype, integer},
185 | hidden,
186 | {validators, ["positive_integer"]}
187 | ]}.
188 |
189 | {validator, "positive_integer", "must be a positive integer",
190 | fun(X) -> X >= 0 end}.
191 |
192 | %% @doc Set the location of crash dumps
193 | {mapping, "erlang.crash_dump", "vm_args.-env ERL_CRASH_DUMP", [
194 | {default, "{{crash_dump}}"},
195 | {datatype, file},
196 | hidden
197 | ]}.
198 |
199 | %% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES,
200 | %% R16+ uses +e
201 | %% @doc Raise the ETS table limit
202 | {mapping, "erlang.max_ets_tables",
203 | cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [
204 | {default, 256000},
205 | {datatype, integer},
206 | hidden
207 | ]}.
208 |
209 | %% @doc Raise the default erlang process limit
210 | {mapping, "erlang.process_limit", "vm_args.+P", [
211 | {datatype, integer},
212 | {default, 256000},
213 | hidden
214 | ]}.
215 |
216 | %% @doc For nodes with many busy_dist_port events, Basho recommends
217 | %% raising the sender-side network distribution buffer size.
218 | %% 32MB may not be sufficient for some workloads and is a suggested
219 | %% starting point. Erlangers may know this as +zdbbl.
220 | %% The Erlang/OTP default is 1024 (1 megabyte).
221 | %% See: http://www.erlang.org/doc/man/erl.html#%2bzdbbl
222 | {mapping, "erlang.distribution_buffer_size", "vm_args.+zdbbl", [
223 | {datatype, bytesize},
224 | {commented, "32MB"},
225 | hidden,
226 | {validators, ["zdbbl_range"]}
227 | ]}.
228 |
229 | {translation, "vm_args.+zdbbl",
230 | fun(Conf) ->
231 | ZDBBL = cuttlefish:conf_get("erlang.distribution_buffer_size", Conf, undefined),
232 | case ZDBBL of
233 | undefined -> undefined;
234 | X when is_integer(X) -> cuttlefish_util:ceiling(X / 1024); %% Bytes to Kilobytes;
235 | _ -> undefined
236 | end
237 | end
238 | }.
239 |
240 | {validator, "zdbbl_range", "must be between 1KB and 2097151KB",
241 | fun(ZDBBL) ->
242 | %% 2097151KB = 2147482624
243 | ZDBBL >= 1024 andalso ZDBBL =< 2147482624
244 | end
245 | }.
246 |
247 | %% @doc Set scheduler forced wakeup interval. All run queues will be
248 | %% scanned each Interval milliseconds. While there are sleeping
249 | %% schedulers in the system, one scheduler will be woken for each
250 | %% non-empty run queue found. An Interval of zero disables this
251 | %% feature, which also is the default.
252 | %%
253 | %% This feature is a workaround for lengthy executing native code, and
254 | %% native code that do not bump reductions properly.
255 | %%
256 | %% More information: http://www.erlang.org/doc/man/erl.html#+sfwi
257 | {mapping, "erlang.schedulers.force_wakeup_interval", "vm_args.+sfwi", [
258 | {commented, 500},
259 | {datatype, integer}
260 | ]}.
261 |
262 | %% @doc Enable or disable scheduler compaction of load. By default
263 | %% scheduler compaction of load is enabled. When enabled, load
264 | %% balancing will strive for a load distribution which causes as many
265 | %% scheduler threads as possible to be fully loaded (i.e., not run out
266 | %% of work). This is accomplished by migrating load (e.g. runnable
267 | %% processes) into a smaller set of schedulers when schedulers
268 | %% frequently run out of work. When disabled, the frequency with which
269 | %% schedulers run out of work will not be taken into account by the
270 | %% load balancing logic.
271 | %%
272 | %% More information: http://www.erlang.org/doc/man/erl.html#+scl
273 | {mapping, "erlang.schedulers.compaction_of_load", "vm_args.+scl", [
274 | {commented, "false"},
275 | {datatype, {enum, [true, false]}}
276 | ]}.
277 |
278 | %% @doc Enable or disable scheduler utilization balancing of load. By
279 | %% default scheduler utilization balancing is disabled and instead
280 | %% scheduler compaction of load is enabled which will strive for a
281 | %% load distribution which causes as many scheduler threads as
282 | %% possible to be fully loaded (i.e., not run out of work). When
283 | %% scheduler utilization balancing is enabled the system will instead
284 | %% try to balance scheduler utilization between schedulers. That is,
285 | %% strive for equal scheduler utilization on all schedulers.
286 | %%
287 | %% More information: http://www.erlang.org/doc/man/erl.html#+sub
288 | {mapping, "erlang.schedulers.utilization_balancing", "vm_args.+sub", [
289 | {commented, "true"},
290 | {datatype, {enum, [true, false]}}
291 | ]}.
292 |
293 | %% @doc For ease of firewall configuration, the Erlang distribution
294 | %% can be bound to a limited range of TCP ports. If this is set, and
295 | %% erlang.distribution.port_range.maximum is *unset*, only this port
296 | %% will be used. If the minimum is *unset*, no restriction will be
297 | %% made on the port range; instead Erlang will listen on a random
298 | %% high-numbered port.
299 | %%
300 | %% More information: http://www.erlang.org/faq/how_do_i.html#id55090
301 | %% http://www.erlang.org/doc/man/kernel_app.html
302 | {mapping, "erlang.distribution.port_range.minimum", "kernel.inet_dist_listen_min", [
303 | {commented, 6000},
304 | {datatype, integer},
305 | hidden
306 | ]}.
307 |
308 | %% @see erlang.distribution.port_range.minimum
309 | {mapping, "erlang.distribution.port_range.maximum", "kernel.inet_dist_listen_max", [
310 | {commented, 7999},
311 | {datatype, integer},
312 | hidden
313 | ]}.
314 |
315 | %% @doc Set the net_kernel's net_ticktime.
316 | %%
317 | %% More information: http://www.erlang.org/doc/man/kernel_app.html#net_ticktime
318 | %% and http://www.erlang.org/doc/man/net_kernel.html#set_net_ticktime-1
319 | {mapping, "erlang.distribution.net_ticktime", "vm_args.-kernel net_ticktime", [
320 | {commented, 60},
321 | {datatype, integer},
322 | hidden
323 | ]}.
324 |
--------------------------------------------------------------------------------
/config/riak_core.schema:
--------------------------------------------------------------------------------
1 | %%-*- mode: erlang -*-
2 |
3 | %% @doc enable active anti-entropy subsystem
4 | {mapping, "anti_entropy", "riak_core.anti_entropy", [
5 | {datatype, {enum, [on, off, debug]}},
6 | {default, on}
7 | ]}.
8 |
9 | { translation,
10 | "riak_core.anti_entropy",
11 | fun(Conf) ->
12 | Setting = cuttlefish:conf_get("anti_entropy", Conf),
13 | case Setting of
14 | on -> {on, []};
15 | debug -> {on, [debug]};
16 | off -> {off, []};
17 | _Default -> {on, []}
18 | end
19 | end
20 | }.
21 |
22 | %% @doc Restrict how fast AAE can build hash trees. Building the tree
23 | %% for a given partition requires a full scan over that partition's
24 | %% data. Once built, trees stay built until they are expired.
25 | %% Config is of the form:
26 | %% {num-builds, per-timespan}
27 | %% Default is 1 build per hour.
28 | {mapping, "anti_entropy.build_limit.number", "riak_core.anti_entropy_build_limit", [
29 | {default, 1},
30 | {datatype, integer}
31 | ]}.
32 |
33 | {mapping, "anti_entropy.build_limit.per_timespan", "riak_core.anti_entropy_build_limit", [
34 | {default, "1h"},
35 | {datatype, {duration, ms}}
36 | ]}.
37 |
38 | {translation,
39 | "riak_core.anti_entropy_build_limit",
40 | fun(Conf) ->
41 | {cuttlefish:conf_get("anti_entropy.build_limit.number", Conf),
42 | cuttlefish:conf_get("anti_entropy.build_limit.per_timespan", Conf)}
43 | end}.
44 |
45 | %% @doc Determine how often hash trees are expired after being built.
46 | %% Periodically expiring a hash tree ensures the on-disk hash tree
47 | %% data stays consistent with the actual k/v backend data. It also
48 | %% helps Riak identify silent disk failures and bit rot. However,
49 | %% expiration is not needed for normal AAE operation and should be
50 | %% infrequent for performance reasons. The time is specified in
51 | %% milliseconds. The default is 1 week.
52 | {mapping, "anti_entropy.expire", "riak_core.anti_entropy_expire", [
53 | {default, "1w"},
54 | {datatype, {duration, ms}}
55 | ]}.
56 |
57 | %% @doc Limit how many AAE exchanges/builds can happen concurrently.
58 | {mapping, "anti_entropy.concurrency", "riak_core.anti_entropy_concurrency", [
59 | {default, 2},
60 | {datatype, integer}
61 | ]}.
62 |
63 | %% @doc The tick determines how often the AAE manager looks for work
64 | %% to do (building/expiring trees, triggering exchanges, etc).
65 | %% The default is every 15 seconds. Lowering this value will
66 | %% speedup the rate that all replicas are synced across the cluster.
67 | %% Increasing the value is not recommended.
68 | {mapping, "anti_entropy.tick", "riak_core.anti_entropy_tick", [
69 | {default, "15s"},
70 | {datatype, {duration, ms}}
71 | ]}.
72 |
73 | %% @doc The directory where AAE hash trees are stored.
74 | {mapping, "anti_entropy.data_dir", "riak_core.anti_entropy_data_dir", [
75 | {default, "{{platform_data_dir}}/anti_entropy"}
76 | ]}.
77 |
78 |
79 | %% @doc This parameter defines the percentage, 1 to 100, of total
80 | %% server memory to assign to leveldb. leveldb will dynamically
81 | %% adjust it internal cache sizs as Riak activates / inactivates
82 | %% vnodes on this server to stay within this size. The memory size
83 | %% can alternately be assigned as a byte count via total_leveldb_mem instead.
84 | {mapping, "anti_entropy.total_leveldb_mem_percent", "riak_core.aae_total_leveldb_mem_percent",
85 | [{default, "80"},
86 | {datatype, integer}]}.
87 |
88 |
89 | %% @doc This parameter defines the number of bytes of
90 | %% server memory to assign to leveldb. leveldb will dynamically
91 | %% adjust it internal cache sizes as Riak activates / inactivates
92 | %% vnodes on this server to stay within this size. The memory size
93 | %% can alternately be assigned as percentage of total server memory
94 | %% via total_leveldb_mem_percent instead.
95 | {mapping, "anti_entropy.total_leveldb_mem", "riak_core.aae_total_leveldb_mem",
96 | [{datatype, bytesize},
97 | {level, advanced}]}.
98 |
99 |
100 | %% @doc The 'sync' parameter defines how new key/value data is placed in the
101 | %% recovery log. The recovery log is only used if the Riak program crashes or
102 | %% the server loses power unexpectedly. The parameter's original intent was
103 | %% to guarantee that each new key / value was written to the physical disk
104 | %% before leveldb responded with “write good”. The reality in modern servers
105 | %% is that many layers of data caching exist between the database program and
106 | %% the physical disks. This flag influences only one of the layers.
107 | {mapping, "anti_entropy.sync", "riak_core.aae_sync",
108 | [{default, false},
109 | {datatype, {enum, [true, false]}},
110 | {level, advanced}]}.
111 |
112 | %% @doc limited_developer_mem is a Riak specific option that is used when
113 | %% a developer is testing a high number of vnodes and/or several VMs
114 | %% on a machine with limited physical memory. Do NOT use this option
115 | %% if making performance measurements. This option overwrites values
116 | %% given to write_buffer_size_min and write_buffer_size_max.
117 | {mapping, "anti_entropy.limited_developer_mem", "riak_core.aae_limited_developer_mem",
118 | [{default, false},
119 | {datatype, {enum, [true, false]}},
120 | {level, advanced}]}.
121 |
122 |
123 | %% @doc Each vnode first stores new key/value data in a memory based write
124 | %% buffer. This write buffer is in parallel to the recovery log mentioned
125 | %% in the “sync” parameter. Riak creates each vnode with a randomly sized
126 | %% write buffer for performance reasons. The random size is somewhere
127 | %% between write_buffer_size_min and write_buffer_size_max.
128 | {mapping, "anti_entropy.write_buffer_size_min", "riak_core.aae_write_buffer_size_min",
129 | [{default, "30MB"},
130 | {datatype, bytesize},
131 | {level, advanced}]}.
132 |
133 | {mapping, "anti_entropy.write_buffer_size_max", "riak_core.aae_write_buffer_size_max",
134 | [{default, "60MB"},
135 | {datatype, bytesize},
136 | {level, advanced}]}.
137 |
138 | %% @doc Whether the distributed throttle for active anti-entropy is
139 | %% enabled.
140 | {mapping, "anti_entropy.throttle", "riak_core.aae_throttle_kill_switch", [
141 | {default, on},
142 | {datatype, {flag, off, on}},
143 | hidden
144 | ]}.
145 |
146 | %% @doc Sets the throttling tiers for active anti-entropy. Each tier
147 | %% is a minimum vnode mailbox size and a time-delay that the throttle
148 | %% should observe at that size and above. For example:
149 | %%
150 | %% anti_entropy.throttle.tier1.mailbox_size = 0
151 | %% anti_entropy.throttle.tier1.delay = 0ms
152 | %% anti_entropy.throttle.tier2.mailbox_size = 40
153 | %% anti_entropy.throttle.tier2.delay = 5ms
154 | %%
155 | %% If configured, there must be a tier which includes a mailbox size
156 | %% of 0. Both .mailbox_size and .delay must be set for each tier.
157 | %% @see anti_entropy.throttle
158 | {mapping,
159 | "anti_entropy.throttle.$tier.mailbox_size",
160 | "riak_core.aae_throttle_limits", [
161 | {datatype, integer},
162 | hidden,
163 | {validators, ["non_negative"]}
164 | ]}.
165 |
166 | %% @see anti_entropy.throttle.$tier.mailbox_size
167 | {mapping,
168 | "anti_entropy.throttle.$tier.delay",
169 | "riak_core.aae_throttle_limits", [
170 | {datatype, {duration, ms}},
171 | hidden
172 | ]}.
173 |
174 | {validator,
175 | "non_negative",
176 | "must be greater than or equal to 0",
177 | fun(Value) -> Value >= 0 end}.
178 |
179 | {translation,
180 | "riak_core.aae_throttle_limits",
181 | fun(Conf) ->
182 | %% Grab all of the possible names of tiers so we can ensure that
183 | %% both mailbox_size and delay are included for each tier.
184 | TierNamesM = cuttlefish_variable:fuzzy_matches(["anti_entropy", "throttle", "$tier", "mailbox_size"], Conf),
185 | TierNamesD = cuttlefish_variable:fuzzy_matches(["anti_entropy", "throttle", "$tier", "delay"], Conf),
186 | TierNames = lists:usort(TierNamesM ++ TierNamesD),
187 | Throttles = lists:sort(lists:foldl(
188 | fun({"$tier", Tier}, Settings) ->
189 | Mbox = cuttlefish:conf_get(["anti_entropy", "throttle", Tier, "mailbox_size"], Conf),
190 | Delay = cuttlefish:conf_get(["anti_entropy", "throttle", Tier, "delay"], Conf),
191 | [{Mbox - 1, Delay}|Settings]
192 | end, [], TierNames)),
193 | case Throttles of
194 | %% -1 is a magic "minimum" bound and must be included, so if it
195 | %% isn't present we call it invalid
196 | [{-1,_}|_] -> Throttles;
197 | _ -> cuttlefish:invalid("anti_entropy.throttle tiers must include a tier with mailbox_size 0")
198 | end
199 | end
200 | }.
201 |
202 |
203 | %% @doc Each database .sst table file can include an optional "bloom filter"
204 | %% that is highly effective in shortcutting data queries that are destined
205 | %% to not find the requested key. The bloom_filter typically increases the
206 | %% size of an .sst table file by about 2%. This option must be set to true
207 | %% in the riak.conf to take effect.
208 | {mapping, "anti_entropy.bloomfilter", "riak_core.aae_use_bloomfilter",
209 | [{default, on},
210 | {datatype, {enum, [on, off]}}]}.
211 |
212 | {translation,
213 | "riak_core.aae_use_bloomfilter",
214 | fun(Conf) ->
215 | case cuttlefish:conf_get("anti_entropy.bloomfilter", Conf) of
216 | on -> true;
217 | off -> false;
218 | _ -> true
219 | end
220 | end
221 | }.
222 |
223 |
224 | %% @doc sst_block_size defines the size threshold for a block / chunk of data
225 | %% within one .sst table file. Each new block gets an index entry in the .sst
226 | %% table file's master index.
227 | {mapping, "anti_entropy.block_size", "riak_core.aae_sst_block_size",
228 | [{default, "4KB"},
229 | {datatype, bytesize},
230 | {level, advanced}]}.
231 |
232 |
233 | %% @doc block_restart_interval defines the key count threshold for a new key
234 | %% entry in the key index for a block.
235 | %% Most clients should leave this parameter alone.
236 | {mapping, "anti_entropy.block_restart_interval", "riak_core.aae_block_restart_interval",
237 | [{default, 16},
238 | {datatype, integer},
239 | {level, advanced}]}.
240 |
241 |
242 | %% @doc verify_checksums controls whether or not validation occurs when Riak
243 | %% requests data from the leveldb database on behalf of the user.
244 | {mapping, "anti_entropy.verify_checksums", "riak_core.aae_verify_checksums",
245 | [{default, true},
246 | {datatype, {enum, [true, false]}},
247 | {level, advanced}]}.
248 |
249 |
250 | %% @doc verify_compaction controls whether or not validation occurs when
251 | %% leveldb reads data as part of its background compaction operations.
252 | {mapping, "anti_entropy.verify_compaction", "riak_core.aae_verify_compaction",
253 | [{default, true},
254 | {datatype, {enum, [true, false]}},
255 | {level, advanced}]}.
256 |
257 | %% @doc The number of worker threads performing LevelDB operations.
258 | {mapping, "anti_entropy.threads", "riak_core.aae_eleveldb_threads",
259 | [{default, 71},
260 | {datatype, integer},
261 | {level, advanced}]}.
262 |
263 | %% @doc Option to override LevelDB's use of fadvise(DONTNEED) with
264 | %% fadvise(WILLNEED) instead. WILLNEED can reduce disk activity on
265 | %% systems where physical memory exceeds the database size.
266 | {mapping, "anti_entropy.fadvise_willneed", "riak_core.aae_fadvise_willneed",
267 | [{default, false},
268 | {datatype, {enum, [true, false]}},
269 | {level, advanced}]}.
270 |
271 | %% Default Bucket Properties
272 |
273 | %% @doc The number of replicas stored. Note: See Replication
274 | %% Properties for further discussion.
275 | %% http://docs.basho.com/riak/latest/dev/advanced/cap-controls/
276 | {mapping, "buckets.default.n_val", "riak_core.default_bucket_props.n_val", [
277 | {datatype, integer},
278 | {default, 3},
279 | hidden
280 | ]}.
281 |
282 | %% @doc Number of partitions in the cluster (only valid when first
283 | %% creating the cluster). Must be a power of 2, minimum 8 and maximum
284 | %% 1024.
285 | {mapping, "ring_size", "riak_core.ring_creation_size", [
286 | {datatype, integer},
287 | {default, 64},
288 | {validators, ["ring_size^2", "ring_size_max", "ring_size_min"]},
289 | {commented, 64}
290 | ]}.
291 |
292 | %% ring_size validators
293 | {validator, "ring_size_max",
294 | "2048 and larger are supported, but considered advanced config",
295 | fun(Size) ->
296 | Size =< 1024
297 | end}.
298 |
299 | {mapping, "buckets.default.pr", "riak_core.default_bucket_props.pr", [
300 | {default, "0"},
301 | {level, advanced}
302 | ]}.
303 |
304 | %% Cut and paste translation screams to be rewritten as a datatype, but that's a
305 | %% "nice to have"
306 | {translation,
307 | "riak_core.default_bucket_props.pr",
308 | fun(Conf) ->
309 | Setting = cuttlefish:conf_get("buckets.default.pr", Conf),
310 | case Setting of
311 | "quorum" -> quorum;
312 | "all" -> all;
313 | X ->
314 | try list_to_integer(Setting) of
315 | Int -> Int
316 | catch
317 | E:R -> error
318 | end
319 | end
320 | end
321 | }.
322 |
323 | {mapping, "buckets.default.r", "riak_core.default_bucket_props.r", [
324 | {default, "quorum"},
325 | {level, advanced}
326 | ]}.
327 | {translation,
328 | "riak_core.default_bucket_props.r",
329 | fun(Conf) ->
330 | Setting = cuttlefish:conf_get("buckets.default.r", Conf),
331 | case Setting of
332 | "quorum" -> quorum;
333 | "all" -> all;
334 | X ->
335 | try list_to_integer(Setting) of
336 | Int -> Int
337 | catch
338 | E:R -> error
339 | end
340 | end
341 | end
342 | }.
343 |
344 | {mapping, "buckets.default.w", "riak_core.default_bucket_props.w", [
345 | {default, "quorum"},
346 | {level, advanced}
347 | ]}.
348 | {translation,
349 | "riak_core.default_bucket_props.w",
350 | fun(Conf) ->
351 | Setting = cuttlefish:conf_get("buckets.default.w", Conf),
352 | case Setting of
353 | "quorum" -> quorum;
354 | "all" -> all;
355 | X ->
356 | try list_to_integer(Setting) of
357 | Int -> Int
358 | catch
359 | E:R -> error
360 | end
361 | end
362 | end
363 | }.
364 |
365 | {mapping, "buckets.default.pw", "riak_core.default_bucket_props.pw", [
366 | {default, "0"},
367 | {level, advanced}
368 | ]}.
369 | {translation,
370 | "riak_core.default_bucket_props.pw",
371 | fun(Conf) ->
372 | Setting = cuttlefish:conf_get("buckets.default.pw", Conf),
373 | case Setting of
374 | "quorum" -> quorum;
375 | "all" -> all;
376 | X ->
377 | try list_to_integer(Setting) of
378 | Int -> Int
379 | catch
380 | E:R -> error
381 | end
382 | end
383 | end
384 | }.
385 |
386 | {mapping, "buckets.default.dw", "riak_core.default_bucket_props.dw", [
387 | {default, "quorum"},
388 | {level, advanced}
389 | ]}.
390 | {translation,
391 | "riak_core.default_bucket_props.dw",
392 | fun(Conf) ->
393 | Setting = cuttlefish:conf_get("buckets.default.dw", Conf),
394 | case Setting of
395 | "quorum" -> quorum;
396 | "all" -> all;
397 | X ->
398 | try list_to_integer(Setting) of
399 | Int -> Int
400 | catch
401 | E:R -> error
402 | end
403 | end
404 | end
405 | }.
406 |
407 | {mapping, "buckets.default.rw", "riak_core.default_bucket_props.rw", [
408 | {default, "quorum"},
409 | {level, advanced}
410 | ]}.
411 | {translation,
412 | "riak_core.default_bucket_props.rw",
413 | fun(Conf) ->
414 | Setting = cuttlefish:conf_get("buckets.default.rw", Conf),
415 | case Setting of
416 | "quorum" -> quorum;
417 | "all" -> all;
418 | X ->
419 | try list_to_integer(Setting) of
420 | Int -> Int
421 | catch
422 | E:R -> error
423 | end
424 | end
425 | end
426 | }.
427 |
428 | %% {mapping, "buckets.default.basic_quorum", "riak_core.default_bucket_props.basic_quorum", false},
429 | %% {mapping, "buckets.default.notfound_ok", "riak_core.default_bucket_props.notfound_ok", true}
430 |
431 | %% @doc whether or not siblings are allowed.
432 | %% Note: See Vector Clocks for a discussion of sibling resolution.
433 | {mapping, "buckets.default.siblings", "riak_core.default_bucket_props.allow_mult", [
434 | {datatype, {enum, [on, off]}},
435 | {default, on},
436 | {level, advanced}
437 | ]}.
438 |
439 | {translation,
440 | "riak_core.default_bucket_props.allow_mult",
441 | fun(Conf) ->
442 | Setting = cuttlefish:conf_get("buckets.default.siblings", Conf),
443 | case Setting of
444 | on -> true;
445 | off -> false;
446 | _Default -> true
447 | end
448 | end}.
449 |
450 | {validator, "ring_size^2", "not a power of 2",
451 | fun(Size) ->
452 | (Size band (Size-1) =:= 0)
453 | end}.
454 |
455 | {validator, "ring_size_min", "must be at least 8",
456 | fun(Size) ->
457 | Size >= 8
458 | end}.
459 |
460 | %% @doc Number of concurrent node-to-node transfers allowed.
461 | {mapping, "transfer_limit", "riak_core.handoff_concurrency", [
462 | {datatype, integer},
463 | {default, 2},
464 | {commented, 2}
465 | ]}.
466 |
467 | %% @doc Default location of ringstate
468 | {mapping, "ring.state_dir", "riak_core.ring_state_dir", [
469 | {datatype, directory},
470 | {default, "$(platform_data_dir)/ring"},
471 | hidden
472 | ]}.
473 |
474 | %% @doc Default cert location for https can be overridden
475 | %% with the ssl config variable, for example:
476 | {mapping, "ssl.certfile", "riak_core.ssl.certfile", [
477 | {datatype, file},
478 | {commented, "$(platform_etc_dir)/cert.pem"}
479 | ]}.
480 |
481 | %% @doc Default key location for https can be overridden with the ssl
482 | %% config variable, for example:
483 | {mapping, "ssl.keyfile", "riak_core.ssl.keyfile", [
484 | {datatype, file},
485 | {commented, "$(platform_etc_dir)/key.pem"}
486 | ]}.
487 |
488 | %% @doc Default signing authority location for https can be overridden
489 | %% with the ssl config variable, for example:
490 | {mapping, "ssl.cacertfile", "riak_core.ssl.cacertfile", [
491 | {datatype, file},
492 | {commented, "$(platform_etc_dir)/cacertfile.pem"}
493 | ]}.
494 |
495 | %% @doc handoff.ip is the network address that Riak binds to for
496 | %% intra-cluster data handoff.
497 | {mapping, "handoff.ip", "riak_core.handoff_ip", [
498 | {default, "{{handoff_ip}}" },
499 | {datatype, string},
500 | {validators, ["valid_ipaddr"]},
501 | hidden
502 | ]}.
503 |
504 | {validator,
505 | "valid_ipaddr",
506 | "must be a valid IP address",
507 | fun(AddrString) ->
508 | case inet_parse:address(AddrString) of
509 | {ok, _} -> true;
510 | {error, _} -> false
511 | end
512 | end}.
513 |
514 | {validator,
515 | "not_localhost",
516 | "can't be a local ip",
517 | fun(AddrString) ->
518 | case inet_parse:address(AddrString) of
519 | {ok, {127, 0, _, _}} -> false;
520 | {ok, _} -> true;
521 | {error, _} -> false
522 | end
523 | end}.
524 |
525 | %% @doc handoff.port is the TCP port that Riak uses for
526 | %% intra-cluster data handoff.
527 | {mapping, "handoff.port", "riak_core.handoff_port", [
528 | {default, {{handoff_port}} },
529 | {datatype, integer},
530 | hidden
531 | ]}.
532 |
533 | %% @doc To encrypt riak_core intra-cluster data handoff traffic,
534 | %% uncomment the following line and edit its path to an appropriate
535 | %% certfile and keyfile. (This example uses a single file with both
536 | %% items concatenated together.)
537 | {mapping, "handoff.ssl.certfile", "riak_core.handoff_ssl_options.certfile", [
538 | %% {commented, "/tmp/erlserver.pem"},
539 | {datatype, file},
540 | hidden
541 | ]}.
542 |
543 | %% @doc if you need a seperate keyfile for handoff
544 | {mapping, "handoff.ssl.keyfile", "riak_core.handoff_ssl_options.keyfile", [
545 | {datatype, file},
546 | hidden
547 | ]}.
548 |
549 | %% @doc Enables/disables outbound handoff transfers for this node. If you
550 | %% turn this setting off at runtime with riak-admin, it will kill any
551 | %% outbound handoffs currently running.
552 | {mapping, "handoff.outbound", "riak_core.disable_outbound_handoff", [
553 | {default, on},
554 | {datatype, {flag, off, on}},
555 | hidden
556 | ]}.
557 |
558 | %% @doc Enables/disables inbound handoff transfers for this node. If you
559 | %% turn this setting off at runtime with riak-admin, it will kill any
560 | %% inbound handoffs currently running.
561 | {mapping, "handoff.inbound", "riak_core.disable_inbound_handoff", [
562 | {default, on},
563 | {datatype, {flag, off, on}},
564 | hidden
565 | ]}.
566 |
567 | %% @doc The time a vnode has to be idle for a handoff to occour. (I think)
568 | {mapping, "handoff.inactivity_timeout", "riak_core.vnode_inactivity_timeout", [
569 | {default, "1m"},
570 | {datatype, {duration, ms}}
571 | ]}.
572 |
573 | %% @doc DTrace support Do not enable 'dtrace' unless your Erlang/OTP
574 | %% runtime is compiled to support DTrace. DTrace is available in
575 | %% R15B01 (supported by the Erlang/OTP official source package) and in
576 | %% R14B04 via a custom source repository & branch.
577 | {mapping, "dtrace", "riak_core.dtrace_support", [
578 | {default, off},
579 | {datatype, flag}
580 | ]}.
581 |
582 | %% consistent on/off (in lieu of enabled/disabled, true/false)
583 | { translation,
584 | "riak_core.dtrace_support",
585 | fun(Conf) ->
586 | Setting = cuttlefish:conf_get("dtrace", Conf),
587 | case Setting of
588 | on -> true;
589 | off -> false;
590 | _Default -> false
591 | end
592 | end
593 | }.
594 |
595 | %% @doc Platform-specific installation paths (substituted by rebar)
596 | {mapping, "platform_bin_dir", "riak_core.platform_bin_dir", [
597 | {datatype, directory},
598 | {default, "{{platform_bin_dir}}"}
599 | ]}.
600 |
601 | %% @see platform_bin_dir
602 | {mapping, "platform_data_dir", "riak_core.platform_data_dir", [
603 | {datatype, directory},
604 | {default, "{{platform_data_dir}}"}
605 | ]}.
606 |
607 | %% @see platform_bin_dir
608 | {mapping, "platform_etc_dir", "riak_core.platform_etc_dir", [
609 | {datatype, directory},
610 | {default, "{{platform_etc_dir}}"}
611 | ]}.
612 |
613 | %% @see platform_bin_dir
614 | {mapping, "platform_lib_dir", "riak_core.platform_lib_dir", [
615 | {datatype, directory},
616 | {default, "{{platform_lib_dir}}"}
617 | ]}.
618 |
619 | %% @see platform_bin_dir
620 | {mapping, "platform_log_dir", "riak_core.platform_log_dir", [
621 | {datatype, directory},
622 | {default, "{{platform_log_dir}}"}
623 | ]}.
624 |
625 | %% @doc Enable consensus subsystem. Set to 'on' to enable the
626 | %% consensus subsystem used for strongly consistent Riak operations.
627 | {mapping, "strong_consistency", "riak_core.enable_consensus", [
628 | {datatype, flag},
629 | {default, off},
630 | {commented, on}
631 | ]}.
632 |
633 | %% @doc Whether to enable the background manager globally. When
634 | %% enabled, participating Riak subsystems will coordinate access to
635 | %% shared resources. This will help to prevent system response
636 | %% degradation under times of heavy load from multiple background
637 | %% tasks. Specific subsystems may also have their own controls over
638 | %% use of the background manager.
639 | {mapping, "background_manager", "riak_core.use_background_manager", [
640 | {datatype, flag},
641 | {default, off},
642 | hidden
643 | ]}.
644 |
645 | %% @doc Interval of time between vnode management
646 | %% activities. Modifying this will change the amount of time between
647 | %% attemps to trigger handoff between this node and any other member
648 | %% of the cluster.
649 | {mapping, "vnode_management_timer", "riak_core.vnode_management_timer", [
650 | {default, "10s"},
651 | {datatype, {duration, ms}},
652 | hidden
653 | ]}.
654 |
655 | %% @doc Home directory for the run user
656 | {mapping, "run_user_home", "setup.home",
657 | [{default, "{{run_user_home}}"},
658 | hidden,
659 | {datatype, string}]}.
660 |
661 | %% Async Job Management
662 | %%
663 | %% This is a translation for mappings that appear in other schema files.
664 | %% Mappings are from "cluster.job.$namespace.$operation"* to
665 | %% "riak_core.job_accept_class" with required attributes
666 | %% [merge, {datatype, {flag, enabled, disabled}}].**
667 | %% * Mappings are only performed on elements with exactly the number of
668 | %% segments shown - any other number of elements, even with a matching
669 | %% prefix, is ignored.
670 | %% ** The 'datatype' should be 'flag', and 'enabled'/'disabled' are our
671 | %% conventions, but any OnFlag/OffFlag pair can be used as long as they map
672 | %% to boolean values.
673 | %% Other attributes, such as 'hidden' or {default, X} are fine, since they
674 | %% don't make it down the stack to here.
675 | %% Job classes that should be enabled by default MUST have a {default, enabled}
676 | %% attribute, as the runtime filter only defaults to accept when no values have
677 | %% been set from ANY schema file.
678 | %%
679 | %% Example:
680 | %% {mapping, "cluster.job.harry.fold", "riak_core.job_accept_class", [
681 | %% merge,
682 | %% {datatype, {flag, enabled, disabled}},
683 | %% {default, enabled}
684 | %% ]}.
685 | %% {mapping, "cluster.job.alice.list", "riak_core.job_accept_class", [
686 | %% merge,
687 | %% {datatype, {flag, enabled, disabled}},
688 | %% {default, disabled}
689 | %% ]}.
690 | %% Results in:
691 | %% {riak_core, [
692 | %% ...
693 | %% {job_accept_class, [{harry, fold}]}
694 | %% ...
695 | %% ]}.
696 | %%
697 | {translation,
698 | "riak_core.job_accept_class",
699 | fun(Conf) ->
700 | Fold =
701 | fun({[_, _, Mod, Op], true}, Result) ->
702 | [{erlang:list_to_atom(Mod), erlang:list_to_atom(Op)} | Result];
703 | ({[_, _, _, _], false}, Result) ->
704 | Result;
705 | ({[_, _, _, _], _} = Setting, _) ->
706 | cuttlefish:invalid(io_lib:format("~p", [Setting]));
707 | (_, Result) ->
708 | Result
709 | end,
710 | lists:sort(lists:foldl(Fold, [],
711 | cuttlefish_variable:filter_by_prefix(["cluster", "job"], Conf)))
712 | end}.
713 |
714 |
715 | %% @doc Some requests to the vnodes are handled by an asyncronous worker pool.
716 | %% This parameter allows for tuning this pools behaviour when it comes dealing
717 | %% with requests that are queued.
718 | %% The default (fifo) will serve requests in the order they arrive at the worker
719 | %% pool. The alternative is to serve the requests in the reverse order, dealing
720 | %% with the most recent request first.
721 | %% There are pro's and con's for both aproaches, it is best to test out what
722 | %% works best for the desired characteristics.
723 | %%
724 | %% As a very rought rule of thumb:
725 | %% - fifo will lead to lower extremes
726 | %% - filo will lead to lower medians/mediums
727 | {mapping, "worker.queue_strategy", "riak_core.queue_worker_strategy",
728 | [{default, fifo},
729 | {datatype, {enum, [fifo, filo]}}]}.
730 |
--------------------------------------------------------------------------------
/apps/tanodb/priv/ui/admin/css/bootstrap.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.5 (http://getbootstrap.com)
3 | * Copyright 2011-2015 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
--------------------------------------------------------------------------------