aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorserxa <serxa@yandex-team.ru>2022-02-10 16:49:08 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:49:08 +0300
commitd6d7db348c2cc64e71243cab9940ee6778f4317d (patch)
treebac67f42a02f9368eb4d329f5d79b77d0a6adc18 /library/cpp
parent8d57b69dee81198a59c39e64704f7dc9f04b4fbf (diff)
downloadydb-d6d7db348c2cc64e71243cab9940ee6778f4317d.tar.gz
Restoring authorship annotation for <serxa@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/actors/core/actor.cpp4
-rw-r--r--library/cpp/actors/core/actor_ut.cpp472
-rw-r--r--library/cpp/actors/core/actorid.h2
-rw-r--r--library/cpp/actors/core/actorsystem.cpp40
-rw-r--r--library/cpp/actors/core/actorsystem.h84
-rw-r--r--library/cpp/actors/core/balancer.cpp586
-rw-r--r--library/cpp/actors/core/balancer.h54
-rw-r--r--library/cpp/actors/core/balancer_ut.cpp450
-rw-r--r--library/cpp/actors/core/config.h478
-rw-r--r--library/cpp/actors/core/cpu_manager.cpp216
-rw-r--r--library/cpp/actors/core/cpu_manager.h114
-rw-r--r--library/cpp/actors/core/cpu_state.h430
-rw-r--r--library/cpp/actors/core/defs.h46
-rw-r--r--library/cpp/actors/core/event_pb.h8
-rw-r--r--library/cpp/actors/core/executor_pool_base.cpp72
-rw-r--r--library/cpp/actors/core/executor_pool_base.h42
-rw-r--r--library/cpp/actors/core/executor_pool_basic.cpp116
-rw-r--r--library/cpp/actors/core/executor_pool_basic.h18
-rw-r--r--library/cpp/actors/core/executor_pool_basic_ut.cpp110
-rw-r--r--library/cpp/actors/core/executor_pool_io.cpp68
-rw-r--r--library/cpp/actors/core/executor_pool_io.h14
-rw-r--r--library/cpp/actors/core/executor_pool_united.cpp2764
-rw-r--r--library/cpp/actors/core/executor_pool_united.h234
-rw-r--r--library/cpp/actors/core/executor_pool_united_ut.cpp404
-rw-r--r--library/cpp/actors/core/executor_thread.cpp268
-rw-r--r--library/cpp/actors/core/executor_thread.h80
-rw-r--r--library/cpp/actors/core/lease.h112
-rw-r--r--library/cpp/actors/core/log.cpp152
-rw-r--r--library/cpp/actors/core/log.h2
-rw-r--r--library/cpp/actors/core/mailbox.cpp16
-rw-r--r--library/cpp/actors/core/mailbox.h2
-rw-r--r--library/cpp/actors/core/mon_stats.h40
-rw-r--r--library/cpp/actors/core/probes.cpp50
-rw-r--r--library/cpp/actors/core/probes.h242
-rw-r--r--library/cpp/actors/core/scheduler_actor.cpp4
-rw-r--r--library/cpp/actors/core/scheduler_basic.cpp12
-rw-r--r--library/cpp/actors/core/scheduler_basic.h4
-rw-r--r--library/cpp/actors/core/ut/ya.make4
-rw-r--r--library/cpp/actors/core/worker_context.cpp14
-rw-r--r--library/cpp/actors/core/worker_context.h350
-rw-r--r--library/cpp/actors/core/ya.make24
-rw-r--r--library/cpp/actors/dnscachelib/dnscache.cpp74
-rw-r--r--library/cpp/actors/dnscachelib/dnscache.h2
-rw-r--r--library/cpp/actors/dnscachelib/probes.cpp6
-rw-r--r--library/cpp/actors/dnscachelib/probes.h12
-rw-r--r--library/cpp/actors/dnscachelib/ya.make4
-rw-r--r--library/cpp/actors/helpers/flow_controlled_queue.cpp6
-rw-r--r--library/cpp/actors/interconnect/interconnect_channel.cpp12
-rw-r--r--library/cpp/actors/interconnect/interconnect_channel.h12
-rw-r--r--library/cpp/actors/interconnect/interconnect_common.h4
-rw-r--r--library/cpp/actors/interconnect/interconnect_tcp_input_session.cpp6
-rw-r--r--library/cpp/actors/interconnect/interconnect_tcp_session.cpp150
-rw-r--r--library/cpp/actors/interconnect/interconnect_tcp_session.h36
-rw-r--r--library/cpp/actors/interconnect/packet.cpp10
-rw-r--r--library/cpp/actors/interconnect/packet.h10
-rw-r--r--library/cpp/actors/interconnect/poller_actor.cpp8
-rw-r--r--library/cpp/actors/interconnect/profiler.h8
-rw-r--r--library/cpp/actors/memory_log/memlog.cpp8
-rw-r--r--library/cpp/actors/testlib/test_runtime.cpp80
-rw-r--r--library/cpp/actors/testlib/test_runtime.h30
-rw-r--r--library/cpp/actors/util/affinity.cpp82
-rw-r--r--library/cpp/actors/util/affinity.h14
-rw-r--r--library/cpp/actors/util/cpumask.h266
-rw-r--r--library/cpp/actors/util/datetime.h164
-rw-r--r--library/cpp/actors/util/thread.h2
-rw-r--r--library/cpp/actors/util/timerfd.h130
-rw-r--r--library/cpp/actors/util/ya.make6
-rw-r--r--library/cpp/bucket_quoter/bucket_quoter.h298
-rw-r--r--library/cpp/containers/stack_vector/stack_vec.h4
-rw-r--r--library/cpp/http/server/http.cpp2
-rw-r--r--library/cpp/lwtrace/all.h370
-rw-r--r--library/cpp/lwtrace/check.cpp32
-rw-r--r--library/cpp/lwtrace/check.h154
-rw-r--r--library/cpp/lwtrace/control.h578
-rw-r--r--library/cpp/lwtrace/custom_action.cpp28
-rw-r--r--library/cpp/lwtrace/custom_action.h126
-rw-r--r--library/cpp/lwtrace/event.h50
-rw-r--r--library/cpp/lwtrace/example1/lwtrace_example1.cpp4
-rw-r--r--library/cpp/lwtrace/example2/lwtrace_example2.cpp32
-rw-r--r--library/cpp/lwtrace/example3/example_query.tr8
-rw-r--r--library/cpp/lwtrace/example3/lwtrace_example3.cpp12
-rw-r--r--library/cpp/lwtrace/example3/my_action.h162
-rwxr-xr-xlibrary/cpp/lwtrace/example3/start_with_query.sh10
-rw-r--r--library/cpp/lwtrace/example3/ya.make6
-rw-r--r--library/cpp/lwtrace/example4/example_query.tr2
-rw-r--r--library/cpp/lwtrace/example4/lwtrace_example4.cpp28
-rwxr-xr-xlibrary/cpp/lwtrace/example4/start_with_query.sh2
-rw-r--r--library/cpp/lwtrace/example4/ya.make6
-rw-r--r--library/cpp/lwtrace/example5/example_query.tr18
-rw-r--r--library/cpp/lwtrace/example5/lwtrace_example5.cpp46
-rwxr-xr-xlibrary/cpp/lwtrace/example5/start_with_query.sh6
-rw-r--r--library/cpp/lwtrace/example5/ya.make24
-rw-r--r--library/cpp/lwtrace/kill_action.cpp4
-rw-r--r--library/cpp/lwtrace/kill_action.h20
-rw-r--r--library/cpp/lwtrace/log.h1792
-rw-r--r--library/cpp/lwtrace/log_shuttle.cpp26
-rw-r--r--library/cpp/lwtrace/log_shuttle.h514
-rw-r--r--library/cpp/lwtrace/lwprobe.h198
-rw-r--r--library/cpp/lwtrace/mon/analytics/all.h4
-rw-r--r--library/cpp/lwtrace/mon/analytics/analytics.cpp10
-rw-r--r--library/cpp/lwtrace/mon/analytics/csv_output.h82
-rw-r--r--library/cpp/lwtrace/mon/analytics/data.h120
-rw-r--r--library/cpp/lwtrace/mon/analytics/html_output.h148
-rw-r--r--library/cpp/lwtrace/mon/analytics/json_output.h174
-rw-r--r--library/cpp/lwtrace/mon/analytics/transform.h324
-rw-r--r--library/cpp/lwtrace/mon/analytics/util.h194
-rw-r--r--library/cpp/lwtrace/mon/analytics/ya.make22
-rw-r--r--library/cpp/lwtrace/mon/mon_lwtrace.cpp7878
-rw-r--r--library/cpp/lwtrace/mon/mon_lwtrace.h30
-rw-r--r--library/cpp/lwtrace/mon/static/analytics.css136
-rw-r--r--library/cpp/lwtrace/mon/static/analytics.flot.html98
-rw-r--r--library/cpp/lwtrace/mon/static/analytics.gantt.html52
-rw-r--r--library/cpp/lwtrace/mon/static/analytics.header.html42
-rw-r--r--library/cpp/lwtrace/mon/static/analytics.js1122
-rw-r--r--library/cpp/lwtrace/mon/static/common.js30
-rw-r--r--library/cpp/lwtrace/mon/static/css/bootstrap.min.css18
-rw-r--r--library/cpp/lwtrace/mon/static/css/d3-gantt.css136
-rw-r--r--library/cpp/lwtrace/mon/static/css/jquery.treegrid.css16
-rw-r--r--library/cpp/lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg576
-rw-r--r--library/cpp/lwtrace/mon/static/header.html22
-rw-r--r--library/cpp/lwtrace/mon/static/js/bootstrap.min.js18
-rw-r--r--library/cpp/lwtrace/mon/static/js/d3-gantt.js1518
-rw-r--r--library/cpp/lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js704
-rw-r--r--library/cpp/lwtrace/mon/static/js/d3.v4.min.js4
-rw-r--r--library/cpp/lwtrace/mon/static/js/filesaver.min.js2
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.flot.extents.js392
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.flot.min.js16
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.flot.navigate.min.js14
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.flot.selection.min.js14
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.min.js10
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js8
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.treegrid.min.js4
-rw-r--r--library/cpp/lwtrace/mon/static/js/jquery.url.min.js2
-rwxr-xr-xlibrary/cpp/lwtrace/mon/trace.sh162
-rw-r--r--library/cpp/lwtrace/mon/ya.make98
-rw-r--r--library/cpp/lwtrace/perf.cpp164
-rw-r--r--library/cpp/lwtrace/perf.h126
-rw-r--r--library/cpp/lwtrace/preprocessor.h524
-rw-r--r--library/cpp/lwtrace/probe.h512
-rw-r--r--library/cpp/lwtrace/probes.cpp6
-rw-r--r--library/cpp/lwtrace/probes.h28
-rw-r--r--library/cpp/lwtrace/protos/lwtrace.proto246
-rw-r--r--library/cpp/lwtrace/protos/ya.make4
-rw-r--r--library/cpp/lwtrace/rwspinlock.h170
-rw-r--r--library/cpp/lwtrace/shuttle.cpp40
-rw-r--r--library/cpp/lwtrace/shuttle.h572
-rw-r--r--library/cpp/lwtrace/signature.h1044
-rw-r--r--library/cpp/lwtrace/sleep_action.cpp2
-rw-r--r--library/cpp/lwtrace/sleep_action.h30
-rw-r--r--library/cpp/lwtrace/start.cpp80
-rw-r--r--library/cpp/lwtrace/start.h10
-rw-r--r--library/cpp/lwtrace/stderr_writer.cpp14
-rw-r--r--library/cpp/lwtrace/stderr_writer.h22
-rw-r--r--library/cpp/lwtrace/symbol.cpp22
-rw-r--r--library/cpp/lwtrace/symbol.h132
-rw-r--r--library/cpp/lwtrace/tests/trace_tests.cpp1404
-rw-r--r--library/cpp/lwtrace/tests/ya.make20
-rw-r--r--library/cpp/lwtrace/trace.cpp1972
-rw-r--r--library/cpp/lwtrace/trace_ut.cpp194
-rw-r--r--library/cpp/lwtrace/ut/ya.make20
-rw-r--r--library/cpp/lwtrace/ya.make26
-rw-r--r--library/cpp/monlib/counters/counters.cpp26
-rw-r--r--library/cpp/monlib/dynamic_counters/counters.cpp8
-rw-r--r--library/cpp/monlib/dynamic_counters/page.cpp10
-rw-r--r--library/cpp/monlib/service/pages/html_mon_page.cpp20
-rw-r--r--library/cpp/monlib/service/pages/mon_page.h2
-rw-r--r--library/cpp/monlib/service/pages/resource_mon_page.cpp38
-rw-r--r--library/cpp/monlib/service/pages/resource_mon_page.h4
-rw-r--r--library/cpp/monlib/service/pages/templates.h60
-rw-r--r--library/cpp/scheme/scheme.h12
-rw-r--r--library/cpp/scheme/scimpl_defs.h16
-rw-r--r--library/cpp/scheme/scimpl_protobuf.cpp60
172 files changed, 17873 insertions, 17873 deletions
diff --git a/library/cpp/actors/core/actor.cpp b/library/cpp/actors/core/actor.cpp
index 6f9ba6a42b..d46d3e9b50 100644
--- a/library/cpp/actors/core/actor.cpp
+++ b/library/cpp/actors/core/actor.cpp
@@ -1,7 +1,7 @@
#include "actor.h"
#include "executor_thread.h"
#include "mailbox.h"
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
namespace NActors {
Y_POD_THREAD(TActivationContext*)
@@ -88,7 +88,7 @@ namespace NActors {
}
i64 TActivationContext::GetCurrentEventTicks() {
- return GetCycleCountFast() - TlsActivationContext->EventStart;
+ return GetCycleCountFast() - TlsActivationContext->EventStart;
}
double TActivationContext::GetCurrentEventTicksAsSeconds() {
diff --git a/library/cpp/actors/core/actor_ut.cpp b/library/cpp/actors/core/actor_ut.cpp
index e1b765ec72..0146b5a6de 100644
--- a/library/cpp/actors/core/actor_ut.cpp
+++ b/library/cpp/actors/core/actor_ut.cpp
@@ -35,7 +35,7 @@ struct TTestEndDecorator : TDecorator {
};
Y_UNIT_TEST_SUITE(ActorBenchmark) {
- static constexpr bool DefaultNoRealtime = true;
+ static constexpr bool DefaultNoRealtime = true;
static constexpr ui32 DefaultSpinThreshold = 1000000;
static constexpr ui32 TotalEventsAmount = 1000;
@@ -43,49 +43,49 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
public:
TDummyActor() : TActor<TDummyActor>(&TDummyActor::StateFunc) {}
STFUNC(StateFunc) {
- (void)ev;
+ (void)ev;
(void)ctx;
}
};
- enum ERole {
- Leader,
- Follower
- };
-
+ enum ERole {
+ Leader,
+ Follower
+ };
+
class TSendReceiveActor : public TActorBootstrapped<TSendReceiveActor> {
public:
static constexpr auto ActorActivityType() {
return ACTORLIB_COMMON;
}
- TSendReceiveActor(double* elapsedTime, TActorId receiver, bool allocation, ERole role, ui32 neighbours = 0)
- : EventsCounter(TotalEventsAmount)
- , ElapsedTime(elapsedTime)
- , Receiver(receiver)
- , AllocatesMemory(allocation)
- , Role(role)
- , MailboxNeighboursCount(neighbours)
+ TSendReceiveActor(double* elapsedTime, TActorId receiver, bool allocation, ERole role, ui32 neighbours = 0)
+ : EventsCounter(TotalEventsAmount)
+ , ElapsedTime(elapsedTime)
+ , Receiver(receiver)
+ , AllocatesMemory(allocation)
+ , Role(role)
+ , MailboxNeighboursCount(neighbours)
{}
void Bootstrap(const TActorContext &ctx) {
if (!Receiver) {
this->Receiver = SelfId();
- } else {
- EventsCounter /= 2; // We want to measure CPU requirement for one-way send
+ } else {
+ EventsCounter /= 2; // We want to measure CPU requirement for one-way send
}
Timer.Reset();
Become(&TThis::StateFunc);
for (ui32 i = 0; i < MailboxNeighboursCount; ++i) {
ctx.RegisterWithSameMailbox(new TDummyActor());
}
- if (Role == Leader) {
- Send(Receiver, new TEvents::TEvPing());
- }
+ if (Role == Leader) {
+ Send(Receiver, new TEvents::TEvPing());
+ }
}
STATEFN(StateFunc) {
- if (EventsCounter == 0 && ElapsedTime != nullptr) {
+ if (EventsCounter == 0 && ElapsedTime != nullptr) {
*ElapsedTime = Timer.Passed() / TotalEventsAmount;
PassAway();
}
@@ -97,91 +97,91 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
ev->DropRewrite();
TActivationContext::Send(ev.Release());
}
- EventsCounter--;
+ EventsCounter--;
}
private:
THPTimer Timer;
- ui64 EventsCounter;
+ ui64 EventsCounter;
double* ElapsedTime;
TActorId Receiver;
bool AllocatesMemory;
- ERole Role;
+ ERole Role;
ui32 MailboxNeighboursCount;
};
- void AddBasicPool(THolder<TActorSystemSetup>& setup, ui32 threads, bool activateEveryEvent) {
- TBasicExecutorPoolConfig basic;
- basic.PoolId = setup->GetExecutorsCount();
- basic.PoolName = TStringBuilder() << "b" << basic.PoolId;
- basic.Threads = threads;
- basic.SpinThreshold = DefaultSpinThreshold;
- basic.TimePerMailbox = TDuration::Hours(1);
- if (activateEveryEvent) {
- basic.EventsPerMailbox = 1;
- } else {
- basic.EventsPerMailbox = Max<ui32>();
- }
- setup->CpuManager.Basic.emplace_back(std::move(basic));
- }
-
- void AddUnitedPool(THolder<TActorSystemSetup>& setup, ui32 concurrency, bool activateEveryEvent) {
- TUnitedExecutorPoolConfig united;
- united.PoolId = setup->GetExecutorsCount();
- united.PoolName = TStringBuilder() << "u" << united.PoolId;
- united.Concurrency = concurrency;
- united.TimePerMailbox = TDuration::Hours(1);
- if (activateEveryEvent) {
- united.EventsPerMailbox = 1;
- } else {
- united.EventsPerMailbox = Max<ui32>();
- }
- setup->CpuManager.United.emplace_back(std::move(united));
- }
-
- THolder<TActorSystemSetup> GetActorSystemSetup(ui32 unitedCpuCount, bool preemption) {
- auto setup = MakeHolder<NActors::TActorSystemSetup>();
- setup->NodeId = 1;
- setup->CpuManager.UnitedWorkers.CpuCount = unitedCpuCount;
- setup->CpuManager.UnitedWorkers.SpinThresholdUs = DefaultSpinThreshold;
- setup->CpuManager.UnitedWorkers.NoRealtime = DefaultNoRealtime;
- if (preemption) {
- setup->CpuManager.UnitedWorkers.PoolLimitUs = 500;
- setup->CpuManager.UnitedWorkers.EventLimitUs = 100;
- setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 100;
- } else {
- setup->CpuManager.UnitedWorkers.PoolLimitUs = 100'000'000'000;
- setup->CpuManager.UnitedWorkers.EventLimitUs = 10'000'000'000;
- setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 10'000'000'000;
- }
- setup->Scheduler = new TBasicSchedulerThread(NActors::TSchedulerConfig(512, 0));
- return setup;
- }
-
- enum class EPoolType {
- Basic,
- United
- };
-
- THolder<TActorSystemSetup> InitActorSystemSetup(EPoolType poolType, ui32 poolsCount, ui32 threads, bool activateEveryEvent, bool preemption) {
- if (poolType == EPoolType::Basic) {
- THolder<TActorSystemSetup> setup = GetActorSystemSetup(0, false);
- for (ui32 i = 0; i < poolsCount; ++i) {
- AddBasicPool(setup, threads, activateEveryEvent);
- }
- return setup;
- } else if (poolType == EPoolType::United) {
- THolder<TActorSystemSetup> setup = GetActorSystemSetup(poolsCount * threads, preemption);
- for (ui32 i = 0; i < poolsCount; ++i) {
- AddUnitedPool(setup, threads, activateEveryEvent);
- }
- return setup;
+ void AddBasicPool(THolder<TActorSystemSetup>& setup, ui32 threads, bool activateEveryEvent) {
+ TBasicExecutorPoolConfig basic;
+ basic.PoolId = setup->GetExecutorsCount();
+ basic.PoolName = TStringBuilder() << "b" << basic.PoolId;
+ basic.Threads = threads;
+ basic.SpinThreshold = DefaultSpinThreshold;
+ basic.TimePerMailbox = TDuration::Hours(1);
+ if (activateEveryEvent) {
+ basic.EventsPerMailbox = 1;
+ } else {
+ basic.EventsPerMailbox = Max<ui32>();
}
- Y_FAIL();
- }
-
- double BenchSendReceive(bool allocation, NActors::TMailboxType::EType mType, EPoolType poolType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
+ setup->CpuManager.Basic.emplace_back(std::move(basic));
+ }
+
+ void AddUnitedPool(THolder<TActorSystemSetup>& setup, ui32 concurrency, bool activateEveryEvent) {
+ TUnitedExecutorPoolConfig united;
+ united.PoolId = setup->GetExecutorsCount();
+ united.PoolName = TStringBuilder() << "u" << united.PoolId;
+ united.Concurrency = concurrency;
+ united.TimePerMailbox = TDuration::Hours(1);
+ if (activateEveryEvent) {
+ united.EventsPerMailbox = 1;
+ } else {
+ united.EventsPerMailbox = Max<ui32>();
+ }
+ setup->CpuManager.United.emplace_back(std::move(united));
+ }
+
+ THolder<TActorSystemSetup> GetActorSystemSetup(ui32 unitedCpuCount, bool preemption) {
+ auto setup = MakeHolder<NActors::TActorSystemSetup>();
+ setup->NodeId = 1;
+ setup->CpuManager.UnitedWorkers.CpuCount = unitedCpuCount;
+ setup->CpuManager.UnitedWorkers.SpinThresholdUs = DefaultSpinThreshold;
+ setup->CpuManager.UnitedWorkers.NoRealtime = DefaultNoRealtime;
+ if (preemption) {
+ setup->CpuManager.UnitedWorkers.PoolLimitUs = 500;
+ setup->CpuManager.UnitedWorkers.EventLimitUs = 100;
+ setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 100;
+ } else {
+ setup->CpuManager.UnitedWorkers.PoolLimitUs = 100'000'000'000;
+ setup->CpuManager.UnitedWorkers.EventLimitUs = 10'000'000'000;
+ setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 10'000'000'000;
+ }
+ setup->Scheduler = new TBasicSchedulerThread(NActors::TSchedulerConfig(512, 0));
+ return setup;
+ }
+
+ enum class EPoolType {
+ Basic,
+ United
+ };
+
+ THolder<TActorSystemSetup> InitActorSystemSetup(EPoolType poolType, ui32 poolsCount, ui32 threads, bool activateEveryEvent, bool preemption) {
+ if (poolType == EPoolType::Basic) {
+ THolder<TActorSystemSetup> setup = GetActorSystemSetup(0, false);
+ for (ui32 i = 0; i < poolsCount; ++i) {
+ AddBasicPool(setup, threads, activateEveryEvent);
+ }
+ return setup;
+ } else if (poolType == EPoolType::United) {
+ THolder<TActorSystemSetup> setup = GetActorSystemSetup(poolsCount * threads, preemption);
+ for (ui32 i = 0; i < poolsCount; ++i) {
+ AddUnitedPool(setup, threads, activateEveryEvent);
+ }
+ return setup;
+ }
+ Y_FAIL();
+ }
+
+ double BenchSendReceive(bool allocation, NActors::TMailboxType::EType mType, EPoolType poolType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
TActorSystem actorSystem(setup);
actorSystem.Start();
@@ -197,86 +197,86 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
pad.Park();
actorSystem.Stop();
- return 1e9 * elapsedTime;
+ return 1e9 * elapsedTime;
}
- double BenchSendActivateReceive(ui32 poolsCount, ui32 threads, bool allocation, EPoolType poolType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, poolsCount, threads, true, false);
- TActorSystem actorSystem(setup);
+ double BenchSendActivateReceive(ui32 poolsCount, ui32 threads, bool allocation, EPoolType poolType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, poolsCount, threads, true, false);
+ TActorSystem actorSystem(setup);
actorSystem.Start();
TThreadParkPad pad;
TAtomic actorsAlive = 0;
double elapsedTime = 0;
- ui32 followerPoolId = 0;
+ ui32 followerPoolId = 0;
- ui32 leaderPoolId = poolsCount == 1 ? 0 : 1;
- TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, allocation, Follower), TMailboxType::HTSwap, followerPoolId);
+ ui32 leaderPoolId = poolsCount == 1 ? 0 : 1;
+ TActorId followerId = actorSystem.Register(
+ new TSendReceiveActor(nullptr, {}, allocation, Follower), TMailboxType::HTSwap, followerPoolId);
THolder<IActor> leader{
new TTestEndDecorator(THolder(
new TSendReceiveActor(&elapsedTime, followerId, allocation, Leader)), &pad, &actorsAlive)};
- actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
-
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
+
pad.Park();
actorSystem.Stop();
- return 1e9 * elapsedTime;
+ return 1e9 * elapsedTime;
}
- double BenchSendActivateReceiveWithMailboxNeighbours(ui32 MailboxNeighbourActors, EPoolType poolType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
- TActorSystem actorSystem(setup);
+ double BenchSendActivateReceiveWithMailboxNeighbours(ui32 MailboxNeighbourActors, EPoolType poolType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
+ TActorSystem actorSystem(setup);
actorSystem.Start();
TThreadParkPad pad;
TAtomic actorsAlive = 0;
double elapsedTime = 0;
- TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, false, Follower, MailboxNeighbourActors), TMailboxType::HTSwap);
+ TActorId followerId = actorSystem.Register(
+ new TSendReceiveActor(nullptr, {}, false, Follower, MailboxNeighbourActors), TMailboxType::HTSwap);
THolder<IActor> leader{
new TTestEndDecorator(THolder(
new TSendReceiveActor(&elapsedTime, followerId, false, Leader, MailboxNeighbourActors)), &pad, &actorsAlive)};
- actorSystem.Register(leader.Release(), TMailboxType::HTSwap);
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap);
pad.Park();
actorSystem.Stop();
- return 1e9 * elapsedTime;
+ return 1e9 * elapsedTime;
}
- double BenchContentedThreads(ui32 threads, ui32 actorsPairsCount, EPoolType poolType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, threads, true, false);
- TActorSystem actorSystem(setup);
+ double BenchContentedThreads(ui32 threads, ui32 actorsPairsCount, EPoolType poolType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, threads, true, false);
+ TActorSystem actorSystem(setup);
actorSystem.Start();
TThreadParkPad pad;
TAtomic actorsAlive = 0;
THPTimer Timer;
- TVector<double> dummy(actorsPairsCount);
+ TVector<double> dummy(actorsPairsCount);
Timer.Reset();
for (ui32 i = 0; i < actorsPairsCount; ++i) {
- ui32 followerPoolId = 0;
- ui32 leaderPoolId = 0;
- TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, true, Follower), TMailboxType::HTSwap, followerPoolId);
+ ui32 followerPoolId = 0;
+ ui32 leaderPoolId = 0;
+ TActorId followerId = actorSystem.Register(
+ new TSendReceiveActor(nullptr, {}, true, Follower), TMailboxType::HTSwap, followerPoolId);
THolder<IActor> leader{
new TTestEndDecorator(THolder(
new TSendReceiveActor(&dummy[i], followerId, true, Leader)), &pad, &actorsAlive)};
- actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
}
pad.Park();
auto elapsedTime = Timer.Passed() / TotalEventsAmount;
actorSystem.Stop();
- return 1e9 * elapsedTime;
+ return 1e9 * elapsedTime;
}
auto Mean(const TVector<double>& data) {
- return Accumulate(data.begin(), data.end(), 0.0) / data.size();
+ return Accumulate(data.begin(), data.end(), 0.0) / data.size();
}
auto Deviation(const TVector<double>& data) {
@@ -285,19 +285,19 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
for (const auto& x : data) {
deviation += (x - mean) * (x - mean);
}
- return std::sqrt(deviation / data.size());
+ return std::sqrt(deviation / data.size());
}
struct TStats {
double Mean;
double Deviation;
TString ToString() {
- return TStringBuilder() << Mean << " ± " << Deviation << " ns " << std::ceil(Deviation / Mean * 1000) / 10.0 << "%";
+ return TStringBuilder() << Mean << " ± " << Deviation << " ns " << std::ceil(Deviation / Mean * 1000) / 10.0 << "%";
}
};
template <typename Func>
- TStats CountStats(Func func, ui32 itersCount = 5) {
+ TStats CountStats(Func func, ui32 itersCount = 5) {
TVector<double> elapsedTimes;
for (ui32 i = 0; i < itersCount; ++i) {
auto elapsedTime = func();
@@ -314,171 +314,171 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
TMailboxType::TinyReadAsFilled
};
- Y_UNIT_TEST(SendReceive1Pool1ThreadAlloc) {
- for (const auto& mType : MailboxTypes) {
- auto stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::Basic);
- });
- Cerr << stats.ToString() << " " << mType << Endl;
- }
- }
-
- Y_UNIT_TEST(SendReceive1Pool1ThreadAllocUnited) {
+ Y_UNIT_TEST(SendReceive1Pool1ThreadAlloc) {
for (const auto& mType : MailboxTypes) {
auto stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::United);
+ return BenchSendReceive(true, mType, EPoolType::Basic);
});
Cerr << stats.ToString() << " " << mType << Endl;
}
}
+ Y_UNIT_TEST(SendReceive1Pool1ThreadAllocUnited) {
+ for (const auto& mType : MailboxTypes) {
+ auto stats = CountStats([mType] {
+ return BenchSendReceive(true, mType, EPoolType::United);
+ });
+ Cerr << stats.ToString() << " " << mType << Endl;
+ }
+ }
+
Y_UNIT_TEST(SendReceive1Pool1ThreadNoAlloc) {
for (const auto& mType : MailboxTypes) {
auto stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::Basic);
+ return BenchSendReceive(false, mType, EPoolType::Basic);
});
Cerr << stats.ToString() << " " << mType << Endl;
}
}
-
- Y_UNIT_TEST(SendReceive1Pool1ThreadNoAllocUnited) {
- for (const auto& mType : MailboxTypes) {
- auto stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::United);
- });
- Cerr << stats.ToString() << " " << mType << Endl;
- }
- }
-
+
+ Y_UNIT_TEST(SendReceive1Pool1ThreadNoAllocUnited) {
+ for (const auto& mType : MailboxTypes) {
+ auto stats = CountStats([mType] {
+ return BenchSendReceive(false, mType, EPoolType::United);
+ });
+ Cerr << stats.ToString() << " " << mType << Endl;
+ }
+ }
+
Y_UNIT_TEST(SendActivateReceive1Pool1ThreadAlloc) {
auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 1, true, EPoolType::Basic);
- });
- Cerr << stats.ToString() << Endl;
- }
-
- Y_UNIT_TEST(SendActivateReceive1Pool1ThreadAllocUnited) {
- auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 1, true, EPoolType::United);
+ return BenchSendActivateReceive(1, 1, true, EPoolType::Basic);
});
Cerr << stats.ToString() << Endl;
}
+ Y_UNIT_TEST(SendActivateReceive1Pool1ThreadAllocUnited) {
+ auto stats = CountStats([] {
+ return BenchSendActivateReceive(1, 1, true, EPoolType::United);
+ });
+ Cerr << stats.ToString() << Endl;
+ }
+
Y_UNIT_TEST(SendActivateReceive1Pool1ThreadNoAlloc) {
auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 1, false, EPoolType::Basic);
- });
- Cerr << stats.ToString() << Endl;
- }
-
- Y_UNIT_TEST(SendActivateReceive1Pool1ThreadNoAllocUnited) {
- auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 1, false, EPoolType::United);
+ return BenchSendActivateReceive(1, 1, false, EPoolType::Basic);
});
Cerr << stats.ToString() << Endl;
}
+ Y_UNIT_TEST(SendActivateReceive1Pool1ThreadNoAllocUnited) {
+ auto stats = CountStats([] {
+ return BenchSendActivateReceive(1, 1, false, EPoolType::United);
+ });
+ Cerr << stats.ToString() << Endl;
+ }
+
Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsAlloc) {
auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 2, true, EPoolType::Basic);
- });
- Cerr << stats.ToString() << Endl;
- }
-
- Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsAllocUnited) {
- auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 2, true, EPoolType::United);
+ return BenchSendActivateReceive(1, 2, true, EPoolType::Basic);
});
Cerr << stats.ToString() << Endl;
}
+ Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsAllocUnited) {
+ auto stats = CountStats([] {
+ return BenchSendActivateReceive(1, 2, true, EPoolType::United);
+ });
+ Cerr << stats.ToString() << Endl;
+ }
+
Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsNoAlloc) {
auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 2, false, EPoolType::Basic);
- });
- Cerr << stats.ToString() << Endl;
- }
-
- Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsNoAllocUnited) {
- auto stats = CountStats([] {
- return BenchSendActivateReceive(1, 2, false, EPoolType::United);
- });
- Cerr << stats.ToString() << Endl;
- }
-
- Y_UNIT_TEST(SendActivateReceive2Pool1ThreadAlloc) {
- auto stats = CountStats([] {
- return BenchSendActivateReceive(2, 1, true, EPoolType::Basic);
- });
- Cerr << stats.ToString() << Endl;
- }
-
- Y_UNIT_TEST(SendActivateReceive2Pool1ThreadAllocUnited) {
- auto stats = CountStats([] {
- return BenchSendActivateReceive(2, 1, true, EPoolType::United);
+ return BenchSendActivateReceive(1, 2, false, EPoolType::Basic);
});
Cerr << stats.ToString() << Endl;
}
- Y_UNIT_TEST(SendActivateReceive2Pool1ThreadNoAlloc) {
+ Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsNoAllocUnited) {
auto stats = CountStats([] {
- return BenchSendActivateReceive(2, 1, false, EPoolType::Basic);
+ return BenchSendActivateReceive(1, 2, false, EPoolType::United);
});
Cerr << stats.ToString() << Endl;
}
- Y_UNIT_TEST(SendActivateReceive2Pool1ThreadNoAllocUnited) {
+ Y_UNIT_TEST(SendActivateReceive2Pool1ThreadAlloc) {
auto stats = CountStats([] {
- return BenchSendActivateReceive(2, 1, false, EPoolType::United);
+ return BenchSendActivateReceive(2, 1, true, EPoolType::Basic);
});
Cerr << stats.ToString() << Endl;
}
- void RunBenchContentedThreads(ui32 threads, EPoolType poolType) {
- for (ui32 actorPairs = 1; actorPairs <= 2 * threads; actorPairs++) {
- auto stats = CountStats([threads, actorPairs, poolType] {
- return BenchContentedThreads(threads, actorPairs, poolType);
- });
- Cerr << stats.ToString() << " actorPairs: " << actorPairs << Endl;
- }
- }
-
- Y_UNIT_TEST(SendActivateReceive1Pool1Threads) { RunBenchContentedThreads(1, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool1ThreadsUnited) { RunBenchContentedThreads(1, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool2Threads) { RunBenchContentedThreads(2, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsUnited) { RunBenchContentedThreads(2, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool3Threads) { RunBenchContentedThreads(3, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool3ThreadsUnited) { RunBenchContentedThreads(3, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool4Threads) { RunBenchContentedThreads(4, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool4ThreadsUnited) { RunBenchContentedThreads(4, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool5Threads) { RunBenchContentedThreads(5, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool5ThreadsUnited) { RunBenchContentedThreads(5, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool6Threads) { RunBenchContentedThreads(6, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool6ThreadsUnited) { RunBenchContentedThreads(6, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool7Threads) { RunBenchContentedThreads(7, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool7ThreadsUnited) { RunBenchContentedThreads(7, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool8Threads) { RunBenchContentedThreads(8, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool8ThreadsUnited) { RunBenchContentedThreads(8, EPoolType::United); }
-
+ Y_UNIT_TEST(SendActivateReceive2Pool1ThreadAllocUnited) {
+ auto stats = CountStats([] {
+ return BenchSendActivateReceive(2, 1, true, EPoolType::United);
+ });
+ Cerr << stats.ToString() << Endl;
+ }
+
+ Y_UNIT_TEST(SendActivateReceive2Pool1ThreadNoAlloc) {
+ auto stats = CountStats([] {
+ return BenchSendActivateReceive(2, 1, false, EPoolType::Basic);
+ });
+ Cerr << stats.ToString() << Endl;
+ }
+
+ Y_UNIT_TEST(SendActivateReceive2Pool1ThreadNoAllocUnited) {
+ auto stats = CountStats([] {
+ return BenchSendActivateReceive(2, 1, false, EPoolType::United);
+ });
+ Cerr << stats.ToString() << Endl;
+ }
+
+ void RunBenchContentedThreads(ui32 threads, EPoolType poolType) {
+ for (ui32 actorPairs = 1; actorPairs <= 2 * threads; actorPairs++) {
+ auto stats = CountStats([threads, actorPairs, poolType] {
+ return BenchContentedThreads(threads, actorPairs, poolType);
+ });
+ Cerr << stats.ToString() << " actorPairs: " << actorPairs << Endl;
+ }
+ }
+
+ Y_UNIT_TEST(SendActivateReceive1Pool1Threads) { RunBenchContentedThreads(1, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool1ThreadsUnited) { RunBenchContentedThreads(1, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool2Threads) { RunBenchContentedThreads(2, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsUnited) { RunBenchContentedThreads(2, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool3Threads) { RunBenchContentedThreads(3, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool3ThreadsUnited) { RunBenchContentedThreads(3, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool4Threads) { RunBenchContentedThreads(4, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool4ThreadsUnited) { RunBenchContentedThreads(4, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool5Threads) { RunBenchContentedThreads(5, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool5ThreadsUnited) { RunBenchContentedThreads(5, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool6Threads) { RunBenchContentedThreads(6, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool6ThreadsUnited) { RunBenchContentedThreads(6, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool7Threads) { RunBenchContentedThreads(7, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool7ThreadsUnited) { RunBenchContentedThreads(7, EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool8Threads) { RunBenchContentedThreads(8, EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool8ThreadsUnited) { RunBenchContentedThreads(8, EPoolType::United); }
+
Y_UNIT_TEST(SendActivateReceiveWithMailboxNeighbours) {
TVector<ui32> NeighbourActors = {0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256};
for (const auto& neighbour : NeighbourActors) {
auto stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::Basic);
- });
- Cerr << stats.ToString() << " neighbourActors: " << neighbour << Endl;
- }
- }
-
- Y_UNIT_TEST(SendActivateReceiveWithMailboxNeighboursUnited) {
- TVector<ui32> NeighbourActors = {0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256};
- for (const auto& neighbour : NeighbourActors) {
- auto stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::United);
+ return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::Basic);
});
- Cerr << stats.ToString() << " neighbourActors: " << neighbour << Endl;
+ Cerr << stats.ToString() << " neighbourActors: " << neighbour << Endl;
}
}
+
+ Y_UNIT_TEST(SendActivateReceiveWithMailboxNeighboursUnited) {
+ TVector<ui32> NeighbourActors = {0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256};
+ for (const auto& neighbour : NeighbourActors) {
+ auto stats = CountStats([neighbour] {
+ return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::United);
+ });
+ Cerr << stats.ToString() << " neighbourActors: " << neighbour << Endl;
+ }
+ }
}
Y_UNIT_TEST_SUITE(TestDecorator) {
diff --git a/library/cpp/actors/core/actorid.h b/library/cpp/actors/core/actorid.h
index d972b1a0ff..b8c41f5dd8 100644
--- a/library/cpp/actors/core/actorid.h
+++ b/library/cpp/actors/core/actorid.h
@@ -180,7 +180,7 @@ namespace NActors {
};
static_assert(sizeof(TActorId) == 16, "expect sizeof(TActorId) == 16");
- static_assert(MaxPools < TActorId::MaxPoolID); // current implementation of united pool has limit MaxPools on pool id
+ static_assert(MaxPools < TActorId::MaxPoolID); // current implementation of united pool has limit MaxPools on pool id
}
template <>
diff --git a/library/cpp/actors/core/actorsystem.cpp b/library/cpp/actors/core/actorsystem.cpp
index c58698a206..b2bed85f92 100644
--- a/library/cpp/actors/core/actorsystem.cpp
+++ b/library/cpp/actors/core/actorsystem.cpp
@@ -1,7 +1,7 @@
#include "defs.h"
#include "actorsystem.h"
#include "callstack.h"
-#include "cpu_manager.h"
+#include "cpu_manager.h"
#include "mailbox.h"
#include "events.h"
#include "interconnect.h"
@@ -9,10 +9,10 @@
#include "scheduler_queue.h"
#include "scheduler_actor.h"
#include "log.h"
-#include "probes.h"
+#include "probes.h"
#include "ask.h"
#include <library/cpp/actors/util/affinity.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <util/generic/hash.h>
#include <util/system/rwlock.h>
#include <util/random/random.h>
@@ -38,8 +38,8 @@ namespace NActors {
TActorSystem::TActorSystem(THolder<TActorSystemSetup>& setup, void* appData,
TIntrusivePtr<NLog::TSettings> loggerSettings)
: NodeId(setup->NodeId)
- , CpuManager(new TCpuManager(setup))
- , ExecutorPoolCount(CpuManager->GetExecutorsCount())
+ , CpuManager(new TCpuManager(setup))
+ , ExecutorPoolCount(CpuManager->GetExecutorsCount())
, Scheduler(setup->Scheduler)
, InterconnectCount((ui32)setup->Interconnect.ProxyActors.size())
, CurrentTimestamp(0)
@@ -105,10 +105,10 @@ namespace NActors {
Y_VERIFY_DEBUG(recipient == ev->GetRecipientRewrite());
const ui32 recpPool = recipient.PoolID();
if (recipient && recpPool < ExecutorPoolCount) {
- if (CpuManager->GetExecutorPool(recpPool)->Send(ev)) {
+ if (CpuManager->GetExecutorPool(recpPool)->Send(ev)) {
return true;
- }
- }
+ }
+ }
Send(ev->ForwardOnNondelivery(TEvents::TEvUndelivered::ReasonActorUnknown));
return false;
@@ -142,7 +142,7 @@ namespace NActors {
const TActorId& parentId) {
Y_VERIFY(executorPool < ExecutorPoolCount, "executorPool# %" PRIu32 ", ExecutorPoolCount# %" PRIu32,
(ui32)executorPool, (ui32)ExecutorPoolCount);
- return CpuManager->GetExecutorPool(executorPool)->Register(actor, mailboxType, revolvingCounter, parentId);
+ return CpuManager->GetExecutorPool(executorPool)->Register(actor, mailboxType, revolvingCounter, parentId);
}
NThreading::TFuture<THolder<IEventBase>> TActorSystem::AskGeneric(TMaybe<ui32> expectedEventType,
@@ -199,20 +199,20 @@ namespace NActors {
return ServiceMap->RegisterLocalService(serviceId, actorId);
}
- void TActorSystem::GetPoolStats(ui32 poolId, TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const {
- CpuManager->GetPoolStats(poolId, poolStats, statsCopy);
- }
-
+ void TActorSystem::GetPoolStats(ui32 poolId, TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const {
+ CpuManager->GetPoolStats(poolId, poolStats, statsCopy);
+ }
+
void TActorSystem::Start() {
Y_VERIFY(StartExecuted == false);
StartExecuted = true;
- ScheduleQueue.Reset(new NSchedulerQueue::TQueueType());
+ ScheduleQueue.Reset(new NSchedulerQueue::TQueueType());
TVector<NSchedulerQueue::TReader*> scheduleReaders;
scheduleReaders.push_back(&ScheduleQueue->Reader);
- CpuManager->PrepareStart(scheduleReaders, this);
+ CpuManager->PrepareStart(scheduleReaders, this);
Scheduler->Prepare(this, &CurrentTimestamp, &CurrentMonotonic);
- Scheduler->PrepareSchedules(&scheduleReaders.front(), (ui32)scheduleReaders.size());
+ Scheduler->PrepareSchedules(&scheduleReaders.front(), (ui32)scheduleReaders.size());
// setup interconnect proxies
{
@@ -243,7 +243,7 @@ namespace NActors {
SystemSetup.Destroy();
Scheduler->PrepareStart();
- CpuManager->Start();
+ CpuManager->Start();
Send(MakeSchedulerActorId(), new TEvSchedulerInitialize(scheduleReaders, &CurrentTimestamp, &CurrentMonotonic));
Scheduler->Start();
}
@@ -259,9 +259,9 @@ namespace NActors {
}
Scheduler->PrepareStop();
- CpuManager->PrepareStop();
+ CpuManager->PrepareStop();
Scheduler->Stop();
- CpuManager->Shutdown();
+ CpuManager->Shutdown();
}
void TActorSystem::Cleanup() {
@@ -269,7 +269,7 @@ namespace NActors {
if (CleanupExecuted || !StartExecuted)
return;
CleanupExecuted = true;
- CpuManager->Cleanup();
+ CpuManager->Cleanup();
Scheduler.Destroy();
}
diff --git a/library/cpp/actors/core/actorsystem.h b/library/cpp/actors/core/actorsystem.h
index 40499d7586..d6d88ba0c2 100644
--- a/library/cpp/actors/core/actorsystem.h
+++ b/library/cpp/actors/core/actorsystem.h
@@ -1,27 +1,27 @@
#pragma once
#include "defs.h"
-
-#include "actor.h"
-#include "balancer.h"
-#include "config.h"
+
+#include "actor.h"
+#include "balancer.h"
+#include "config.h"
#include "event.h"
#include "log_settings.h"
#include "scheduler_cookie.h"
#include "mon_stats.h"
-
+
#include <library/cpp/threading/future/future.h>
#include <library/cpp/actors/util/ticket_lock.h>
-
+
#include <util/generic/vector.h>
#include <util/datetime/base.h>
#include <util/system/mutex.h>
namespace NActors {
class TActorSystem;
- class TCpuManager;
+ class TCpuManager;
class IExecutorPool;
- struct TWorkerContext;
+ struct TWorkerContext;
inline TActorId MakeInterconnectProxyId(ui32 destNodeId) {
char data[12];
@@ -62,9 +62,9 @@ namespace NActors {
virtual ~IExecutorPool() {
}
- // for workers
- virtual ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) = 0;
- virtual void ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingCounter) = 0;
+ // for workers
+ virtual ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) = 0;
+ virtual void ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingCounter) = 0;
/**
* Schedule one-shot event that will be send at given time point in the future.
@@ -72,9 +72,9 @@ namespace NActors {
* @param deadline the wallclock time point in future when event must be send
* @param ev the event to send
* @param cookie cookie that will be piggybacked with event
- * @param workerId index of thread which will perform event dispatching
+ * @param workerId index of thread which will perform event dispatching
*/
- virtual void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) = 0;
+ virtual void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) = 0;
/**
* Schedule one-shot event that will be send at given time point in the future.
@@ -82,9 +82,9 @@ namespace NActors {
* @param deadline the monotonic time point in future when event must be send
* @param ev the event to send
* @param cookie cookie that will be piggybacked with event
- * @param workerId index of thread which will perform event dispatching
+ * @param workerId index of thread which will perform event dispatching
*/
- virtual void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) = 0;
+ virtual void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) = 0;
/**
* Schedule one-shot event that will be send after given delay.
@@ -92,9 +92,9 @@ namespace NActors {
* @param delta the time from now to delay event sending
* @param ev the event to send
* @param cookie cookie that will be piggybacked with event
- * @param workerId index of thread which will perform event dispatching
+ * @param workerId index of thread which will perform event dispatching
*/
- virtual void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) = 0;
+ virtual void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) = 0;
// for actorsystem
virtual bool Send(TAutoPtr<IEventHandle>& ev) = 0;
@@ -104,7 +104,7 @@ namespace NActors {
virtual TActorId Register(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId) = 0;
// lifecycle stuff
- virtual void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) = 0;
+ virtual void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) = 0;
virtual void Start() = 0;
virtual void PrepareStop() = 0;
virtual void Shutdown() = 0;
@@ -115,7 +115,7 @@ namespace NActors {
Y_UNUSED(poolStats);
Y_UNUSED(statsCopy);
}
-
+
virtual TString GetName() const {
return TString();
}
@@ -127,7 +127,7 @@ namespace NActors {
// generic
virtual TAffinity* Affinity() const = 0;
- virtual void SetRealTimeMode() const {}
+ virtual void SetRealTimeMode() const {}
};
// could be proxy to in-pool schedulers (for NUMA-aware executors)
@@ -137,7 +137,7 @@ namespace NActors {
}
virtual void Prepare(TActorSystem* actorSystem, volatile ui64* currentTimestamp, volatile ui64* currentMonotonic) = 0;
- virtual void PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) = 0;
+ virtual void PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) = 0;
virtual void PrepareStart() { /* empty */ }
virtual void Start() = 0;
virtual void PrepareStop() = 0;
@@ -180,14 +180,14 @@ namespace NActors {
struct TActorSystemSetup {
ui32 NodeId = 0;
- // Either Executors or CpuManager must be initialized
+ // Either Executors or CpuManager must be initialized
ui32 ExecutorsCount = 0;
TArrayHolder<TAutoPtr<IExecutorPool>> Executors;
-
- TAutoPtr<IBalancer> Balancer; // main implementation will be implicitly created if not set
-
- TCpuManagerConfig CpuManager;
-
+
+ TAutoPtr<IBalancer> Balancer; // main implementation will be implicitly created if not set
+
+ TCpuManagerConfig CpuManager;
+
TAutoPtr<ISchedulerThread> Scheduler;
ui32 MaxActivityType = 5; // for default entries
@@ -195,18 +195,18 @@ namespace NActors {
using TLocalServices = TVector<std::pair<TActorId, TActorSetupCmd>>;
TLocalServices LocalServices;
-
- ui32 GetExecutorsCount() const {
- return Executors ? ExecutorsCount : CpuManager.GetExecutorsCount();
- }
-
- TString GetPoolName(ui32 poolId) const {
- return Executors ? Executors[poolId]->GetName() : CpuManager.GetPoolName(poolId);
- }
-
- ui32 GetThreads(ui32 poolId) const {
- return Executors ? Executors[poolId]->GetThreads() : CpuManager.GetThreads(poolId);
- }
+
+ ui32 GetExecutorsCount() const {
+ return Executors ? ExecutorsCount : CpuManager.GetExecutorsCount();
+ }
+
+ TString GetPoolName(ui32 poolId) const {
+ return Executors ? Executors[poolId]->GetName() : CpuManager.GetPoolName(poolId);
+ }
+
+ ui32 GetThreads(ui32 poolId) const {
+ return Executors ? Executors[poolId]->GetThreads() : CpuManager.GetThreads(poolId);
+ }
};
class TActorSystem : TNonCopyable {
@@ -214,9 +214,9 @@ namespace NActors {
public:
const ui32 NodeId;
-
+
private:
- THolder<TCpuManager> CpuManager;
+ THolder<TCpuManager> CpuManager;
const ui32 ExecutorPoolCount;
TAutoPtr<ISchedulerThread> Scheduler;
@@ -353,7 +353,7 @@ namespace NActors {
return LoggerSettings0.Get();
}
- void GetPoolStats(ui32 poolId, TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const;
+ void GetPoolStats(ui32 poolId, TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const;
void DeferPreStop(std::function<void()> fn) {
DeferredPreStop.push_back(std::move(fn));
diff --git a/library/cpp/actors/core/balancer.cpp b/library/cpp/actors/core/balancer.cpp
index cc5417b0b5..6ee975bec1 100644
--- a/library/cpp/actors/core/balancer.cpp
+++ b/library/cpp/actors/core/balancer.cpp
@@ -1,293 +1,293 @@
-#include "balancer.h"
-
-#include "probes.h"
-
-#include <library/cpp/actors/util/intrinsics.h>
-#include <library/cpp/actors/util/datetime.h>
-
-#include <util/system/spinlock.h>
-
-#include <algorithm>
-
-namespace NActors {
- LWTRACE_USING(ACTORLIB_PROVIDER);
-
- // Describes balancing-related state of pool, the most notable is `Importance` to add new cpu
- struct TLevel {
- // Balancer will try to give more cpu to overloaded pools
- enum ELoadClass {
- Underloaded = 0,
- Moderate = 1,
- Overloaded = 2,
- };
-
- double ScaleFactor;
- ELoadClass LoadClass;
- ui64 Importance; // pool with lower importance is allowed to pass cpu to pool with higher, but the opposite is forbidden
-
- TLevel() {}
-
- TLevel(const TBalancingConfig& cfg, TPoolId poolId, ui64 currentCpus, double cpuIdle) {
- ScaleFactor = double(currentCpus) / cfg.Cpus;
- if (cpuIdle > 1.3) { // TODO: add a better underload criterion, based on estimated latency w/o 1 cpu
- LoadClass = Underloaded;
- } else if (cpuIdle < 0.2) { // TODO: add a better overload criterion, based on latency
- LoadClass = Overloaded;
- } else {
- LoadClass = Moderate;
- }
- Importance = MakeImportance(LoadClass, cfg.Priority, ScaleFactor, cpuIdle, poolId);
- }
-
- private:
- // Importance is simple ui64 value (from highest to lowest):
- // 2 Bits: LoadClass
- // 8 Bits: Priority
- // 10 Bits: -ScaleFactor (for max-min fairness with weights equal to TBalancingConfig::Cpus)
- // 10 Bits: -CpuIdle
- // 6 Bits: PoolId
- static ui64 MakeImportance(ELoadClass load, ui8 priority, double scaleFactor, double cpuIdle, TPoolId poolId) {
- ui64 idle = std::clamp<i64>(1024 - cpuIdle * 512, 0, 1023);
- ui64 scale = std::clamp<i64>(1024 - scaleFactor * 32, 0, 1023);
-
- Y_VERIFY(ui64(load) < (1ull << 2ull));
- Y_VERIFY(ui64(priority) < (1ull << 8ull));
- Y_VERIFY(ui64(scale) < (1ull << 10ull));
- Y_VERIFY(ui64(idle) < (1ull << 10ull));
- Y_VERIFY(ui64(poolId) < (1ull << 6ull));
-
- static_assert(ui64(MaxPools) <= (1ull << 6ull));
-
- ui64 importance =
- (ui64(load) << ui64(6 + 10 + 10 + 8)) |
- (ui64(priority) << ui64(6 + 10 + 10)) |
- (ui64(scale) << ui64(6 + 10)) |
- (ui64(idle) << ui64(6)) |
- ui64(poolId);
- return importance;
- }
- };
-
- // Main balancer implemenation
- class TBalancer: public IBalancer {
- private:
- struct TCpu;
- struct TPool;
-
- bool Disabled = true;
- TSpinLock Lock;
- ui64 NextBalanceTs;
- TVector<TCpu> Cpus; // Indexed by CpuId, can have gaps
- TVector<TPool> Pools; // Indexed by PoolId, can have gaps
- TBalancerConfig Config;
-
- public:
- // Setup
- TBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts);
- bool AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* cpu) override;
- ~TBalancer();
-
- // Balancing
- bool TryLock(ui64 ts) override;
- void SetPoolStats(TPoolId pool, const TBalancerStats& stats) override;
- void Balance() override;
- void Unlock() override;
-
- private:
- void MoveCpu(TPool& from, TPool& to);
- };
-
- struct TBalancer::TPool {
- TBalancingConfig Config;
- TPoolId PoolId;
- TString PoolName;
-
- // Input data for balancing
- TBalancerStats Prev;
- TBalancerStats Next;
-
- // Derived stats
- double CpuLoad;
- double CpuIdle;
-
- // Classification
- // NOTE: We want to avoid passing cpu back and forth, so we must consider not only current level,
- // NOTE: but expected levels after movements also
- TLevel CurLevel; // Level with current amount of cpu
- TLevel AddLevel; // Level after one cpu acception
- TLevel SubLevel; // Level after one cpu donation
-
- // Balancing state
- ui64 CurrentCpus = 0; // Total number of cpus assigned for this pool (zero means pools is not balanced)
- ui64 PrevCpus = 0; // Cpus in last period
-
- explicit TPool(const TBalancingConfig& cfg = {})
- : Config(cfg)
- {}
-
- void Configure(const TBalancingConfig& cfg, const TString& poolName) {
- Config = cfg;
- // Enforce constraints
- Config.MinCpus = std::clamp<ui32>(Config.MinCpus, 1, Config.Cpus);
- Config.MaxCpus = Max<ui32>(Config.MaxCpus, Config.Cpus);
- PoolName = poolName;
- }
- };
-
- struct TBalancer::TCpu {
- TCpuState* State = nullptr; // Cpu state, nullptr means cpu is not used (gap)
- TCpuAllocation Alloc;
- TPoolId Current;
- TPoolId Assigned;
- };
-
- TBalancer::TBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts)
- : NextBalanceTs(ts)
- , Config(config)
- {
- for (TPoolId pool = 0; pool < MaxPools; pool++) {
- Pools.emplace_back();
- Pools.back().PoolId = pool;
- }
- for (const TUnitedExecutorPoolConfig& united : unitedPools) {
- Pools[united.PoolId].Configure(united.Balancing, united.PoolName);
- }
- }
-
- TBalancer::~TBalancer() {
- }
-
- bool TBalancer::AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* state) {
- // Setup
- TCpuId cpuId = cpuAlloc.CpuId;
- if (Cpus.size() <= cpuId) {
- Cpus.resize(cpuId + 1);
- }
- TCpu& cpu = Cpus[cpuId];
- cpu.State = state;
- cpu.Alloc = cpuAlloc;
-
- // Fill every pool with cpus up to TBalancingConfig::Cpus
- TPoolId pool = 0;
- for (TPool& p : Pools) {
- if (p.CurrentCpus < p.Config.Cpus) {
- p.CurrentCpus++;
- break;
- }
- pool++;
- }
- if (pool != MaxPools) { // cpu under balancer control
- state->SwitchPool(pool);
- state->AssignPool(pool);
- Disabled = false;
- return true;
- }
- return false; // non-balanced cpu
- }
-
- bool TBalancer::TryLock(ui64 ts) {
- if (!Disabled && NextBalanceTs < ts && Lock.TryAcquire()) {
- NextBalanceTs = ts + Us2Ts(Config.PeriodUs);
- return true;
- }
- return false;
- }
-
- void TBalancer::SetPoolStats(TPoolId pool, const TBalancerStats& stats) {
- Y_VERIFY(pool < MaxPools);
- TPool& p = Pools[pool];
- p.Prev = p.Next;
- p.Next = stats;
- }
-
- void TBalancer::Balance() {
- // Update every cpu state
- for (TCpu& cpu : Cpus) {
- if (cpu.State) {
- cpu.State->Load(cpu.Assigned, cpu.Current);
- if (cpu.Current < MaxPools && cpu.Current != cpu.Assigned) {
- return; // previous movement has not been applied yet, wait
- }
- }
- }
-
- // Process stats, classify and compute pool importance
- TStackVec<TPool*, MaxPools> order;
- for (TPool& pool : Pools) {
- if (pool.Config.Cpus == 0) {
- continue; // skip gaps (non-existent or non-united pools)
- }
- if (pool.Prev.Ts == 0 || pool.Prev.Ts >= pool.Next.Ts) {
- return; // invalid stats
- }
-
- // Compute derived stats
- pool.CpuLoad = (pool.Next.CpuUs - pool.Prev.CpuUs) / Ts2Us(pool.Next.Ts - pool.Prev.Ts);
- if (pool.Prev.IdleUs == ui64(-1) || pool.Next.IdleUs == ui64(-1)) {
- pool.CpuIdle = pool.CurrentCpus - pool.CpuLoad; // for tests
- } else {
- pool.CpuIdle = (pool.Next.IdleUs - pool.Prev.IdleUs) / Ts2Us(pool.Next.Ts - pool.Prev.Ts);
- }
-
- // Compute levels
- pool.CurLevel = TLevel(pool.Config, pool.PoolId, pool.CurrentCpus, pool.CpuIdle);
- pool.AddLevel = TLevel(pool.Config, pool.PoolId, pool.CurrentCpus + 1, pool.CpuIdle); // we expect taken cpu to became utilized
- pool.SubLevel = TLevel(pool.Config, pool.PoolId, pool.CurrentCpus - 1, pool.CpuIdle - 1);
-
- // Prepare for balancing
- pool.PrevCpus = pool.CurrentCpus;
- order.push_back(&pool);
- }
-
- // Sort pools by importance
- std::sort(order.begin(), order.end(), [] (TPool* l, TPool* r) {return l->CurLevel.Importance < r->CurLevel.Importance; });
- for (TPool* pool : order) {
- LWPROBE(PoolStats, pool->PoolId, pool->PoolName, pool->CurrentCpus, pool->CurLevel.LoadClass, pool->Config.Priority, pool->CurLevel.ScaleFactor, pool->CpuIdle, pool->CpuLoad, pool->CurLevel.Importance, pool->AddLevel.Importance, pool->SubLevel.Importance);
- }
-
- // Move cpus from lower importance to higher importance pools
- for (auto toIter = order.rbegin(); toIter != order.rend(); ++toIter) {
- TPool& to = **toIter;
- if (to.CurLevel.LoadClass == TLevel::Overloaded && // if pool is overloaded
- to.CurrentCpus < to.Config.MaxCpus) // and constraints would not be violated
- {
- for (auto fromIter = order.begin(); (*fromIter)->CurLevel.Importance < to.CurLevel.Importance; ++fromIter) {
- TPool& from = **fromIter;
- if (from.CurrentCpus == from.PrevCpus && // if not balanced yet
- from.CurrentCpus > from.Config.MinCpus && // and constraints would not be violated
- from.SubLevel.Importance < to.AddLevel.Importance) // and which of two pools is more important would not change after cpu movement
- {
- MoveCpu(from, to);
- from.CurrentCpus--;
- to.CurrentCpus++;
- break;
- }
- }
- }
- }
- }
-
- void TBalancer::MoveCpu(TBalancer::TPool& from, TBalancer::TPool& to) {
- for (auto ci = Cpus.rbegin(), ce = Cpus.rend(); ci != ce; ci++) {
- TCpu& cpu = *ci;
- if (!cpu.State) {
- continue;
- }
- if (cpu.Assigned == from.PoolId) {
- cpu.State->AssignPool(to.PoolId);
- cpu.Assigned = to.PoolId;
- LWPROBE(MoveCpu, from.PoolId, to.PoolId, from.PoolName, to.PoolName, cpu.Alloc.CpuId);
- return;
- }
- }
- Y_FAIL();
- }
-
- void TBalancer::Unlock() {
- Lock.Release();
- }
-
- IBalancer* MakeBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts) {
- return new TBalancer(config, unitedPools, ts);
- }
-}
+#include "balancer.h"
+
+#include "probes.h"
+
+#include <library/cpp/actors/util/intrinsics.h>
+#include <library/cpp/actors/util/datetime.h>
+
+#include <util/system/spinlock.h>
+
+#include <algorithm>
+
+namespace NActors {
+ LWTRACE_USING(ACTORLIB_PROVIDER);
+
+ // Describes balancing-related state of pool, the most notable is `Importance` to add new cpu
+ struct TLevel {
+ // Balancer will try to give more cpu to overloaded pools
+ enum ELoadClass {
+ Underloaded = 0,
+ Moderate = 1,
+ Overloaded = 2,
+ };
+
+ double ScaleFactor;
+ ELoadClass LoadClass;
+ ui64 Importance; // pool with lower importance is allowed to pass cpu to pool with higher, but the opposite is forbidden
+
+ TLevel() {}
+
+ TLevel(const TBalancingConfig& cfg, TPoolId poolId, ui64 currentCpus, double cpuIdle) {
+ ScaleFactor = double(currentCpus) / cfg.Cpus;
+ if (cpuIdle > 1.3) { // TODO: add a better underload criterion, based on estimated latency w/o 1 cpu
+ LoadClass = Underloaded;
+ } else if (cpuIdle < 0.2) { // TODO: add a better overload criterion, based on latency
+ LoadClass = Overloaded;
+ } else {
+ LoadClass = Moderate;
+ }
+ Importance = MakeImportance(LoadClass, cfg.Priority, ScaleFactor, cpuIdle, poolId);
+ }
+
+ private:
+ // Importance is simple ui64 value (from highest to lowest):
+ // 2 Bits: LoadClass
+ // 8 Bits: Priority
+ // 10 Bits: -ScaleFactor (for max-min fairness with weights equal to TBalancingConfig::Cpus)
+ // 10 Bits: -CpuIdle
+ // 6 Bits: PoolId
+ static ui64 MakeImportance(ELoadClass load, ui8 priority, double scaleFactor, double cpuIdle, TPoolId poolId) {
+ ui64 idle = std::clamp<i64>(1024 - cpuIdle * 512, 0, 1023);
+ ui64 scale = std::clamp<i64>(1024 - scaleFactor * 32, 0, 1023);
+
+ Y_VERIFY(ui64(load) < (1ull << 2ull));
+ Y_VERIFY(ui64(priority) < (1ull << 8ull));
+ Y_VERIFY(ui64(scale) < (1ull << 10ull));
+ Y_VERIFY(ui64(idle) < (1ull << 10ull));
+ Y_VERIFY(ui64(poolId) < (1ull << 6ull));
+
+ static_assert(ui64(MaxPools) <= (1ull << 6ull));
+
+ ui64 importance =
+ (ui64(load) << ui64(6 + 10 + 10 + 8)) |
+ (ui64(priority) << ui64(6 + 10 + 10)) |
+ (ui64(scale) << ui64(6 + 10)) |
+ (ui64(idle) << ui64(6)) |
+ ui64(poolId);
+ return importance;
+ }
+ };
+
+ // Main balancer implemenation
+ class TBalancer: public IBalancer {
+ private:
+ struct TCpu;
+ struct TPool;
+
+ bool Disabled = true;
+ TSpinLock Lock;
+ ui64 NextBalanceTs;
+ TVector<TCpu> Cpus; // Indexed by CpuId, can have gaps
+ TVector<TPool> Pools; // Indexed by PoolId, can have gaps
+ TBalancerConfig Config;
+
+ public:
+ // Setup
+ TBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts);
+ bool AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* cpu) override;
+ ~TBalancer();
+
+ // Balancing
+ bool TryLock(ui64 ts) override;
+ void SetPoolStats(TPoolId pool, const TBalancerStats& stats) override;
+ void Balance() override;
+ void Unlock() override;
+
+ private:
+ void MoveCpu(TPool& from, TPool& to);
+ };
+
+ struct TBalancer::TPool {
+ TBalancingConfig Config;
+ TPoolId PoolId;
+ TString PoolName;
+
+ // Input data for balancing
+ TBalancerStats Prev;
+ TBalancerStats Next;
+
+ // Derived stats
+ double CpuLoad;
+ double CpuIdle;
+
+ // Classification
+ // NOTE: We want to avoid passing cpu back and forth, so we must consider not only current level,
+ // NOTE: but expected levels after movements also
+ TLevel CurLevel; // Level with current amount of cpu
+ TLevel AddLevel; // Level after one cpu acception
+ TLevel SubLevel; // Level after one cpu donation
+
+ // Balancing state
+ ui64 CurrentCpus = 0; // Total number of cpus assigned for this pool (zero means pools is not balanced)
+ ui64 PrevCpus = 0; // Cpus in last period
+
+ explicit TPool(const TBalancingConfig& cfg = {})
+ : Config(cfg)
+ {}
+
+ void Configure(const TBalancingConfig& cfg, const TString& poolName) {
+ Config = cfg;
+ // Enforce constraints
+ Config.MinCpus = std::clamp<ui32>(Config.MinCpus, 1, Config.Cpus);
+ Config.MaxCpus = Max<ui32>(Config.MaxCpus, Config.Cpus);
+ PoolName = poolName;
+ }
+ };
+
+ struct TBalancer::TCpu {
+ TCpuState* State = nullptr; // Cpu state, nullptr means cpu is not used (gap)
+ TCpuAllocation Alloc;
+ TPoolId Current;
+ TPoolId Assigned;
+ };
+
+ TBalancer::TBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts)
+ : NextBalanceTs(ts)
+ , Config(config)
+ {
+ for (TPoolId pool = 0; pool < MaxPools; pool++) {
+ Pools.emplace_back();
+ Pools.back().PoolId = pool;
+ }
+ for (const TUnitedExecutorPoolConfig& united : unitedPools) {
+ Pools[united.PoolId].Configure(united.Balancing, united.PoolName);
+ }
+ }
+
+ TBalancer::~TBalancer() {
+ }
+
+ bool TBalancer::AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* state) {
+ // Setup
+ TCpuId cpuId = cpuAlloc.CpuId;
+ if (Cpus.size() <= cpuId) {
+ Cpus.resize(cpuId + 1);
+ }
+ TCpu& cpu = Cpus[cpuId];
+ cpu.State = state;
+ cpu.Alloc = cpuAlloc;
+
+ // Fill every pool with cpus up to TBalancingConfig::Cpus
+ TPoolId pool = 0;
+ for (TPool& p : Pools) {
+ if (p.CurrentCpus < p.Config.Cpus) {
+ p.CurrentCpus++;
+ break;
+ }
+ pool++;
+ }
+ if (pool != MaxPools) { // cpu under balancer control
+ state->SwitchPool(pool);
+ state->AssignPool(pool);
+ Disabled = false;
+ return true;
+ }
+ return false; // non-balanced cpu
+ }
+
+ bool TBalancer::TryLock(ui64 ts) {
+ if (!Disabled && NextBalanceTs < ts && Lock.TryAcquire()) {
+ NextBalanceTs = ts + Us2Ts(Config.PeriodUs);
+ return true;
+ }
+ return false;
+ }
+
+ void TBalancer::SetPoolStats(TPoolId pool, const TBalancerStats& stats) {
+ Y_VERIFY(pool < MaxPools);
+ TPool& p = Pools[pool];
+ p.Prev = p.Next;
+ p.Next = stats;
+ }
+
+ void TBalancer::Balance() {
+ // Update every cpu state
+ for (TCpu& cpu : Cpus) {
+ if (cpu.State) {
+ cpu.State->Load(cpu.Assigned, cpu.Current);
+ if (cpu.Current < MaxPools && cpu.Current != cpu.Assigned) {
+ return; // previous movement has not been applied yet, wait
+ }
+ }
+ }
+
+ // Process stats, classify and compute pool importance
+ TStackVec<TPool*, MaxPools> order;
+ for (TPool& pool : Pools) {
+ if (pool.Config.Cpus == 0) {
+ continue; // skip gaps (non-existent or non-united pools)
+ }
+ if (pool.Prev.Ts == 0 || pool.Prev.Ts >= pool.Next.Ts) {
+ return; // invalid stats
+ }
+
+ // Compute derived stats
+ pool.CpuLoad = (pool.Next.CpuUs - pool.Prev.CpuUs) / Ts2Us(pool.Next.Ts - pool.Prev.Ts);
+ if (pool.Prev.IdleUs == ui64(-1) || pool.Next.IdleUs == ui64(-1)) {
+ pool.CpuIdle = pool.CurrentCpus - pool.CpuLoad; // for tests
+ } else {
+ pool.CpuIdle = (pool.Next.IdleUs - pool.Prev.IdleUs) / Ts2Us(pool.Next.Ts - pool.Prev.Ts);
+ }
+
+ // Compute levels
+ pool.CurLevel = TLevel(pool.Config, pool.PoolId, pool.CurrentCpus, pool.CpuIdle);
+ pool.AddLevel = TLevel(pool.Config, pool.PoolId, pool.CurrentCpus + 1, pool.CpuIdle); // we expect taken cpu to became utilized
+ pool.SubLevel = TLevel(pool.Config, pool.PoolId, pool.CurrentCpus - 1, pool.CpuIdle - 1);
+
+ // Prepare for balancing
+ pool.PrevCpus = pool.CurrentCpus;
+ order.push_back(&pool);
+ }
+
+ // Sort pools by importance
+ std::sort(order.begin(), order.end(), [] (TPool* l, TPool* r) {return l->CurLevel.Importance < r->CurLevel.Importance; });
+ for (TPool* pool : order) {
+ LWPROBE(PoolStats, pool->PoolId, pool->PoolName, pool->CurrentCpus, pool->CurLevel.LoadClass, pool->Config.Priority, pool->CurLevel.ScaleFactor, pool->CpuIdle, pool->CpuLoad, pool->CurLevel.Importance, pool->AddLevel.Importance, pool->SubLevel.Importance);
+ }
+
+ // Move cpus from lower importance to higher importance pools
+ for (auto toIter = order.rbegin(); toIter != order.rend(); ++toIter) {
+ TPool& to = **toIter;
+ if (to.CurLevel.LoadClass == TLevel::Overloaded && // if pool is overloaded
+ to.CurrentCpus < to.Config.MaxCpus) // and constraints would not be violated
+ {
+ for (auto fromIter = order.begin(); (*fromIter)->CurLevel.Importance < to.CurLevel.Importance; ++fromIter) {
+ TPool& from = **fromIter;
+ if (from.CurrentCpus == from.PrevCpus && // if not balanced yet
+ from.CurrentCpus > from.Config.MinCpus && // and constraints would not be violated
+ from.SubLevel.Importance < to.AddLevel.Importance) // and which of two pools is more important would not change after cpu movement
+ {
+ MoveCpu(from, to);
+ from.CurrentCpus--;
+ to.CurrentCpus++;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ void TBalancer::MoveCpu(TBalancer::TPool& from, TBalancer::TPool& to) {
+ for (auto ci = Cpus.rbegin(), ce = Cpus.rend(); ci != ce; ci++) {
+ TCpu& cpu = *ci;
+ if (!cpu.State) {
+ continue;
+ }
+ if (cpu.Assigned == from.PoolId) {
+ cpu.State->AssignPool(to.PoolId);
+ cpu.Assigned = to.PoolId;
+ LWPROBE(MoveCpu, from.PoolId, to.PoolId, from.PoolName, to.PoolName, cpu.Alloc.CpuId);
+ return;
+ }
+ }
+ Y_FAIL();
+ }
+
+ void TBalancer::Unlock() {
+ Lock.Release();
+ }
+
+ IBalancer* MakeBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts) {
+ return new TBalancer(config, unitedPools, ts);
+ }
+}
diff --git a/library/cpp/actors/core/balancer.h b/library/cpp/actors/core/balancer.h
index 9763ec79e1..cf4ea776f0 100644
--- a/library/cpp/actors/core/balancer.h
+++ b/library/cpp/actors/core/balancer.h
@@ -1,27 +1,27 @@
-#pragma once
-
-#include "defs.h"
-#include "config.h"
-#include "cpu_state.h"
-
-namespace NActors {
- // Per-pool statistics used by balancer
- struct TBalancerStats {
- ui64 Ts = 0; // Measurement timestamp
- ui64 CpuUs = 0; // Total cpu microseconds consumed by pool on all cpus since start
- ui64 IdleUs = ui64(-1); // Total cpu microseconds in spinning or waiting on futex
- };
-
- // Pool cpu balancer
- struct IBalancer {
- virtual ~IBalancer() {}
- virtual bool AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* cpu) = 0;
- virtual bool TryLock(ui64 ts) = 0;
- virtual void SetPoolStats(TPoolId pool, const TBalancerStats& stats) = 0;
- virtual void Balance() = 0;
- virtual void Unlock() = 0;
- // TODO: add method for reconfiguration on fly
- };
-
- IBalancer* MakeBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts);
-}
+#pragma once
+
+#include "defs.h"
+#include "config.h"
+#include "cpu_state.h"
+
+namespace NActors {
+ // Per-pool statistics used by balancer
+ struct TBalancerStats {
+ ui64 Ts = 0; // Measurement timestamp
+ ui64 CpuUs = 0; // Total cpu microseconds consumed by pool on all cpus since start
+ ui64 IdleUs = ui64(-1); // Total cpu microseconds in spinning or waiting on futex
+ };
+
+ // Pool cpu balancer
+ struct IBalancer {
+ virtual ~IBalancer() {}
+ virtual bool AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* cpu) = 0;
+ virtual bool TryLock(ui64 ts) = 0;
+ virtual void SetPoolStats(TPoolId pool, const TBalancerStats& stats) = 0;
+ virtual void Balance() = 0;
+ virtual void Unlock() = 0;
+ // TODO: add method for reconfiguration on fly
+ };
+
+ IBalancer* MakeBalancer(const TBalancerConfig& config, const TVector<TUnitedExecutorPoolConfig>& unitedPools, ui64 ts);
+}
diff --git a/library/cpp/actors/core/balancer_ut.cpp b/library/cpp/actors/core/balancer_ut.cpp
index 7e5e95f4b9..ac4ebdccb3 100644
--- a/library/cpp/actors/core/balancer_ut.cpp
+++ b/library/cpp/actors/core/balancer_ut.cpp
@@ -1,225 +1,225 @@
-#include "balancer.h"
-
-#include <library/cpp/actors/util/datetime.h>
-#include <library/cpp/lwtrace/all.h>
-#include <library/cpp/testing/unittest/registar.h>
-
-#include <util/stream/str.h>
-
-using namespace NActors;
-
-////////////////////////////////////////////////////////////////////////////////
-
-Y_UNIT_TEST_SUITE(PoolCpuBalancer) {
- struct TTest {
- TCpuManagerConfig Config;
- TCpuMask Available;
- THolder<IBalancer> Balancer;
- TVector<TCpuState> CpuStates;
- TVector<ui64> CpuUs;
- ui64 Now = 0;
-
- void SetCpuCount(size_t count) {
- Config.UnitedWorkers.CpuCount = count;
- for (TCpuId cpuId = 0; cpuId < count; cpuId++) {
- Available.Set(cpuId);
- }
- }
-
- void AddPool(ui32 minCpus, ui32 cpus, ui32 maxCpus, ui8 priority = 0) {
- TUnitedExecutorPoolConfig u;
- u.PoolId = TPoolId(Config.United.size());
- u.Balancing.Cpus = cpus;
- u.Balancing.MinCpus = minCpus;
- u.Balancing.MaxCpus = maxCpus;
- u.Balancing.Priority = priority;
- Config.United.push_back(u);
- }
-
- void Start() {
- TCpuAllocationConfig allocation(Available, Config);
- Balancer.Reset(MakeBalancer(Config.UnitedWorkers.Balancer, Config.United, 0));
- CpuStates.resize(allocation.Items.size()); // do not resize it later to avoid dangling pointers
- CpuUs.resize(CpuStates.size());
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- bool added = Balancer->AddCpu(cpuAlloc, &CpuStates[cpuAlloc.CpuId]);
- UNIT_ASSERT(added);
- }
- }
-
- void Balance(ui64 deltaTs, const TVector<ui64>& cpuUs) {
- Now += deltaTs;
- ui64 ts = Now;
- if (Balancer->TryLock(ts)) {
- for (TPoolId pool = 0; pool < cpuUs.size(); pool++) {
- CpuUs[pool] += cpuUs[pool];
- TBalancerStats stats;
- stats.Ts = ts;
- stats.CpuUs = CpuUs[pool];
- Balancer->SetPoolStats(pool, stats);
- }
- Balancer->Balance();
- Balancer->Unlock();
- }
- }
-
- void ApplyMovements() {
- for (TCpuState& state : CpuStates) {
- TPoolId current;
- TPoolId assigned;
- state.Load(assigned, current);
- state.SwitchPool(assigned);
- }
- }
-
- static TString ToStr(const TVector<ui64>& values) {
- TStringStream ss;
- ss << "{";
- for (auto v : values) {
- ss << " " << v;
- }
- ss << " }";
- return ss.Str();
- }
-
- void AssertPoolsCurrentCpus(const TVector<ui64>& cpuRequired) {
- TVector<ui64> cpuCurrent;
- cpuCurrent.resize(cpuRequired.size());
- for (TCpuState& state : CpuStates) {
- TPoolId current;
- TPoolId assigned;
- state.Load(assigned, current);
- cpuCurrent[current]++;
- }
- for (TPoolId pool = 0; pool < cpuRequired.size(); pool++) {
- UNIT_ASSERT_C(cpuCurrent[pool] == cpuRequired[pool],
- "cpu distribution mismatch, required " << ToStr(cpuRequired) << " but got " << ToStr(cpuCurrent));
- }
- }
- };
-
- Y_UNIT_TEST(StartLwtrace) {
- NLWTrace::StartLwtraceFromEnv();
- }
-
- Y_UNIT_TEST(AllOverloaded) {
- TTest t;
- int cpus = 10;
- t.SetCpuCount(cpus);
- t.AddPool(1, 1, 10); // pool=0
- t.AddPool(1, 2, 10); // pool=1
- t.AddPool(1, 3, 10); // pool=2
- t.AddPool(1, 4, 10); // pool=2
- t.Start();
- ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
- ui64 totalCpuUs = cpus * Ts2Us(dts); // pretend every pool has consumed as whole actorsystem, overload
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {totalCpuUs, totalCpuUs, totalCpuUs, totalCpuUs});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 2, 3, 4});
- }
-
- Y_UNIT_TEST(OneOverloaded) {
- TTest t;
- int cpus = 10;
- t.SetCpuCount(cpus);
- t.AddPool(1, 1, 10); // pool=0
- t.AddPool(1, 2, 10); // pool=1
- t.AddPool(1, 3, 10); // pool=2
- t.AddPool(1, 4, 10); // pool=2
- t.Start();
- ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
- ui64 totalCpuUs = cpus * Ts2Us(dts);
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {totalCpuUs, 0, 0, 0});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({7, 1, 1, 1});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {0, totalCpuUs, 0, 0});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 7, 1, 1});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {0, 0, totalCpuUs, 0});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 1, 7, 1});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {0, 0, 0, totalCpuUs});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 1, 1, 7});
- }
-
- Y_UNIT_TEST(TwoOverloadedFairness) {
- TTest t;
- int cpus = 10;
- t.SetCpuCount(cpus);
- t.AddPool(1, 1, 10); // pool=0
- t.AddPool(1, 2, 10); // pool=1
- t.AddPool(1, 3, 10); // pool=2
- t.AddPool(1, 4, 10); // pool=2
- t.Start();
- ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
- ui64 totalCpuUs = cpus * Ts2Us(dts);
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {totalCpuUs, totalCpuUs, 0, 0});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({3, 5, 1, 1});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {totalCpuUs, 0, totalCpuUs, 0});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({2, 1, 6, 1});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {totalCpuUs, 0, 0, totalCpuUs});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({2, 1, 1, 6});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {0, totalCpuUs, totalCpuUs, 0});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 3, 5, 1});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {0, totalCpuUs, 0, totalCpuUs});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 3, 1, 5});
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {0, 0, totalCpuUs, totalCpuUs});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({1, 1, 3, 5});
- }
-
- Y_UNIT_TEST(TwoOverloadedPriority) {
- TTest t;
- int cpus = 20;
- t.SetCpuCount(cpus);
- t.AddPool(1, 5, 20, 0); // pool=0
- t.AddPool(1, 5, 20, 1); // pool=1
- t.AddPool(1, 5, 20, 2); // pool=2
- t.AddPool(1, 5, 20, 3); // pool=3
- t.Start();
- ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
- ui64 mErlang = Ts2Us(dts) / 1000;
- for (int i = 0; i < cpus; i++) {
- t.Balance(dts, {20000 * mErlang, 2500 * mErlang, 4500 * mErlang, 9500 * mErlang});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({2, 3, 5, 10});
- t.Balance(dts, {20000 * mErlang, 2500 * mErlang, 4500 * mErlang, 8500 * mErlang});
- t.ApplyMovements();
- t.AssertPoolsCurrentCpus({3, 3, 5, 9});
- // NOTE: this operation require one move, but we do not make global analysis, so multiple steps (1->2 & 0->1) are required (can be optimized later)
- for (int i = 0; i < 3; i++) {
- t.Balance(dts, {20000 * mErlang, 2500 * mErlang, 5500 * mErlang, 8500 * mErlang});
- t.ApplyMovements();
- }
- t.AssertPoolsCurrentCpus({2, 3, 6, 9});
- }
-}
+#include "balancer.h"
+
+#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/lwtrace/all.h>
+#include <library/cpp/testing/unittest/registar.h>
+
+#include <util/stream/str.h>
+
+using namespace NActors;
+
+////////////////////////////////////////////////////////////////////////////////
+
+Y_UNIT_TEST_SUITE(PoolCpuBalancer) {
+ struct TTest {
+ TCpuManagerConfig Config;
+ TCpuMask Available;
+ THolder<IBalancer> Balancer;
+ TVector<TCpuState> CpuStates;
+ TVector<ui64> CpuUs;
+ ui64 Now = 0;
+
+ void SetCpuCount(size_t count) {
+ Config.UnitedWorkers.CpuCount = count;
+ for (TCpuId cpuId = 0; cpuId < count; cpuId++) {
+ Available.Set(cpuId);
+ }
+ }
+
+ void AddPool(ui32 minCpus, ui32 cpus, ui32 maxCpus, ui8 priority = 0) {
+ TUnitedExecutorPoolConfig u;
+ u.PoolId = TPoolId(Config.United.size());
+ u.Balancing.Cpus = cpus;
+ u.Balancing.MinCpus = minCpus;
+ u.Balancing.MaxCpus = maxCpus;
+ u.Balancing.Priority = priority;
+ Config.United.push_back(u);
+ }
+
+ void Start() {
+ TCpuAllocationConfig allocation(Available, Config);
+ Balancer.Reset(MakeBalancer(Config.UnitedWorkers.Balancer, Config.United, 0));
+ CpuStates.resize(allocation.Items.size()); // do not resize it later to avoid dangling pointers
+ CpuUs.resize(CpuStates.size());
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ bool added = Balancer->AddCpu(cpuAlloc, &CpuStates[cpuAlloc.CpuId]);
+ UNIT_ASSERT(added);
+ }
+ }
+
+ void Balance(ui64 deltaTs, const TVector<ui64>& cpuUs) {
+ Now += deltaTs;
+ ui64 ts = Now;
+ if (Balancer->TryLock(ts)) {
+ for (TPoolId pool = 0; pool < cpuUs.size(); pool++) {
+ CpuUs[pool] += cpuUs[pool];
+ TBalancerStats stats;
+ stats.Ts = ts;
+ stats.CpuUs = CpuUs[pool];
+ Balancer->SetPoolStats(pool, stats);
+ }
+ Balancer->Balance();
+ Balancer->Unlock();
+ }
+ }
+
+ void ApplyMovements() {
+ for (TCpuState& state : CpuStates) {
+ TPoolId current;
+ TPoolId assigned;
+ state.Load(assigned, current);
+ state.SwitchPool(assigned);
+ }
+ }
+
+ static TString ToStr(const TVector<ui64>& values) {
+ TStringStream ss;
+ ss << "{";
+ for (auto v : values) {
+ ss << " " << v;
+ }
+ ss << " }";
+ return ss.Str();
+ }
+
+ void AssertPoolsCurrentCpus(const TVector<ui64>& cpuRequired) {
+ TVector<ui64> cpuCurrent;
+ cpuCurrent.resize(cpuRequired.size());
+ for (TCpuState& state : CpuStates) {
+ TPoolId current;
+ TPoolId assigned;
+ state.Load(assigned, current);
+ cpuCurrent[current]++;
+ }
+ for (TPoolId pool = 0; pool < cpuRequired.size(); pool++) {
+ UNIT_ASSERT_C(cpuCurrent[pool] == cpuRequired[pool],
+ "cpu distribution mismatch, required " << ToStr(cpuRequired) << " but got " << ToStr(cpuCurrent));
+ }
+ }
+ };
+
+ Y_UNIT_TEST(StartLwtrace) {
+ NLWTrace::StartLwtraceFromEnv();
+ }
+
+ Y_UNIT_TEST(AllOverloaded) {
+ TTest t;
+ int cpus = 10;
+ t.SetCpuCount(cpus);
+ t.AddPool(1, 1, 10); // pool=0
+ t.AddPool(1, 2, 10); // pool=1
+ t.AddPool(1, 3, 10); // pool=2
+ t.AddPool(1, 4, 10); // pool=2
+ t.Start();
+ ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
+ ui64 totalCpuUs = cpus * Ts2Us(dts); // pretend every pool has consumed as whole actorsystem, overload
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {totalCpuUs, totalCpuUs, totalCpuUs, totalCpuUs});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 2, 3, 4});
+ }
+
+ Y_UNIT_TEST(OneOverloaded) {
+ TTest t;
+ int cpus = 10;
+ t.SetCpuCount(cpus);
+ t.AddPool(1, 1, 10); // pool=0
+ t.AddPool(1, 2, 10); // pool=1
+ t.AddPool(1, 3, 10); // pool=2
+ t.AddPool(1, 4, 10); // pool=2
+ t.Start();
+ ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
+ ui64 totalCpuUs = cpus * Ts2Us(dts);
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {totalCpuUs, 0, 0, 0});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({7, 1, 1, 1});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {0, totalCpuUs, 0, 0});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 7, 1, 1});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {0, 0, totalCpuUs, 0});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 1, 7, 1});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {0, 0, 0, totalCpuUs});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 1, 1, 7});
+ }
+
+ Y_UNIT_TEST(TwoOverloadedFairness) {
+ TTest t;
+ int cpus = 10;
+ t.SetCpuCount(cpus);
+ t.AddPool(1, 1, 10); // pool=0
+ t.AddPool(1, 2, 10); // pool=1
+ t.AddPool(1, 3, 10); // pool=2
+ t.AddPool(1, 4, 10); // pool=2
+ t.Start();
+ ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
+ ui64 totalCpuUs = cpus * Ts2Us(dts);
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {totalCpuUs, totalCpuUs, 0, 0});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({3, 5, 1, 1});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {totalCpuUs, 0, totalCpuUs, 0});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({2, 1, 6, 1});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {totalCpuUs, 0, 0, totalCpuUs});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({2, 1, 1, 6});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {0, totalCpuUs, totalCpuUs, 0});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 3, 5, 1});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {0, totalCpuUs, 0, totalCpuUs});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 3, 1, 5});
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {0, 0, totalCpuUs, totalCpuUs});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({1, 1, 3, 5});
+ }
+
+ Y_UNIT_TEST(TwoOverloadedPriority) {
+ TTest t;
+ int cpus = 20;
+ t.SetCpuCount(cpus);
+ t.AddPool(1, 5, 20, 0); // pool=0
+ t.AddPool(1, 5, 20, 1); // pool=1
+ t.AddPool(1, 5, 20, 2); // pool=2
+ t.AddPool(1, 5, 20, 3); // pool=3
+ t.Start();
+ ui64 dts = 1.01 * Us2Ts(t.Config.UnitedWorkers.Balancer.PeriodUs);
+ ui64 mErlang = Ts2Us(dts) / 1000;
+ for (int i = 0; i < cpus; i++) {
+ t.Balance(dts, {20000 * mErlang, 2500 * mErlang, 4500 * mErlang, 9500 * mErlang});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({2, 3, 5, 10});
+ t.Balance(dts, {20000 * mErlang, 2500 * mErlang, 4500 * mErlang, 8500 * mErlang});
+ t.ApplyMovements();
+ t.AssertPoolsCurrentCpus({3, 3, 5, 9});
+ // NOTE: this operation require one move, but we do not make global analysis, so multiple steps (1->2 & 0->1) are required (can be optimized later)
+ for (int i = 0; i < 3; i++) {
+ t.Balance(dts, {20000 * mErlang, 2500 * mErlang, 5500 * mErlang, 8500 * mErlang});
+ t.ApplyMovements();
+ }
+ t.AssertPoolsCurrentCpus({2, 3, 6, 9});
+ }
+}
diff --git a/library/cpp/actors/core/config.h b/library/cpp/actors/core/config.h
index 2486bf4c43..750bdd3a07 100644
--- a/library/cpp/actors/core/config.h
+++ b/library/cpp/actors/core/config.h
@@ -1,239 +1,239 @@
-#pragma once
-
-#include "defs.h"
-#include <library/cpp/actors/util/cpumask.h>
-#include <library/cpp/monlib/dynamic_counters/counters.h>
-#include <util/datetime/base.h>
-#include <util/generic/ptr.h>
-#include <util/generic/string.h>
-#include <util/generic/vector.h>
-
-namespace NActors {
-
- struct TBalancingConfig {
- // Default cpu count (used during overload). Zero value disables this pool balancing
- // 1) Sum of `Cpus` on all pools cannot be changed without restart
- // (changing cpu mode between Shared and Assigned is not implemented yet)
- // 2) This sum must be equal to TUnitedWorkersConfig::CpuCount,
- // otherwise `CpuCount - SUM(Cpus)` cpus will be in Shared mode (i.e. actorsystem 2.0)
- ui32 Cpus = 0;
-
- ui32 MinCpus = 0; // Lower balancing bound, should be at least 1, and not greater than `Cpus`
- ui32 MaxCpus = 0; // Higher balancing bound, should be not lower than `Cpus`
- ui8 Priority = 0; // Priority of pool to obtain cpu due to balancing (higher is better)
- ui64 ToleratedLatencyUs = 0; // p100-latency threshold indicating that more cpus are required by pool
- };
-
- struct TBalancerConfig {
- ui64 PeriodUs = 15000000; // Time between balancer steps
- };
-
- struct TBasicExecutorPoolConfig {
- static constexpr TDuration DEFAULT_TIME_PER_MAILBOX = TDuration::MilliSeconds(10);
- static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = 100;
-
- ui32 PoolId = 0;
- TString PoolName;
- ui32 Threads = 1;
- ui64 SpinThreshold = 100;
- TCpuMask Affinity; // Executor thread affinity
- TDuration TimePerMailbox = DEFAULT_TIME_PER_MAILBOX;
- ui32 EventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX;
- int RealtimePriority = 0;
- ui32 MaxActivityType = 1;
- };
-
- struct TIOExecutorPoolConfig {
- ui32 PoolId = 0;
- TString PoolName;
- ui32 Threads = 1;
- TCpuMask Affinity; // Executor thread affinity
- ui32 MaxActivityType = 1;
- };
-
- struct TUnitedExecutorPoolConfig {
- static constexpr TDuration DEFAULT_TIME_PER_MAILBOX = TDuration::MilliSeconds(10);
- static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = 100;
-
- ui32 PoolId = 0;
- TString PoolName;
-
- // Resource sharing
- ui32 Concurrency = 0; // Limits simultaneously running mailboxes count if set to non-zero value (do not set if Balancing.Cpus != 0)
- TPoolWeight Weight = 0; // Weight in fair cpu-local pool scheduler
- TCpuMask Allowed; // Allowed CPUs for workers to run this pool on (ignored if balancer works, i.e. actorsystem 1.5)
-
- // Single mailbox execution limits
- TDuration TimePerMailbox = DEFAULT_TIME_PER_MAILBOX;
- ui32 EventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX;
-
- // Introspection
- ui32 MaxActivityType = 1;
-
- // Long-term balancing
- TBalancingConfig Balancing;
- };
-
- struct TUnitedWorkersConfig {
- ui32 CpuCount = 0; // Total CPUs running united workers (i.e. TBasicExecutorPoolConfig::Threads analog); set to zero to disable united workers
- ui64 SpinThresholdUs = 100; // Limit for active spinning in case all pools became idle
- ui64 PoolLimitUs = 500; // Soft limit on pool execution
- ui64 EventLimitUs = 100; // Hard limit on last event execution exceeding pool limit
- ui64 LimitPrecisionUs = 100; // Maximum delay of timer on limit excess (delay needed to avoid settimer syscall on every pool switch)
- ui64 FastWorkerPriority = 10; // Real-time priority of workers not exceeding hard limits
- ui64 IdleWorkerPriority = 20; // Real-time priority of standby workers waiting for hard preemption on timers (should be greater than FastWorkerPriority)
- TCpuMask Allowed; // Allowed CPUs for workers to run on (every worker has affinity for exactly one cpu)
- bool NoRealtime = false; // For environments w/o permissions for RT-threads
- bool NoAffinity = false; // For environments w/o permissions for cpu affinity
- TBalancerConfig Balancer;
- };
-
- struct TCpuManagerConfig {
- TUnitedWorkersConfig UnitedWorkers;
- TVector<TBasicExecutorPoolConfig> Basic;
- TVector<TIOExecutorPoolConfig> IO;
- TVector<TUnitedExecutorPoolConfig> United;
-
- ui32 GetExecutorsCount() const {
- return Basic.size() + IO.size() + United.size();
- }
-
- TString GetPoolName(ui32 poolId) const {
- for (const auto& p : Basic) {
- if (p.PoolId == poolId) {
- return p.PoolName;
- }
- }
- for (const auto& p : IO) {
- if (p.PoolId == poolId) {
- return p.PoolName;
- }
- }
- for (const auto& p : United) {
- if (p.PoolId == poolId) {
- return p.PoolName;
- }
- }
- Y_FAIL("undefined pool id: %" PRIu32, (ui32)poolId);
- }
-
- ui32 GetThreads(ui32 poolId) const {
- for (const auto& p : Basic) {
- if (p.PoolId == poolId) {
- return p.Threads;
- }
- }
- for (const auto& p : IO) {
- if (p.PoolId == poolId) {
- return p.Threads;
- }
- }
- for (const auto& p : United) {
- if (p.PoolId == poolId) {
- return p.Concurrency ? p.Concurrency : UnitedWorkers.CpuCount;
- }
- }
- Y_FAIL("undefined pool id: %" PRIu32, (ui32)poolId);
- }
- };
-
- struct TSchedulerConfig {
- TSchedulerConfig(
- ui64 resolution = 1024,
- ui64 spinThreshold = 100,
- ui64 progress = 10000,
- bool useSchedulerActor = false)
- : ResolutionMicroseconds(resolution)
- , SpinThreshold(spinThreshold)
- , ProgressThreshold(progress)
- , UseSchedulerActor(useSchedulerActor)
- {}
-
- ui64 ResolutionMicroseconds = 1024;
- ui64 SpinThreshold = 100;
- ui64 ProgressThreshold = 10000;
- bool UseSchedulerActor = false; // False is default because tests use scheduler thread
- ui64 RelaxedSendPaceEventsPerSecond = 200000;
- ui64 RelaxedSendPaceEventsPerCycle = RelaxedSendPaceEventsPerSecond * ResolutionMicroseconds / 1000000;
- // For resolution >= 250000 microseconds threshold is SendPace
- // For resolution <= 250 microseconds threshold is 20 * SendPace
- ui64 RelaxedSendThresholdEventsPerSecond = RelaxedSendPaceEventsPerSecond *
- (20 - ((20 - 1) * ClampVal(ResolutionMicroseconds, ui64(250), ui64(250000)) - 250) / (250000 - 250));
- ui64 RelaxedSendThresholdEventsPerCycle = RelaxedSendThresholdEventsPerSecond * ResolutionMicroseconds / 1000000;
-
- // Optional subsection for scheduler counters (usually subsystem=utils)
- NMonitoring::TDynamicCounterPtr MonCounters = nullptr;
- };
-
- struct TCpuAllocation {
- struct TPoolAllocation {
- TPoolId PoolId;
- TPoolWeight Weight;
-
- TPoolAllocation(TPoolId poolId = 0, TPoolWeight weight = 0)
- : PoolId(poolId)
- , Weight(weight)
- {}
- };
-
- TCpuId CpuId;
- TVector<TPoolAllocation> AllowedPools;
-
- TPoolsMask GetPoolsMask() const {
- TPoolsMask mask = 0;
- for (const auto& pa : AllowedPools) {
- if (pa.PoolId < MaxPools) {
- mask &= (1ull << pa.PoolId);
- }
- }
- return mask;
- }
-
- bool HasPool(TPoolId pool) const {
- for (const auto& pa : AllowedPools) {
- if (pa.PoolId == pool) {
- return true;
- }
- }
- return false;
- }
- };
-
- struct TCpuAllocationConfig {
- TVector<TCpuAllocation> Items;
-
- TCpuAllocationConfig(const TCpuMask& available, const TCpuManagerConfig& cfg) {
- for (const TUnitedExecutorPoolConfig& pool : cfg.United) {
- Y_VERIFY(pool.PoolId < MaxPools, "wrong PoolId of united executor pool: %s(%d)",
- pool.PoolName.c_str(), (pool.PoolId));
- }
- ui32 allocated[MaxPools] = {0};
- for (TCpuId cpu = 0; cpu < available.Size() && Items.size() < cfg.UnitedWorkers.CpuCount; cpu++) {
- if (available.IsSet(cpu)) {
- TCpuAllocation item;
- item.CpuId = cpu;
- for (const TUnitedExecutorPoolConfig& pool : cfg.United) {
- if (cfg.UnitedWorkers.Allowed.IsEmpty() || cfg.UnitedWorkers.Allowed.IsSet(cpu)) {
- if (pool.Allowed.IsEmpty() || pool.Allowed.IsSet(cpu)) {
- item.AllowedPools.emplace_back(pool.PoolId, pool.Weight);
- allocated[pool.PoolId]++;
- }
- }
- }
- if (!item.AllowedPools.empty()) {
- Items.push_back(item);
- }
- }
- }
- for (const TUnitedExecutorPoolConfig& pool : cfg.United) {
- Y_VERIFY(allocated[pool.PoolId] > 0, "unable to allocate cpu for united executor pool: %s(%d)",
- pool.PoolName.c_str(), (pool.PoolId));
- }
- }
-
- operator bool() const {
- return !Items.empty();
- }
- };
-
-}
+#pragma once
+
+#include "defs.h"
+#include <library/cpp/actors/util/cpumask.h>
+#include <library/cpp/monlib/dynamic_counters/counters.h>
+#include <util/datetime/base.h>
+#include <util/generic/ptr.h>
+#include <util/generic/string.h>
+#include <util/generic/vector.h>
+
+namespace NActors {
+
+ struct TBalancingConfig {
+ // Default cpu count (used during overload). Zero value disables this pool balancing
+ // 1) Sum of `Cpus` on all pools cannot be changed without restart
+ // (changing cpu mode between Shared and Assigned is not implemented yet)
+ // 2) This sum must be equal to TUnitedWorkersConfig::CpuCount,
+ // otherwise `CpuCount - SUM(Cpus)` cpus will be in Shared mode (i.e. actorsystem 2.0)
+ ui32 Cpus = 0;
+
+ ui32 MinCpus = 0; // Lower balancing bound, should be at least 1, and not greater than `Cpus`
+ ui32 MaxCpus = 0; // Higher balancing bound, should be not lower than `Cpus`
+ ui8 Priority = 0; // Priority of pool to obtain cpu due to balancing (higher is better)
+ ui64 ToleratedLatencyUs = 0; // p100-latency threshold indicating that more cpus are required by pool
+ };
+
+ struct TBalancerConfig {
+ ui64 PeriodUs = 15000000; // Time between balancer steps
+ };
+
+ struct TBasicExecutorPoolConfig {
+ static constexpr TDuration DEFAULT_TIME_PER_MAILBOX = TDuration::MilliSeconds(10);
+ static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = 100;
+
+ ui32 PoolId = 0;
+ TString PoolName;
+ ui32 Threads = 1;
+ ui64 SpinThreshold = 100;
+ TCpuMask Affinity; // Executor thread affinity
+ TDuration TimePerMailbox = DEFAULT_TIME_PER_MAILBOX;
+ ui32 EventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX;
+ int RealtimePriority = 0;
+ ui32 MaxActivityType = 1;
+ };
+
+ struct TIOExecutorPoolConfig {
+ ui32 PoolId = 0;
+ TString PoolName;
+ ui32 Threads = 1;
+ TCpuMask Affinity; // Executor thread affinity
+ ui32 MaxActivityType = 1;
+ };
+
+ struct TUnitedExecutorPoolConfig {
+ static constexpr TDuration DEFAULT_TIME_PER_MAILBOX = TDuration::MilliSeconds(10);
+ static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = 100;
+
+ ui32 PoolId = 0;
+ TString PoolName;
+
+ // Resource sharing
+ ui32 Concurrency = 0; // Limits simultaneously running mailboxes count if set to non-zero value (do not set if Balancing.Cpus != 0)
+ TPoolWeight Weight = 0; // Weight in fair cpu-local pool scheduler
+ TCpuMask Allowed; // Allowed CPUs for workers to run this pool on (ignored if balancer works, i.e. actorsystem 1.5)
+
+ // Single mailbox execution limits
+ TDuration TimePerMailbox = DEFAULT_TIME_PER_MAILBOX;
+ ui32 EventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX;
+
+ // Introspection
+ ui32 MaxActivityType = 1;
+
+ // Long-term balancing
+ TBalancingConfig Balancing;
+ };
+
+ struct TUnitedWorkersConfig {
+ ui32 CpuCount = 0; // Total CPUs running united workers (i.e. TBasicExecutorPoolConfig::Threads analog); set to zero to disable united workers
+ ui64 SpinThresholdUs = 100; // Limit for active spinning in case all pools became idle
+ ui64 PoolLimitUs = 500; // Soft limit on pool execution
+ ui64 EventLimitUs = 100; // Hard limit on last event execution exceeding pool limit
+ ui64 LimitPrecisionUs = 100; // Maximum delay of timer on limit excess (delay needed to avoid settimer syscall on every pool switch)
+ ui64 FastWorkerPriority = 10; // Real-time priority of workers not exceeding hard limits
+ ui64 IdleWorkerPriority = 20; // Real-time priority of standby workers waiting for hard preemption on timers (should be greater than FastWorkerPriority)
+ TCpuMask Allowed; // Allowed CPUs for workers to run on (every worker has affinity for exactly one cpu)
+ bool NoRealtime = false; // For environments w/o permissions for RT-threads
+ bool NoAffinity = false; // For environments w/o permissions for cpu affinity
+ TBalancerConfig Balancer;
+ };
+
+ struct TCpuManagerConfig {
+ TUnitedWorkersConfig UnitedWorkers;
+ TVector<TBasicExecutorPoolConfig> Basic;
+ TVector<TIOExecutorPoolConfig> IO;
+ TVector<TUnitedExecutorPoolConfig> United;
+
+ ui32 GetExecutorsCount() const {
+ return Basic.size() + IO.size() + United.size();
+ }
+
+ TString GetPoolName(ui32 poolId) const {
+ for (const auto& p : Basic) {
+ if (p.PoolId == poolId) {
+ return p.PoolName;
+ }
+ }
+ for (const auto& p : IO) {
+ if (p.PoolId == poolId) {
+ return p.PoolName;
+ }
+ }
+ for (const auto& p : United) {
+ if (p.PoolId == poolId) {
+ return p.PoolName;
+ }
+ }
+ Y_FAIL("undefined pool id: %" PRIu32, (ui32)poolId);
+ }
+
+ ui32 GetThreads(ui32 poolId) const {
+ for (const auto& p : Basic) {
+ if (p.PoolId == poolId) {
+ return p.Threads;
+ }
+ }
+ for (const auto& p : IO) {
+ if (p.PoolId == poolId) {
+ return p.Threads;
+ }
+ }
+ for (const auto& p : United) {
+ if (p.PoolId == poolId) {
+ return p.Concurrency ? p.Concurrency : UnitedWorkers.CpuCount;
+ }
+ }
+ Y_FAIL("undefined pool id: %" PRIu32, (ui32)poolId);
+ }
+ };
+
+ struct TSchedulerConfig {
+ TSchedulerConfig(
+ ui64 resolution = 1024,
+ ui64 spinThreshold = 100,
+ ui64 progress = 10000,
+ bool useSchedulerActor = false)
+ : ResolutionMicroseconds(resolution)
+ , SpinThreshold(spinThreshold)
+ , ProgressThreshold(progress)
+ , UseSchedulerActor(useSchedulerActor)
+ {}
+
+ ui64 ResolutionMicroseconds = 1024;
+ ui64 SpinThreshold = 100;
+ ui64 ProgressThreshold = 10000;
+ bool UseSchedulerActor = false; // False is default because tests use scheduler thread
+ ui64 RelaxedSendPaceEventsPerSecond = 200000;
+ ui64 RelaxedSendPaceEventsPerCycle = RelaxedSendPaceEventsPerSecond * ResolutionMicroseconds / 1000000;
+ // For resolution >= 250000 microseconds threshold is SendPace
+ // For resolution <= 250 microseconds threshold is 20 * SendPace
+ ui64 RelaxedSendThresholdEventsPerSecond = RelaxedSendPaceEventsPerSecond *
+ (20 - ((20 - 1) * ClampVal(ResolutionMicroseconds, ui64(250), ui64(250000)) - 250) / (250000 - 250));
+ ui64 RelaxedSendThresholdEventsPerCycle = RelaxedSendThresholdEventsPerSecond * ResolutionMicroseconds / 1000000;
+
+ // Optional subsection for scheduler counters (usually subsystem=utils)
+ NMonitoring::TDynamicCounterPtr MonCounters = nullptr;
+ };
+
+ struct TCpuAllocation {
+ struct TPoolAllocation {
+ TPoolId PoolId;
+ TPoolWeight Weight;
+
+ TPoolAllocation(TPoolId poolId = 0, TPoolWeight weight = 0)
+ : PoolId(poolId)
+ , Weight(weight)
+ {}
+ };
+
+ TCpuId CpuId;
+ TVector<TPoolAllocation> AllowedPools;
+
+ TPoolsMask GetPoolsMask() const {
+ TPoolsMask mask = 0;
+ for (const auto& pa : AllowedPools) {
+ if (pa.PoolId < MaxPools) {
+ mask &= (1ull << pa.PoolId);
+ }
+ }
+ return mask;
+ }
+
+ bool HasPool(TPoolId pool) const {
+ for (const auto& pa : AllowedPools) {
+ if (pa.PoolId == pool) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+ struct TCpuAllocationConfig {
+ TVector<TCpuAllocation> Items;
+
+ TCpuAllocationConfig(const TCpuMask& available, const TCpuManagerConfig& cfg) {
+ for (const TUnitedExecutorPoolConfig& pool : cfg.United) {
+ Y_VERIFY(pool.PoolId < MaxPools, "wrong PoolId of united executor pool: %s(%d)",
+ pool.PoolName.c_str(), (pool.PoolId));
+ }
+ ui32 allocated[MaxPools] = {0};
+ for (TCpuId cpu = 0; cpu < available.Size() && Items.size() < cfg.UnitedWorkers.CpuCount; cpu++) {
+ if (available.IsSet(cpu)) {
+ TCpuAllocation item;
+ item.CpuId = cpu;
+ for (const TUnitedExecutorPoolConfig& pool : cfg.United) {
+ if (cfg.UnitedWorkers.Allowed.IsEmpty() || cfg.UnitedWorkers.Allowed.IsSet(cpu)) {
+ if (pool.Allowed.IsEmpty() || pool.Allowed.IsSet(cpu)) {
+ item.AllowedPools.emplace_back(pool.PoolId, pool.Weight);
+ allocated[pool.PoolId]++;
+ }
+ }
+ }
+ if (!item.AllowedPools.empty()) {
+ Items.push_back(item);
+ }
+ }
+ }
+ for (const TUnitedExecutorPoolConfig& pool : cfg.United) {
+ Y_VERIFY(allocated[pool.PoolId] > 0, "unable to allocate cpu for united executor pool: %s(%d)",
+ pool.PoolName.c_str(), (pool.PoolId));
+ }
+ }
+
+ operator bool() const {
+ return !Items.empty();
+ }
+ };
+
+}
diff --git a/library/cpp/actors/core/cpu_manager.cpp b/library/cpp/actors/core/cpu_manager.cpp
index 39089b5d83..26aca975e9 100644
--- a/library/cpp/actors/core/cpu_manager.cpp
+++ b/library/cpp/actors/core/cpu_manager.cpp
@@ -1,108 +1,108 @@
-#include "cpu_manager.h"
-#include "probes.h"
-
-namespace NActors {
- LWTRACE_USING(ACTORLIB_PROVIDER);
-
- void TCpuManager::Setup() {
- TAffinity available;
- available.Current();
- TCpuAllocationConfig allocation(available, Config);
-
- if (allocation) {
- if (!Balancer) {
- Balancer.Reset(MakeBalancer(Config.UnitedWorkers.Balancer, Config.United, GetCycleCountFast()));
- }
- UnitedWorkers.Reset(new TUnitedWorkers(Config.UnitedWorkers, Config.United, allocation, Balancer.Get()));
- }
-
- Executors.Reset(new TAutoPtr<IExecutorPool>[ExecutorPoolCount]);
-
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- Executors[excIdx].Reset(CreateExecutorPool(excIdx));
- }
- }
-
- void TCpuManager::PrepareStart(TVector<NSchedulerQueue::TReader*>& scheduleReaders, TActorSystem* actorSystem) {
- if (UnitedWorkers) {
- UnitedWorkers->Prepare(actorSystem, scheduleReaders);
- }
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- NSchedulerQueue::TReader* readers;
- ui32 readersCount = 0;
- Executors[excIdx]->Prepare(actorSystem, &readers, &readersCount);
- for (ui32 i = 0; i != readersCount; ++i, ++readers) {
- scheduleReaders.push_back(readers);
- }
- }
- }
-
- void TCpuManager::Start() {
- if (UnitedWorkers) {
- UnitedWorkers->Start();
- }
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- Executors[excIdx]->Start();
- }
- }
-
- void TCpuManager::PrepareStop() {
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- Executors[excIdx]->PrepareStop();
- }
- if (UnitedWorkers) {
- UnitedWorkers->PrepareStop();
- }
- }
-
- void TCpuManager::Shutdown() {
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- Executors[excIdx]->Shutdown();
- }
- if (UnitedWorkers) {
- UnitedWorkers->Shutdown();
- }
- for (ui32 round = 0, done = 0; done < ExecutorPoolCount && round < 3; ++round) {
- done = 0;
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- if (Executors[excIdx]->Cleanup()) {
- ++done;
- }
- }
- }
- }
-
- void TCpuManager::Cleanup() {
- for (ui32 round = 0, done = 0; done < ExecutorPoolCount; ++round) {
- Y_VERIFY(round < 10, "actorsystem cleanup could not be completed in 10 rounds");
- done = 0;
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- if (Executors[excIdx]->Cleanup()) {
- ++done;
- }
- }
- }
- Executors.Destroy();
- UnitedWorkers.Destroy();
- }
-
- IExecutorPool* TCpuManager::CreateExecutorPool(ui32 poolId) {
- for (TBasicExecutorPoolConfig& cfg : Config.Basic) {
- if (cfg.PoolId == poolId) {
- return new TBasicExecutorPool(cfg);
- }
- }
- for (TIOExecutorPoolConfig& cfg : Config.IO) {
- if (cfg.PoolId == poolId) {
- return new TIOExecutorPool(cfg);
- }
- }
- for (TUnitedExecutorPoolConfig& cfg : Config.United) {
- if (cfg.PoolId == poolId) {
- IExecutorPool* result = new TUnitedExecutorPool(cfg, UnitedWorkers.Get());
- return result;
- }
- }
- Y_FAIL("missing PoolId: %d", int(poolId));
- }
-}
+#include "cpu_manager.h"
+#include "probes.h"
+
+namespace NActors {
+ LWTRACE_USING(ACTORLIB_PROVIDER);
+
+ void TCpuManager::Setup() {
+ TAffinity available;
+ available.Current();
+ TCpuAllocationConfig allocation(available, Config);
+
+ if (allocation) {
+ if (!Balancer) {
+ Balancer.Reset(MakeBalancer(Config.UnitedWorkers.Balancer, Config.United, GetCycleCountFast()));
+ }
+ UnitedWorkers.Reset(new TUnitedWorkers(Config.UnitedWorkers, Config.United, allocation, Balancer.Get()));
+ }
+
+ Executors.Reset(new TAutoPtr<IExecutorPool>[ExecutorPoolCount]);
+
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ Executors[excIdx].Reset(CreateExecutorPool(excIdx));
+ }
+ }
+
+ void TCpuManager::PrepareStart(TVector<NSchedulerQueue::TReader*>& scheduleReaders, TActorSystem* actorSystem) {
+ if (UnitedWorkers) {
+ UnitedWorkers->Prepare(actorSystem, scheduleReaders);
+ }
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ NSchedulerQueue::TReader* readers;
+ ui32 readersCount = 0;
+ Executors[excIdx]->Prepare(actorSystem, &readers, &readersCount);
+ for (ui32 i = 0; i != readersCount; ++i, ++readers) {
+ scheduleReaders.push_back(readers);
+ }
+ }
+ }
+
+ void TCpuManager::Start() {
+ if (UnitedWorkers) {
+ UnitedWorkers->Start();
+ }
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ Executors[excIdx]->Start();
+ }
+ }
+
+ void TCpuManager::PrepareStop() {
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ Executors[excIdx]->PrepareStop();
+ }
+ if (UnitedWorkers) {
+ UnitedWorkers->PrepareStop();
+ }
+ }
+
+ void TCpuManager::Shutdown() {
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ Executors[excIdx]->Shutdown();
+ }
+ if (UnitedWorkers) {
+ UnitedWorkers->Shutdown();
+ }
+ for (ui32 round = 0, done = 0; done < ExecutorPoolCount && round < 3; ++round) {
+ done = 0;
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ if (Executors[excIdx]->Cleanup()) {
+ ++done;
+ }
+ }
+ }
+ }
+
+ void TCpuManager::Cleanup() {
+ for (ui32 round = 0, done = 0; done < ExecutorPoolCount; ++round) {
+ Y_VERIFY(round < 10, "actorsystem cleanup could not be completed in 10 rounds");
+ done = 0;
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ if (Executors[excIdx]->Cleanup()) {
+ ++done;
+ }
+ }
+ }
+ Executors.Destroy();
+ UnitedWorkers.Destroy();
+ }
+
+ IExecutorPool* TCpuManager::CreateExecutorPool(ui32 poolId) {
+ for (TBasicExecutorPoolConfig& cfg : Config.Basic) {
+ if (cfg.PoolId == poolId) {
+ return new TBasicExecutorPool(cfg);
+ }
+ }
+ for (TIOExecutorPoolConfig& cfg : Config.IO) {
+ if (cfg.PoolId == poolId) {
+ return new TIOExecutorPool(cfg);
+ }
+ }
+ for (TUnitedExecutorPoolConfig& cfg : Config.United) {
+ if (cfg.PoolId == poolId) {
+ IExecutorPool* result = new TUnitedExecutorPool(cfg, UnitedWorkers.Get());
+ return result;
+ }
+ }
+ Y_FAIL("missing PoolId: %d", int(poolId));
+ }
+}
diff --git a/library/cpp/actors/core/cpu_manager.h b/library/cpp/actors/core/cpu_manager.h
index 454035477b..fc67bfd34c 100644
--- a/library/cpp/actors/core/cpu_manager.h
+++ b/library/cpp/actors/core/cpu_manager.h
@@ -1,57 +1,57 @@
-#pragma once
-
-#include "actorsystem.h"
-#include "executor_pool_basic.h"
-#include "executor_pool_io.h"
-#include "executor_pool_united.h"
-
-namespace NActors {
- class TCpuManager : public TNonCopyable {
- const ui32 ExecutorPoolCount;
- TArrayHolder<TAutoPtr<IExecutorPool>> Executors;
- THolder<TUnitedWorkers> UnitedWorkers;
- THolder<IBalancer> Balancer;
- TCpuManagerConfig Config;
- public:
- explicit TCpuManager(THolder<TActorSystemSetup>& setup)
- : ExecutorPoolCount(setup->GetExecutorsCount())
- , Balancer(setup->Balancer)
- , Config(setup->CpuManager)
- {
- if (setup->Executors) { // Explicit mode w/o united pools
- Executors.Reset(setup->Executors.Release());
- for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
- IExecutorPool* pool = Executors[excIdx].Get();
- Y_VERIFY(dynamic_cast<TUnitedExecutorPool*>(pool) == nullptr,
- "united executor pool is prohibited in explicit mode of NActors::TCpuManager");
- }
- } else {
- Setup();
- }
- }
-
- void Setup();
- void PrepareStart(TVector<NSchedulerQueue::TReader*>& scheduleReaders, TActorSystem* actorSystem);
- void Start();
- void PrepareStop();
- void Shutdown();
- void Cleanup();
-
- ui32 GetExecutorsCount() const {
- return ExecutorPoolCount;
- }
-
- IExecutorPool* GetExecutorPool(ui32 poolId) {
- return Executors[poolId].Get();
- }
-
- void GetPoolStats(ui32 poolId, TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const {
- if (poolId < ExecutorPoolCount) {
- Executors[poolId]->GetCurrentStats(poolStats, statsCopy);
- }
- }
-
- private:
- IExecutorPool* CreateExecutorPool(ui32 poolId);
- };
-}
+#pragma once
+
+#include "actorsystem.h"
+#include "executor_pool_basic.h"
+#include "executor_pool_io.h"
+#include "executor_pool_united.h"
+
+namespace NActors {
+ class TCpuManager : public TNonCopyable {
+ const ui32 ExecutorPoolCount;
+ TArrayHolder<TAutoPtr<IExecutorPool>> Executors;
+ THolder<TUnitedWorkers> UnitedWorkers;
+ THolder<IBalancer> Balancer;
+ TCpuManagerConfig Config;
+ public:
+ explicit TCpuManager(THolder<TActorSystemSetup>& setup)
+ : ExecutorPoolCount(setup->GetExecutorsCount())
+ , Balancer(setup->Balancer)
+ , Config(setup->CpuManager)
+ {
+ if (setup->Executors) { // Explicit mode w/o united pools
+ Executors.Reset(setup->Executors.Release());
+ for (ui32 excIdx = 0; excIdx != ExecutorPoolCount; ++excIdx) {
+ IExecutorPool* pool = Executors[excIdx].Get();
+ Y_VERIFY(dynamic_cast<TUnitedExecutorPool*>(pool) == nullptr,
+ "united executor pool is prohibited in explicit mode of NActors::TCpuManager");
+ }
+ } else {
+ Setup();
+ }
+ }
+
+ void Setup();
+ void PrepareStart(TVector<NSchedulerQueue::TReader*>& scheduleReaders, TActorSystem* actorSystem);
+ void Start();
+ void PrepareStop();
+ void Shutdown();
+ void Cleanup();
+
+ ui32 GetExecutorsCount() const {
+ return ExecutorPoolCount;
+ }
+
+ IExecutorPool* GetExecutorPool(ui32 poolId) {
+ return Executors[poolId].Get();
+ }
+
+ void GetPoolStats(ui32 poolId, TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const {
+ if (poolId < ExecutorPoolCount) {
+ Executors[poolId]->GetCurrentStats(poolStats, statsCopy);
+ }
+ }
+
+ private:
+ IExecutorPool* CreateExecutorPool(ui32 poolId);
+ };
+}
diff --git a/library/cpp/actors/core/cpu_state.h b/library/cpp/actors/core/cpu_state.h
index b8030149a7..34febf7ccf 100644
--- a/library/cpp/actors/core/cpu_state.h
+++ b/library/cpp/actors/core/cpu_state.h
@@ -1,215 +1,215 @@
-#pragma once
-
-#include "defs.h"
-
-#include <library/cpp/actors/util/futex.h>
-
-namespace NActors {
-
- class alignas(64) TCpuState {
- // Atomic cachelign-aligned 64-bit state, see description below
- TAtomic State = 0;
- char Padding[64 - sizeof(TAtomic)];
-
- // Bits 0-31: Currently executing pool
- // - value less than MaxPools means cpu is executing corresponding pool (fast-worker is executing or waiting for slow-workers)
- // - one of Cpu* values in case of idle cpu
- // - used as futex by blocked fast-worker
- static constexpr ui64 CurrentBits = 32;
- static constexpr ui64 CurrentMask = ui64((1ull << CurrentBits) - 1);
-
- // Bits 32-63: Assigned pool
- // - value is set by balancer
- // - NOT used as futex
- // - Not balanced
- static constexpr ui64 AssignedOffs = 32;
- static constexpr ui64 AssignedMask = ~CurrentMask;
-
- public:
- TCpuState() {
- Y_UNUSED(Padding);
- }
-
- void Load(TPoolId& assigned, TPoolId& current) const {
- TAtomicBase state = AtomicLoad(&State);
- assigned = (state & AssignedMask) >> AssignedOffs;
- current = state & CurrentMask;
- }
-
- TPoolId CurrentPool() const {
- return TPoolId(AtomicLoad(&State) & CurrentMask);
- }
-
- void SwitchPool(TPoolId pool) {
- while (true) {
- TAtomicBase state = AtomicLoad(&State);
- if (AtomicCas(&State, (state & ~CurrentMask) | pool, state)) {
- return;
- }
- }
- }
-
- TPoolId AssignedPool() const {
- return TPoolId((AtomicLoad(&State) & AssignedMask) >> AssignedOffs);
- }
-
- // Assigns new pool to cpu and wakes it up if cpu is idle
- void AssignPool(TPoolId pool) {
- while (true) {
- TAtomicBase state = AtomicLoad(&State);
- TPoolId current(state & CurrentMask);
- if (Y_UNLIKELY(current == CpuStopped)) {
- return; // it would be better to shutdown instead of balancing
- }
- // Idle cpu must be woken up after balancing to handle pending tokens (if any) in assigned/schedulable pool(s)
- if (current == CpuSpinning) {
- if (AtomicCas(&State, (ui64(pool) << AssignedOffs) | pool, state)) {
- return; // successfully woken up
- }
- } else if (current == CpuBlocked) {
- if (AtomicCas(&State, (ui64(pool) << AssignedOffs) | pool, state)) {
- FutexWake();
- return; // successfully woken up
- }
- } else {
- if (AtomicCas(&State, (ui64(pool) << AssignedOffs) | (state & ~AssignedMask), state)) {
- return; // wakeup is not required
- }
- }
- }
- }
-
- void Stop() {
- while (true) {
- TAtomicBase state = AtomicLoad(&State);
- if (AtomicCas(&State, (state & ~CurrentMask) | CpuStopped, state)) {
- FutexWake();
- return; // successfully stopped
- }
- }
- }
-
- // Start waiting, returns false in case of actorsystem shutdown
- bool StartSpinning() {
- while (true) {
- TAtomicBase state = AtomicLoad(&State);
- TPoolId current(state & CurrentMask);
- if (Y_UNLIKELY(current == CpuStopped)) {
- return false;
- }
- Y_VERIFY_DEBUG(current < MaxPools, "unexpected already waiting state of cpu (%d)", (int)current);
- if (AtomicCas(&State, (state & ~CurrentMask) | CpuSpinning, state)) { // successfully marked as spinning
- return true;
- }
- }
- }
-
- bool StartBlocking() {
- while (true) {
- TAtomicBase state = AtomicLoad(&State);
- TPoolId current(state & CurrentMask);
- if (current == CpuSpinning) {
- if (AtomicCas(&State, (state & ~CurrentMask) | CpuBlocked, state)) {
- return false; // successful switch
- }
- } else {
- return true; // wakeup
- }
- }
- }
-
- bool Block(ui64 timeoutNs, TPoolId& result) {
-#ifdef _linux_
- timespec timeout;
- timeout.tv_sec = timeoutNs / 1'000'000'000;
- timeout.tv_nsec = timeoutNs % 1'000'000'000;
- SysFutex(Futex(), FUTEX_WAIT_PRIVATE, CpuBlocked, &timeout, nullptr, 0);
-#else
- NanoSleep(timeoutNs); // non-linux wake is not supported, cpu will go idle on wake after blocked state
-#endif
- TAtomicBase state = AtomicLoad(&State);
- TPoolId current(state & CurrentMask);
- if (current == CpuBlocked) {
- return false; // timeout
- } else {
- result = current;
- return true; // wakeup
- }
- }
-
- enum EWakeResult {
- Woken, // successfully woken up
- NotIdle, // cpu is already not idle
- Forbidden, // cpu is assigned to another pool
- Stopped, // cpu is shutdown
- };
-
- EWakeResult WakeWithoutToken(TPoolId pool) {
- while (true) {
- TAtomicBase state = RelaxedLoad(&State);
- TPoolId current(state & CurrentMask);
- TPoolId assigned((state & AssignedMask) >> AssignedOffs);
- if (assigned == CpuShared || assigned == pool) {
- if (current == CpuSpinning) {
- if (AtomicCas(&State, (state & ~CurrentMask) | pool, state)) {
- return Woken;
- }
- } else if (current == CpuBlocked) {
- if (AtomicCas(&State, (state & ~CurrentMask) | pool, state)) {
- FutexWake();
- return Woken;
- }
- } else if (current == CpuStopped) {
- return Stopped;
- } else {
- return NotIdle;
- }
- } else {
- return Forbidden;
- }
- }
- }
-
- EWakeResult WakeWithTokenAcquired(TPoolId token) {
- while (true) {
- TAtomicBase state = RelaxedLoad(&State);
- TPoolId current(state & CurrentMask);
- // NOTE: We ignore assigned value because we already have token, so
- // NOTE: not assigned pool may be run here. This will be fixed
- // NOTE: after we finish with current activation
- if (current == CpuSpinning) {
- if (AtomicCas(&State, (state & ~CurrentMask) | token, state)) {
- return Woken;
- }
- } else if (current == CpuBlocked) {
- if (AtomicCas(&State, (state & ~CurrentMask) | token, state)) {
- FutexWake();
- return Woken;
- }
- } else if (current == CpuStopped) {
- return Stopped;
- } else {
- return NotIdle;
- }
- }
- }
-
- bool IsPoolReassigned(TPoolId current) const {
- TAtomicBase state = AtomicLoad(&State);
- TPoolId assigned((state & AssignedMask) >> AssignedOffs);
- return assigned != current;
- }
-
- private:
- void* Futex() {
- return (void*)&State; // little endian assumed
- }
-
- void FutexWake() {
-#ifdef _linux_
- SysFutex(Futex(), FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
-#endif
- }
- };
-
-}
+#pragma once
+
+#include "defs.h"
+
+#include <library/cpp/actors/util/futex.h>
+
+namespace NActors {
+
+ class alignas(64) TCpuState {
+ // Atomic cachelign-aligned 64-bit state, see description below
+ TAtomic State = 0;
+ char Padding[64 - sizeof(TAtomic)];
+
+ // Bits 0-31: Currently executing pool
+ // - value less than MaxPools means cpu is executing corresponding pool (fast-worker is executing or waiting for slow-workers)
+ // - one of Cpu* values in case of idle cpu
+ // - used as futex by blocked fast-worker
+ static constexpr ui64 CurrentBits = 32;
+ static constexpr ui64 CurrentMask = ui64((1ull << CurrentBits) - 1);
+
+ // Bits 32-63: Assigned pool
+ // - value is set by balancer
+ // - NOT used as futex
+ // - Not balanced
+ static constexpr ui64 AssignedOffs = 32;
+ static constexpr ui64 AssignedMask = ~CurrentMask;
+
+ public:
+ TCpuState() {
+ Y_UNUSED(Padding);
+ }
+
+ void Load(TPoolId& assigned, TPoolId& current) const {
+ TAtomicBase state = AtomicLoad(&State);
+ assigned = (state & AssignedMask) >> AssignedOffs;
+ current = state & CurrentMask;
+ }
+
+ TPoolId CurrentPool() const {
+ return TPoolId(AtomicLoad(&State) & CurrentMask);
+ }
+
+ void SwitchPool(TPoolId pool) {
+ while (true) {
+ TAtomicBase state = AtomicLoad(&State);
+ if (AtomicCas(&State, (state & ~CurrentMask) | pool, state)) {
+ return;
+ }
+ }
+ }
+
+ TPoolId AssignedPool() const {
+ return TPoolId((AtomicLoad(&State) & AssignedMask) >> AssignedOffs);
+ }
+
+ // Assigns new pool to cpu and wakes it up if cpu is idle
+ void AssignPool(TPoolId pool) {
+ while (true) {
+ TAtomicBase state = AtomicLoad(&State);
+ TPoolId current(state & CurrentMask);
+ if (Y_UNLIKELY(current == CpuStopped)) {
+ return; // it would be better to shutdown instead of balancing
+ }
+ // Idle cpu must be woken up after balancing to handle pending tokens (if any) in assigned/schedulable pool(s)
+ if (current == CpuSpinning) {
+ if (AtomicCas(&State, (ui64(pool) << AssignedOffs) | pool, state)) {
+ return; // successfully woken up
+ }
+ } else if (current == CpuBlocked) {
+ if (AtomicCas(&State, (ui64(pool) << AssignedOffs) | pool, state)) {
+ FutexWake();
+ return; // successfully woken up
+ }
+ } else {
+ if (AtomicCas(&State, (ui64(pool) << AssignedOffs) | (state & ~AssignedMask), state)) {
+ return; // wakeup is not required
+ }
+ }
+ }
+ }
+
+ void Stop() {
+ while (true) {
+ TAtomicBase state = AtomicLoad(&State);
+ if (AtomicCas(&State, (state & ~CurrentMask) | CpuStopped, state)) {
+ FutexWake();
+ return; // successfully stopped
+ }
+ }
+ }
+
+ // Start waiting, returns false in case of actorsystem shutdown
+ bool StartSpinning() {
+ while (true) {
+ TAtomicBase state = AtomicLoad(&State);
+ TPoolId current(state & CurrentMask);
+ if (Y_UNLIKELY(current == CpuStopped)) {
+ return false;
+ }
+ Y_VERIFY_DEBUG(current < MaxPools, "unexpected already waiting state of cpu (%d)", (int)current);
+ if (AtomicCas(&State, (state & ~CurrentMask) | CpuSpinning, state)) { // successfully marked as spinning
+ return true;
+ }
+ }
+ }
+
+ bool StartBlocking() {
+ while (true) {
+ TAtomicBase state = AtomicLoad(&State);
+ TPoolId current(state & CurrentMask);
+ if (current == CpuSpinning) {
+ if (AtomicCas(&State, (state & ~CurrentMask) | CpuBlocked, state)) {
+ return false; // successful switch
+ }
+ } else {
+ return true; // wakeup
+ }
+ }
+ }
+
+ bool Block(ui64 timeoutNs, TPoolId& result) {
+#ifdef _linux_
+ timespec timeout;
+ timeout.tv_sec = timeoutNs / 1'000'000'000;
+ timeout.tv_nsec = timeoutNs % 1'000'000'000;
+ SysFutex(Futex(), FUTEX_WAIT_PRIVATE, CpuBlocked, &timeout, nullptr, 0);
+#else
+ NanoSleep(timeoutNs); // non-linux wake is not supported, cpu will go idle on wake after blocked state
+#endif
+ TAtomicBase state = AtomicLoad(&State);
+ TPoolId current(state & CurrentMask);
+ if (current == CpuBlocked) {
+ return false; // timeout
+ } else {
+ result = current;
+ return true; // wakeup
+ }
+ }
+
+ enum EWakeResult {
+ Woken, // successfully woken up
+ NotIdle, // cpu is already not idle
+ Forbidden, // cpu is assigned to another pool
+ Stopped, // cpu is shutdown
+ };
+
+ EWakeResult WakeWithoutToken(TPoolId pool) {
+ while (true) {
+ TAtomicBase state = RelaxedLoad(&State);
+ TPoolId current(state & CurrentMask);
+ TPoolId assigned((state & AssignedMask) >> AssignedOffs);
+ if (assigned == CpuShared || assigned == pool) {
+ if (current == CpuSpinning) {
+ if (AtomicCas(&State, (state & ~CurrentMask) | pool, state)) {
+ return Woken;
+ }
+ } else if (current == CpuBlocked) {
+ if (AtomicCas(&State, (state & ~CurrentMask) | pool, state)) {
+ FutexWake();
+ return Woken;
+ }
+ } else if (current == CpuStopped) {
+ return Stopped;
+ } else {
+ return NotIdle;
+ }
+ } else {
+ return Forbidden;
+ }
+ }
+ }
+
+ EWakeResult WakeWithTokenAcquired(TPoolId token) {
+ while (true) {
+ TAtomicBase state = RelaxedLoad(&State);
+ TPoolId current(state & CurrentMask);
+ // NOTE: We ignore assigned value because we already have token, so
+ // NOTE: not assigned pool may be run here. This will be fixed
+ // NOTE: after we finish with current activation
+ if (current == CpuSpinning) {
+ if (AtomicCas(&State, (state & ~CurrentMask) | token, state)) {
+ return Woken;
+ }
+ } else if (current == CpuBlocked) {
+ if (AtomicCas(&State, (state & ~CurrentMask) | token, state)) {
+ FutexWake();
+ return Woken;
+ }
+ } else if (current == CpuStopped) {
+ return Stopped;
+ } else {
+ return NotIdle;
+ }
+ }
+ }
+
+ bool IsPoolReassigned(TPoolId current) const {
+ TAtomicBase state = AtomicLoad(&State);
+ TPoolId assigned((state & AssignedMask) >> AssignedOffs);
+ return assigned != current;
+ }
+
+ private:
+ void* Futex() {
+ return (void*)&State; // little endian assumed
+ }
+
+ void FutexWake() {
+#ifdef _linux_
+ SysFutex(Futex(), FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
+#endif
+ }
+ };
+
+}
diff --git a/library/cpp/actors/core/defs.h b/library/cpp/actors/core/defs.h
index 980b7d767b..d331e98833 100644
--- a/library/cpp/actors/core/defs.h
+++ b/library/cpp/actors/core/defs.h
@@ -13,30 +13,30 @@
#define ACTORSLIB_COLLECT_EXEC_STATS
namespace NActors {
- using TPoolId = ui8;
- using TPoolsMask = ui64;
- static constexpr TPoolId PoolBits = 6;
- static constexpr TPoolId MaxPools = (1 << PoolBits) - 1; // maximum amount of pools (poolid=63 is reserved)
- static constexpr TPoolsMask WaitPoolsFlag = (1ull << MaxPools); // wait-for-slow-workers flag bitmask
-
- // Special TPoolId values used by TCpuState
- static constexpr TPoolId CpuSpinning = MaxPools; // fast-worker is actively spinning, no slow-workers
- static constexpr TPoolId CpuBlocked = MaxPools + 1; // fast-worker is blocked, no slow-workers
- static constexpr TPoolId CpuStopped = TPoolId(-1); // special value indicating worker should stop
- static constexpr TPoolId CpuShared = MaxPools; // special value for `assigned` meaning balancer disabled, pool scheduler is used instead
-
- using TPoolWeight = ui16;
- static constexpr TPoolWeight MinPoolWeight = 1;
- static constexpr TPoolWeight DefPoolWeight = 32;
- static constexpr TPoolWeight MaxPoolWeight = 1024;
-
- using TWorkerId = ui16;
- static constexpr TWorkerId WorkerBits = 11;
- static constexpr TWorkerId MaxWorkers = 1 << WorkerBits;
-
- using TThreadId = ui64;
- static constexpr TThreadId UnknownThreadId = ui64(-1);
+ using TPoolId = ui8;
+ using TPoolsMask = ui64;
+ static constexpr TPoolId PoolBits = 6;
+ static constexpr TPoolId MaxPools = (1 << PoolBits) - 1; // maximum amount of pools (poolid=63 is reserved)
+ static constexpr TPoolsMask WaitPoolsFlag = (1ull << MaxPools); // wait-for-slow-workers flag bitmask
+ // Special TPoolId values used by TCpuState
+ static constexpr TPoolId CpuSpinning = MaxPools; // fast-worker is actively spinning, no slow-workers
+ static constexpr TPoolId CpuBlocked = MaxPools + 1; // fast-worker is blocked, no slow-workers
+ static constexpr TPoolId CpuStopped = TPoolId(-1); // special value indicating worker should stop
+ static constexpr TPoolId CpuShared = MaxPools; // special value for `assigned` meaning balancer disabled, pool scheduler is used instead
+
+ using TPoolWeight = ui16;
+ static constexpr TPoolWeight MinPoolWeight = 1;
+ static constexpr TPoolWeight DefPoolWeight = 32;
+ static constexpr TPoolWeight MaxPoolWeight = 1024;
+
+ using TWorkerId = ui16;
+ static constexpr TWorkerId WorkerBits = 11;
+ static constexpr TWorkerId MaxWorkers = 1 << WorkerBits;
+
+ using TThreadId = ui64;
+ static constexpr TThreadId UnknownThreadId = ui64(-1);
+
struct TMailboxType {
enum EType {
Inherited = -1, // inherit mailbox from parent
diff --git a/library/cpp/actors/core/event_pb.h b/library/cpp/actors/core/event_pb.h
index d7546b901a..bf9695da95 100644
--- a/library/cpp/actors/core/event_pb.h
+++ b/library/cpp/actors/core/event_pb.h
@@ -291,10 +291,10 @@ namespace NActors {
}
public:
- void ReservePayload(size_t size) {
- Payload.reserve(size);
- }
-
+ void ReservePayload(size_t size) {
+ Payload.reserve(size);
+ }
+
ui32 AddPayload(TRope&& rope) {
const ui32 id = Payload.size();
Payload.push_back(std::move(rope));
diff --git a/library/cpp/actors/core/executor_pool_base.cpp b/library/cpp/actors/core/executor_pool_base.cpp
index c3b9999168..7340458631 100644
--- a/library/cpp/actors/core/executor_pool_base.cpp
+++ b/library/cpp/actors/core/executor_pool_base.cpp
@@ -1,8 +1,8 @@
#include "executor_pool_base.h"
#include "executor_thread.h"
#include "mailbox.h"
-#include "probes.h"
-#include <library/cpp/actors/util/datetime.h>
+#include "probes.h"
+#include <library/cpp/actors/util/datetime.h>
namespace NActors {
LWTRACE_USING(ACTORLIB_PROVIDER);
@@ -11,44 +11,44 @@ namespace NActors {
actor->SelfActorId = self;
actor->Registered(sys, owner);
}
-
- TExecutorPoolBaseMailboxed::TExecutorPoolBaseMailboxed(ui32 poolId, ui32 maxActivityType)
+
+ TExecutorPoolBaseMailboxed::TExecutorPoolBaseMailboxed(ui32 poolId, ui32 maxActivityType)
: IExecutorPool(poolId)
, ActorSystem(nullptr)
, MailboxTable(new TMailboxTable)
#ifdef ACTORSLIB_COLLECT_EXEC_STATS
, Stats(maxActivityType)
#endif
- {}
-
- TExecutorPoolBaseMailboxed::~TExecutorPoolBaseMailboxed() {
- MailboxTable.Destroy();
+ {}
+
+ TExecutorPoolBaseMailboxed::~TExecutorPoolBaseMailboxed() {
+ MailboxTable.Destroy();
}
- TExecutorPoolBase::TExecutorPoolBase(ui32 poolId, ui32 threads, TAffinity* affinity, ui32 maxActivityType)
- : TExecutorPoolBaseMailboxed(poolId, maxActivityType)
- , PoolThreads(threads)
- , ThreadsAffinity(affinity)
- {}
-
+ TExecutorPoolBase::TExecutorPoolBase(ui32 poolId, ui32 threads, TAffinity* affinity, ui32 maxActivityType)
+ : TExecutorPoolBaseMailboxed(poolId, maxActivityType)
+ , PoolThreads(threads)
+ , ThreadsAffinity(affinity)
+ {}
+
TExecutorPoolBase::~TExecutorPoolBase() {
while (Activations.Pop(0))
;
}
- void TExecutorPoolBaseMailboxed::ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingWriteCounter) {
- Y_UNUSED(workerId);
+ void TExecutorPoolBaseMailboxed::ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingWriteCounter) {
+ Y_UNUSED(workerId);
MailboxTable->ReclaimMailbox(mailboxType, hint, revolvingWriteCounter);
}
- ui64 TExecutorPoolBaseMailboxed::AllocateID() {
+ ui64 TExecutorPoolBaseMailboxed::AllocateID() {
return ActorSystem->AllocateIDSpace(1);
}
- bool TExecutorPoolBaseMailboxed::Send(TAutoPtr<IEventHandle>& ev) {
+ bool TExecutorPoolBaseMailboxed::Send(TAutoPtr<IEventHandle>& ev) {
Y_VERIFY_DEBUG(ev->GetRecipientRewrite().PoolID() == PoolId);
#ifdef ACTORSLIB_COLLECT_EXEC_STATS
- RelaxedStore(&ev->SendTime, (::NHPTimer::STime)GetCycleCountFast());
+ RelaxedStore(&ev->SendTime, (::NHPTimer::STime)GetCycleCountFast());
#endif
return MailboxTable->SendTo(ev, this);
}
@@ -57,8 +57,8 @@ namespace NActors {
ScheduleActivationEx(activation, AtomicIncrement(ActivationsRevolvingCounter));
}
- TActorId TExecutorPoolBaseMailboxed::Register(IActor* actor, TMailboxType::EType mailboxType, ui64 revolvingWriteCounter, const TActorId& parentId) {
- NHPTimer::STime hpstart = GetCycleCountFast();
+ TActorId TExecutorPoolBaseMailboxed::Register(IActor* actor, TMailboxType::EType mailboxType, ui64 revolvingWriteCounter, const TActorId& parentId) {
+ NHPTimer::STime hpstart = GetCycleCountFast();
#ifdef ACTORSLIB_COLLECT_EXEC_STATS
ui32 at = actor->GetActivityType();
if (at >= Stats.MaxActivityType())
@@ -72,7 +72,7 @@ namespace NActors {
TMailboxHeader* mailbox = nullptr;
if (revolvingWriteCounter == 0)
- revolvingWriteCounter = AtomicIncrement(RegisterRevolvingCounter);
+ revolvingWriteCounter = AtomicIncrement(RegisterRevolvingCounter);
{
ui32 hintBackoff = 0;
@@ -105,34 +105,34 @@ namespace NActors {
switch (mailboxType) {
case TMailboxType::Simple:
- UnlockFromExecution((TMailboxTable::TSimpleMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
+ UnlockFromExecution((TMailboxTable::TSimpleMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
break;
case TMailboxType::Revolving:
- UnlockFromExecution((TMailboxTable::TRevolvingMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
+ UnlockFromExecution((TMailboxTable::TRevolvingMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
break;
case TMailboxType::HTSwap:
- UnlockFromExecution((TMailboxTable::THTSwapMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
+ UnlockFromExecution((TMailboxTable::THTSwapMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
break;
case TMailboxType::ReadAsFilled:
- UnlockFromExecution((TMailboxTable::TReadAsFilledMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
+ UnlockFromExecution((TMailboxTable::TReadAsFilledMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
break;
case TMailboxType::TinyReadAsFilled:
- UnlockFromExecution((TMailboxTable::TTinyReadAsFilledMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
+ UnlockFromExecution((TMailboxTable::TTinyReadAsFilledMailbox*)mailbox, this, false, hint, MaxWorkers, ++revolvingWriteCounter);
break;
default:
Y_FAIL();
}
- NHPTimer::STime elapsed = GetCycleCountFast() - hpstart;
+ NHPTimer::STime elapsed = GetCycleCountFast() - hpstart;
if (elapsed > 1000000) {
LWPROBE(SlowRegisterNew, PoolId, NHPTimer::GetSeconds(elapsed) * 1000.0);
}
return actorId;
- }
-
- TActorId TExecutorPoolBaseMailboxed::Register(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId) {
- NHPTimer::STime hpstart = GetCycleCountFast();
+ }
+
+ TActorId TExecutorPoolBaseMailboxed::Register(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId) {
+ NHPTimer::STime hpstart = GetCycleCountFast();
#ifdef ACTORSLIB_COLLECT_EXEC_STATS
ui32 at = actor->GetActivityType();
if (at >= Stats.MaxActivityType())
@@ -146,19 +146,19 @@ namespace NActors {
const TActorId actorId(ActorSystem->NodeId, PoolId, localActorId, hint);
DoActorInit(ActorSystem, actor, actorId, parentId);
- NHPTimer::STime elapsed = GetCycleCountFast() - hpstart;
+ NHPTimer::STime elapsed = GetCycleCountFast() - hpstart;
if (elapsed > 1000000) {
LWPROBE(SlowRegisterAdd, PoolId, NHPTimer::GetSeconds(elapsed) * 1000.0);
}
return actorId;
- }
-
+ }
+
TAffinity* TExecutorPoolBase::Affinity() const {
return ThreadsAffinity.Get();
}
- bool TExecutorPoolBaseMailboxed::Cleanup() {
+ bool TExecutorPoolBaseMailboxed::Cleanup() {
return MailboxTable->Cleanup();
}
diff --git a/library/cpp/actors/core/executor_pool_base.h b/library/cpp/actors/core/executor_pool_base.h
index c84ce1af77..22247ae1c7 100644
--- a/library/cpp/actors/core/executor_pool_base.h
+++ b/library/cpp/actors/core/executor_pool_base.h
@@ -8,7 +8,7 @@
#include <library/cpp/actors/util/threadparkpad.h>
namespace NActors {
- class TExecutorPoolBaseMailboxed: public IExecutorPool {
+ class TExecutorPoolBaseMailboxed: public IExecutorPool {
protected:
TActorSystem* ActorSystem;
THolder<TMailboxTable> MailboxTable;
@@ -17,33 +17,33 @@ namespace NActors {
// registrations might be done in threads from other pools)
TExecutorThreadStats Stats;
#endif
- TAtomic RegisterRevolvingCounter = 0;
- ui64 AllocateID();
+ TAtomic RegisterRevolvingCounter = 0;
+ ui64 AllocateID();
public:
- TExecutorPoolBaseMailboxed(ui32 poolId, ui32 maxActivityType);
- ~TExecutorPoolBaseMailboxed();
- void ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingWriteCounter) override;
+ TExecutorPoolBaseMailboxed(ui32 poolId, ui32 maxActivityType);
+ ~TExecutorPoolBaseMailboxed();
+ void ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingWriteCounter) override;
bool Send(TAutoPtr<IEventHandle>& ev) override;
TActorId Register(IActor* actor, TMailboxType::EType mailboxType, ui64 revolvingWriteCounter, const TActorId& parentId) override;
TActorId Register(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId) override;
bool Cleanup() override;
- };
+ };
- class TExecutorPoolBase: public TExecutorPoolBaseMailboxed {
- protected:
- const ui32 PoolThreads;
- TIntrusivePtr<TAffinity> ThreadsAffinity;
- TAtomic Semaphore = 0;
- TUnorderedCache<ui32, 512, 4> Activations;
- TAtomic ActivationsRevolvingCounter = 0;
- volatile bool StopFlag = false;
- public:
- TExecutorPoolBase(ui32 poolId, ui32 threads, TAffinity* affinity, ui32 maxActivityType);
- ~TExecutorPoolBase();
- void ScheduleActivation(ui32 activation) override;
+ class TExecutorPoolBase: public TExecutorPoolBaseMailboxed {
+ protected:
+ const ui32 PoolThreads;
+ TIntrusivePtr<TAffinity> ThreadsAffinity;
+ TAtomic Semaphore = 0;
+ TUnorderedCache<ui32, 512, 4> Activations;
+ TAtomic ActivationsRevolvingCounter = 0;
+ volatile bool StopFlag = false;
+ public:
+ TExecutorPoolBase(ui32 poolId, ui32 threads, TAffinity* affinity, ui32 maxActivityType);
+ ~TExecutorPoolBase();
+ void ScheduleActivation(ui32 activation) override;
TAffinity* Affinity() const override;
ui32 GetThreads() const override;
};
-
- void DoActorInit(TActorSystem*, IActor*, const TActorId&, const TActorId&);
+
+ void DoActorInit(TActorSystem*, IActor*, const TActorId&, const TActorId&);
}
diff --git a/library/cpp/actors/core/executor_pool_basic.cpp b/library/cpp/actors/core/executor_pool_basic.cpp
index 4dce16939a..16541889c6 100644
--- a/library/cpp/actors/core/executor_pool_basic.cpp
+++ b/library/cpp/actors/core/executor_pool_basic.cpp
@@ -1,8 +1,8 @@
#include "executor_pool_basic.h"
-#include "probes.h"
+#include "probes.h"
#include "mailbox.h"
#include <library/cpp/actors/util/affinity.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#ifdef _linux_
#include <pthread.h>
@@ -12,7 +12,7 @@ namespace NActors {
LWTRACE_USING(ACTORLIB_PROVIDER);
constexpr TDuration TBasicExecutorPool::DEFAULT_TIME_PER_MAILBOX;
-
+
TBasicExecutorPool::TBasicExecutorPool(
ui32 poolId,
ui32 threads,
@@ -23,7 +23,7 @@ namespace NActors {
ui32 eventsPerMailbox,
int realtimePriority,
ui32 maxActivityType)
- : TExecutorPoolBase(poolId, threads, affinity, maxActivityType)
+ : TExecutorPoolBase(poolId, threads, affinity, maxActivityType)
, SpinThreshold(spinThreshold)
, SpinThresholdCycles(spinThreshold * NHPTimer::GetCyclesPerSecond() * 0.000001) // convert microseconds to cycles
, Threads(new TThreadCtx[threads])
@@ -38,45 +38,45 @@ namespace NActors {
{
}
- TBasicExecutorPool::TBasicExecutorPool(const TBasicExecutorPoolConfig& cfg)
- : TBasicExecutorPool(
- cfg.PoolId,
- cfg.Threads,
- cfg.SpinThreshold,
- cfg.PoolName,
- new TAffinity(cfg.Affinity),
- cfg.TimePerMailbox,
- cfg.EventsPerMailbox,
- cfg.RealtimePriority,
- cfg.MaxActivityType
- )
- {}
-
+ TBasicExecutorPool::TBasicExecutorPool(const TBasicExecutorPoolConfig& cfg)
+ : TBasicExecutorPool(
+ cfg.PoolId,
+ cfg.Threads,
+ cfg.SpinThreshold,
+ cfg.PoolName,
+ new TAffinity(cfg.Affinity),
+ cfg.TimePerMailbox,
+ cfg.EventsPerMailbox,
+ cfg.RealtimePriority,
+ cfg.MaxActivityType
+ )
+ {}
+
TBasicExecutorPool::~TBasicExecutorPool() {
Threads.Destroy();
}
- ui32 TBasicExecutorPool::GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
- ui32 workerId = wctx.WorkerId;
- Y_VERIFY_DEBUG(workerId < PoolThreads);
+ ui32 TBasicExecutorPool::GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
+ ui32 workerId = wctx.WorkerId;
+ Y_VERIFY_DEBUG(workerId < PoolThreads);
NHPTimer::STime elapsed = 0;
NHPTimer::STime parked = 0;
NHPTimer::STime blocked = 0;
- NHPTimer::STime hpstart = GetCycleCountFast();
+ NHPTimer::STime hpstart = GetCycleCountFast();
NHPTimer::STime hpnow;
- TThreadCtx& threadCtx = Threads[workerId];
+ TThreadCtx& threadCtx = Threads[workerId];
AtomicSet(threadCtx.WaitingFlag, TThreadCtx::WS_NONE);
if (Y_UNLIKELY(AtomicGet(threadCtx.BlockedFlag) != TThreadCtx::BS_NONE)) {
do {
if (AtomicCas(&threadCtx.BlockedFlag, TThreadCtx::BS_BLOCKED, TThreadCtx::BS_BLOCKING)) {
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
elapsed += hpnow - hpstart;
if (threadCtx.BlockedPad.Park()) // interrupted
return 0;
- hpstart = GetCycleCountFast();
+ hpstart = GetCycleCountFast();
blocked += hpstart - hpnow;
}
} while (AtomicGet(threadCtx.BlockedFlag) != TThreadCtx::BS_NONE && !AtomicLoad(&StopFlag));
@@ -94,7 +94,7 @@ namespace NActors {
// counter just turned into a duration and we should store that
// duration. Otherwise another thread raced with us and
// subtracted some other timestamp t2.
- const i64 t = GetCycleCountFast();
+ const i64 t = GetCycleCountFast();
const i64 x = AtomicGetAndAdd(MaxUtilizationCounter, t);
if (x < 0 && x + t > 0)
AtomicStore(&MaxUtilizationAccumulator, x + t);
@@ -106,14 +106,14 @@ namespace NActors {
if (SpinThreshold > 0) {
// spin configured period
AtomicSet(threadCtx.WaitingFlag, TThreadCtx::WS_ACTIVE);
- ui64 start = GetCycleCountFast();
+ ui64 start = GetCycleCountFast();
bool doSpin = true;
while (true) {
for (ui32 j = 0; doSpin && j < 12; ++j) {
- if (GetCycleCountFast() >= (start + SpinThresholdCycles)) {
- doSpin = false;
- break;
- }
+ if (GetCycleCountFast() >= (start + SpinThresholdCycles)) {
+ doSpin = false;
+ break;
+ }
for (ui32 i = 0; i < 12; ++i) {
if (AtomicLoad(&threadCtx.WaitingFlag) == TThreadCtx::WS_ACTIVE) {
SpinLockPause();
@@ -122,7 +122,7 @@ namespace NActors {
break;
}
}
- }
+ }
if (!doSpin) {
break;
}
@@ -134,23 +134,23 @@ namespace NActors {
if (AtomicLoad(&threadCtx.WaitingFlag) == TThreadCtx::WS_ACTIVE) {
if (AtomicCas(&threadCtx.WaitingFlag, TThreadCtx::WS_BLOCKED, TThreadCtx::WS_ACTIVE)) {
do {
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
elapsed += hpnow - hpstart;
if (threadCtx.Pad.Park()) // interrupted
return 0;
- hpstart = GetCycleCountFast();
+ hpstart = GetCycleCountFast();
parked += hpstart - hpnow;
} while (AtomicLoad(&threadCtx.WaitingFlag) == TThreadCtx::WS_BLOCKED);
}
- }
+ }
} else {
AtomicSet(threadCtx.WaitingFlag, TThreadCtx::WS_BLOCKED);
do {
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
elapsed += hpnow - hpstart;
if (threadCtx.Pad.Park()) // interrupted
return 0;
- hpstart = GetCycleCountFast();
+ hpstart = GetCycleCountFast();
parked += hpstart - hpnow;
} while (AtomicLoad(&threadCtx.WaitingFlag) == TThreadCtx::WS_BLOCKED);
}
@@ -170,7 +170,7 @@ namespace NActors {
// arbitrary order, which would cause counter to oscillate
// around zero. When it crosses zero is a good indication of a
// correct value.
- const i64 t = GetCycleCountFast();
+ const i64 t = GetCycleCountFast();
const i64 x = AtomicGetAndAdd(MaxUtilizationCounter, -t);
if (x > 0 && x - t < 0)
AtomicStore(&MaxUtilizationAccumulator, x);
@@ -183,17 +183,17 @@ namespace NActors {
// ok, has work suggested, must dequeue
while (!RelaxedLoad(&StopFlag)) {
if (const ui32 activation = Activations.Pop(++revolvingCounter)) {
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
elapsed += hpnow - hpstart;
- wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, elapsed);
+ wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, elapsed);
if (parked > 0) {
- wctx.AddParkedCycles(parked);
+ wctx.AddParkedCycles(parked);
}
if (blocked > 0) {
- wctx.AddBlockedCycles(blocked);
+ wctx.AddBlockedCycles(blocked);
}
return activation;
- }
+ }
SpinLockPause();
}
@@ -201,7 +201,7 @@ namespace NActors {
return 0;
}
- inline void TBasicExecutorPool::WakeUpLoop() {
+ inline void TBasicExecutorPool::WakeUpLoop() {
for (ui32 i = 0;;) {
TThreadCtx& threadCtx = Threads[i % PoolThreads];
switch (AtomicLoad(&threadCtx.WaitingFlag)) {
@@ -230,7 +230,7 @@ namespace NActors {
Activations.Push(activation, revolvingCounter);
const TAtomic x = AtomicIncrement(Semaphore);
if (x <= 0) { // we must find someone to wake-up
- WakeUpLoop();
+ WakeUpLoop();
}
}
@@ -247,7 +247,7 @@ namespace NActors {
}
}
- void TBasicExecutorPool::Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) {
+ void TBasicExecutorPool::Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) {
TAffinityGuard affinityGuard(Affinity());
ActorSystem = actorSystem;
@@ -259,7 +259,7 @@ namespace NActors {
Threads[i].Thread.Reset(
new TExecutorThread(
i,
- 0, // CpuId is not used in BASIC pool
+ 0, // CpuId is not used in BASIC pool
actorSystem,
this,
MailboxTable.Get(),
@@ -277,7 +277,7 @@ namespace NActors {
TAffinityGuard affinityGuard(Affinity());
ThreadUtilization = 0;
- AtomicAdd(MaxUtilizationCounter, -(i64)GetCycleCountFast());
+ AtomicAdd(MaxUtilizationCounter, -(i64)GetCycleCountFast());
for (ui32 i = 0; i != PoolThreads; ++i) {
Threads[i].Thread->Start();
@@ -297,27 +297,27 @@ namespace NActors {
Threads[i].Thread->Join();
}
- void TBasicExecutorPool::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_VERIFY_DEBUG(workerId < PoolThreads);
+ void TBasicExecutorPool::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_VERIFY_DEBUG(workerId < PoolThreads);
- Schedule(deadline - ActorSystem->Timestamp(), ev, cookie, workerId);
+ Schedule(deadline - ActorSystem->Timestamp(), ev, cookie, workerId);
}
- void TBasicExecutorPool::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_VERIFY_DEBUG(workerId < PoolThreads);
+ void TBasicExecutorPool::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_VERIFY_DEBUG(workerId < PoolThreads);
const auto current = ActorSystem->Monotonic();
if (deadline < current)
deadline = current;
- ScheduleWriters[workerId].Push(deadline.MicroSeconds(), ev.Release(), cookie);
+ ScheduleWriters[workerId].Push(deadline.MicroSeconds(), ev.Release(), cookie);
}
- void TBasicExecutorPool::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_VERIFY_DEBUG(workerId < PoolThreads);
+ void TBasicExecutorPool::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_VERIFY_DEBUG(workerId < PoolThreads);
const auto deadline = ActorSystem->Monotonic() + delta;
- ScheduleWriters[workerId].Push(deadline.MicroSeconds(), ev.Release(), cookie);
+ ScheduleWriters[workerId].Push(deadline.MicroSeconds(), ev.Release(), cookie);
}
void TBasicExecutorPool::SetRealTimeMode() const {
@@ -421,7 +421,7 @@ namespace NActors {
; // other thread woke this sleeping thread
}
// if thread has already been awakened then we must awaken the other
- WakeUpLoop();
+ WakeUpLoop();
}
}
}
diff --git a/library/cpp/actors/core/executor_pool_basic.h b/library/cpp/actors/core/executor_pool_basic.h
index 023190f7fe..83224ed9d3 100644
--- a/library/cpp/actors/core/executor_pool_basic.h
+++ b/library/cpp/actors/core/executor_pool_basic.h
@@ -67,8 +67,8 @@ namespace NActors {
TMutex ChangeThreadsLock;
public:
- static constexpr TDuration DEFAULT_TIME_PER_MAILBOX = TBasicExecutorPoolConfig::DEFAULT_TIME_PER_MAILBOX;
- static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX;
+ static constexpr TDuration DEFAULT_TIME_PER_MAILBOX = TBasicExecutorPoolConfig::DEFAULT_TIME_PER_MAILBOX;
+ static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX;
TBasicExecutorPool(ui32 poolId,
ui32 threads,
@@ -79,18 +79,18 @@ namespace NActors {
ui32 eventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX,
int realtimePriority = 0,
ui32 maxActivityType = 1);
- explicit TBasicExecutorPool(const TBasicExecutorPoolConfig& cfg);
+ explicit TBasicExecutorPool(const TBasicExecutorPoolConfig& cfg);
~TBasicExecutorPool();
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingReadCounter) override;
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingReadCounter) override;
- void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
- void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
- void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
void ScheduleActivationEx(ui32 activation, ui64 revolvingWriteCounter) override;
- void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) override;
+ void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) override;
void Start() override;
void PrepareStop() override;
void Shutdown() override;
@@ -106,6 +106,6 @@ namespace NActors {
void SetThreadCount(ui32 threads);
private:
- void WakeUpLoop();
+ void WakeUpLoop();
};
}
diff --git a/library/cpp/actors/core/executor_pool_basic_ut.cpp b/library/cpp/actors/core/executor_pool_basic_ut.cpp
index 76dff693af..be87e5df33 100644
--- a/library/cpp/actors/core/executor_pool_basic_ut.cpp
+++ b/library/cpp/actors/core/executor_pool_basic_ut.cpp
@@ -377,59 +377,59 @@ Y_UNIT_TEST_SUITE(BasicExecutorPool) {
Sleep(TDuration::MilliSeconds(1));
}
}
-
- Y_UNIT_TEST(CheckStats) {
- const size_t size = 4;
- const size_t msgCount = 1e4;
- TBasicExecutorPool* executorPool = new TBasicExecutorPool(0, size, 50);
-
- auto setup = GetActorSystemSetup(executorPool);
- TActorSystem actorSystem(setup);
- actorSystem.Start();
-
- auto begin = TInstant::Now();
-
- auto actor = new TTestSenderActor();
- auto actorId = actorSystem.Register(actor);
- actor->Start(actor->SelfId(), msgCount);
- actorSystem.Send(actorId, new TEvMsg());
-
- while (actor->GetCounter()) {
- auto now = TInstant::Now();
- UNIT_ASSERT_C(now - begin < TDuration::Seconds(5), "Counter is " << actor->GetCounter());
-
- Sleep(TDuration::MilliSeconds(1));
- }
-
- TVector<TExecutorThreadStats> stats;
- TExecutorPoolStats poolStats;
- actorSystem.GetPoolStats(0, poolStats, stats);
- // Sum all per-thread counters into the 0th element
- for (ui32 idx = 1; idx < stats.size(); ++idx) {
- stats[0].Aggregate(stats[idx]);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(stats[0].SentEvents, msgCount - 1);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PreemptedEvents, 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].NonDeliveredEvents, 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].EmptyMailboxActivation, 0);
- //UNIT_ASSERT_VALUES_EQUAL(stats[0].CpuNs, 0); // depends on total duration of test, so undefined
- UNIT_ASSERT(stats[0].ElapsedTicks > 0);
- UNIT_ASSERT(stats[0].ParkedTicks > 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].BlockedTicks, 0);
- UNIT_ASSERT(stats[0].ActivationTimeHistogram.TotalSamples >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].EventDeliveryTimeHistogram.TotalSamples, msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].EventProcessingCountHistogram.TotalSamples, msgCount);
- UNIT_ASSERT(stats[0].EventProcessingTimeHistogram.TotalSamples > 0);
- UNIT_ASSERT(stats[0].ElapsedTicksByActivity[0] > 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEventsByActivity[0], msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ActorsAliveByActivity[0], 1);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ScheduledEventsByActivity[0], 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolDestroyedActors, 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolAllocatedMailboxes, 4095); // one line
- UNIT_ASSERT(stats[0].MailboxPushedOutByTime + stats[0].MailboxPushedOutByEventCount >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].MailboxPushedOutBySoftPreemption, 0);
- }
+
+ Y_UNIT_TEST(CheckStats) {
+ const size_t size = 4;
+ const size_t msgCount = 1e4;
+ TBasicExecutorPool* executorPool = new TBasicExecutorPool(0, size, 50);
+
+ auto setup = GetActorSystemSetup(executorPool);
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ auto begin = TInstant::Now();
+
+ auto actor = new TTestSenderActor();
+ auto actorId = actorSystem.Register(actor);
+ actor->Start(actor->SelfId(), msgCount);
+ actorSystem.Send(actorId, new TEvMsg());
+
+ while (actor->GetCounter()) {
+ auto now = TInstant::Now();
+ UNIT_ASSERT_C(now - begin < TDuration::Seconds(5), "Counter is " << actor->GetCounter());
+
+ Sleep(TDuration::MilliSeconds(1));
+ }
+
+ TVector<TExecutorThreadStats> stats;
+ TExecutorPoolStats poolStats;
+ actorSystem.GetPoolStats(0, poolStats, stats);
+ // Sum all per-thread counters into the 0th element
+ for (ui32 idx = 1; idx < stats.size(); ++idx) {
+ stats[0].Aggregate(stats[idx]);
+ }
+
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].SentEvents, msgCount - 1);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PreemptedEvents, 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].NonDeliveredEvents, 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].EmptyMailboxActivation, 0);
+ //UNIT_ASSERT_VALUES_EQUAL(stats[0].CpuNs, 0); // depends on total duration of test, so undefined
+ UNIT_ASSERT(stats[0].ElapsedTicks > 0);
+ UNIT_ASSERT(stats[0].ParkedTicks > 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].BlockedTicks, 0);
+ UNIT_ASSERT(stats[0].ActivationTimeHistogram.TotalSamples >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].EventDeliveryTimeHistogram.TotalSamples, msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].EventProcessingCountHistogram.TotalSamples, msgCount);
+ UNIT_ASSERT(stats[0].EventProcessingTimeHistogram.TotalSamples > 0);
+ UNIT_ASSERT(stats[0].ElapsedTicksByActivity[0] > 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEventsByActivity[0], msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ActorsAliveByActivity[0], 1);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ScheduledEventsByActivity[0], 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolDestroyedActors, 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolAllocatedMailboxes, 4095); // one line
+ UNIT_ASSERT(stats[0].MailboxPushedOutByTime + stats[0].MailboxPushedOutByEventCount >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].MailboxPushedOutBySoftPreemption, 0);
+ }
}
diff --git a/library/cpp/actors/core/executor_pool_io.cpp b/library/cpp/actors/core/executor_pool_io.cpp
index fb557ae6b0..29e64220db 100644
--- a/library/cpp/actors/core/executor_pool_io.cpp
+++ b/library/cpp/actors/core/executor_pool_io.cpp
@@ -1,59 +1,59 @@
#include "executor_pool_io.h"
#include "mailbox.h"
#include <library/cpp/actors/util/affinity.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
namespace NActors {
- TIOExecutorPool::TIOExecutorPool(ui32 poolId, ui32 threads, const TString& poolName, TAffinity* affinity, ui32 maxActivityType)
- : TExecutorPoolBase(poolId, threads, affinity, maxActivityType)
+ TIOExecutorPool::TIOExecutorPool(ui32 poolId, ui32 threads, const TString& poolName, TAffinity* affinity, ui32 maxActivityType)
+ : TExecutorPoolBase(poolId, threads, affinity, maxActivityType)
, Threads(new TThreadCtx[threads])
, PoolName(poolName)
- {}
-
- TIOExecutorPool::TIOExecutorPool(const TIOExecutorPoolConfig& cfg)
- : TIOExecutorPool(
- cfg.PoolId,
- cfg.Threads,
- cfg.PoolName,
- new TAffinity(cfg.Affinity),
- cfg.MaxActivityType
- )
- {}
-
+ {}
+
+ TIOExecutorPool::TIOExecutorPool(const TIOExecutorPoolConfig& cfg)
+ : TIOExecutorPool(
+ cfg.PoolId,
+ cfg.Threads,
+ cfg.PoolName,
+ new TAffinity(cfg.Affinity),
+ cfg.MaxActivityType
+ )
+ {}
+
TIOExecutorPool::~TIOExecutorPool() {
Threads.Destroy();
while (ThreadQueue.Pop(0))
;
}
- ui32 TIOExecutorPool::GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
- ui32 workerId = wctx.WorkerId;
- Y_VERIFY_DEBUG(workerId < PoolThreads);
+ ui32 TIOExecutorPool::GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
+ ui32 workerId = wctx.WorkerId;
+ Y_VERIFY_DEBUG(workerId < PoolThreads);
NHPTimer::STime elapsed = 0;
NHPTimer::STime parked = 0;
- NHPTimer::STime hpstart = GetCycleCountFast();
+ NHPTimer::STime hpstart = GetCycleCountFast();
NHPTimer::STime hpnow;
const TAtomic x = AtomicDecrement(Semaphore);
if (x < 0) {
- TThreadCtx& threadCtx = Threads[workerId];
- ThreadQueue.Push(workerId + 1, revolvingCounter);
- hpnow = GetCycleCountFast();
+ TThreadCtx& threadCtx = Threads[workerId];
+ ThreadQueue.Push(workerId + 1, revolvingCounter);
+ hpnow = GetCycleCountFast();
elapsed += hpnow - hpstart;
if (threadCtx.Pad.Park())
return 0;
- hpstart = GetCycleCountFast();
+ hpstart = GetCycleCountFast();
parked += hpstart - hpnow;
}
while (!RelaxedLoad(&StopFlag)) {
if (const ui32 activation = Activations.Pop(++revolvingCounter)) {
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
elapsed += hpnow - hpstart;
- wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, elapsed);
+ wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, elapsed);
if (parked > 0) {
- wctx.AddParkedCycles(parked);
+ wctx.AddParkedCycles(parked);
}
return activation;
}
@@ -63,12 +63,12 @@ namespace NActors {
return 0;
}
- void TIOExecutorPool::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Schedule(deadline - ActorSystem->Timestamp(), ev, cookie, workerId);
+ void TIOExecutorPool::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Schedule(deadline - ActorSystem->Timestamp(), ev, cookie, workerId);
}
- void TIOExecutorPool::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_UNUSED(workerId);
+ void TIOExecutorPool::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_UNUSED(workerId);
const auto current = ActorSystem->Monotonic();
if (deadline < current)
@@ -78,8 +78,8 @@ namespace NActors {
ScheduleQueue->Writer.Push(deadline.MicroSeconds(), ev.Release(), cookie);
}
- void TIOExecutorPool::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_UNUSED(workerId);
+ void TIOExecutorPool::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_UNUSED(workerId);
const auto deadline = ActorSystem->Monotonic() + delta;
TTicketLock::TGuard guard(&ScheduleLock);
@@ -101,7 +101,7 @@ namespace NActors {
}
}
- void TIOExecutorPool::Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) {
+ void TIOExecutorPool::Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) {
TAffinityGuard affinityGuard(Affinity());
ActorSystem = actorSystem;
@@ -109,7 +109,7 @@ namespace NActors {
ScheduleQueue.Reset(new NSchedulerQueue::TQueueType());
for (ui32 i = 0; i != PoolThreads; ++i) {
- Threads[i].Thread.Reset(new TExecutorThread(i, 0, actorSystem, this, MailboxTable.Get(), PoolName));
+ Threads[i].Thread.Reset(new TExecutorThread(i, 0, actorSystem, this, MailboxTable.Get(), PoolName));
}
*scheduleReaders = &ScheduleQueue->Reader;
diff --git a/library/cpp/actors/core/executor_pool_io.h b/library/cpp/actors/core/executor_pool_io.h
index e576d642a1..00de73bacd 100644
--- a/library/cpp/actors/core/executor_pool_io.h
+++ b/library/cpp/actors/core/executor_pool_io.h
@@ -25,20 +25,20 @@ namespace NActors {
const TString PoolName;
public:
- TIOExecutorPool(ui32 poolId, ui32 threads, const TString& poolName = "", TAffinity* affinity = nullptr,
+ TIOExecutorPool(ui32 poolId, ui32 threads, const TString& poolName = "", TAffinity* affinity = nullptr,
ui32 maxActivityType = 1);
- explicit TIOExecutorPool(const TIOExecutorPoolConfig& cfg);
+ explicit TIOExecutorPool(const TIOExecutorPoolConfig& cfg);
~TIOExecutorPool();
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override;
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override;
- void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
- void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
- void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
void ScheduleActivationEx(ui32 activation, ui64 revolvingWriteCounter) override;
- void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) override;
+ void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) override;
void Start() override;
void PrepareStop() override;
void Shutdown() override;
diff --git a/library/cpp/actors/core/executor_pool_united.cpp b/library/cpp/actors/core/executor_pool_united.cpp
index dac6245635..d932714aa9 100644
--- a/library/cpp/actors/core/executor_pool_united.cpp
+++ b/library/cpp/actors/core/executor_pool_united.cpp
@@ -1,1428 +1,1428 @@
-#include "executor_pool_united.h"
-
-#include "balancer.h"
-#include "cpu_state.h"
-#include "executor_thread.h"
-#include "probes.h"
+#include "executor_pool_united.h"
+
+#include "balancer.h"
+#include "cpu_state.h"
+#include "executor_thread.h"
+#include "probes.h"
#include "mailbox.h"
-#include "scheduler_queue.h"
+#include "scheduler_queue.h"
#include <library/cpp/actors/util/affinity.h>
-#include <library/cpp/actors/util/datetime.h>
-#include <library/cpp/actors/util/futex.h>
-#include <library/cpp/actors/util/intrinsics.h>
-#include <library/cpp/actors/util/timerfd.h>
-
-#include <util/system/datetime.h>
-#include <util/system/hp_timer.h>
+#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/futex.h>
+#include <library/cpp/actors/util/intrinsics.h>
+#include <library/cpp/actors/util/timerfd.h>
-#include <algorithm>
+#include <util/system/datetime.h>
+#include <util/system/hp_timer.h>
+#include <algorithm>
+
namespace NActors {
LWTRACE_USING(ACTORLIB_PROVIDER);
- struct TUnitedWorkers::TWorker: public TNonCopyable {
- TAutoPtr<TExecutorThread> Thread;
- volatile TThreadId ThreadId = UnknownThreadId;
- NSchedulerQueue::TQueueType SchedulerQueue;
- };
-
- struct TUnitedWorkers::TPool: public TNonCopyable {
- TAtomic Waiters = 0; // Number of idle cpus, waiting for activations in this pool
- char Padding[64 - sizeof(TAtomic)];
-
- TUnorderedCache<ui32, 512, 4> Activations; // MPMC-queue for mailbox activations
- TAtomic Active = 0; // Number of mailboxes ready for execution or currently executing
- TAtomic Tokens = 0; // Pending tokens (token is required for worker to start execution, guarantees concurrency limit and activation availability)
- volatile bool StopFlag = false;
-
- // Configuration
- TPoolId PoolId;
- TAtomicBase Concurrency; // Max concurrent workers running this pool
- IExecutorPool* ExecutorPool;
- TMailboxTable* MailboxTable;
- ui64 TimePerMailboxTs;
- ui32 EventsPerMailbox;
-
- // Cpus this pool is allowed to run on
- // Cpus are specified in wake order
- TStackVec<TCpu*, 15> WakeOrderCpus;
-
- ~TPool() {
- while (Activations.Pop(0)) {}
- }
-
- void Stop() {
- AtomicStore(&StopFlag, true);
- }
-
- bool IsUnited() const {
- return WakeOrderCpus.size();
- }
-
- // Add activation of newly scheduled mailbox. Returns generated token (unless concurrency is exceeded)
- bool PushActivation(ui32 activation, ui64 revolvingCounter) {
- Activations.Push(activation, revolvingCounter);
- TAtomicBase active = AtomicIncrement(Active);
- if (active <= Concurrency) { // token generated
- AtomicIncrement(Tokens);
- return true;
- }
- return false;
- }
-
- template <bool Relaxed>
- static bool TryAcquireTokenImpl(TAtomic* tokens) {
- while (true) {
- TAtomicBase value;
- if constexpr (Relaxed) {
- value = RelaxedLoad(tokens);
- } else {
- value = AtomicLoad(tokens);
- }
- if (value > 0) {
- if (AtomicCas(tokens, value - 1, value)) {
- return true; // token acquired
- }
- } else {
- return false; // no more tokens
- }
- }
- }
-
- // Try acquire pending token. Must be done before execution
- bool TryAcquireToken() {
- return TryAcquireTokenImpl<false>(&Tokens);
- }
-
- // Try acquire pending token. Must be done before execution
- bool TryAcquireTokenRelaxed() {
- return TryAcquireTokenImpl<true>(&Tokens);
- }
-
- // Get activation. Requires acquired token.
- void BeginExecution(ui32& activation, ui64 revolvingCounter) {
- while (!RelaxedLoad(&StopFlag)) {
- if (activation = Activations.Pop(++revolvingCounter)) {
- return;
- }
- SpinLockPause();
- }
- activation = 0; // should stop
- }
-
- // End currently active execution and start new one if token is available.
- // Reuses token if it's not destroyed.
- // Returned `true` means successful switch, `activation` is filled.
- // Returned `false` means execution has ended, no need to call StopExecution()
- bool NextExecution(ui32& activation, ui64 revolvingCounter) {
- if (AtomicDecrement(Active) >= Concurrency) { // reuse just released token
- BeginExecution(activation, revolvingCounter);
- return true;
- } else if (TryAcquireToken()) { // another token acquired
- BeginExecution(activation, revolvingCounter);
- return true;
- }
- return false; // no more tokens available
- }
-
- // Stop active execution. Returns released token (unless it is destroyed)
- bool StopExecution() {
- TAtomicBase active = AtomicDecrement(Active);
- if (active >= Concurrency) { // token released
- AtomicIncrement(Tokens);
- return true;
- }
- return false; // token destroyed
- }
-
- // Switch worker context into this pool
- void Switch(TWorkerContext& wctx, ui64 softDeadlineTs, TExecutorThreadStats& stats) {
- wctx.Switch(ExecutorPool, MailboxTable, TimePerMailboxTs, EventsPerMailbox, softDeadlineTs, &stats);
- }
- };
-
- class TPoolScheduler {
- class TSchedulable {
- // Lower PoolBits store PoolId
- // All other higher bits store virtual runtime in cycles
- using TValue = ui64;
- TValue Value;
-
- static constexpr ui64 PoolIdMask = ui64((1ull << PoolBits) - 1);
- static constexpr ui64 VRunTsMask = ~PoolIdMask;
-
- public:
- explicit TSchedulable(TPoolId poolId = MaxPools, ui64 vrunts = 0)
- : Value((poolId & PoolIdMask) | (vrunts & VRunTsMask))
- {}
-
- TPoolId GetPoolId() const {
- return Value & PoolIdMask;
- }
-
- ui64 GetVRunTs() const {
- // Do not truncate pool id
- // NOTE: it decrease accuracy, but improves performance
- return Value;
- }
-
- ui64 GetPreciseVRunTs() const {
- return Value & VRunTsMask;
- }
-
- void SetVRunTs(ui64 vrunts) {
- Value = (Value & PoolIdMask) | (vrunts & VRunTsMask);
- }
-
- void Account(ui64 base, ui64 ts) {
- // Add at least minimum amount to change Value
- SetVRunTs(base + Max(ts, PoolIdMask + 1));
- }
- };
-
- // For min-heap of Items
- struct TCmp {
- bool operator()(TSchedulable lhs, TSchedulable rhs) const {
- return lhs.GetVRunTs() > rhs.GetVRunTs();
- }
- };
-
- TPoolId Size = 0; // total number of pools on this cpu
- TPoolId Current = 0; // index of current pool in `Items`
-
- // At the beginning `Current` items are orginized as binary min-heap -- ready to be scheduled
- // The rest `Size - Current` items are unordered (required to keep track of last vrunts)
- TSchedulable Items[MaxPools]; // virtual runtime in cycles for each pool
- ui64 MinVRunTs = 0; // virtual runtime used by waking pools (system's vrunts)
- ui64 Ts = 0; // real timestamp of current execution start (for accounting)
-
- // Maps PoolId into it's inverse weight
- ui64 InvWeights[MaxPools];
- static constexpr ui64 VRunTsOverflow = ui64(1ull << 62ull) / MaxPoolWeight;
-
- public:
- void AddPool(TPoolId pool, TPoolWeight weight) {
- Items[Size] = TSchedulable(pool, MinVRunTs);
- Size++;
- InvWeights[pool] = MaxPoolWeight / std::clamp(weight ? weight : DefPoolWeight, MinPoolWeight, MaxPoolWeight);
- }
-
- // Iterate over pools in scheduling order
- // should be used in construction:
- // for (TPoolId pool = Begin(); pool != End(); pool = Next())
- TPoolId Begin() {
- // Wrap vruntime around to avoid overflow, if required
- if (Y_UNLIKELY(MinVRunTs >= VRunTsOverflow)) {
- for (TPoolId i = 0; i < Size; i++) {
- ui64 ts = Items[i].GetPreciseVRunTs();
- Items[i].SetVRunTs(ts >= VRunTsOverflow ? ts - VRunTsOverflow : 0);
+ struct TUnitedWorkers::TWorker: public TNonCopyable {
+ TAutoPtr<TExecutorThread> Thread;
+ volatile TThreadId ThreadId = UnknownThreadId;
+ NSchedulerQueue::TQueueType SchedulerQueue;
+ };
+
+ struct TUnitedWorkers::TPool: public TNonCopyable {
+ TAtomic Waiters = 0; // Number of idle cpus, waiting for activations in this pool
+ char Padding[64 - sizeof(TAtomic)];
+
+ TUnorderedCache<ui32, 512, 4> Activations; // MPMC-queue for mailbox activations
+ TAtomic Active = 0; // Number of mailboxes ready for execution or currently executing
+ TAtomic Tokens = 0; // Pending tokens (token is required for worker to start execution, guarantees concurrency limit and activation availability)
+ volatile bool StopFlag = false;
+
+ // Configuration
+ TPoolId PoolId;
+ TAtomicBase Concurrency; // Max concurrent workers running this pool
+ IExecutorPool* ExecutorPool;
+ TMailboxTable* MailboxTable;
+ ui64 TimePerMailboxTs;
+ ui32 EventsPerMailbox;
+
+ // Cpus this pool is allowed to run on
+ // Cpus are specified in wake order
+ TStackVec<TCpu*, 15> WakeOrderCpus;
+
+ ~TPool() {
+ while (Activations.Pop(0)) {}
+ }
+
+ void Stop() {
+ AtomicStore(&StopFlag, true);
+ }
+
+ bool IsUnited() const {
+ return WakeOrderCpus.size();
+ }
+
+ // Add activation of newly scheduled mailbox. Returns generated token (unless concurrency is exceeded)
+ bool PushActivation(ui32 activation, ui64 revolvingCounter) {
+ Activations.Push(activation, revolvingCounter);
+ TAtomicBase active = AtomicIncrement(Active);
+ if (active <= Concurrency) { // token generated
+ AtomicIncrement(Tokens);
+ return true;
+ }
+ return false;
+ }
+
+ template <bool Relaxed>
+ static bool TryAcquireTokenImpl(TAtomic* tokens) {
+ while (true) {
+ TAtomicBase value;
+ if constexpr (Relaxed) {
+ value = RelaxedLoad(tokens);
+ } else {
+ value = AtomicLoad(tokens);
}
- MinVRunTs -= VRunTsOverflow;
- }
- Current = Size;
- std::make_heap(Items, Items + Current, TCmp());
- return Next();
- }
-
- constexpr TPoolId End() const {
- return MaxPools;
- }
-
- TPoolId Next() {
- if (Current > 0) {
- std::pop_heap(Items, Items + Current, TCmp());
- Current--;
- return CurrentPool();
- } else {
- return End();
- }
- }
-
- // Scheduling was successful, we are going to run CurrentPool()
- void Scheduled() {
- MinVRunTs = Max(MinVRunTs, Items[Current].GetPreciseVRunTs());
- // NOTE: Ts is propagated on Account() to avoid gaps
- }
-
- // Schedule specific pool that woke up cpu after idle
- void ScheduledAfterIdle(TPoolId pool, ui64 ts) {
- if (Y_UNLIKELY(ts < Ts)) { // anomaly: time goes backwards (e.g. rdtsc is reset to zero on cpu reset)
- Ts = ts; // just skip anomalous time slice
- return;
- }
- MinVRunTs += (ts - Ts) * (MaxPoolWeight / DefPoolWeight); // propagate system's vrunts to blur difference between pools
- Ts = ts; // propagate time w/o accounting to any pool
-
- // Set specified pool as current, it requires scan
- for (Current = 0; Current < Size && pool != Items[Current].GetPoolId(); Current++) {}
- Y_VERIFY(Current < Size);
- }
-
- // Account currently running pool till now (ts)
- void Account(ui64 ts) {
- // Skip time slice for the first run and when time goes backwards (e.g. rdtsc is reset to zero on cpu reset)
- if (Y_LIKELY(Ts > 0 && Ts <= ts)) {
- TPoolId pool = CurrentPool();
- Y_VERIFY(pool < MaxPools);
- Items[Current].Account(MinVRunTs, (ts - Ts) * InvWeights[pool]);
- }
- Ts = ts; // propagate time
- }
-
- TPoolId CurrentPool() const {
- return Items[Current].GetPoolId();
- }
- };
-
- // Cyclic array of timers for idle workers to wait for hard preemption on
- struct TIdleQueue: public TNonCopyable {
- TArrayHolder<TTimerFd> Timers;
- size_t Size;
- TAtomic EnqueueCounter = 0;
- TAtomic DequeueCounter = 0;
-
- explicit TIdleQueue(size_t size)
- : Timers(new TTimerFd[size])
- , Size(size)
- {}
-
- void Stop() {
- for (size_t i = 0; i < Size; i++) {
- Timers[i].Wake();
- }
- }
-
- // Returns timer which new idle-worker should wait for
- TTimerFd* Enqueue() {
- return &Timers[AtomicGetAndIncrement(EnqueueCounter) % Size];
- }
-
- // Returns timer that hard preemption should trigger to wake idle-worker
- TTimerFd* Dequeue() {
- return &Timers[AtomicGetAndIncrement(DequeueCounter) % Size];
- }
- };
-
- // Base class for cpu-local managers that help workers on single cpu to cooperate
- struct TCpuLocalManager: public TThrRefBase {
- TUnitedWorkers* United;
-
- explicit TCpuLocalManager(TUnitedWorkers* united)
- : United(united)
- {}
-
- virtual TWorkerId WorkerCount() const = 0;
- virtual void AddWorker(TWorkerId workerId) = 0;
- virtual void Stop() = 0;
- };
-
- // Represents cpu with single associated worker that is able to execute any pool.
- // It always executes pool assigned by balancer and switch pool only if assigned pool has changed
- struct TAssignedCpu: public TCpuLocalManager {
- bool Started = false;
-
- TAssignedCpu(TUnitedWorkers* united)
- : TCpuLocalManager(united)
- {}
-
- TWorkerId WorkerCount() const override {
- return 1;
- }
-
- void AddWorker(TWorkerId workerId) override {
- Y_UNUSED(workerId);
- }
-
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
- ui32 activation;
- if (Y_UNLIKELY(!Started)) {
- Started = true;
- } else if (Y_UNLIKELY(United->IsPoolReassigned(wctx))) {
- United->StopExecution(wctx.PoolId); // stop current execution and switch pool if reassigned
- } else if (United->NextExecution(wctx.PoolId, activation, revolvingCounter)) {
- return activation; // another activation from currently executing pool (or 0 if stopped)
- }
-
- // Switch to another pool, it blocks until token is acquired
- if (Y_UNLIKELY(!SwitchPool(wctx))) {
- return 0; // stopped
- }
- United->SwitchPool(wctx, 0);
- United->BeginExecution(wctx.PoolId, activation, revolvingCounter);
- return activation;
- }
-
- void Stop() override {
- }
-
- private:
- // Sets next pool to run, and acquires token, blocks if there are no tokens
- bool SwitchPool(TWorkerContext& wctx) {
- if (Y_UNLIKELY(United->IsStopped())) {
- return false;
- }
-
- // Run balancer (if it's time to)
- United->Balance();
-
- // Select pool to execute
- wctx.PoolId = United->AssignedPool(wctx);
- Y_VERIFY(wctx.PoolId != CpuShared);
- if (United->TryAcquireToken(wctx.PoolId)) {
- return true;
- }
-
- // No more work -- wait for activations (spinning, then blocked)
- wctx.PoolId = United->Idle(wctx.PoolId, wctx);
-
- // Wakeup or stop occured
- if (Y_UNLIKELY(wctx.PoolId == CpuStopped)) {
- return false;
- }
- return true; // United->Idle() has already acquired token
- }
- };
-
- // Lock-free data structure that help workers on single cpu to discover their state and do hard preemptions
- struct TSharedCpu: public TCpuLocalManager {
- // Current lease
- volatile TLease::TValue CurrentLease;
- char Padding1[64 - sizeof(TLease)];
-
- // Slow pools
- // the highest bit: 1=wait-for-slow-workers mode 0=else
- // any lower bit (poolId is bit position): 1=pool-is-slow 0=pool-is-fast
- volatile TPoolsMask SlowPoolsMask = 0;
- char Padding2[64 - sizeof(TPoolsMask)];
-
- // Must be accessed under never expiring lease to avoid races
- TPoolScheduler PoolSched;
- TWorkerId FastWorker = MaxWorkers;
- TTimerFd* PreemptionTimer = nullptr;
- ui64 HardPreemptionTs = 0;
- bool Started = false;
-
- TIdleQueue IdleQueue;
-
- struct TConfig {
- const TCpuId CpuId;
- const TWorkerId Workers;
- ui64 SoftLimitTs;
- ui64 HardLimitTs;
- ui64 EventLimitTs;
- ui64 LimitPrecisionTs;
- const int IdleWorkerPriority;
- const int FastWorkerPriority;
- const bool NoRealtime;
- const bool NoAffinity;
- const TCpuAllocation CpuAlloc;
-
- TConfig(const TCpuAllocation& allocation, const TUnitedWorkersConfig& united)
- : CpuId(allocation.CpuId)
- , Workers(allocation.AllowedPools.size() + 1)
- , SoftLimitTs(Us2Ts(united.PoolLimitUs))
- , HardLimitTs(Us2Ts(united.PoolLimitUs + united.EventLimitUs))
- , EventLimitTs(Us2Ts(united.EventLimitUs))
- , LimitPrecisionTs(Us2Ts(united.LimitPrecisionUs))
- , IdleWorkerPriority(std::clamp<ui64>(united.IdleWorkerPriority ? united.IdleWorkerPriority : 20, 1, 99))
- , FastWorkerPriority(std::clamp<ui64>(united.FastWorkerPriority ? united.FastWorkerPriority : 10, 1, IdleWorkerPriority - 1))
- , NoRealtime(united.NoRealtime)
- , NoAffinity(united.NoAffinity)
- , CpuAlloc(allocation)
- {}
- };
-
- TConfig Config;
- TVector<TWorkerId> Workers;
-
- TSharedCpu(const TConfig& cfg, TUnitedWorkers* united)
- : TCpuLocalManager(united)
- , IdleQueue(cfg.Workers)
- , Config(cfg)
- {
- for (const auto& pa : Config.CpuAlloc.AllowedPools) {
- PoolSched.AddPool(pa.PoolId, pa.Weight);
- }
- }
-
- TWorkerId WorkerCount() const override {
- return Config.Workers;
- }
-
- void AddWorker(TWorkerId workerId) override {
- if (Workers.empty()) {
- // Grant lease to the first worker
- AtomicStore(&CurrentLease, TLease(workerId, NeverExpire).Value);
- }
- Workers.push_back(workerId);
- }
-
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
- ui32 activation;
- if (!wctx.Lease.IsNeverExpiring()) {
- if (wctx.SoftDeadlineTs < GetCycleCountFast()) { // stop if lease has expired or is near to be expired
- United->StopExecution(wctx.PoolId);
- } else if (United->NextExecution(wctx.PoolId, activation, revolvingCounter)) {
- return activation; // another activation from currently executing pool (or 0 if stopped)
- }
- }
-
- // Switch to another pool, it blocks until token is acquired
- if (Y_UNLIKELY(!SwitchPool(wctx))) {
- return 0; // stopped
- }
- United->BeginExecution(wctx.PoolId, activation, revolvingCounter);
- return activation;
- }
-
- void Stop() override {
- IdleQueue.Stop();
- }
-
- private:
- enum EPriority {
- IdlePriority, // highest (real-time, Config.IdleWorkerPriority)
- FastPriority, // normal (real-time, Config.FastWorkerPriority)
- SlowPriority, // lowest (not real-time)
- };
-
- enum EWorkerAction {
- // Fast-worker
- ExecuteFast,
- WaitForSlow,
-
- // Slow-worker
- BecameIdle,
- WakeFast,
-
- // Idle-worker
- BecameFast,
- Standby,
-
- // Common
- Stopped,
- };
-
- // Thread-safe; should be called from worker
- // Blocks for idle-workers; sets lease and next pool to run
- bool SwitchPool(TWorkerContext& wctx) {
- TTimerFd* idleTimer = nullptr;
- while (true) {
- if (DisablePreemptionAndTryExtend(wctx.Lease)) { // if fast-worker
- if (Y_UNLIKELY(!Started)) {
- SetPriority(0, FastPriority);
- Started = true;
- }
- while (true) {
- switch (FastWorkerAction(wctx)) {
- case ExecuteFast:
- United->SwitchPool(wctx, wctx.Lease.GetPreciseExpireTs() - Config.EventLimitTs);
- EnablePreemptionAndGrant(wctx.Lease);
- return true;
- case WaitForSlow:
- FastWorkerSleep(GetCycleCountFast() + Config.SoftLimitTs);
- break;
- case Stopped: return false;
- default: Y_FAIL();
+ if (value > 0) {
+ if (AtomicCas(tokens, value - 1, value)) {
+ return true; // token acquired
+ }
+ } else {
+ return false; // no more tokens
+ }
+ }
+ }
+
+ // Try acquire pending token. Must be done before execution
+ bool TryAcquireToken() {
+ return TryAcquireTokenImpl<false>(&Tokens);
+ }
+
+ // Try acquire pending token. Must be done before execution
+ bool TryAcquireTokenRelaxed() {
+ return TryAcquireTokenImpl<true>(&Tokens);
+ }
+
+ // Get activation. Requires acquired token.
+ void BeginExecution(ui32& activation, ui64 revolvingCounter) {
+ while (!RelaxedLoad(&StopFlag)) {
+ if (activation = Activations.Pop(++revolvingCounter)) {
+ return;
+ }
+ SpinLockPause();
+ }
+ activation = 0; // should stop
+ }
+
+ // End currently active execution and start new one if token is available.
+ // Reuses token if it's not destroyed.
+ // Returned `true` means successful switch, `activation` is filled.
+ // Returned `false` means execution has ended, no need to call StopExecution()
+ bool NextExecution(ui32& activation, ui64 revolvingCounter) {
+ if (AtomicDecrement(Active) >= Concurrency) { // reuse just released token
+ BeginExecution(activation, revolvingCounter);
+ return true;
+ } else if (TryAcquireToken()) { // another token acquired
+ BeginExecution(activation, revolvingCounter);
+ return true;
+ }
+ return false; // no more tokens available
+ }
+
+ // Stop active execution. Returns released token (unless it is destroyed)
+ bool StopExecution() {
+ TAtomicBase active = AtomicDecrement(Active);
+ if (active >= Concurrency) { // token released
+ AtomicIncrement(Tokens);
+ return true;
+ }
+ return false; // token destroyed
+ }
+
+ // Switch worker context into this pool
+ void Switch(TWorkerContext& wctx, ui64 softDeadlineTs, TExecutorThreadStats& stats) {
+ wctx.Switch(ExecutorPool, MailboxTable, TimePerMailboxTs, EventsPerMailbox, softDeadlineTs, &stats);
+ }
+ };
+
+ class TPoolScheduler {
+ class TSchedulable {
+ // Lower PoolBits store PoolId
+ // All other higher bits store virtual runtime in cycles
+ using TValue = ui64;
+ TValue Value;
+
+ static constexpr ui64 PoolIdMask = ui64((1ull << PoolBits) - 1);
+ static constexpr ui64 VRunTsMask = ~PoolIdMask;
+
+ public:
+ explicit TSchedulable(TPoolId poolId = MaxPools, ui64 vrunts = 0)
+ : Value((poolId & PoolIdMask) | (vrunts & VRunTsMask))
+ {}
+
+ TPoolId GetPoolId() const {
+ return Value & PoolIdMask;
+ }
+
+ ui64 GetVRunTs() const {
+ // Do not truncate pool id
+ // NOTE: it decrease accuracy, but improves performance
+ return Value;
+ }
+
+ ui64 GetPreciseVRunTs() const {
+ return Value & VRunTsMask;
+ }
+
+ void SetVRunTs(ui64 vrunts) {
+ Value = (Value & PoolIdMask) | (vrunts & VRunTsMask);
+ }
+
+ void Account(ui64 base, ui64 ts) {
+ // Add at least minimum amount to change Value
+ SetVRunTs(base + Max(ts, PoolIdMask + 1));
+ }
+ };
+
+ // For min-heap of Items
+ struct TCmp {
+ bool operator()(TSchedulable lhs, TSchedulable rhs) const {
+ return lhs.GetVRunTs() > rhs.GetVRunTs();
+ }
+ };
+
+ TPoolId Size = 0; // total number of pools on this cpu
+ TPoolId Current = 0; // index of current pool in `Items`
+
+ // At the beginning `Current` items are orginized as binary min-heap -- ready to be scheduled
+ // The rest `Size - Current` items are unordered (required to keep track of last vrunts)
+ TSchedulable Items[MaxPools]; // virtual runtime in cycles for each pool
+ ui64 MinVRunTs = 0; // virtual runtime used by waking pools (system's vrunts)
+ ui64 Ts = 0; // real timestamp of current execution start (for accounting)
+
+ // Maps PoolId into it's inverse weight
+ ui64 InvWeights[MaxPools];
+ static constexpr ui64 VRunTsOverflow = ui64(1ull << 62ull) / MaxPoolWeight;
+
+ public:
+ void AddPool(TPoolId pool, TPoolWeight weight) {
+ Items[Size] = TSchedulable(pool, MinVRunTs);
+ Size++;
+ InvWeights[pool] = MaxPoolWeight / std::clamp(weight ? weight : DefPoolWeight, MinPoolWeight, MaxPoolWeight);
+ }
+
+ // Iterate over pools in scheduling order
+ // should be used in construction:
+ // for (TPoolId pool = Begin(); pool != End(); pool = Next())
+ TPoolId Begin() {
+ // Wrap vruntime around to avoid overflow, if required
+ if (Y_UNLIKELY(MinVRunTs >= VRunTsOverflow)) {
+ for (TPoolId i = 0; i < Size; i++) {
+ ui64 ts = Items[i].GetPreciseVRunTs();
+ Items[i].SetVRunTs(ts >= VRunTsOverflow ? ts - VRunTsOverflow : 0);
+ }
+ MinVRunTs -= VRunTsOverflow;
+ }
+ Current = Size;
+ std::make_heap(Items, Items + Current, TCmp());
+ return Next();
+ }
+
+ constexpr TPoolId End() const {
+ return MaxPools;
+ }
+
+ TPoolId Next() {
+ if (Current > 0) {
+ std::pop_heap(Items, Items + Current, TCmp());
+ Current--;
+ return CurrentPool();
+ } else {
+ return End();
+ }
+ }
+
+ // Scheduling was successful, we are going to run CurrentPool()
+ void Scheduled() {
+ MinVRunTs = Max(MinVRunTs, Items[Current].GetPreciseVRunTs());
+ // NOTE: Ts is propagated on Account() to avoid gaps
+ }
+
+ // Schedule specific pool that woke up cpu after idle
+ void ScheduledAfterIdle(TPoolId pool, ui64 ts) {
+ if (Y_UNLIKELY(ts < Ts)) { // anomaly: time goes backwards (e.g. rdtsc is reset to zero on cpu reset)
+ Ts = ts; // just skip anomalous time slice
+ return;
+ }
+ MinVRunTs += (ts - Ts) * (MaxPoolWeight / DefPoolWeight); // propagate system's vrunts to blur difference between pools
+ Ts = ts; // propagate time w/o accounting to any pool
+
+ // Set specified pool as current, it requires scan
+ for (Current = 0; Current < Size && pool != Items[Current].GetPoolId(); Current++) {}
+ Y_VERIFY(Current < Size);
+ }
+
+ // Account currently running pool till now (ts)
+ void Account(ui64 ts) {
+ // Skip time slice for the first run and when time goes backwards (e.g. rdtsc is reset to zero on cpu reset)
+ if (Y_LIKELY(Ts > 0 && Ts <= ts)) {
+ TPoolId pool = CurrentPool();
+ Y_VERIFY(pool < MaxPools);
+ Items[Current].Account(MinVRunTs, (ts - Ts) * InvWeights[pool]);
+ }
+ Ts = ts; // propagate time
+ }
+
+ TPoolId CurrentPool() const {
+ return Items[Current].GetPoolId();
+ }
+ };
+
+ // Cyclic array of timers for idle workers to wait for hard preemption on
+ struct TIdleQueue: public TNonCopyable {
+ TArrayHolder<TTimerFd> Timers;
+ size_t Size;
+ TAtomic EnqueueCounter = 0;
+ TAtomic DequeueCounter = 0;
+
+ explicit TIdleQueue(size_t size)
+ : Timers(new TTimerFd[size])
+ , Size(size)
+ {}
+
+ void Stop() {
+ for (size_t i = 0; i < Size; i++) {
+ Timers[i].Wake();
+ }
+ }
+
+ // Returns timer which new idle-worker should wait for
+ TTimerFd* Enqueue() {
+ return &Timers[AtomicGetAndIncrement(EnqueueCounter) % Size];
+ }
+
+ // Returns timer that hard preemption should trigger to wake idle-worker
+ TTimerFd* Dequeue() {
+ return &Timers[AtomicGetAndIncrement(DequeueCounter) % Size];
+ }
+ };
+
+ // Base class for cpu-local managers that help workers on single cpu to cooperate
+ struct TCpuLocalManager: public TThrRefBase {
+ TUnitedWorkers* United;
+
+ explicit TCpuLocalManager(TUnitedWorkers* united)
+ : United(united)
+ {}
+
+ virtual TWorkerId WorkerCount() const = 0;
+ virtual void AddWorker(TWorkerId workerId) = 0;
+ virtual void Stop() = 0;
+ };
+
+ // Represents cpu with single associated worker that is able to execute any pool.
+ // It always executes pool assigned by balancer and switch pool only if assigned pool has changed
+ struct TAssignedCpu: public TCpuLocalManager {
+ bool Started = false;
+
+ TAssignedCpu(TUnitedWorkers* united)
+ : TCpuLocalManager(united)
+ {}
+
+ TWorkerId WorkerCount() const override {
+ return 1;
+ }
+
+ void AddWorker(TWorkerId workerId) override {
+ Y_UNUSED(workerId);
+ }
+
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
+ ui32 activation;
+ if (Y_UNLIKELY(!Started)) {
+ Started = true;
+ } else if (Y_UNLIKELY(United->IsPoolReassigned(wctx))) {
+ United->StopExecution(wctx.PoolId); // stop current execution and switch pool if reassigned
+ } else if (United->NextExecution(wctx.PoolId, activation, revolvingCounter)) {
+ return activation; // another activation from currently executing pool (or 0 if stopped)
+ }
+
+ // Switch to another pool, it blocks until token is acquired
+ if (Y_UNLIKELY(!SwitchPool(wctx))) {
+ return 0; // stopped
+ }
+ United->SwitchPool(wctx, 0);
+ United->BeginExecution(wctx.PoolId, activation, revolvingCounter);
+ return activation;
+ }
+
+ void Stop() override {
+ }
+
+ private:
+ // Sets next pool to run, and acquires token, blocks if there are no tokens
+ bool SwitchPool(TWorkerContext& wctx) {
+ if (Y_UNLIKELY(United->IsStopped())) {
+ return false;
+ }
+
+ // Run balancer (if it's time to)
+ United->Balance();
+
+ // Select pool to execute
+ wctx.PoolId = United->AssignedPool(wctx);
+ Y_VERIFY(wctx.PoolId != CpuShared);
+ if (United->TryAcquireToken(wctx.PoolId)) {
+ return true;
+ }
+
+ // No more work -- wait for activations (spinning, then blocked)
+ wctx.PoolId = United->Idle(wctx.PoolId, wctx);
+
+ // Wakeup or stop occured
+ if (Y_UNLIKELY(wctx.PoolId == CpuStopped)) {
+ return false;
+ }
+ return true; // United->Idle() has already acquired token
+ }
+ };
+
+ // Lock-free data structure that help workers on single cpu to discover their state and do hard preemptions
+ struct TSharedCpu: public TCpuLocalManager {
+ // Current lease
+ volatile TLease::TValue CurrentLease;
+ char Padding1[64 - sizeof(TLease)];
+
+ // Slow pools
+ // the highest bit: 1=wait-for-slow-workers mode 0=else
+ // any lower bit (poolId is bit position): 1=pool-is-slow 0=pool-is-fast
+ volatile TPoolsMask SlowPoolsMask = 0;
+ char Padding2[64 - sizeof(TPoolsMask)];
+
+ // Must be accessed under never expiring lease to avoid races
+ TPoolScheduler PoolSched;
+ TWorkerId FastWorker = MaxWorkers;
+ TTimerFd* PreemptionTimer = nullptr;
+ ui64 HardPreemptionTs = 0;
+ bool Started = false;
+
+ TIdleQueue IdleQueue;
+
+ struct TConfig {
+ const TCpuId CpuId;
+ const TWorkerId Workers;
+ ui64 SoftLimitTs;
+ ui64 HardLimitTs;
+ ui64 EventLimitTs;
+ ui64 LimitPrecisionTs;
+ const int IdleWorkerPriority;
+ const int FastWorkerPriority;
+ const bool NoRealtime;
+ const bool NoAffinity;
+ const TCpuAllocation CpuAlloc;
+
+ TConfig(const TCpuAllocation& allocation, const TUnitedWorkersConfig& united)
+ : CpuId(allocation.CpuId)
+ , Workers(allocation.AllowedPools.size() + 1)
+ , SoftLimitTs(Us2Ts(united.PoolLimitUs))
+ , HardLimitTs(Us2Ts(united.PoolLimitUs + united.EventLimitUs))
+ , EventLimitTs(Us2Ts(united.EventLimitUs))
+ , LimitPrecisionTs(Us2Ts(united.LimitPrecisionUs))
+ , IdleWorkerPriority(std::clamp<ui64>(united.IdleWorkerPriority ? united.IdleWorkerPriority : 20, 1, 99))
+ , FastWorkerPriority(std::clamp<ui64>(united.FastWorkerPriority ? united.FastWorkerPriority : 10, 1, IdleWorkerPriority - 1))
+ , NoRealtime(united.NoRealtime)
+ , NoAffinity(united.NoAffinity)
+ , CpuAlloc(allocation)
+ {}
+ };
+
+ TConfig Config;
+ TVector<TWorkerId> Workers;
+
+ TSharedCpu(const TConfig& cfg, TUnitedWorkers* united)
+ : TCpuLocalManager(united)
+ , IdleQueue(cfg.Workers)
+ , Config(cfg)
+ {
+ for (const auto& pa : Config.CpuAlloc.AllowedPools) {
+ PoolSched.AddPool(pa.PoolId, pa.Weight);
+ }
+ }
+
+ TWorkerId WorkerCount() const override {
+ return Config.Workers;
+ }
+
+ void AddWorker(TWorkerId workerId) override {
+ if (Workers.empty()) {
+ // Grant lease to the first worker
+ AtomicStore(&CurrentLease, TLease(workerId, NeverExpire).Value);
+ }
+ Workers.push_back(workerId);
+ }
+
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) {
+ ui32 activation;
+ if (!wctx.Lease.IsNeverExpiring()) {
+ if (wctx.SoftDeadlineTs < GetCycleCountFast()) { // stop if lease has expired or is near to be expired
+ United->StopExecution(wctx.PoolId);
+ } else if (United->NextExecution(wctx.PoolId, activation, revolvingCounter)) {
+ return activation; // another activation from currently executing pool (or 0 if stopped)
+ }
+ }
+
+ // Switch to another pool, it blocks until token is acquired
+ if (Y_UNLIKELY(!SwitchPool(wctx))) {
+ return 0; // stopped
+ }
+ United->BeginExecution(wctx.PoolId, activation, revolvingCounter);
+ return activation;
+ }
+
+ void Stop() override {
+ IdleQueue.Stop();
+ }
+
+ private:
+ enum EPriority {
+ IdlePriority, // highest (real-time, Config.IdleWorkerPriority)
+ FastPriority, // normal (real-time, Config.FastWorkerPriority)
+ SlowPriority, // lowest (not real-time)
+ };
+
+ enum EWorkerAction {
+ // Fast-worker
+ ExecuteFast,
+ WaitForSlow,
+
+ // Slow-worker
+ BecameIdle,
+ WakeFast,
+
+ // Idle-worker
+ BecameFast,
+ Standby,
+
+ // Common
+ Stopped,
+ };
+
+ // Thread-safe; should be called from worker
+ // Blocks for idle-workers; sets lease and next pool to run
+ bool SwitchPool(TWorkerContext& wctx) {
+ TTimerFd* idleTimer = nullptr;
+ while (true) {
+ if (DisablePreemptionAndTryExtend(wctx.Lease)) { // if fast-worker
+ if (Y_UNLIKELY(!Started)) {
+ SetPriority(0, FastPriority);
+ Started = true;
+ }
+ while (true) {
+ switch (FastWorkerAction(wctx)) {
+ case ExecuteFast:
+ United->SwitchPool(wctx, wctx.Lease.GetPreciseExpireTs() - Config.EventLimitTs);
+ EnablePreemptionAndGrant(wctx.Lease);
+ return true;
+ case WaitForSlow:
+ FastWorkerSleep(GetCycleCountFast() + Config.SoftLimitTs);
+ break;
+ case Stopped: return false;
+ default: Y_FAIL();
+ }
+ }
+ } else if (wctx.Lease.IsNeverExpiring()) { // if idle-worker
+ switch (IdleWorkerAction(idleTimer, wctx.Lease.GetWorkerId())) {
+ case BecameFast:
+ SetPriority(0, FastPriority);
+ break; // try acquire new lease
+ case Standby:
+ if (!idleTimer) {
+ idleTimer = IdleQueue.Enqueue();
}
- }
- } else if (wctx.Lease.IsNeverExpiring()) { // if idle-worker
- switch (IdleWorkerAction(idleTimer, wctx.Lease.GetWorkerId())) {
- case BecameFast:
- SetPriority(0, FastPriority);
- break; // try acquire new lease
- case Standby:
- if (!idleTimer) {
- idleTimer = IdleQueue.Enqueue();
- }
- SetPriority(0, IdlePriority);
- idleTimer->Wait();
+ SetPriority(0, IdlePriority);
+ idleTimer->Wait();
break;
- case Stopped: return false;
- default: Y_FAIL();
+ case Stopped: return false;
+ default: Y_FAIL();
}
- } else { // lease has expired and hard preemption occured, so we are executing in a slow-worker
- wctx.IncrementPreemptedEvents();
- switch (SlowWorkerAction(wctx.PoolId)) {
- case WakeFast:
- WakeFastWorker();
+ } else { // lease has expired and hard preemption occured, so we are executing in a slow-worker
+ wctx.IncrementPreemptedEvents();
+ switch (SlowWorkerAction(wctx.PoolId)) {
+ case WakeFast:
+ WakeFastWorker();
[[fallthrough]]; // no break; pass through
- case BecameIdle:
- wctx.Lease = wctx.Lease.NeverExpire();
- wctx.PoolId = MaxPools;
- idleTimer = nullptr;
+ case BecameIdle:
+ wctx.Lease = wctx.Lease.NeverExpire();
+ wctx.PoolId = MaxPools;
+ idleTimer = nullptr;
break;
- case Stopped: return false;
- default: Y_FAIL();
+ case Stopped: return false;
+ default: Y_FAIL();
}
}
- }
- }
-
- enum ETryRunPool {
- RunFastPool,
- RunSlowPool,
- NoTokens,
- };
-
- ETryRunPool TryRun(TPoolId pool) {
- while (true) {
- // updates WaitPoolsFlag in SlowPoolsMask according to scheduled pool slowness
- TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
- if ((1ull << pool) & slow) { // we are about to execute slow pool (fast-worker will just wait, token is NOT required)
- if (slow & WaitPoolsFlag) {
- return RunSlowPool; // wait flag is already set
- } else {
- if (AtomicCas(&SlowPoolsMask, slow | WaitPoolsFlag, slow)) { // try set wait flag
- return RunSlowPool; // wait flag has been successfully set
- }
- }
- } else { // we are about to execute fast pool, token required
- if (slow & WaitPoolsFlag) { // reset wait flag if required
- if (AtomicCas(&SlowPoolsMask, slow & ~WaitPoolsFlag, slow)) { // try reset wait flag
- return United->TryAcquireToken(pool) ? RunFastPool : NoTokens; // wait flag has been successfully reset
- }
- } else {
- return United->TryAcquireToken(pool) ? RunFastPool : NoTokens; // wait flag is already reset
+ }
+ }
+
+ enum ETryRunPool {
+ RunFastPool,
+ RunSlowPool,
+ NoTokens,
+ };
+
+ ETryRunPool TryRun(TPoolId pool) {
+ while (true) {
+ // updates WaitPoolsFlag in SlowPoolsMask according to scheduled pool slowness
+ TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
+ if ((1ull << pool) & slow) { // we are about to execute slow pool (fast-worker will just wait, token is NOT required)
+ if (slow & WaitPoolsFlag) {
+ return RunSlowPool; // wait flag is already set
+ } else {
+ if (AtomicCas(&SlowPoolsMask, slow | WaitPoolsFlag, slow)) { // try set wait flag
+ return RunSlowPool; // wait flag has been successfully set
+ }
}
- }
- }
- }
-
- EWorkerAction FastWorkerAction(TWorkerContext& wctx) {
- if (Y_UNLIKELY(United->IsStopped())) {
- return Stopped;
- }
-
- // Account current pool
- ui64 ts = GetCycleCountFast();
- PoolSched.Account(ts);
-
- // Select next pool to execute
- for (wctx.PoolId = PoolSched.Begin(); wctx.PoolId != PoolSched.End(); wctx.PoolId = PoolSched.Next()) {
- switch (TryRun(wctx.PoolId)) {
- case RunFastPool:
- PoolSched.Scheduled();
- wctx.Lease = PostponePreemption(wctx.Lease.GetWorkerId(), ts);
- return ExecuteFast;
- case RunSlowPool:
- PoolSched.Scheduled();
- ResetPreemption(wctx.Lease.GetWorkerId(), ts); // there is no point in preemption during wait
- return WaitForSlow;
- case NoTokens: // concurrency limit reached, or no more work in pool
- break; // just try next pool (if any)
- }
- }
-
- // No more work, no slow-workers -- wait for activations (active, then blocked)
- wctx.PoolId = United->Idle(CpuShared, wctx);
-
- // Wakeup or stop occured
- if (Y_UNLIKELY(wctx.PoolId == CpuStopped)) {
- return Stopped;
- }
- ts = GetCycleCountFast();
- PoolSched.ScheduledAfterIdle(wctx.PoolId, ts);
- wctx.Lease = PostponePreemption(wctx.Lease.GetWorkerId(), ts);
- return ExecuteFast; // United->Idle() has already acquired token
- }
-
- EWorkerAction IdleWorkerAction(TTimerFd* idleTimer, TWorkerId workerId) {
- if (Y_UNLIKELY(United->IsStopped())) {
- return Stopped;
- }
- if (!idleTimer) { // either worker start or became idle -- hard preemption is not required
- return Standby;
- }
-
- TLease lease = TLease(AtomicLoad(&CurrentLease));
- ui64 ts = GetCycleCountFast();
- if (lease.GetExpireTs() < ts) { // current lease has expired
- if (TryBeginHardPreemption(lease)) {
- SetPoolIsSlowFlag(PoolSched.CurrentPool());
- TWorkerId preempted = lease.GetWorkerId();
- SetPriority(United->GetWorkerThreadId(preempted), SlowPriority);
- LWPROBE(HardPreemption, Config.CpuId, PoolSched.CurrentPool(), preempted, workerId);
- EndHardPreemption(workerId);
- return BecameFast;
- } else {
- // Lease has been changed just now, no way we need preemption right now, so no retry needed
- return Standby;
- }
+ } else { // we are about to execute fast pool, token required
+ if (slow & WaitPoolsFlag) { // reset wait flag if required
+ if (AtomicCas(&SlowPoolsMask, slow & ~WaitPoolsFlag, slow)) { // try reset wait flag
+ return United->TryAcquireToken(pool) ? RunFastPool : NoTokens; // wait flag has been successfully reset
+ }
+ } else {
+ return United->TryAcquireToken(pool) ? RunFastPool : NoTokens; // wait flag is already reset
+ }
+ }
+ }
+ }
+
+ EWorkerAction FastWorkerAction(TWorkerContext& wctx) {
+ if (Y_UNLIKELY(United->IsStopped())) {
+ return Stopped;
+ }
+
+ // Account current pool
+ ui64 ts = GetCycleCountFast();
+ PoolSched.Account(ts);
+
+ // Select next pool to execute
+ for (wctx.PoolId = PoolSched.Begin(); wctx.PoolId != PoolSched.End(); wctx.PoolId = PoolSched.Next()) {
+ switch (TryRun(wctx.PoolId)) {
+ case RunFastPool:
+ PoolSched.Scheduled();
+ wctx.Lease = PostponePreemption(wctx.Lease.GetWorkerId(), ts);
+ return ExecuteFast;
+ case RunSlowPool:
+ PoolSched.Scheduled();
+ ResetPreemption(wctx.Lease.GetWorkerId(), ts); // there is no point in preemption during wait
+ return WaitForSlow;
+ case NoTokens: // concurrency limit reached, or no more work in pool
+ break; // just try next pool (if any)
+ }
+ }
+
+ // No more work, no slow-workers -- wait for activations (active, then blocked)
+ wctx.PoolId = United->Idle(CpuShared, wctx);
+
+ // Wakeup or stop occured
+ if (Y_UNLIKELY(wctx.PoolId == CpuStopped)) {
+ return Stopped;
+ }
+ ts = GetCycleCountFast();
+ PoolSched.ScheduledAfterIdle(wctx.PoolId, ts);
+ wctx.Lease = PostponePreemption(wctx.Lease.GetWorkerId(), ts);
+ return ExecuteFast; // United->Idle() has already acquired token
+ }
+
+ EWorkerAction IdleWorkerAction(TTimerFd* idleTimer, TWorkerId workerId) {
+ if (Y_UNLIKELY(United->IsStopped())) {
+ return Stopped;
+ }
+ if (!idleTimer) { // either worker start or became idle -- hard preemption is not required
+ return Standby;
+ }
+
+ TLease lease = TLease(AtomicLoad(&CurrentLease));
+ ui64 ts = GetCycleCountFast();
+ if (lease.GetExpireTs() < ts) { // current lease has expired
+ if (TryBeginHardPreemption(lease)) {
+ SetPoolIsSlowFlag(PoolSched.CurrentPool());
+ TWorkerId preempted = lease.GetWorkerId();
+ SetPriority(United->GetWorkerThreadId(preempted), SlowPriority);
+ LWPROBE(HardPreemption, Config.CpuId, PoolSched.CurrentPool(), preempted, workerId);
+ EndHardPreemption(workerId);
+ return BecameFast;
+ } else {
+ // Lease has been changed just now, no way we need preemption right now, so no retry needed
+ return Standby;
+ }
} else {
- // Lease has not expired yet (maybe never expiring lease)
- return Standby;
- }
- }
-
- EWorkerAction SlowWorkerAction(TPoolId pool) {
- if (Y_UNLIKELY(United->IsStopped())) {
- return Stopped;
- }
- while (true) {
- TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
- if (slow & (1ull << pool)) {
- if (slow == (1ull << pool) & WaitPoolsFlag) { // the last slow pool is going to became fast
- if (AtomicCas(&SlowPoolsMask, 0, slow)) { // reset both pool-is-slow flag and WaitPoolsFlag
- return WakeFast;
- }
- } else { // there are (a) several slow-worker or (b) one slow-worker w/o waiting fast-worker
- if (AtomicCas(&SlowPoolsMask, slow & ~(1ull << pool), slow)) { // reset pool-is-slow flag
- return BecameIdle;
- }
- }
- } else {
- // SlowWorkerAction has been called between TryBeginHardPreemption and SetPoolIsSlowFlag
- // flag for this pool is not set yet, but we can be sure pool is slow:
- // - because SlowWorkerAction has been called;
- // - this mean lease has expired and hard preemption occured.
- // So just wait other worker to call SetPoolIsSlowFlag
- LWPROBE(SlowWorkerActionRace, Config.CpuId, pool, slow);
+ // Lease has not expired yet (maybe never expiring lease)
+ return Standby;
+ }
+ }
+
+ EWorkerAction SlowWorkerAction(TPoolId pool) {
+ if (Y_UNLIKELY(United->IsStopped())) {
+ return Stopped;
+ }
+ while (true) {
+ TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
+ if (slow & (1ull << pool)) {
+ if (slow == (1ull << pool) & WaitPoolsFlag) { // the last slow pool is going to became fast
+ if (AtomicCas(&SlowPoolsMask, 0, slow)) { // reset both pool-is-slow flag and WaitPoolsFlag
+ return WakeFast;
+ }
+ } else { // there are (a) several slow-worker or (b) one slow-worker w/o waiting fast-worker
+ if (AtomicCas(&SlowPoolsMask, slow & ~(1ull << pool), slow)) { // reset pool-is-slow flag
+ return BecameIdle;
+ }
+ }
+ } else {
+ // SlowWorkerAction has been called between TryBeginHardPreemption and SetPoolIsSlowFlag
+ // flag for this pool is not set yet, but we can be sure pool is slow:
+ // - because SlowWorkerAction has been called;
+ // - this mean lease has expired and hard preemption occured.
+ // So just wait other worker to call SetPoolIsSlowFlag
+ LWPROBE(SlowWorkerActionRace, Config.CpuId, pool, slow);
+ }
+ }
+ }
+
+ void SetPoolIsSlowFlag(TPoolId pool) {
+ while (true) {
+ TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
+ if ((slow & (1ull << pool)) == 0) { // if pool is fast
+ if (AtomicCas(&SlowPoolsMask, slow | (1ull << pool), slow)) { // set pool-is-slow flag
+ return;
+ }
+ } else {
+ Y_FAIL("two slow-workers executing the same pool on the same core");
+ return; // pool is already slow
+ }
+ }
+ }
+
+ bool TryBeginHardPreemption(TLease lease) {
+ return AtomicCas(&CurrentLease, HardPreemptionLease, lease);
+ }
+
+ void EndHardPreemption(TWorkerId to) {
+ ATOMIC_COMPILER_BARRIER();
+ if (!AtomicCas(&CurrentLease, TLease(to, NeverExpire), HardPreemptionLease)) {
+ Y_FAIL("hard preemption failed");
+ }
+ }
+
+ bool DisablePreemptionAndTryExtend(TLease lease) {
+ return AtomicCas(&CurrentLease, lease.NeverExpire(), lease);
+ }
+
+ void EnablePreemptionAndGrant(TLease lease) {
+ ATOMIC_COMPILER_BARRIER();
+ if (!AtomicCas(&CurrentLease, lease, lease.NeverExpire())) {
+ Y_FAIL("lease grant failed");
+ }
+ }
+
+ void FastWorkerSleep(ui64 deadlineTs) {
+ while (true) {
+ TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
+ if ((slow & WaitPoolsFlag) == 0) {
+ return; // woken by WakeFast action
}
- }
- }
-
- void SetPoolIsSlowFlag(TPoolId pool) {
- while (true) {
- TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
- if ((slow & (1ull << pool)) == 0) { // if pool is fast
- if (AtomicCas(&SlowPoolsMask, slow | (1ull << pool), slow)) { // set pool-is-slow flag
- return;
- }
- } else {
- Y_FAIL("two slow-workers executing the same pool on the same core");
- return; // pool is already slow
+ ui64 ts = GetCycleCountFast();
+ if (deadlineTs <= ts) {
+ if (AtomicCas(&SlowPoolsMask, slow & ~WaitPoolsFlag, slow)) { // try reset wait flag
+ return; // wait flag has been successfully reset after timeout
+ }
+ } else { // should wait
+ ui64 timeoutNs = Ts2Ns(deadlineTs - ts);
+#ifdef _linux_
+ timespec timeout;
+ timeout.tv_sec = timeoutNs / 1'000'000'000;
+ timeout.tv_nsec = timeoutNs % 1'000'000'000;
+ SysFutex(FastWorkerFutex(), FUTEX_WAIT_PRIVATE, FastWorkerFutexValue(slow), &timeout, nullptr, 0);
+#else
+ NanoSleep(timeoutNs); // non-linux wake is not supported, cpu will go idle on slow -> fast switch
+#endif
}
- }
- }
-
- bool TryBeginHardPreemption(TLease lease) {
- return AtomicCas(&CurrentLease, HardPreemptionLease, lease);
- }
-
- void EndHardPreemption(TWorkerId to) {
- ATOMIC_COMPILER_BARRIER();
- if (!AtomicCas(&CurrentLease, TLease(to, NeverExpire), HardPreemptionLease)) {
- Y_FAIL("hard preemption failed");
- }
- }
-
- bool DisablePreemptionAndTryExtend(TLease lease) {
- return AtomicCas(&CurrentLease, lease.NeverExpire(), lease);
- }
-
- void EnablePreemptionAndGrant(TLease lease) {
- ATOMIC_COMPILER_BARRIER();
- if (!AtomicCas(&CurrentLease, lease, lease.NeverExpire())) {
- Y_FAIL("lease grant failed");
- }
- }
-
- void FastWorkerSleep(ui64 deadlineTs) {
- while (true) {
- TPoolsMask slow = AtomicLoad(&SlowPoolsMask);
- if ((slow & WaitPoolsFlag) == 0) {
- return; // woken by WakeFast action
- }
- ui64 ts = GetCycleCountFast();
- if (deadlineTs <= ts) {
- if (AtomicCas(&SlowPoolsMask, slow & ~WaitPoolsFlag, slow)) { // try reset wait flag
- return; // wait flag has been successfully reset after timeout
+ }
+ }
+
+ void WakeFastWorker() {
+#ifdef _linux_
+ SysFutex(FastWorkerFutex(), FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
+#endif
+ }
+
+#ifdef _linux_
+ ui32* FastWorkerFutex() {
+ // Actually we wait on one highest bit, but futex value size is 4 bytes on all platforms
+ static_assert(sizeof(TPoolsMask) >= 4, "cannot be used as futex value on linux");
+ return (ui32*)&SlowPoolsMask + 1; // higher 32 bits (little endian assumed)
+ }
+
+ ui32 FastWorkerFutexValue(TPoolsMask slow) {
+ return ui32(slow >> 32); // higher 32 bits
+ }
+#endif
+
+ void SetPriority(TThreadId tid, EPriority priority) {
+ if (Config.NoRealtime) {
+ return;
+ }
+#ifdef _linux_
+ int policy;
+ struct sched_param param;
+ switch (priority) {
+ case IdlePriority:
+ policy = SCHED_FIFO;
+ param.sched_priority = Config.IdleWorkerPriority;
+ break;
+ case FastPriority:
+ policy = SCHED_FIFO;
+ param.sched_priority = Config.FastWorkerPriority;
+ break;
+ case SlowPriority:
+ policy = SCHED_OTHER;
+ param.sched_priority = 0;
+ break;
+ }
+ int ret = sched_setscheduler(tid, policy, &param);
+ switch (ret) {
+ case 0: return;
+ case EINVAL:
+ Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> EINVAL", tid, policy, param.sched_priority);
+ case EPERM:
+ // Requirements:
+ // * CAP_SYS_NICE capability to run real-time processes and set cpu affinity.
+ // Either run under root or set application capabilities:
+ // sudo setcap cap_sys_nice=eip BINARY
+ // * Non-zero rt-runtime (in case cgroups are used).
+ // Either (a) disable global limit on RT processes bandwidth:
+ // sudo sysctl -w kernel.sched_rt_runtime_us=-1
+ // Or (b) set non-zero rt-runtime for your cgroup:
+ // echo -1 > /sys/fs/cgroup/cpu/[cgroup]/cpu.rt_runtime_us
+ // (also set the same value for every parent cgroup)
+ // https://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt
+ Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> EPERM", tid, policy, param.sched_priority);
+ case ESRCH:
+ Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> ESRCH", tid, policy, param.sched_priority);
+ default:
+ Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> %d", tid, policy, param.sched_priority, ret);
+ }
+#else
+ Y_UNUSED(tid);
+ Y_UNUSED(priority);
+#endif
+ }
+
+ void ResetPreemption(TWorkerId fastWorkerId, ui64 ts) {
+ if (Y_UNLIKELY(!PreemptionTimer)) {
+ return;
+ }
+ if (FastWorker == fastWorkerId && HardPreemptionTs > 0) {
+ PreemptionTimer->Reset();
+ LWPROBE(ResetPreemptionTimer, Config.CpuId, FastWorker, PreemptionTimer->Fd, Ts2Ms(ts), Ts2Ms(HardPreemptionTs));
+ HardPreemptionTs = 0;
+ }
+ }
+
+ TLease PostponePreemption(TWorkerId fastWorkerId, ui64 ts) {
+ // Select new timer after hard preemption
+ if (FastWorker != fastWorkerId) {
+ FastWorker = fastWorkerId;
+ PreemptionTimer = IdleQueue.Dequeue();
+ HardPreemptionTs = 0;
+ }
+
+ ui64 hardPreemptionTs = ts + Config.HardLimitTs;
+ if (hardPreemptionTs > HardPreemptionTs) {
+ // Reset timer (at most once in TickIntervalTs, sacrifice precision)
+ HardPreemptionTs = hardPreemptionTs + Config.LimitPrecisionTs;
+ PreemptionTimer->Set(HardPreemptionTs);
+ LWPROBE(SetPreemptionTimer, Config.CpuId, FastWorker, PreemptionTimer->Fd, Ts2Ms(ts), Ts2Ms(HardPreemptionTs));
+ }
+
+ return TLease(fastWorkerId, hardPreemptionTs);
+ }
+ };
+
+ // Proxy for start and switching TUnitedExecutorPool-s on single cpu via GetReadyActivation()
+ // (does not implement any other method in IExecutorPool)
+ class TCpuExecutorPool: public IExecutorPool {
+ const TString Name;
+
+ public:
+ explicit TCpuExecutorPool(const TString& name)
+ : IExecutorPool(MaxPools)
+ , Name(name)
+ {}
+
+ TString GetName() const override {
+ return Name;
+ }
+
+ void SetRealTimeMode() const override {
+ // derived classes controls rt-priority - do nothing
+ }
+
+ // Should never be called
+ void ReclaimMailbox(TMailboxType::EType, ui32, TWorkerId, ui64) override { Y_FAIL(); }
+ void Schedule(TInstant, TAutoPtr<IEventHandle>, ISchedulerCookie*, TWorkerId) override { Y_FAIL(); }
+ void Schedule(TMonotonic, TAutoPtr<IEventHandle>, ISchedulerCookie*, TWorkerId) override { Y_FAIL(); }
+ void Schedule(TDuration, TAutoPtr<IEventHandle>, ISchedulerCookie*, TWorkerId) override { Y_FAIL(); }
+ bool Send(TAutoPtr<IEventHandle>&) override { Y_FAIL(); }
+ void ScheduleActivation(ui32) override { Y_FAIL(); }
+ void ScheduleActivationEx(ui32, ui64) override { Y_FAIL(); }
+ TActorId Register(IActor*, TMailboxType::EType, ui64, const TActorId&) override { Y_FAIL(); }
+ TActorId Register(IActor*, TMailboxHeader*, ui32, const TActorId&) override { Y_FAIL(); }
+ void Prepare(TActorSystem*, NSchedulerQueue::TReader**, ui32*) override { Y_FAIL(); }
+ void Start() override { Y_FAIL(); }
+ void PrepareStop() override { Y_FAIL(); }
+ void Shutdown() override { Y_FAIL(); }
+ bool Cleanup() override { Y_FAIL(); }
+ };
+
+ // Proxy executor pool working with cpu-local scheduler (aka actorsystem 2.0)
+ class TSharedCpuExecutorPool: public TCpuExecutorPool {
+ TSharedCpu* Local;
+ TIntrusivePtr<TAffinity> SingleCpuAffinity; // no migration support yet
+ public:
+ explicit TSharedCpuExecutorPool(TSharedCpu* local, const TUnitedWorkersConfig& config)
+ : TCpuExecutorPool("u-" + ToString(local->Config.CpuId))
+ , Local(local)
+ , SingleCpuAffinity(config.NoAffinity ? nullptr : new TAffinity(TCpuMask(local->Config.CpuId)))
+ {}
+
+ TAffinity* Affinity() const override {
+ return SingleCpuAffinity.Get();
+ }
+
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override {
+ return Local->GetReadyActivation(wctx, revolvingCounter);
+ }
+ };
+
+ // Proxy executor pool working with balancer and assigned pools (aka actorsystem 1.5)
+ class TAssignedCpuExecutorPool: public TCpuExecutorPool {
+ TAssignedCpu* Local;
+ TIntrusivePtr<TAffinity> CpuAffinity;
+ public:
+ explicit TAssignedCpuExecutorPool(TAssignedCpu* local, const TUnitedWorkersConfig& config)
+ : TCpuExecutorPool("United")
+ , Local(local)
+ , CpuAffinity(config.NoAffinity ? nullptr : new TAffinity(config.Allowed))
+ {}
+
+ TAffinity* Affinity() const override {
+ return CpuAffinity.Get();
+ }
+
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override {
+ return Local->GetReadyActivation(wctx, revolvingCounter);
+ }
+ };
+
+ // Representation of a single cpu and it's state visible to other cpus and pools
+ struct TUnitedWorkers::TCpu: public TNonCopyable {
+ struct TScopedWaiters {
+ TCpu& Cpu;
+ TPool* AssignedPool; // nullptr if CpuShared
+
+ // Subscribe on wakeups from allowed pools
+ TScopedWaiters(TCpu& cpu, TPool* assignedPool) : Cpu(cpu), AssignedPool(assignedPool) {
+ if (!AssignedPool) {
+ for (TPool* pool : Cpu.AllowedPools) {
+ AtomicIncrement(pool->Waiters);
+ }
+ } else {
+ AtomicIncrement(AssignedPool->Waiters);
+ }
+ }
+
+ // Unsubscribe from pools we've subscribed on
+ ~TScopedWaiters() {
+ if (!AssignedPool) {
+ for (TPool* pool : Cpu.AllowedPools) {
+ AtomicDecrement(pool->Waiters);
+ }
+ } else {
+ AtomicDecrement(AssignedPool->Waiters);
+ }
+ }
+ };
+
+ // Current cpu state important for other cpus and balancer
+ TCpuState State;
+
+ // Thread-safe per pool stats
+ // NOTE: It's guaranteed that cpu never executes two instance of the same pool
+ TVector<TExecutorThreadStats> PoolStats;
+
+ // Configuration
+ TCpuId CpuId;
+ THolder<TCpuLocalManager> LocalManager;
+ THolder<TCpuExecutorPool> ExecutorPool;
+
+ // Pools allowed to run on this cpu
+ TStackVec<TPool*, 15> AllowedPools;
+
+ void Stop() {
+ if (LocalManager) {
+ State.Stop();
+ LocalManager->Stop();
+ }
+ }
+
+ bool StartSpinning(TUnitedWorkers* united, TPool* assignedPool, TPoolId& result) {
+ // Mark cpu as idle
+ if (Y_UNLIKELY(!State.StartSpinning())) {
+ result = CpuStopped;
+ return true;
+ }
+
+ // Avoid using multiple atomic seq_cst loads in cycle, use barrier once and relaxed ops
+ AtomicBarrier();
+
+ // Check there is no pending tokens (can be released before Waiters increment)
+ if (!assignedPool) {
+ for (TPool* pool : AllowedPools) {
+ if (pool->TryAcquireTokenRelaxed()) {
+ result = WakeWithTokenAcquired(united, pool->PoolId);
+ return true; // token acquired or stop
}
- } else { // should wait
- ui64 timeoutNs = Ts2Ns(deadlineTs - ts);
-#ifdef _linux_
- timespec timeout;
- timeout.tv_sec = timeoutNs / 1'000'000'000;
- timeout.tv_nsec = timeoutNs % 1'000'000'000;
- SysFutex(FastWorkerFutex(), FUTEX_WAIT_PRIVATE, FastWorkerFutexValue(slow), &timeout, nullptr, 0);
-#else
- NanoSleep(timeoutNs); // non-linux wake is not supported, cpu will go idle on slow -> fast switch
-#endif
- }
- }
- }
-
- void WakeFastWorker() {
-#ifdef _linux_
- SysFutex(FastWorkerFutex(), FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
-#endif
- }
-
-#ifdef _linux_
- ui32* FastWorkerFutex() {
- // Actually we wait on one highest bit, but futex value size is 4 bytes on all platforms
- static_assert(sizeof(TPoolsMask) >= 4, "cannot be used as futex value on linux");
- return (ui32*)&SlowPoolsMask + 1; // higher 32 bits (little endian assumed)
- }
-
- ui32 FastWorkerFutexValue(TPoolsMask slow) {
- return ui32(slow >> 32); // higher 32 bits
- }
-#endif
-
- void SetPriority(TThreadId tid, EPriority priority) {
- if (Config.NoRealtime) {
- return;
- }
-#ifdef _linux_
- int policy;
- struct sched_param param;
- switch (priority) {
- case IdlePriority:
- policy = SCHED_FIFO;
- param.sched_priority = Config.IdleWorkerPriority;
- break;
- case FastPriority:
- policy = SCHED_FIFO;
- param.sched_priority = Config.FastWorkerPriority;
- break;
- case SlowPriority:
- policy = SCHED_OTHER;
- param.sched_priority = 0;
- break;
- }
- int ret = sched_setscheduler(tid, policy, &param);
- switch (ret) {
- case 0: return;
- case EINVAL:
- Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> EINVAL", tid, policy, param.sched_priority);
- case EPERM:
- // Requirements:
- // * CAP_SYS_NICE capability to run real-time processes and set cpu affinity.
- // Either run under root or set application capabilities:
- // sudo setcap cap_sys_nice=eip BINARY
- // * Non-zero rt-runtime (in case cgroups are used).
- // Either (a) disable global limit on RT processes bandwidth:
- // sudo sysctl -w kernel.sched_rt_runtime_us=-1
- // Or (b) set non-zero rt-runtime for your cgroup:
- // echo -1 > /sys/fs/cgroup/cpu/[cgroup]/cpu.rt_runtime_us
- // (also set the same value for every parent cgroup)
- // https://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt
- Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> EPERM", tid, policy, param.sched_priority);
- case ESRCH:
- Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> ESRCH", tid, policy, param.sched_priority);
- default:
- Y_FAIL("sched_setscheduler(%" PRIu64 ", %d, %d) -> %d", tid, policy, param.sched_priority, ret);
- }
-#else
- Y_UNUSED(tid);
- Y_UNUSED(priority);
-#endif
- }
-
- void ResetPreemption(TWorkerId fastWorkerId, ui64 ts) {
- if (Y_UNLIKELY(!PreemptionTimer)) {
- return;
- }
- if (FastWorker == fastWorkerId && HardPreemptionTs > 0) {
- PreemptionTimer->Reset();
- LWPROBE(ResetPreemptionTimer, Config.CpuId, FastWorker, PreemptionTimer->Fd, Ts2Ms(ts), Ts2Ms(HardPreemptionTs));
- HardPreemptionTs = 0;
- }
- }
-
- TLease PostponePreemption(TWorkerId fastWorkerId, ui64 ts) {
- // Select new timer after hard preemption
- if (FastWorker != fastWorkerId) {
- FastWorker = fastWorkerId;
- PreemptionTimer = IdleQueue.Dequeue();
- HardPreemptionTs = 0;
- }
-
- ui64 hardPreemptionTs = ts + Config.HardLimitTs;
- if (hardPreemptionTs > HardPreemptionTs) {
- // Reset timer (at most once in TickIntervalTs, sacrifice precision)
- HardPreemptionTs = hardPreemptionTs + Config.LimitPrecisionTs;
- PreemptionTimer->Set(HardPreemptionTs);
- LWPROBE(SetPreemptionTimer, Config.CpuId, FastWorker, PreemptionTimer->Fd, Ts2Ms(ts), Ts2Ms(HardPreemptionTs));
- }
-
- return TLease(fastWorkerId, hardPreemptionTs);
- }
- };
-
- // Proxy for start and switching TUnitedExecutorPool-s on single cpu via GetReadyActivation()
- // (does not implement any other method in IExecutorPool)
- class TCpuExecutorPool: public IExecutorPool {
- const TString Name;
-
- public:
- explicit TCpuExecutorPool(const TString& name)
- : IExecutorPool(MaxPools)
- , Name(name)
- {}
-
- TString GetName() const override {
- return Name;
- }
-
- void SetRealTimeMode() const override {
- // derived classes controls rt-priority - do nothing
- }
-
- // Should never be called
- void ReclaimMailbox(TMailboxType::EType, ui32, TWorkerId, ui64) override { Y_FAIL(); }
- void Schedule(TInstant, TAutoPtr<IEventHandle>, ISchedulerCookie*, TWorkerId) override { Y_FAIL(); }
- void Schedule(TMonotonic, TAutoPtr<IEventHandle>, ISchedulerCookie*, TWorkerId) override { Y_FAIL(); }
- void Schedule(TDuration, TAutoPtr<IEventHandle>, ISchedulerCookie*, TWorkerId) override { Y_FAIL(); }
- bool Send(TAutoPtr<IEventHandle>&) override { Y_FAIL(); }
- void ScheduleActivation(ui32) override { Y_FAIL(); }
- void ScheduleActivationEx(ui32, ui64) override { Y_FAIL(); }
- TActorId Register(IActor*, TMailboxType::EType, ui64, const TActorId&) override { Y_FAIL(); }
- TActorId Register(IActor*, TMailboxHeader*, ui32, const TActorId&) override { Y_FAIL(); }
- void Prepare(TActorSystem*, NSchedulerQueue::TReader**, ui32*) override { Y_FAIL(); }
- void Start() override { Y_FAIL(); }
- void PrepareStop() override { Y_FAIL(); }
- void Shutdown() override { Y_FAIL(); }
- bool Cleanup() override { Y_FAIL(); }
- };
-
- // Proxy executor pool working with cpu-local scheduler (aka actorsystem 2.0)
- class TSharedCpuExecutorPool: public TCpuExecutorPool {
- TSharedCpu* Local;
- TIntrusivePtr<TAffinity> SingleCpuAffinity; // no migration support yet
- public:
- explicit TSharedCpuExecutorPool(TSharedCpu* local, const TUnitedWorkersConfig& config)
- : TCpuExecutorPool("u-" + ToString(local->Config.CpuId))
- , Local(local)
- , SingleCpuAffinity(config.NoAffinity ? nullptr : new TAffinity(TCpuMask(local->Config.CpuId)))
- {}
-
- TAffinity* Affinity() const override {
- return SingleCpuAffinity.Get();
- }
-
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override {
- return Local->GetReadyActivation(wctx, revolvingCounter);
- }
- };
-
- // Proxy executor pool working with balancer and assigned pools (aka actorsystem 1.5)
- class TAssignedCpuExecutorPool: public TCpuExecutorPool {
- TAssignedCpu* Local;
- TIntrusivePtr<TAffinity> CpuAffinity;
- public:
- explicit TAssignedCpuExecutorPool(TAssignedCpu* local, const TUnitedWorkersConfig& config)
- : TCpuExecutorPool("United")
- , Local(local)
- , CpuAffinity(config.NoAffinity ? nullptr : new TAffinity(config.Allowed))
- {}
-
- TAffinity* Affinity() const override {
- return CpuAffinity.Get();
- }
-
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override {
- return Local->GetReadyActivation(wctx, revolvingCounter);
- }
- };
-
- // Representation of a single cpu and it's state visible to other cpus and pools
- struct TUnitedWorkers::TCpu: public TNonCopyable {
- struct TScopedWaiters {
- TCpu& Cpu;
- TPool* AssignedPool; // nullptr if CpuShared
-
- // Subscribe on wakeups from allowed pools
- TScopedWaiters(TCpu& cpu, TPool* assignedPool) : Cpu(cpu), AssignedPool(assignedPool) {
- if (!AssignedPool) {
- for (TPool* pool : Cpu.AllowedPools) {
- AtomicIncrement(pool->Waiters);
+ }
+ } else {
+ if (assignedPool->TryAcquireTokenRelaxed()) {
+ result = WakeWithTokenAcquired(united, assignedPool->PoolId);
+ return true; // token acquired or stop
+ }
+ }
+
+ // At this point we can be sure wakeup won't be lost
+ // So we can actively spin or block w/o checking for pending tokens
+ return false;
+ }
+
+ bool ActiveWait(ui64 spinThresholdTs, TPoolId& result) {
+ ui64 deadline = GetCycleCountFast() + spinThresholdTs;
+ while (GetCycleCountFast() < deadline) {
+ for (ui32 i = 0; i < 12; ++i) {
+ TPoolId current = State.CurrentPool();
+ if (current == CpuSpinning) {
+ SpinLockPause();
+ } else {
+ result = current;
+ return true; // wakeup
}
- } else {
- AtomicIncrement(AssignedPool->Waiters);
- }
- }
-
- // Unsubscribe from pools we've subscribed on
- ~TScopedWaiters() {
- if (!AssignedPool) {
- for (TPool* pool : Cpu.AllowedPools) {
- AtomicDecrement(pool->Waiters);
- }
- } else {
- AtomicDecrement(AssignedPool->Waiters);
- }
- }
- };
-
- // Current cpu state important for other cpus and balancer
- TCpuState State;
-
- // Thread-safe per pool stats
- // NOTE: It's guaranteed that cpu never executes two instance of the same pool
- TVector<TExecutorThreadStats> PoolStats;
-
- // Configuration
- TCpuId CpuId;
- THolder<TCpuLocalManager> LocalManager;
- THolder<TCpuExecutorPool> ExecutorPool;
-
- // Pools allowed to run on this cpu
- TStackVec<TPool*, 15> AllowedPools;
-
- void Stop() {
- if (LocalManager) {
- State.Stop();
- LocalManager->Stop();
- }
- }
-
- bool StartSpinning(TUnitedWorkers* united, TPool* assignedPool, TPoolId& result) {
- // Mark cpu as idle
- if (Y_UNLIKELY(!State.StartSpinning())) {
- result = CpuStopped;
- return true;
- }
-
- // Avoid using multiple atomic seq_cst loads in cycle, use barrier once and relaxed ops
- AtomicBarrier();
-
- // Check there is no pending tokens (can be released before Waiters increment)
- if (!assignedPool) {
- for (TPool* pool : AllowedPools) {
- if (pool->TryAcquireTokenRelaxed()) {
- result = WakeWithTokenAcquired(united, pool->PoolId);
- return true; // token acquired or stop
- }
- }
- } else {
- if (assignedPool->TryAcquireTokenRelaxed()) {
- result = WakeWithTokenAcquired(united, assignedPool->PoolId);
- return true; // token acquired or stop
- }
- }
-
- // At this point we can be sure wakeup won't be lost
- // So we can actively spin or block w/o checking for pending tokens
- return false;
- }
-
- bool ActiveWait(ui64 spinThresholdTs, TPoolId& result) {
- ui64 deadline = GetCycleCountFast() + spinThresholdTs;
- while (GetCycleCountFast() < deadline) {
- for (ui32 i = 0; i < 12; ++i) {
- TPoolId current = State.CurrentPool();
- if (current == CpuSpinning) {
- SpinLockPause();
- } else {
- result = current;
- return true; // wakeup
- }
- }
- }
- return false; // spin threshold exceeded, no wakeups
- }
-
- bool StartBlocking(TPoolId& result) {
- // Switch into blocked state
- if (State.StartBlocking()) {
- result = State.CurrentPool();
- return true;
- } else {
- return false;
- }
- }
-
- bool BlockedWait(TPoolId& result, ui64 timeoutNs) {
- return State.Block(timeoutNs, result);
- }
-
- void SwitchPool(TPoolId pool) {
- return State.SwitchPool(pool);
- }
-
- private:
- TPoolId WakeWithTokenAcquired(TUnitedWorkers* united, TPoolId token) {
- switch (State.WakeWithTokenAcquired(token)) {
- case TCpuState::Woken: // we've got token and successfully woken up this cpu
- // NOTE: sending thread may also wakeup another worker, which wont be able to acquire token and will go idle (it's ok)
- return token;
- case TCpuState::NotIdle: { // wakeup event has also occured
- TPoolId wakeup = State.CurrentPool();
- if (wakeup != token) { // token and wakeup for different pools
- united->TryWake(wakeup); // rewake another cpu to avoid losing wakeup
- }
- return token;
- }
- case TCpuState::Forbidden:
- Y_FAIL();
- case TCpuState::Stopped:
- return CpuStopped;
- }
- }
- };
-
- TUnitedWorkers::TUnitedWorkers(
- const TUnitedWorkersConfig& config,
- const TVector<TUnitedExecutorPoolConfig>& unitedPools,
- const TCpuAllocationConfig& allocation,
- IBalancer* balancer)
- : Balancer(balancer)
- , Config(config)
- , Allocation(allocation)
- {
- // Find max pool id and initialize pools
- PoolCount = 0;
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- for (const auto& pa : cpuAlloc.AllowedPools) {
- PoolCount = Max<size_t>(PoolCount, pa.PoolId + 1);
- }
- }
- Pools.Reset(new TPool[PoolCount]);
-
- // Find max cpu id and initialize cpus
- CpuCount = 0;
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- CpuCount = Max<size_t>(CpuCount, cpuAlloc.CpuId + 1);
- }
- Cpus.Reset(new TCpu[CpuCount]);
-
- // Setup allocated cpus
- // NOTE: leave gaps for not allocated cpus (default-initialized)
- WorkerCount = 0;
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- TCpu& cpu = Cpus[cpuAlloc.CpuId];
- cpu.CpuId = cpuAlloc.CpuId;
- cpu.PoolStats.resize(PoolCount); // NOTE: also may have gaps
- for (const auto& pa : cpuAlloc.AllowedPools) {
- cpu.AllowedPools.emplace_back(&Pools[pa.PoolId]);
- }
-
- // Setup balancing and cpu-local manager
- if (!Balancer->AddCpu(cpuAlloc, &cpu.State)) {
- cpu.State.SwitchPool(0); // set initial state to non-idle to avoid losing wakeups on start
- cpu.State.AssignPool(CpuShared);
- TSharedCpu* local = new TSharedCpu(TSharedCpu::TConfig(cpuAlloc, Config), this);
- cpu.LocalManager.Reset(local);
- cpu.ExecutorPool.Reset(new TSharedCpuExecutorPool(local, Config));
- } else {
- TAssignedCpu* local = new TAssignedCpu(this);
- cpu.LocalManager.Reset(local);
- cpu.ExecutorPool.Reset(new TAssignedCpuExecutorPool(local, Config));
- }
- WorkerCount += cpu.LocalManager->WorkerCount();
- }
-
- // Initialize workers
- Workers.Reset(new TWorker[WorkerCount]);
-
- // Setup pools
- // NOTE: leave gaps for not united pools (default-initialized)
- for (const TUnitedExecutorPoolConfig& cfg : unitedPools) {
- TPool& pool = Pools[cfg.PoolId];
- Y_VERIFY(cfg.PoolId < MaxPools);
- pool.PoolId = cfg.PoolId;
- pool.Concurrency = cfg.Concurrency ? cfg.Concurrency : Config.CpuCount;
- pool.ExecutorPool = nullptr; // should be set later using SetupPool()
- pool.MailboxTable = nullptr; // should be set later using SetupPool()
- pool.TimePerMailboxTs = DurationToCycles(cfg.TimePerMailbox);
- pool.EventsPerMailbox = cfg.EventsPerMailbox;
-
- // Reinitialize per cpu pool stats with right MaxActivityType
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- TCpu& cpu = Cpus[cpuAlloc.CpuId];
- cpu.PoolStats[cfg.PoolId] = TExecutorThreadStats(cfg.MaxActivityType);
- }
-
- // Setup WakeOrderCpus: left to right exclusive cpus, then left to right shared cpus.
- // Waking exclusive cpus first reduce load on shared cpu and improve latency isolation, which is
- // the point of using exclusive cpu. But note that number of actively spinning idle cpus may increase,
- // so cpu consumption on light load is higher.
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- TCpu& cpu = Cpus[cpuAlloc.CpuId];
- if (cpu.AllowedPools.size() == 1 && cpu.AllowedPools[0] == &pool) {
- pool.WakeOrderCpus.emplace_back(&cpu);
- }
- }
- for (const TCpuAllocation& cpuAlloc : allocation.Items) {
- TCpu& cpu = Cpus[cpuAlloc.CpuId];
- if (cpu.AllowedPools.size() > 1 && cpuAlloc.HasPool(pool.PoolId)) {
- pool.WakeOrderCpus.emplace_back(&cpu);
- }
- }
- }
- }
-
- TUnitedWorkers::~TUnitedWorkers() {
- }
-
- void TUnitedWorkers::Prepare(TActorSystem* actorSystem, TVector<NSchedulerQueue::TReader*>& scheduleReaders) {
- // Setup allocated cpus
- // NOTE: leave gaps for not allocated cpus (default-initialized)
- TWorkerId workers = 0;
- for (TCpuId cpuId = 0; cpuId < CpuCount; cpuId++) {
- TCpu& cpu = Cpus[cpuId];
-
- // Setup cpu-local workers
- if (cpu.LocalManager) {
- for (size_t i = 0; i < cpu.LocalManager->WorkerCount(); i++) {
- TWorkerId workerId = workers++;
- cpu.LocalManager->AddWorker(workerId);
-
- // Setup worker
- Y_VERIFY(workerId < WorkerCount);
- Workers[workerId].Thread.Reset(new TExecutorThread(
- workerId,
- cpu.CpuId,
- actorSystem,
- cpu.ExecutorPool.Get(), // use cpu-local manager as proxy executor for all workers on cpu
- nullptr, // MailboxTable is pool-specific, will be set on pool switch
- cpu.ExecutorPool->GetName()));
- // NOTE: TWorker::ThreadId will be initialized after in Start()
-
- scheduleReaders.push_back(&Workers[workerId].SchedulerQueue.Reader);
- }
- }
- }
- }
-
- void TUnitedWorkers::Start() {
- for (TWorkerId workerId = 0; workerId < WorkerCount; workerId++) {
- Workers[workerId].Thread->Start();
- }
- for (TWorkerId workerId = 0; workerId < WorkerCount; workerId++) {
- AtomicStore(&Workers[workerId].ThreadId, Workers[workerId].Thread->GetThreadId());
- }
+ }
+ }
+ return false; // spin threshold exceeded, no wakeups
+ }
+
+ bool StartBlocking(TPoolId& result) {
+ // Switch into blocked state
+ if (State.StartBlocking()) {
+ result = State.CurrentPool();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool BlockedWait(TPoolId& result, ui64 timeoutNs) {
+ return State.Block(timeoutNs, result);
+ }
+
+ void SwitchPool(TPoolId pool) {
+ return State.SwitchPool(pool);
+ }
+
+ private:
+ TPoolId WakeWithTokenAcquired(TUnitedWorkers* united, TPoolId token) {
+ switch (State.WakeWithTokenAcquired(token)) {
+ case TCpuState::Woken: // we've got token and successfully woken up this cpu
+ // NOTE: sending thread may also wakeup another worker, which wont be able to acquire token and will go idle (it's ok)
+ return token;
+ case TCpuState::NotIdle: { // wakeup event has also occured
+ TPoolId wakeup = State.CurrentPool();
+ if (wakeup != token) { // token and wakeup for different pools
+ united->TryWake(wakeup); // rewake another cpu to avoid losing wakeup
+ }
+ return token;
+ }
+ case TCpuState::Forbidden:
+ Y_FAIL();
+ case TCpuState::Stopped:
+ return CpuStopped;
+ }
+ }
+ };
+
+ TUnitedWorkers::TUnitedWorkers(
+ const TUnitedWorkersConfig& config,
+ const TVector<TUnitedExecutorPoolConfig>& unitedPools,
+ const TCpuAllocationConfig& allocation,
+ IBalancer* balancer)
+ : Balancer(balancer)
+ , Config(config)
+ , Allocation(allocation)
+ {
+ // Find max pool id and initialize pools
+ PoolCount = 0;
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ for (const auto& pa : cpuAlloc.AllowedPools) {
+ PoolCount = Max<size_t>(PoolCount, pa.PoolId + 1);
+ }
+ }
+ Pools.Reset(new TPool[PoolCount]);
+
+ // Find max cpu id and initialize cpus
+ CpuCount = 0;
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ CpuCount = Max<size_t>(CpuCount, cpuAlloc.CpuId + 1);
+ }
+ Cpus.Reset(new TCpu[CpuCount]);
+
+ // Setup allocated cpus
+ // NOTE: leave gaps for not allocated cpus (default-initialized)
+ WorkerCount = 0;
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ TCpu& cpu = Cpus[cpuAlloc.CpuId];
+ cpu.CpuId = cpuAlloc.CpuId;
+ cpu.PoolStats.resize(PoolCount); // NOTE: also may have gaps
+ for (const auto& pa : cpuAlloc.AllowedPools) {
+ cpu.AllowedPools.emplace_back(&Pools[pa.PoolId]);
+ }
+
+ // Setup balancing and cpu-local manager
+ if (!Balancer->AddCpu(cpuAlloc, &cpu.State)) {
+ cpu.State.SwitchPool(0); // set initial state to non-idle to avoid losing wakeups on start
+ cpu.State.AssignPool(CpuShared);
+ TSharedCpu* local = new TSharedCpu(TSharedCpu::TConfig(cpuAlloc, Config), this);
+ cpu.LocalManager.Reset(local);
+ cpu.ExecutorPool.Reset(new TSharedCpuExecutorPool(local, Config));
+ } else {
+ TAssignedCpu* local = new TAssignedCpu(this);
+ cpu.LocalManager.Reset(local);
+ cpu.ExecutorPool.Reset(new TAssignedCpuExecutorPool(local, Config));
+ }
+ WorkerCount += cpu.LocalManager->WorkerCount();
+ }
+
+ // Initialize workers
+ Workers.Reset(new TWorker[WorkerCount]);
+
+ // Setup pools
+ // NOTE: leave gaps for not united pools (default-initialized)
+ for (const TUnitedExecutorPoolConfig& cfg : unitedPools) {
+ TPool& pool = Pools[cfg.PoolId];
+ Y_VERIFY(cfg.PoolId < MaxPools);
+ pool.PoolId = cfg.PoolId;
+ pool.Concurrency = cfg.Concurrency ? cfg.Concurrency : Config.CpuCount;
+ pool.ExecutorPool = nullptr; // should be set later using SetupPool()
+ pool.MailboxTable = nullptr; // should be set later using SetupPool()
+ pool.TimePerMailboxTs = DurationToCycles(cfg.TimePerMailbox);
+ pool.EventsPerMailbox = cfg.EventsPerMailbox;
+
+ // Reinitialize per cpu pool stats with right MaxActivityType
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ TCpu& cpu = Cpus[cpuAlloc.CpuId];
+ cpu.PoolStats[cfg.PoolId] = TExecutorThreadStats(cfg.MaxActivityType);
+ }
+
+ // Setup WakeOrderCpus: left to right exclusive cpus, then left to right shared cpus.
+ // Waking exclusive cpus first reduce load on shared cpu and improve latency isolation, which is
+ // the point of using exclusive cpu. But note that number of actively spinning idle cpus may increase,
+ // so cpu consumption on light load is higher.
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ TCpu& cpu = Cpus[cpuAlloc.CpuId];
+ if (cpu.AllowedPools.size() == 1 && cpu.AllowedPools[0] == &pool) {
+ pool.WakeOrderCpus.emplace_back(&cpu);
+ }
+ }
+ for (const TCpuAllocation& cpuAlloc : allocation.Items) {
+ TCpu& cpu = Cpus[cpuAlloc.CpuId];
+ if (cpu.AllowedPools.size() > 1 && cpuAlloc.HasPool(pool.PoolId)) {
+ pool.WakeOrderCpus.emplace_back(&cpu);
+ }
+ }
+ }
}
- inline TThreadId TUnitedWorkers::GetWorkerThreadId(TWorkerId workerId) const {
- volatile TThreadId* threadId = &Workers[workerId].ThreadId;
-#ifdef _linux_
- while (AtomicLoad(threadId) == UnknownThreadId) {
- NanoSleep(1000);
+ TUnitedWorkers::~TUnitedWorkers() {
+ }
+
+ void TUnitedWorkers::Prepare(TActorSystem* actorSystem, TVector<NSchedulerQueue::TReader*>& scheduleReaders) {
+ // Setup allocated cpus
+ // NOTE: leave gaps for not allocated cpus (default-initialized)
+ TWorkerId workers = 0;
+ for (TCpuId cpuId = 0; cpuId < CpuCount; cpuId++) {
+ TCpu& cpu = Cpus[cpuId];
+
+ // Setup cpu-local workers
+ if (cpu.LocalManager) {
+ for (size_t i = 0; i < cpu.LocalManager->WorkerCount(); i++) {
+ TWorkerId workerId = workers++;
+ cpu.LocalManager->AddWorker(workerId);
+
+ // Setup worker
+ Y_VERIFY(workerId < WorkerCount);
+ Workers[workerId].Thread.Reset(new TExecutorThread(
+ workerId,
+ cpu.CpuId,
+ actorSystem,
+ cpu.ExecutorPool.Get(), // use cpu-local manager as proxy executor for all workers on cpu
+ nullptr, // MailboxTable is pool-specific, will be set on pool switch
+ cpu.ExecutorPool->GetName()));
+ // NOTE: TWorker::ThreadId will be initialized after in Start()
+
+ scheduleReaders.push_back(&Workers[workerId].SchedulerQueue.Reader);
+ }
+ }
}
-#endif
- return AtomicLoad(threadId);
- }
-
- inline NSchedulerQueue::TWriter* TUnitedWorkers::GetScheduleWriter(TWorkerId workerId) const {
- return &Workers[workerId].SchedulerQueue.Writer;
- }
-
- void TUnitedWorkers::SetupPool(TPoolId pool, IExecutorPool* executorPool, TMailboxTable* mailboxTable) {
- Pools[pool].ExecutorPool = executorPool;
- Pools[pool].MailboxTable = mailboxTable;
}
- void TUnitedWorkers::PrepareStop() {
+ void TUnitedWorkers::Start() {
+ for (TWorkerId workerId = 0; workerId < WorkerCount; workerId++) {
+ Workers[workerId].Thread->Start();
+ }
+ for (TWorkerId workerId = 0; workerId < WorkerCount; workerId++) {
+ AtomicStore(&Workers[workerId].ThreadId, Workers[workerId].Thread->GetThreadId());
+ }
+ }
+
+ inline TThreadId TUnitedWorkers::GetWorkerThreadId(TWorkerId workerId) const {
+ volatile TThreadId* threadId = &Workers[workerId].ThreadId;
+#ifdef _linux_
+ while (AtomicLoad(threadId) == UnknownThreadId) {
+ NanoSleep(1000);
+ }
+#endif
+ return AtomicLoad(threadId);
+ }
+
+ inline NSchedulerQueue::TWriter* TUnitedWorkers::GetScheduleWriter(TWorkerId workerId) const {
+ return &Workers[workerId].SchedulerQueue.Writer;
+ }
+
+ void TUnitedWorkers::SetupPool(TPoolId pool, IExecutorPool* executorPool, TMailboxTable* mailboxTable) {
+ Pools[pool].ExecutorPool = executorPool;
+ Pools[pool].MailboxTable = mailboxTable;
+ }
+
+ void TUnitedWorkers::PrepareStop() {
AtomicStore(&StopFlag, true);
- for (TPoolId pool = 0; pool < PoolCount; pool++) {
- Pools[pool].Stop();
- }
- for (TCpuId cpuId = 0; cpuId < CpuCount; cpuId++) {
- Cpus[cpuId].Stop();
- }
- }
-
- void TUnitedWorkers::Shutdown() {
- for (TWorkerId workerId = 0; workerId < WorkerCount; workerId++) {
- Workers[workerId].Thread->Join();
- }
- }
-
- inline void TUnitedWorkers::PushActivation(TPoolId pool, ui32 activation, ui64 revolvingCounter) {
- if (Pools[pool].PushActivation(activation, revolvingCounter)) { // token generated
- TryWake(pool);
+ for (TPoolId pool = 0; pool < PoolCount; pool++) {
+ Pools[pool].Stop();
}
+ for (TCpuId cpuId = 0; cpuId < CpuCount; cpuId++) {
+ Cpus[cpuId].Stop();
+ }
}
- inline bool TUnitedWorkers::TryAcquireToken(TPoolId pool) {
- return Pools[pool].TryAcquireToken();
+ void TUnitedWorkers::Shutdown() {
+ for (TWorkerId workerId = 0; workerId < WorkerCount; workerId++) {
+ Workers[workerId].Thread->Join();
+ }
}
- inline void TUnitedWorkers::TryWake(TPoolId pool) {
- // Avoid using multiple atomic seq_cst loads in cycle, use barrier once
- AtomicBarrier();
-
- // Scan every allowed cpu in pool's wakeup order and try to wake the first idle cpu
- if (RelaxedLoad(&Pools[pool].Waiters) > 0) {
- for (TCpu* cpu : Pools[pool].WakeOrderCpus) {
- if (cpu->State.WakeWithoutToken(pool) == TCpuState::Woken) {
- return; // successful wake up
- }
- }
- }
+ inline void TUnitedWorkers::PushActivation(TPoolId pool, ui32 activation, ui64 revolvingCounter) {
+ if (Pools[pool].PushActivation(activation, revolvingCounter)) { // token generated
+ TryWake(pool);
+ }
+ }
- // Cpu has not been woken up
+ inline bool TUnitedWorkers::TryAcquireToken(TPoolId pool) {
+ return Pools[pool].TryAcquireToken();
}
- inline void TUnitedWorkers::BeginExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter) {
- Pools[pool].BeginExecution(activation, revolvingCounter);
+ inline void TUnitedWorkers::TryWake(TPoolId pool) {
+ // Avoid using multiple atomic seq_cst loads in cycle, use barrier once
+ AtomicBarrier();
+
+ // Scan every allowed cpu in pool's wakeup order and try to wake the first idle cpu
+ if (RelaxedLoad(&Pools[pool].Waiters) > 0) {
+ for (TCpu* cpu : Pools[pool].WakeOrderCpus) {
+ if (cpu->State.WakeWithoutToken(pool) == TCpuState::Woken) {
+ return; // successful wake up
+ }
+ }
+ }
+
+ // Cpu has not been woken up
+ }
+
+ inline void TUnitedWorkers::BeginExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter) {
+ Pools[pool].BeginExecution(activation, revolvingCounter);
}
- inline bool TUnitedWorkers::NextExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter) {
- return Pools[pool].NextExecution(activation, revolvingCounter);
- }
+ inline bool TUnitedWorkers::NextExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter) {
+ return Pools[pool].NextExecution(activation, revolvingCounter);
+ }
- inline void TUnitedWorkers::StopExecution(TPoolId pool) {
- if (Pools[pool].StopExecution()) { // pending token
- TryWake(pool);
- }
+ inline void TUnitedWorkers::StopExecution(TPoolId pool) {
+ if (Pools[pool].StopExecution()) { // pending token
+ TryWake(pool);
+ }
}
- inline void TUnitedWorkers::Balance() {
- ui64 ts = GetCycleCountFast();
- if (Balancer->TryLock(ts)) {
- for (TPoolId pool = 0; pool < PoolCount; pool++) {
- if (Pools[pool].IsUnited()) {
- ui64 ElapsedTs = 0;
- ui64 ParkedTs = 0;
- for (TCpu* cpu : Pools[pool].WakeOrderCpus) {
- const TExecutorThreadStats& cpuStats = cpu->PoolStats[pool];
- ElapsedTs += cpuStats.ElapsedTicks;
- ParkedTs += cpuStats.ParkedTicks;
- }
- TBalancerStats stats;
- stats.Ts = ts;
- stats.CpuUs = Ts2Us(ElapsedTs);
- stats.IdleUs = Ts2Us(ParkedTs);
- Balancer->SetPoolStats(pool, stats);
- }
- }
- Balancer->Balance();
- Balancer->Unlock();
- }
+ inline void TUnitedWorkers::Balance() {
+ ui64 ts = GetCycleCountFast();
+ if (Balancer->TryLock(ts)) {
+ for (TPoolId pool = 0; pool < PoolCount; pool++) {
+ if (Pools[pool].IsUnited()) {
+ ui64 ElapsedTs = 0;
+ ui64 ParkedTs = 0;
+ for (TCpu* cpu : Pools[pool].WakeOrderCpus) {
+ const TExecutorThreadStats& cpuStats = cpu->PoolStats[pool];
+ ElapsedTs += cpuStats.ElapsedTicks;
+ ParkedTs += cpuStats.ParkedTicks;
+ }
+ TBalancerStats stats;
+ stats.Ts = ts;
+ stats.CpuUs = Ts2Us(ElapsedTs);
+ stats.IdleUs = Ts2Us(ParkedTs);
+ Balancer->SetPoolStats(pool, stats);
+ }
+ }
+ Balancer->Balance();
+ Balancer->Unlock();
+ }
+ }
+
+ inline TPoolId TUnitedWorkers::AssignedPool(TWorkerContext& wctx) {
+ return Cpus[wctx.CpuId].State.AssignedPool();
+ }
+
+ inline bool TUnitedWorkers::IsPoolReassigned(TWorkerContext& wctx) {
+ return Cpus[wctx.CpuId].State.IsPoolReassigned(wctx.PoolId);
+ }
+
+ inline void TUnitedWorkers::SwitchPool(TWorkerContext& wctx, ui64 softDeadlineTs) {
+ Pools[wctx.PoolId].Switch(wctx, softDeadlineTs, Cpus[wctx.CpuId].PoolStats[wctx.PoolId]);
+ Cpus[wctx.CpuId].SwitchPool(wctx.PoolId);
+ }
+
+ TPoolId TUnitedWorkers::Idle(TPoolId assigned, TWorkerContext& wctx) {
+ wctx.SwitchToIdle();
+
+ TPoolId result;
+ TTimeTracker timeTracker;
+ TCpu& cpu = Cpus[wctx.CpuId];
+ TPool* assignedPool = assigned == CpuShared ? nullptr : &Pools[assigned];
+ TCpu::TScopedWaiters scopedWaiters(cpu, assignedPool);
+ while (true) {
+ if (cpu.StartSpinning(this, assignedPool, result)) {
+ break; // token already acquired (or stop)
+ }
+ result = WaitSequence(cpu, wctx, timeTracker);
+ if (Y_UNLIKELY(result == CpuStopped) || TryAcquireToken(result)) {
+ break; // token acquired (or stop)
+ }
+ }
+
+ wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
+ return result;
}
- inline TPoolId TUnitedWorkers::AssignedPool(TWorkerContext& wctx) {
- return Cpus[wctx.CpuId].State.AssignedPool();
+ TPoolId TUnitedWorkers::WaitSequence(TCpu& cpu, TWorkerContext& wctx, TTimeTracker& timeTracker) {
+ TPoolId result;
+ if (cpu.ActiveWait(Us2Ts(Config.SpinThresholdUs), result)) {
+ wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
+ return result;
+ }
+ if (cpu.StartBlocking(result)) {
+ wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
+ return result;
+ }
+ wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
+ bool wakeup;
+ do {
+ wakeup = cpu.BlockedWait(result, Config.Balancer.PeriodUs * 1000);
+ wctx.AddParkedCycles(timeTracker.Elapsed());
+ } while (!wakeup);
+ return result;
}
- inline bool TUnitedWorkers::IsPoolReassigned(TWorkerContext& wctx) {
- return Cpus[wctx.CpuId].State.IsPoolReassigned(wctx.PoolId);
- }
-
- inline void TUnitedWorkers::SwitchPool(TWorkerContext& wctx, ui64 softDeadlineTs) {
- Pools[wctx.PoolId].Switch(wctx, softDeadlineTs, Cpus[wctx.CpuId].PoolStats[wctx.PoolId]);
- Cpus[wctx.CpuId].SwitchPool(wctx.PoolId);
- }
-
- TPoolId TUnitedWorkers::Idle(TPoolId assigned, TWorkerContext& wctx) {
- wctx.SwitchToIdle();
-
- TPoolId result;
- TTimeTracker timeTracker;
- TCpu& cpu = Cpus[wctx.CpuId];
- TPool* assignedPool = assigned == CpuShared ? nullptr : &Pools[assigned];
- TCpu::TScopedWaiters scopedWaiters(cpu, assignedPool);
- while (true) {
- if (cpu.StartSpinning(this, assignedPool, result)) {
- break; // token already acquired (or stop)
- }
- result = WaitSequence(cpu, wctx, timeTracker);
- if (Y_UNLIKELY(result == CpuStopped) || TryAcquireToken(result)) {
- break; // token acquired (or stop)
- }
- }
-
- wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
- return result;
- }
-
- TPoolId TUnitedWorkers::WaitSequence(TCpu& cpu, TWorkerContext& wctx, TTimeTracker& timeTracker) {
- TPoolId result;
- if (cpu.ActiveWait(Us2Ts(Config.SpinThresholdUs), result)) {
- wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
- return result;
- }
- if (cpu.StartBlocking(result)) {
- wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
- return result;
- }
- wctx.AddElapsedCycles(IActor::ACTOR_SYSTEM, timeTracker.Elapsed());
- bool wakeup;
- do {
- wakeup = cpu.BlockedWait(result, Config.Balancer.PeriodUs * 1000);
- wctx.AddParkedCycles(timeTracker.Elapsed());
- } while (!wakeup);
- return result;
- }
-
- void TUnitedWorkers::GetCurrentStats(TPoolId pool, TVector<TExecutorThreadStats>& statsCopy) const {
- size_t idx = 1;
- statsCopy.resize(idx + Pools[pool].WakeOrderCpus.size());
- for (TCpu* cpu : Pools[pool].WakeOrderCpus) {
- TExecutorThreadStats& s = statsCopy[idx++];
- s = TExecutorThreadStats();
- s.Aggregate(cpu->PoolStats[pool]);
- }
- }
-
- TUnitedExecutorPool::TUnitedExecutorPool(const TUnitedExecutorPoolConfig& cfg, TUnitedWorkers* united)
- : TExecutorPoolBaseMailboxed(cfg.PoolId, cfg.MaxActivityType)
- , United(united)
- , PoolName(cfg.PoolName)
- {
- United->SetupPool(TPoolId(cfg.PoolId), this, MailboxTable.Get());
- }
-
- void TUnitedExecutorPool::Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) {
- ActorSystem = actorSystem;
-
- // Schedule readers are initialized through TUnitedWorkers::Prepare
- *scheduleReaders = nullptr;
- *scheduleSz = 0;
- }
-
- void TUnitedExecutorPool::Start() {
- // workers are actually started in TUnitedWorkers::Start()
- }
-
- void TUnitedExecutorPool::PrepareStop() {
- }
-
- void TUnitedExecutorPool::Shutdown() {
- // workers are actually joined in TUnitedWorkers::Shutdown()
- }
-
- TAffinity* TUnitedExecutorPool::Affinity() const {
- Y_FAIL(); // should never be called, TCpuExecutorPool is used instead
- }
-
- ui32 TUnitedExecutorPool::GetThreads() const {
- return 0;
- }
-
- ui32 TUnitedExecutorPool::GetReadyActivation(TWorkerContext&, ui64) {
- Y_FAIL(); // should never be called, TCpu*ExecutorPool is used instead
- }
-
- inline void TUnitedExecutorPool::ScheduleActivation(ui32 activation) {
- TUnitedExecutorPool::ScheduleActivationEx(activation, AtomicIncrement(ActivationsRevolvingCounter));
- }
-
- inline void TUnitedExecutorPool::ScheduleActivationEx(ui32 activation, ui64 revolvingCounter) {
- United->PushActivation(PoolId, activation, revolvingCounter);
- }
-
- void TUnitedExecutorPool::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- TUnitedExecutorPool::Schedule(deadline - ActorSystem->Timestamp(), ev, cookie, workerId);
- }
-
- void TUnitedExecutorPool::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_VERIFY_DEBUG(workerId < United->GetWorkerCount());
- const auto current = ActorSystem->Monotonic();
- if (deadline < current) {
- deadline = current;
- }
- United->GetScheduleWriter(workerId)->Push(deadline.MicroSeconds(), ev.Release(), cookie);
- }
-
- void TUnitedExecutorPool::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
- Y_VERIFY_DEBUG(workerId < United->GetWorkerCount());
- const auto deadline = ActorSystem->Monotonic() + delta;
- United->GetScheduleWriter(workerId)->Push(deadline.MicroSeconds(), ev.Release(), cookie);
- }
-
- void TUnitedExecutorPool::GetCurrentStats(TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const {
- Y_UNUSED(poolStats);
- if (statsCopy.empty()) {
- statsCopy.resize(1);
- }
- statsCopy[0] = TExecutorThreadStats();
- statsCopy[0].Aggregate(Stats);
- United->GetCurrentStats(PoolId, statsCopy);
+ void TUnitedWorkers::GetCurrentStats(TPoolId pool, TVector<TExecutorThreadStats>& statsCopy) const {
+ size_t idx = 1;
+ statsCopy.resize(idx + Pools[pool].WakeOrderCpus.size());
+ for (TCpu* cpu : Pools[pool].WakeOrderCpus) {
+ TExecutorThreadStats& s = statsCopy[idx++];
+ s = TExecutorThreadStats();
+ s.Aggregate(cpu->PoolStats[pool]);
+ }
+ }
+
+ TUnitedExecutorPool::TUnitedExecutorPool(const TUnitedExecutorPoolConfig& cfg, TUnitedWorkers* united)
+ : TExecutorPoolBaseMailboxed(cfg.PoolId, cfg.MaxActivityType)
+ , United(united)
+ , PoolName(cfg.PoolName)
+ {
+ United->SetupPool(TPoolId(cfg.PoolId), this, MailboxTable.Get());
+ }
+
+ void TUnitedExecutorPool::Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) {
+ ActorSystem = actorSystem;
+
+ // Schedule readers are initialized through TUnitedWorkers::Prepare
+ *scheduleReaders = nullptr;
+ *scheduleSz = 0;
+ }
+
+ void TUnitedExecutorPool::Start() {
+ // workers are actually started in TUnitedWorkers::Start()
+ }
+
+ void TUnitedExecutorPool::PrepareStop() {
+ }
+
+ void TUnitedExecutorPool::Shutdown() {
+ // workers are actually joined in TUnitedWorkers::Shutdown()
+ }
+
+ TAffinity* TUnitedExecutorPool::Affinity() const {
+ Y_FAIL(); // should never be called, TCpuExecutorPool is used instead
+ }
+
+ ui32 TUnitedExecutorPool::GetThreads() const {
+ return 0;
+ }
+
+ ui32 TUnitedExecutorPool::GetReadyActivation(TWorkerContext&, ui64) {
+ Y_FAIL(); // should never be called, TCpu*ExecutorPool is used instead
+ }
+
+ inline void TUnitedExecutorPool::ScheduleActivation(ui32 activation) {
+ TUnitedExecutorPool::ScheduleActivationEx(activation, AtomicIncrement(ActivationsRevolvingCounter));
+ }
+
+ inline void TUnitedExecutorPool::ScheduleActivationEx(ui32 activation, ui64 revolvingCounter) {
+ United->PushActivation(PoolId, activation, revolvingCounter);
+ }
+
+ void TUnitedExecutorPool::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ TUnitedExecutorPool::Schedule(deadline - ActorSystem->Timestamp(), ev, cookie, workerId);
+ }
+
+ void TUnitedExecutorPool::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_VERIFY_DEBUG(workerId < United->GetWorkerCount());
+ const auto current = ActorSystem->Monotonic();
+ if (deadline < current) {
+ deadline = current;
+ }
+ United->GetScheduleWriter(workerId)->Push(deadline.MicroSeconds(), ev.Release(), cookie);
}
+
+ void TUnitedExecutorPool::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) {
+ Y_VERIFY_DEBUG(workerId < United->GetWorkerCount());
+ const auto deadline = ActorSystem->Monotonic() + delta;
+ United->GetScheduleWriter(workerId)->Push(deadline.MicroSeconds(), ev.Release(), cookie);
+ }
+
+ void TUnitedExecutorPool::GetCurrentStats(TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const {
+ Y_UNUSED(poolStats);
+ if (statsCopy.empty()) {
+ statsCopy.resize(1);
+ }
+ statsCopy[0] = TExecutorThreadStats();
+ statsCopy[0].Aggregate(Stats);
+ United->GetCurrentStats(PoolId, statsCopy);
+ }
}
diff --git a/library/cpp/actors/core/executor_pool_united.h b/library/cpp/actors/core/executor_pool_united.h
index a090ba2466..8f5cabe365 100644
--- a/library/cpp/actors/core/executor_pool_united.h
+++ b/library/cpp/actors/core/executor_pool_united.h
@@ -1,133 +1,133 @@
#pragma once
#include "actorsystem.h"
-#include "balancer.h"
+#include "balancer.h"
#include "scheduler_queue.h"
#include "executor_pool_base.h"
-
+
#include <library/cpp/actors/util/unordered_cache.h>
-
+
#include <library/cpp/monlib/dynamic_counters/counters.h>
-#include <library/cpp/actors/util/unordered_cache.h>
-#include <library/cpp/containers/stack_vector/stack_vec.h>
-
-#include <util/generic/noncopyable.h>
-
+#include <library/cpp/actors/util/unordered_cache.h>
+#include <library/cpp/containers/stack_vector/stack_vec.h>
+
+#include <util/generic/noncopyable.h>
+
namespace NActors {
- class TMailboxTable;
-
- class TUnitedWorkers: public TNonCopyable {
- struct TWorker;
- struct TPool;
- struct TCpu;
-
- size_t WorkerCount;
- TArrayHolder<TWorker> Workers; // indexed by WorkerId
- size_t PoolCount;
- TArrayHolder<TPool> Pools; // indexed by PoolId, so may include not used (not united) pools
- size_t CpuCount;
- TArrayHolder<TCpu> Cpus; // indexed by CpuId, so may include not allocated CPUs
-
- IBalancer* Balancer; // external pool cpu balancer
-
- TUnitedWorkersConfig Config;
- TCpuAllocationConfig Allocation;
-
- volatile bool StopFlag = false;
-
- public:
- TUnitedWorkers(
- const TUnitedWorkersConfig& config,
- const TVector<TUnitedExecutorPoolConfig>& unitedPools,
- const TCpuAllocationConfig& allocation,
- IBalancer* balancer);
- ~TUnitedWorkers();
- void Prepare(TActorSystem* actorSystem, TVector<NSchedulerQueue::TReader*>& scheduleReaders);
- void Start();
- void PrepareStop();
- void Shutdown();
-
- bool IsStopped() const {
- return RelaxedLoad(&StopFlag);
- }
-
- TWorkerId GetWorkerCount() const {
- return WorkerCount;
- }
-
- // Returns thread id of a worker
- TThreadId GetWorkerThreadId(TWorkerId workerId) const;
-
- // Returns per worker schedule writers
- NSchedulerQueue::TWriter* GetScheduleWriter(TWorkerId workerId) const;
-
- // Sets executor for specified pool
- void SetupPool(TPoolId pool, IExecutorPool* executorPool, TMailboxTable* mailboxTable);
-
- // Add activation of newly scheduled mailbox and wake cpu to execute it if required
- void PushActivation(TPoolId pool, ui32 activation, ui64 revolvingCounter);
-
- // Try acquire pending token. Must be done before execution
- bool TryAcquireToken(TPoolId pool);
-
- // Try to wake idle cpu waiting for tokens on specified pool
- void TryWake(TPoolId pool);
-
- // Get activation from pool; requires pool's token
- void BeginExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter);
-
- // Stop currently active execution and start new one if token is available
- // NOTE: Reuses token if it's not destroyed
- bool NextExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter);
-
- // Stop active execution
- void StopExecution(TPoolId pool);
-
- // Runs balancer to assign pools to cpus
- void Balance();
-
- // Returns pool to be executed by worker or `CpuShared`
- TPoolId AssignedPool(TWorkerContext& wctx);
-
- // Checks if balancer has assigned another pool for worker's cpu
- bool IsPoolReassigned(TWorkerContext& wctx);
-
- // Switch worker context into specified pool
- void SwitchPool(TWorkerContext& wctx, ui64 softDeadlineTs);
-
- // Wait for tokens from any pool allowed on specified cpu
- TPoolId Idle(TPoolId assigned, TWorkerContext& wctx);
-
- // Fill stats for specified pool
- void GetCurrentStats(TPoolId pool, TVector<TExecutorThreadStats>& statsCopy) const;
-
- private:
- TPoolId WaitSequence(TCpu& cpu, TWorkerContext& wctx, TTimeTracker& timeTracker);
- };
-
- class TUnitedExecutorPool: public TExecutorPoolBaseMailboxed {
- TUnitedWorkers* United;
- const TString PoolName;
- TAtomic ActivationsRevolvingCounter = 0;
- public:
- TUnitedExecutorPool(const TUnitedExecutorPoolConfig& cfg, TUnitedWorkers* united);
-
- void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) override;
+ class TMailboxTable;
+
+ class TUnitedWorkers: public TNonCopyable {
+ struct TWorker;
+ struct TPool;
+ struct TCpu;
+
+ size_t WorkerCount;
+ TArrayHolder<TWorker> Workers; // indexed by WorkerId
+ size_t PoolCount;
+ TArrayHolder<TPool> Pools; // indexed by PoolId, so may include not used (not united) pools
+ size_t CpuCount;
+ TArrayHolder<TCpu> Cpus; // indexed by CpuId, so may include not allocated CPUs
+
+ IBalancer* Balancer; // external pool cpu balancer
+
+ TUnitedWorkersConfig Config;
+ TCpuAllocationConfig Allocation;
+
+ volatile bool StopFlag = false;
+
+ public:
+ TUnitedWorkers(
+ const TUnitedWorkersConfig& config,
+ const TVector<TUnitedExecutorPoolConfig>& unitedPools,
+ const TCpuAllocationConfig& allocation,
+ IBalancer* balancer);
+ ~TUnitedWorkers();
+ void Prepare(TActorSystem* actorSystem, TVector<NSchedulerQueue::TReader*>& scheduleReaders);
+ void Start();
+ void PrepareStop();
+ void Shutdown();
+
+ bool IsStopped() const {
+ return RelaxedLoad(&StopFlag);
+ }
+
+ TWorkerId GetWorkerCount() const {
+ return WorkerCount;
+ }
+
+ // Returns thread id of a worker
+ TThreadId GetWorkerThreadId(TWorkerId workerId) const;
+
+ // Returns per worker schedule writers
+ NSchedulerQueue::TWriter* GetScheduleWriter(TWorkerId workerId) const;
+
+ // Sets executor for specified pool
+ void SetupPool(TPoolId pool, IExecutorPool* executorPool, TMailboxTable* mailboxTable);
+
+ // Add activation of newly scheduled mailbox and wake cpu to execute it if required
+ void PushActivation(TPoolId pool, ui32 activation, ui64 revolvingCounter);
+
+ // Try acquire pending token. Must be done before execution
+ bool TryAcquireToken(TPoolId pool);
+
+ // Try to wake idle cpu waiting for tokens on specified pool
+ void TryWake(TPoolId pool);
+
+ // Get activation from pool; requires pool's token
+ void BeginExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter);
+
+ // Stop currently active execution and start new one if token is available
+ // NOTE: Reuses token if it's not destroyed
+ bool NextExecution(TPoolId pool, ui32& activation, ui64 revolvingCounter);
+
+ // Stop active execution
+ void StopExecution(TPoolId pool);
+
+ // Runs balancer to assign pools to cpus
+ void Balance();
+
+ // Returns pool to be executed by worker or `CpuShared`
+ TPoolId AssignedPool(TWorkerContext& wctx);
+
+ // Checks if balancer has assigned another pool for worker's cpu
+ bool IsPoolReassigned(TWorkerContext& wctx);
+
+ // Switch worker context into specified pool
+ void SwitchPool(TWorkerContext& wctx, ui64 softDeadlineTs);
+
+ // Wait for tokens from any pool allowed on specified cpu
+ TPoolId Idle(TPoolId assigned, TWorkerContext& wctx);
+
+ // Fill stats for specified pool
+ void GetCurrentStats(TPoolId pool, TVector<TExecutorThreadStats>& statsCopy) const;
+
+ private:
+ TPoolId WaitSequence(TCpu& cpu, TWorkerContext& wctx, TTimeTracker& timeTracker);
+ };
+
+ class TUnitedExecutorPool: public TExecutorPoolBaseMailboxed {
+ TUnitedWorkers* United;
+ const TString PoolName;
+ TAtomic ActivationsRevolvingCounter = 0;
+ public:
+ TUnitedExecutorPool(const TUnitedExecutorPoolConfig& cfg, TUnitedWorkers* united);
+
+ void Prepare(TActorSystem* actorSystem, NSchedulerQueue::TReader** scheduleReaders, ui32* scheduleSz) override;
void Start() override;
void PrepareStop() override;
void Shutdown() override;
- TAffinity* Affinity() const override;
- ui32 GetThreads() const override;
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingReadCounter) override;
- void ScheduleActivation(ui32 activation) override;
- void ScheduleActivationEx(ui32 activation, ui64 revolvingWriteCounter) override;
- void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
- void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
- void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
-
+ TAffinity* Affinity() const override;
+ ui32 GetThreads() const override;
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingReadCounter) override;
+ void ScheduleActivation(ui32 activation) override;
+ void ScheduleActivationEx(ui32 activation, ui64 revolvingWriteCounter) override;
+ void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+ void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie, TWorkerId workerId) override;
+
void GetCurrentStats(TExecutorPoolStats& poolStats, TVector<TExecutorThreadStats>& statsCopy) const override;
-
+
TString GetName() const override {
return PoolName;
}
diff --git a/library/cpp/actors/core/executor_pool_united_ut.cpp b/library/cpp/actors/core/executor_pool_united_ut.cpp
index d4df17f1b8..97e1f91557 100644
--- a/library/cpp/actors/core/executor_pool_united_ut.cpp
+++ b/library/cpp/actors/core/executor_pool_united_ut.cpp
@@ -18,18 +18,18 @@ struct TEvMsg : public NActors::TEventBase<TEvMsg, 10347> {
////////////////////////////////////////////////////////////////////////////////
-inline ui64 DoTimedWork(ui64 workUs) {
- ui64 startUs = ThreadCPUTime();
- ui64 endUs = startUs + workUs;
- ui64 nowUs = startUs;
- do {
- ui64 endTs = GetCycleCountFast() + Us2Ts(endUs - nowUs);
- while (GetCycleCountFast() <= endTs) {}
- nowUs = ThreadCPUTime();
- } while (nowUs <= endUs);
- return nowUs - startUs;
-}
-
+inline ui64 DoTimedWork(ui64 workUs) {
+ ui64 startUs = ThreadCPUTime();
+ ui64 endUs = startUs + workUs;
+ ui64 nowUs = startUs;
+ do {
+ ui64 endTs = GetCycleCountFast() + Us2Ts(endUs - nowUs);
+ while (GetCycleCountFast() <= endTs) {}
+ nowUs = ThreadCPUTime();
+ } while (nowUs <= endUs);
+ return nowUs - startUs;
+}
+
class TTestSenderActor : public IActor {
private:
using EActivityType = IActor::EActivityType ;
@@ -48,7 +48,7 @@ public:
, Action(action)
{}
- void Start(TActorId receiver, size_t count) {
+ void Start(TActorId receiver, size_t count) {
AtomicSet(Counter, count);
Receiver = receiver;
}
@@ -68,14 +68,14 @@ public:
}
private:
- STFUNC(Execute) {
+ STFUNC(Execute) {
Y_UNUSED(ctx);
switch (ev->GetTypeRewrite()) {
hFunc(TEvMsg, Handle);
}
}
- void Handle(TEvMsg::TPtr &ev) {
+ void Handle(TEvMsg::TPtr &ev) {
Y_UNUSED(ev);
Action();
TAtomicBase count = AtomicDecrement(Counter);
@@ -86,57 +86,57 @@ private:
}
};
-// Single cpu balancer that switches pool on every activation; not thread-safe
-struct TRoundRobinBalancer: public IBalancer {
- TCpuState* State;
- TMap<TPoolId, TPoolId> NextPool;
-
- bool AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* cpu) override {
- State = cpu;
- TPoolId prev = cpuAlloc.AllowedPools.rbegin()->PoolId;
- for (auto& p : cpuAlloc.AllowedPools) {
- NextPool[prev] = p.PoolId;
- prev = p.PoolId;
- }
- return true;
- }
-
- bool TryLock(ui64) override { return true; }
- void SetPoolStats(TPoolId, const TBalancerStats&) override {}
- void Unlock() override {}
-
- void Balance() override {
- TPoolId assigned;
- TPoolId current;
- State->Load(assigned, current);
- State->AssignPool(NextPool[assigned]);
- }
-};
-
-void AddUnitedPool(THolder<TActorSystemSetup>& setup, ui32 concurrency = 0) {
- TUnitedExecutorPoolConfig united;
- united.PoolId = setup->GetExecutorsCount();
- united.Concurrency = concurrency;
- setup->CpuManager.United.emplace_back(std::move(united));
-}
-
-THolder<TActorSystemSetup> GetActorSystemSetup(ui32 cpuCount) {
+// Single cpu balancer that switches pool on every activation; not thread-safe
+struct TRoundRobinBalancer: public IBalancer {
+ TCpuState* State;
+ TMap<TPoolId, TPoolId> NextPool;
+
+ bool AddCpu(const TCpuAllocation& cpuAlloc, TCpuState* cpu) override {
+ State = cpu;
+ TPoolId prev = cpuAlloc.AllowedPools.rbegin()->PoolId;
+ for (auto& p : cpuAlloc.AllowedPools) {
+ NextPool[prev] = p.PoolId;
+ prev = p.PoolId;
+ }
+ return true;
+ }
+
+ bool TryLock(ui64) override { return true; }
+ void SetPoolStats(TPoolId, const TBalancerStats&) override {}
+ void Unlock() override {}
+
+ void Balance() override {
+ TPoolId assigned;
+ TPoolId current;
+ State->Load(assigned, current);
+ State->AssignPool(NextPool[assigned]);
+ }
+};
+
+void AddUnitedPool(THolder<TActorSystemSetup>& setup, ui32 concurrency = 0) {
+ TUnitedExecutorPoolConfig united;
+ united.PoolId = setup->GetExecutorsCount();
+ united.Concurrency = concurrency;
+ setup->CpuManager.United.emplace_back(std::move(united));
+}
+
+THolder<TActorSystemSetup> GetActorSystemSetup(ui32 cpuCount) {
auto setup = MakeHolder<NActors::TActorSystemSetup>();
setup->NodeId = 1;
- setup->CpuManager.UnitedWorkers.CpuCount = cpuCount;
- setup->CpuManager.UnitedWorkers.NoRealtime = true; // unavailable in test environment
+ setup->CpuManager.UnitedWorkers.CpuCount = cpuCount;
+ setup->CpuManager.UnitedWorkers.NoRealtime = true; // unavailable in test environment
setup->Scheduler = new TBasicSchedulerThread(NActors::TSchedulerConfig(512, 0));
return setup;
}
-Y_UNIT_TEST_SUITE(UnitedExecutorPool) {
+Y_UNIT_TEST_SUITE(UnitedExecutorPool) {
-#ifdef _linux_
+#ifdef _linux_
- Y_UNIT_TEST(OnePoolManyCpus) {
+ Y_UNIT_TEST(OnePoolManyCpus) {
const size_t msgCount = 1e4;
- auto setup = GetActorSystemSetup(4);
- AddUnitedPool(setup);
+ auto setup = GetActorSystemSetup(4);
+ AddUnitedPool(setup);
TActorSystem actorSystem(setup);
actorSystem.Start();
@@ -153,186 +153,186 @@ Y_UNIT_TEST_SUITE(UnitedExecutorPool) {
Sleep(TDuration::MilliSeconds(1));
}
-
- TVector<TExecutorThreadStats> stats;
- TExecutorPoolStats poolStats;
- actorSystem.GetPoolStats(0, poolStats, stats);
- // Sum all per-thread counters into the 0th element
- for (ui32 idx = 1; idx < stats.size(); ++idx) {
- stats[0].Aggregate(stats[idx]);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(stats[0].SentEvents, msgCount - 1);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
- //UNIT_ASSERT_VALUES_EQUAL(stats[0].PreemptedEvents, 0); // depends on execution time and system load, so may be non-zero
- UNIT_ASSERT_VALUES_EQUAL(stats[0].NonDeliveredEvents, 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].EmptyMailboxActivation, 0);
- //UNIT_ASSERT_VALUES_EQUAL(stats[0].CpuNs, 0); // depends on total duration of test, so undefined
- UNIT_ASSERT(stats[0].ElapsedTicks > 0);
- UNIT_ASSERT(stats[0].ParkedTicks == 0); // per-pool parked time does not make sense for united pools
- UNIT_ASSERT_VALUES_EQUAL(stats[0].BlockedTicks, 0);
- UNIT_ASSERT(stats[0].ActivationTimeHistogram.TotalSamples >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].EventDeliveryTimeHistogram.TotalSamples, msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].EventProcessingCountHistogram.TotalSamples, msgCount);
- UNIT_ASSERT(stats[0].EventProcessingTimeHistogram.TotalSamples > 0);
- UNIT_ASSERT(stats[0].ElapsedTicksByActivity[0] > 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEventsByActivity[0], msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ActorsAliveByActivity[0], 1);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ScheduledEventsByActivity[0], 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolDestroyedActors, 0);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolAllocatedMailboxes, 4095); // one line
- UNIT_ASSERT(stats[0].MailboxPushedOutByTime + stats[0].MailboxPushedOutByEventCount + stats[0].MailboxPushedOutBySoftPreemption >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
+
+ TVector<TExecutorThreadStats> stats;
+ TExecutorPoolStats poolStats;
+ actorSystem.GetPoolStats(0, poolStats, stats);
+ // Sum all per-thread counters into the 0th element
+ for (ui32 idx = 1; idx < stats.size(); ++idx) {
+ stats[0].Aggregate(stats[idx]);
+ }
+
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].SentEvents, msgCount - 1);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
+ //UNIT_ASSERT_VALUES_EQUAL(stats[0].PreemptedEvents, 0); // depends on execution time and system load, so may be non-zero
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].NonDeliveredEvents, 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].EmptyMailboxActivation, 0);
+ //UNIT_ASSERT_VALUES_EQUAL(stats[0].CpuNs, 0); // depends on total duration of test, so undefined
+ UNIT_ASSERT(stats[0].ElapsedTicks > 0);
+ UNIT_ASSERT(stats[0].ParkedTicks == 0); // per-pool parked time does not make sense for united pools
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].BlockedTicks, 0);
+ UNIT_ASSERT(stats[0].ActivationTimeHistogram.TotalSamples >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].EventDeliveryTimeHistogram.TotalSamples, msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].EventProcessingCountHistogram.TotalSamples, msgCount);
+ UNIT_ASSERT(stats[0].EventProcessingTimeHistogram.TotalSamples > 0);
+ UNIT_ASSERT(stats[0].ElapsedTicksByActivity[0] > 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEventsByActivity[0], msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ActorsAliveByActivity[0], 1);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ScheduledEventsByActivity[0], 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolDestroyedActors, 0);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolAllocatedMailboxes, 4095); // one line
+ UNIT_ASSERT(stats[0].MailboxPushedOutByTime + stats[0].MailboxPushedOutByEventCount + stats[0].MailboxPushedOutBySoftPreemption >= msgCount / TBasicExecutorPoolConfig::DEFAULT_EVENTS_PER_MAILBOX);
}
- Y_UNIT_TEST(ManyPoolsOneSharedCpu) {
+ Y_UNIT_TEST(ManyPoolsOneSharedCpu) {
const size_t msgCount = 1e4;
- const size_t pools = 4;
- auto setup = GetActorSystemSetup(1);
- for (size_t pool = 0; pool < pools; pool++) {
- AddUnitedPool(setup);
- }
+ const size_t pools = 4;
+ auto setup = GetActorSystemSetup(1);
+ for (size_t pool = 0; pool < pools; pool++) {
+ AddUnitedPool(setup);
+ }
TActorSystem actorSystem(setup);
actorSystem.Start();
auto begin = TInstant::Now();
- TVector<TTestSenderActor*> actors;
- for (size_t pool = 0; pool < pools; pool++) {
- auto actor = new TTestSenderActor();
- auto actorId = actorSystem.Register(actor, TMailboxType::HTSwap, pool);
- actor->Start(actor->SelfId(), msgCount);
- actorSystem.Send(actorId, new TEvMsg());
- actors.push_back(actor);
+ TVector<TTestSenderActor*> actors;
+ for (size_t pool = 0; pool < pools; pool++) {
+ auto actor = new TTestSenderActor();
+ auto actorId = actorSystem.Register(actor, TMailboxType::HTSwap, pool);
+ actor->Start(actor->SelfId(), msgCount);
+ actorSystem.Send(actorId, new TEvMsg());
+ actors.push_back(actor);
}
while (true) {
- size_t left = 0;
- for (auto actor : actors) {
- left += actor->GetCounter();
+ size_t left = 0;
+ for (auto actor : actors) {
+ left += actor->GetCounter();
}
- if (left == 0) {
+ if (left == 0) {
break;
}
auto now = TInstant::Now();
- UNIT_ASSERT_C(now - begin < TDuration::Seconds(5), "left " << left);
+ UNIT_ASSERT_C(now - begin < TDuration::Seconds(5), "left " << left);
Sleep(TDuration::MilliSeconds(1));
}
-
- for (size_t pool = 0; pool < pools; pool++) {
- TVector<TExecutorThreadStats> stats;
- TExecutorPoolStats poolStats;
- actorSystem.GetPoolStats(pool, poolStats, stats);
- // Sum all per-thread counters into the 0th element
- for (ui32 idx = 1; idx < stats.size(); ++idx) {
- stats[0].Aggregate(stats[idx]);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
- }
+
+ for (size_t pool = 0; pool < pools; pool++) {
+ TVector<TExecutorThreadStats> stats;
+ TExecutorPoolStats poolStats;
+ actorSystem.GetPoolStats(pool, poolStats, stats);
+ // Sum all per-thread counters into the 0th element
+ for (ui32 idx = 1; idx < stats.size(); ++idx) {
+ stats[0].Aggregate(stats[idx]);
+ }
+
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
+ }
}
- Y_UNIT_TEST(ManyPoolsOneAssignedCpu) {
- const size_t msgCount = 1e4;
- const size_t pools = 4;
- auto setup = GetActorSystemSetup(1);
- setup->Balancer.Reset(new TRoundRobinBalancer());
- for (size_t pool = 0; pool < pools; pool++) {
- AddUnitedPool(setup);
- }
+ Y_UNIT_TEST(ManyPoolsOneAssignedCpu) {
+ const size_t msgCount = 1e4;
+ const size_t pools = 4;
+ auto setup = GetActorSystemSetup(1);
+ setup->Balancer.Reset(new TRoundRobinBalancer());
+ for (size_t pool = 0; pool < pools; pool++) {
+ AddUnitedPool(setup);
+ }
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ auto begin = TInstant::Now();
+
+ TVector<TTestSenderActor*> actors;
+ for (size_t pool = 0; pool < pools; pool++) {
+ auto actor = new TTestSenderActor();
+ auto actorId = actorSystem.Register(actor, TMailboxType::HTSwap, pool);
+ actor->Start(actor->SelfId(), msgCount);
+ actorSystem.Send(actorId, new TEvMsg());
+ actors.push_back(actor);
+ }
+
+ while (true) {
+ size_t left = 0;
+ for (auto actor : actors) {
+ left += actor->GetCounter();
+ }
+ if (left == 0) {
+ break;
+ }
+ auto now = TInstant::Now();
+ UNIT_ASSERT_C(now - begin < TDuration::Seconds(5), "left " << left);
+ Sleep(TDuration::MilliSeconds(1));
+ }
+
+ for (size_t pool = 0; pool < pools; pool++) {
+ TVector<TExecutorThreadStats> stats;
+ TExecutorPoolStats poolStats;
+ actorSystem.GetPoolStats(pool, poolStats, stats);
+ // Sum all per-thread counters into the 0th element
+ for (ui32 idx = 1; idx < stats.size(); ++idx) {
+ stats[0].Aggregate(stats[idx]);
+ }
+
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
+ }
+ }
+
+ Y_UNIT_TEST(ManyPoolsOneCpuSlowEvents) {
+ const size_t msgCount = 3;
+ const size_t pools = 4;
+ auto setup = GetActorSystemSetup(1);
+ for (size_t pool = 0; pool < pools; pool++) {
+ AddUnitedPool(setup);
+ }
TActorSystem actorSystem(setup);
actorSystem.Start();
auto begin = TInstant::Now();
- TVector<TTestSenderActor*> actors;
- for (size_t pool = 0; pool < pools; pool++) {
- auto actor = new TTestSenderActor();
- auto actorId = actorSystem.Register(actor, TMailboxType::HTSwap, pool);
- actor->Start(actor->SelfId(), msgCount);
- actorSystem.Send(actorId, new TEvMsg());
- actors.push_back(actor);
+ TVector<TTestSenderActor*> actors;
+ for (size_t pool = 0; pool < pools; pool++) {
+ auto actor = new TTestSenderActor([]() {
+ DoTimedWork(100'000);
+ });
+ auto actorId = actorSystem.Register(actor, TMailboxType::HTSwap, pool);
+ actor->Start(actor->SelfId(), msgCount);
+ actorSystem.Send(actorId, new TEvMsg());
+ actors.push_back(actor);
}
while (true) {
- size_t left = 0;
- for (auto actor : actors) {
- left += actor->GetCounter();
+ size_t left = 0;
+ for (auto actor : actors) {
+ left += actor->GetCounter();
}
- if (left == 0) {
+ if (left == 0) {
break;
}
auto now = TInstant::Now();
- UNIT_ASSERT_C(now - begin < TDuration::Seconds(5), "left " << left);
+ UNIT_ASSERT_C(now - begin < TDuration::Seconds(15), "left " << left);
Sleep(TDuration::MilliSeconds(1));
}
- for (size_t pool = 0; pool < pools; pool++) {
- TVector<TExecutorThreadStats> stats;
- TExecutorPoolStats poolStats;
- actorSystem.GetPoolStats(pool, poolStats, stats);
- // Sum all per-thread counters into the 0th element
- for (ui32 idx = 1; idx < stats.size(); ++idx) {
- stats[0].Aggregate(stats[idx]);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
+ for (size_t pool = 0; pool < pools; pool++) {
+ TVector<TExecutorThreadStats> stats;
+ TExecutorPoolStats poolStats;
+ actorSystem.GetPoolStats(pool, poolStats, stats);
+ // Sum all per-thread counters into the 0th element
+ for (ui32 idx = 1; idx < stats.size(); ++idx) {
+ stats[0].Aggregate(stats[idx]);
+ }
+
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PreemptedEvents, msgCount); // every 100ms event should be preempted
+ UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
}
- }
-
- Y_UNIT_TEST(ManyPoolsOneCpuSlowEvents) {
- const size_t msgCount = 3;
- const size_t pools = 4;
- auto setup = GetActorSystemSetup(1);
- for (size_t pool = 0; pool < pools; pool++) {
- AddUnitedPool(setup);
- }
- TActorSystem actorSystem(setup);
- actorSystem.Start();
-
- auto begin = TInstant::Now();
-
- TVector<TTestSenderActor*> actors;
- for (size_t pool = 0; pool < pools; pool++) {
- auto actor = new TTestSenderActor([]() {
- DoTimedWork(100'000);
- });
- auto actorId = actorSystem.Register(actor, TMailboxType::HTSwap, pool);
- actor->Start(actor->SelfId(), msgCount);
- actorSystem.Send(actorId, new TEvMsg());
- actors.push_back(actor);
- }
-
- while (true) {
- size_t left = 0;
- for (auto actor : actors) {
- left += actor->GetCounter();
- }
- if (left == 0) {
- break;
- }
- auto now = TInstant::Now();
- UNIT_ASSERT_C(now - begin < TDuration::Seconds(15), "left " << left);
- Sleep(TDuration::MilliSeconds(1));
- }
-
- for (size_t pool = 0; pool < pools; pool++) {
- TVector<TExecutorThreadStats> stats;
- TExecutorPoolStats poolStats;
- actorSystem.GetPoolStats(pool, poolStats, stats);
- // Sum all per-thread counters into the 0th element
- for (ui32 idx = 1; idx < stats.size(); ++idx) {
- stats[0].Aggregate(stats[idx]);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(stats[0].ReceivedEvents, msgCount);
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PreemptedEvents, msgCount); // every 100ms event should be preempted
- UNIT_ASSERT_VALUES_EQUAL(stats[0].PoolActorRegistrations, 1);
- }
- }
+ }
-#endif
+#endif
}
diff --git a/library/cpp/actors/core/executor_thread.cpp b/library/cpp/actors/core/executor_thread.cpp
index 446b651efd..1fd93f1a42 100644
--- a/library/cpp/actors/core/executor_thread.cpp
+++ b/library/cpp/actors/core/executor_thread.cpp
@@ -7,18 +7,18 @@
#include <library/cpp/actors/prof/tag.h>
#include <library/cpp/actors/util/affinity.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <library/cpp/actors/util/thread.h>
#ifdef BALLOC
#include <library/cpp/balloc/optional/operators.h>
#endif
-#ifdef _linux_
-#include <sys/syscall.h>
-#include <unistd.h>
-#endif
-
+#ifdef _linux_
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
#include <util/system/type_name.h>
#include <util/system/datetime.h>
@@ -28,42 +28,42 @@ namespace NActors {
constexpr TDuration TExecutorThread::DEFAULT_TIME_PER_MAILBOX;
TExecutorThread::TExecutorThread(
- TWorkerId workerId,
- TWorkerId cpuId,
- TActorSystem* actorSystem,
- IExecutorPool* executorPool,
- TMailboxTable* mailboxTable,
- const TString& threadName,
- TDuration timePerMailbox,
- ui32 eventsPerMailbox)
- : ActorSystem(actorSystem)
+ TWorkerId workerId,
+ TWorkerId cpuId,
+ TActorSystem* actorSystem,
+ IExecutorPool* executorPool,
+ TMailboxTable* mailboxTable,
+ const TString& threadName,
+ TDuration timePerMailbox,
+ ui32 eventsPerMailbox)
+ : ActorSystem(actorSystem)
, ExecutorPool(executorPool)
- , Ctx(workerId, cpuId, actorSystem ? actorSystem->GetMaxActivityType() : 1)
+ , Ctx(workerId, cpuId, actorSystem ? actorSystem->GetMaxActivityType() : 1)
, ThreadName(threadName)
- {
- Ctx.Switch(
- ExecutorPool,
- mailboxTable,
- NHPTimer::GetClockRate() * timePerMailbox.SecondsFloat(),
- eventsPerMailbox,
- ui64(-1), // infinite soft deadline
- &Ctx.WorkerStats);
- }
+ {
+ Ctx.Switch(
+ ExecutorPool,
+ mailboxTable,
+ NHPTimer::GetClockRate() * timePerMailbox.SecondsFloat(),
+ eventsPerMailbox,
+ ui64(-1), // infinite soft deadline
+ &Ctx.WorkerStats);
+ }
TActorId TExecutorThread::RegisterActor(IActor* actor, TMailboxType::EType mailboxType, ui32 poolId, const TActorId& parentId) {
if (poolId == Max<ui32>())
- return Ctx.Executor->Register(actor, mailboxType, ++RevolvingWriteCounter, parentId ? parentId : CurrentRecipient);
+ return Ctx.Executor->Register(actor, mailboxType, ++RevolvingWriteCounter, parentId ? parentId : CurrentRecipient);
else
return ActorSystem->Register(actor, mailboxType, poolId, ++RevolvingWriteCounter, parentId ? parentId : CurrentRecipient);
}
TActorId TExecutorThread::RegisterActor(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId) {
- return Ctx.Executor->Register(actor, mailbox, hint, parentId ? parentId : CurrentRecipient);
+ return Ctx.Executor->Register(actor, mailbox, hint, parentId ? parentId : CurrentRecipient);
}
void TExecutorThread::UnregisterActor(TMailboxHeader* mailbox, ui64 localActorId) {
IActor* actor = mailbox->DetachActor(localActorId);
- Ctx.DecrementActorsAliveByActivity(actor->GetActivityType());
+ Ctx.DecrementActorsAliveByActivity(actor->GetActivityType());
DyingActors.push_back(THolder(actor));
}
@@ -73,17 +73,17 @@ namespace NActors {
void TExecutorThread::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie) {
++CurrentActorScheduledEventsCounter;
- Ctx.Executor->Schedule(deadline, ev, cookie, Ctx.WorkerId);
+ Ctx.Executor->Schedule(deadline, ev, cookie, Ctx.WorkerId);
}
void TExecutorThread::Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie) {
++CurrentActorScheduledEventsCounter;
- Ctx.Executor->Schedule(deadline, ev, cookie, Ctx.WorkerId);
+ Ctx.Executor->Schedule(deadline, ev, cookie, Ctx.WorkerId);
}
void TExecutorThread::Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie) {
++CurrentActorScheduledEventsCounter;
- Ctx.Executor->Schedule(delta, ev, cookie, Ctx.WorkerId);
+ Ctx.Executor->Schedule(delta, ev, cookie, Ctx.WorkerId);
}
template <class T>
@@ -96,7 +96,7 @@ namespace NActors {
} catch (...) {
return "unknown-type";
}
- }
+ }
inline TString ActorTypeName(const IActor* actor, ui32 activityType) {
return actor ? SafeTypeName(actor) : ("activityType_" + ToString(activityType) + " (destroyed)");
@@ -113,8 +113,8 @@ namespace NActors {
baseEv ? SafeTypeName(baseEv) : (ev ? ToString(ev->Type) : TString("nullptr")),
currentRecipient.ToString(),
SafeTypeName(actor));
- }
-
+ }
+
inline void LwTraceSlowEvent(IEventHandle* ev, ui32 evTypeForTracing, const IActor* actor, ui32 poolId, ui32 activityType,
const TActorId& currentRecipient, double eventMs) {
// Event could have been destroyed by actor->Receive();
@@ -126,25 +126,25 @@ namespace NActors {
currentRecipient.ToString(),
ActorTypeName(actor, activityType));
}
-
+
template <typename TMailbox>
void TExecutorThread::Execute(TMailbox* mailbox, ui32 hint) {
Y_VERIFY_DEBUG(DyingActors.empty());
bool reclaimAsFree = false;
- NHPTimer::STime hpstart = GetCycleCountFast();
+ NHPTimer::STime hpstart = GetCycleCountFast();
NHPTimer::STime hpprev = hpstart;
- IActor* actor = nullptr;
+ IActor* actor = nullptr;
ui32 prevActivityType = std::numeric_limits<ui32>::max();
- TActorId recipient;
- for (ui32 executed = 0; executed < Ctx.EventsPerMailbox; ++executed) {
+ TActorId recipient;
+ for (ui32 executed = 0; executed < Ctx.EventsPerMailbox; ++executed) {
TAutoPtr<IEventHandle> ev(mailbox->Pop());
if (!!ev) {
NHPTimer::STime hpnow;
- recipient = ev->GetRecipientRewrite();
- if (actor = mailbox->FindActor(recipient.LocalId())) {
+ recipient = ev->GetRecipientRewrite();
+ if (actor = mailbox->FindActor(recipient.LocalId())) {
TActorContext ctx(*mailbox, *this, hpprev, recipient);
TlsActivationContext = &ctx;
@@ -156,16 +156,16 @@ namespace NActors {
CurrentActorScheduledEventsCounter = 0;
if (executed == 0) {
- double usec = Ctx.AddActivationStats(AtomicLoad(&mailbox->ScheduleMoment), hpprev);
- if (usec > 500) {
- GLOBAL_LWPROBE(ACTORLIB_PROVIDER, SlowActivation, Ctx.PoolId, usec / 1000.0);
+ double usec = Ctx.AddActivationStats(AtomicLoad(&mailbox->ScheduleMoment), hpprev);
+ if (usec > 500) {
+ GLOBAL_LWPROBE(ACTORLIB_PROVIDER, SlowActivation, Ctx.PoolId, usec / 1000.0);
}
- }
+ }
- i64 usecDeliv = Ctx.AddEventDeliveryStats(ev->SendTime, hpprev);
+ i64 usecDeliv = Ctx.AddEventDeliveryStats(ev->SendTime, hpprev);
if (usecDeliv > 5000) {
double sinceActivationMs = NHPTimer::GetSeconds(hpprev - hpstart) * 1000.0;
- LwTraceSlowDelivery(ev.Get(), actor, Ctx.PoolId, CurrentRecipient, NHPTimer::GetSeconds(hpprev - ev->SendTime) * 1000.0, sinceActivationMs, executed);
+ LwTraceSlowDelivery(ev.Get(), actor, Ctx.PoolId, CurrentRecipient, NHPTimer::GetSeconds(hpprev - ev->SendTime) * 1000.0, sinceActivationMs, executed);
}
ui32 evTypeForTracing = ev->Type;
@@ -179,7 +179,7 @@ namespace NActors {
actor->Receive(ev, ctx);
size_t dyingActorsCnt = DyingActors.size();
- Ctx.UpdateActorsStats(dyingActorsCnt);
+ Ctx.UpdateActorsStats(dyingActorsCnt);
if (dyingActorsCnt) {
DropUnregistered();
actor = nullptr;
@@ -188,11 +188,11 @@ namespace NActors {
if (mailbox->IsEmpty()) // was not-free and become free, we must reclaim mailbox
reclaimAsFree = true;
- hpnow = GetCycleCountFast();
- NHPTimer::STime elapsed = Ctx.AddEventProcessingStats(hpprev, hpnow, activityType, CurrentActorScheduledEventsCounter);
- if (elapsed > 1000000) {
- LwTraceSlowEvent(ev.Get(), evTypeForTracing, actor, Ctx.PoolId, activityType, CurrentRecipient, NHPTimer::GetSeconds(elapsed) * 1000.0);
- }
+ hpnow = GetCycleCountFast();
+ NHPTimer::STime elapsed = Ctx.AddEventProcessingStats(hpprev, hpnow, activityType, CurrentActorScheduledEventsCounter);
+ if (elapsed > 1000000) {
+ LwTraceSlowEvent(ev.Get(), evTypeForTracing, actor, Ctx.PoolId, activityType, CurrentRecipient, NHPTimer::GetSeconds(elapsed) * 1000.0);
+ }
// The actor might have been destroyed
if (actor)
@@ -204,99 +204,99 @@ namespace NActors {
if (nonDelivered.Get()) {
ActorSystem->Send(nonDelivered);
} else {
- Ctx.IncrementNonDeliveredEvents();
+ Ctx.IncrementNonDeliveredEvents();
}
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
}
hpprev = hpnow;
- // Soft preemption in united pool
- if (Ctx.SoftDeadlineTs < (ui64)hpnow) {
- AtomicStore(&mailbox->ScheduleMoment, hpnow);
- Ctx.IncrementMailboxPushedOutBySoftPreemption();
- LWTRACK(MailboxPushedOutBySoftPreemption,
- Ctx.Orbit,
- Ctx.PoolId,
- Ctx.Executor->GetName(),
- executed + 1,
- CyclesToDuration(hpnow - hpstart),
- Ctx.WorkerId,
- recipient.ToString(),
- SafeTypeName(actor));
- break;
- }
-
+ // Soft preemption in united pool
+ if (Ctx.SoftDeadlineTs < (ui64)hpnow) {
+ AtomicStore(&mailbox->ScheduleMoment, hpnow);
+ Ctx.IncrementMailboxPushedOutBySoftPreemption();
+ LWTRACK(MailboxPushedOutBySoftPreemption,
+ Ctx.Orbit,
+ Ctx.PoolId,
+ Ctx.Executor->GetName(),
+ executed + 1,
+ CyclesToDuration(hpnow - hpstart),
+ Ctx.WorkerId,
+ recipient.ToString(),
+ SafeTypeName(actor));
+ break;
+ }
+
// time limit inside one mailbox passed, let others do some work
- if (hpnow - hpstart > (i64)Ctx.TimePerMailboxTs) {
- AtomicStore(&mailbox->ScheduleMoment, hpnow);
- Ctx.IncrementMailboxPushedOutByTime();
- LWTRACK(MailboxPushedOutByTime,
- Ctx.Orbit,
- Ctx.PoolId,
- Ctx.Executor->GetName(),
- executed + 1,
- CyclesToDuration(hpnow - hpstart),
- Ctx.WorkerId,
- recipient.ToString(),
- SafeTypeName(actor));
+ if (hpnow - hpstart > (i64)Ctx.TimePerMailboxTs) {
+ AtomicStore(&mailbox->ScheduleMoment, hpnow);
+ Ctx.IncrementMailboxPushedOutByTime();
+ LWTRACK(MailboxPushedOutByTime,
+ Ctx.Orbit,
+ Ctx.PoolId,
+ Ctx.Executor->GetName(),
+ executed + 1,
+ CyclesToDuration(hpnow - hpstart),
+ Ctx.WorkerId,
+ recipient.ToString(),
+ SafeTypeName(actor));
break;
}
- if (executed + 1 == Ctx.EventsPerMailbox) {
- AtomicStore(&mailbox->ScheduleMoment, hpnow);
- Ctx.IncrementMailboxPushedOutByEventCount();
- LWTRACK(MailboxPushedOutByEventCount,
- Ctx.Orbit,
- Ctx.PoolId,
- Ctx.Executor->GetName(),
- executed + 1,
- CyclesToDuration(hpnow - hpstart),
- Ctx.WorkerId,
- recipient.ToString(),
- SafeTypeName(actor));
+ if (executed + 1 == Ctx.EventsPerMailbox) {
+ AtomicStore(&mailbox->ScheduleMoment, hpnow);
+ Ctx.IncrementMailboxPushedOutByEventCount();
+ LWTRACK(MailboxPushedOutByEventCount,
+ Ctx.Orbit,
+ Ctx.PoolId,
+ Ctx.Executor->GetName(),
+ executed + 1,
+ CyclesToDuration(hpnow - hpstart),
+ Ctx.WorkerId,
+ recipient.ToString(),
+ SafeTypeName(actor));
break;
}
} else {
if (executed == 0)
- Ctx.IncrementEmptyMailboxActivation();
- LWTRACK(MailboxEmpty,
- Ctx.Orbit,
- Ctx.PoolId,
- Ctx.Executor->GetName(),
- executed,
- CyclesToDuration(GetCycleCountFast() - hpstart),
- Ctx.WorkerId,
- recipient.ToString(),
- SafeTypeName(actor));
+ Ctx.IncrementEmptyMailboxActivation();
+ LWTRACK(MailboxEmpty,
+ Ctx.Orbit,
+ Ctx.PoolId,
+ Ctx.Executor->GetName(),
+ executed,
+ CyclesToDuration(GetCycleCountFast() - hpstart),
+ Ctx.WorkerId,
+ recipient.ToString(),
+ SafeTypeName(actor));
break; // empty queue, leave
}
}
NProfiling::TMemoryTagScope::Reset(0);
TlsActivationContext = nullptr;
- UnlockFromExecution(mailbox, Ctx.Executor, reclaimAsFree, hint, Ctx.WorkerId, RevolvingWriteCounter);
- }
-
- TThreadId TExecutorThread::GetThreadId() const {
-#ifdef _linux_
- while (AtomicLoad(&ThreadId) == UnknownThreadId) {
- NanoSleep(1000);
- }
-#endif
- return ThreadId;
+ UnlockFromExecution(mailbox, Ctx.Executor, reclaimAsFree, hint, Ctx.WorkerId, RevolvingWriteCounter);
}
+ TThreadId TExecutorThread::GetThreadId() const {
+#ifdef _linux_
+ while (AtomicLoad(&ThreadId) == UnknownThreadId) {
+ NanoSleep(1000);
+ }
+#endif
+ return ThreadId;
+ }
+
void* TExecutorThread::ThreadProc() {
-#ifdef _linux_
- pid_t tid = syscall(SYS_gettid);
- AtomicSet(ThreadId, (ui64)tid);
-#endif
-
+#ifdef _linux_
+ pid_t tid = syscall(SYS_gettid);
+ AtomicSet(ThreadId, (ui64)tid);
+#endif
+
#ifdef BALLOC
ThreadDisableBalloc();
#endif
-
+
if (ThreadName) {
::SetCurrentThreadName(ThreadName);
}
@@ -304,20 +304,20 @@ namespace NActors {
ExecutorPool->SetRealTimeMode();
TAffinityGuard affinity(ExecutorPool->Affinity());
- NHPTimer::STime hpnow = GetCycleCountFast();
+ NHPTimer::STime hpnow = GetCycleCountFast();
NHPTimer::STime hpprev = hpnow;
ui64 execCount = 0;
ui64 readyActivationCount = 0;
i64 execCycles = 0;
i64 nonExecCycles = 0;
-
+
for (;;) {
- if (ui32 activation = ExecutorPool->GetReadyActivation(Ctx, ++RevolvingReadCounter)) {
- LWTRACK(ActivationBegin, Ctx.Orbit, Ctx.CpuId, Ctx.PoolId, Ctx.WorkerId, NHPTimer::GetSeconds(Ctx.Lease.GetPreciseExpireTs()) * 1e3);
+ if (ui32 activation = ExecutorPool->GetReadyActivation(Ctx, ++RevolvingReadCounter)) {
+ LWTRACK(ActivationBegin, Ctx.Orbit, Ctx.CpuId, Ctx.PoolId, Ctx.WorkerId, NHPTimer::GetSeconds(Ctx.Lease.GetPreciseExpireTs()) * 1e3);
readyActivationCount++;
- if (TMailboxHeader* header = Ctx.MailboxTable->Get(activation)) {
+ if (TMailboxHeader* header = Ctx.MailboxTable->Get(activation)) {
if (header->LockForExecution()) {
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
nonExecCycles += hpnow - hpprev;
hpprev = hpnow;
switch (header->Type) {
@@ -337,27 +337,27 @@ namespace NActors {
Execute(static_cast<TMailboxTable::TTinyReadAsFilledMailbox*>(header), activation);
break;
}
- hpnow = GetCycleCountFast();
+ hpnow = GetCycleCountFast();
execCycles += hpnow - hpprev;
hpprev = hpnow;
execCount++;
if (execCycles + nonExecCycles > 39000000) { // every 15 ms at 2.6GHz, so 1000 items is 15 sec (solomon interval)
- LWPROBE(ExecutorThreadStats, ExecutorPool->PoolId, ExecutorPool->GetName(), Ctx.WorkerId,
+ LWPROBE(ExecutorThreadStats, ExecutorPool->PoolId, ExecutorPool->GetName(), Ctx.WorkerId,
execCount, readyActivationCount,
NHPTimer::GetSeconds(execCycles) * 1000.0, NHPTimer::GetSeconds(nonExecCycles) * 1000.0);
execCount = 0;
readyActivationCount = 0;
execCycles = 0;
nonExecCycles = 0;
- Ctx.UpdateThreadTime();
+ Ctx.UpdateThreadTime();
}
}
}
- LWTRACK(ActivationEnd, Ctx.Orbit, Ctx.CpuId, Ctx.PoolId, Ctx.WorkerId);
- Ctx.Orbit.Reset();
- } else { // no activation means PrepareStop was called so thread must terminate
+ LWTRACK(ActivationEnd, Ctx.Orbit, Ctx.CpuId, Ctx.PoolId, Ctx.WorkerId);
+ Ctx.Orbit.Reset();
+ } else { // no activation means PrepareStop was called so thread must terminate
break;
- }
+ }
}
return nullptr;
}
diff --git a/library/cpp/actors/core/executor_thread.h b/library/cpp/actors/core/executor_thread.h
index 9d3c573f0d..5599c82e58 100644
--- a/library/cpp/actors/core/executor_thread.h
+++ b/library/cpp/actors/core/executor_thread.h
@@ -5,23 +5,23 @@
#include "actor.h"
#include "actorsystem.h"
#include "callstack.h"
-#include "probes.h"
-#include "worker_context.h"
-
-#include <library/cpp/actors/util/datetime.h>
+#include "probes.h"
+#include "worker_context.h"
+#include <library/cpp/actors/util/datetime.h>
+
#include <util/system/thread.h>
namespace NActors {
-
+
class TExecutorThread: public ISimpleThread {
public:
static constexpr TDuration DEFAULT_TIME_PER_MAILBOX =
TDuration::MilliSeconds(10);
static constexpr ui32 DEFAULT_EVENTS_PER_MAILBOX = 100;
- TExecutorThread(TWorkerId workerId,
- TWorkerId cpuId,
+ TExecutorThread(TWorkerId workerId,
+ TWorkerId cpuId,
TActorSystem* actorSystem,
IExecutorPool* executorPool,
TMailboxTable* mailboxTable,
@@ -29,16 +29,16 @@ namespace NActors {
TDuration timePerMailbox = DEFAULT_TIME_PER_MAILBOX,
ui32 eventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX);
- TExecutorThread(TWorkerId workerId,
- TActorSystem* actorSystem,
- IExecutorPool* executorPool,
- TMailboxTable* mailboxTable,
- const TString& threadName,
- TDuration timePerMailbox = DEFAULT_TIME_PER_MAILBOX,
- ui32 eventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX)
- : TExecutorThread(workerId, 0, actorSystem, executorPool, mailboxTable, threadName, timePerMailbox, eventsPerMailbox)
- {}
-
+ TExecutorThread(TWorkerId workerId,
+ TActorSystem* actorSystem,
+ IExecutorPool* executorPool,
+ TMailboxTable* mailboxTable,
+ const TString& threadName,
+ TDuration timePerMailbox = DEFAULT_TIME_PER_MAILBOX,
+ ui32 eventsPerMailbox = DEFAULT_EVENTS_PER_MAILBOX)
+ : TExecutorThread(workerId, 0, actorSystem, executorPool, mailboxTable, threadName, timePerMailbox, eventsPerMailbox)
+ {}
+
TActorId RegisterActor(IActor* actor, TMailboxType::EType mailboxType = TMailboxType::HTSwap, ui32 poolId = Max<ui32>(),
const TActorId& parentId = TActorId());
TActorId RegisterActor(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId = TActorId());
@@ -50,22 +50,22 @@ namespace NActors {
void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie = nullptr);
void Schedule(TDuration delta, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie = nullptr);
- bool Send(TAutoPtr<IEventHandle> ev) {
-#ifdef USE_ACTOR_CALLSTACK
- ev->Callstack = TCallstack::GetTlsCallstack();
- ev->Callstack.Trace();
+ bool Send(TAutoPtr<IEventHandle> ev) {
+#ifdef USE_ACTOR_CALLSTACK
+ ev->Callstack = TCallstack::GetTlsCallstack();
+ ev->Callstack.Trace();
#endif
- Ctx.IncrementSentEvents();
- return ActorSystem->Send(ev);
+ Ctx.IncrementSentEvents();
+ return ActorSystem->Send(ev);
}
- void GetCurrentStats(TExecutorThreadStats& statsCopy) const {
- Ctx.GetCurrentStats(statsCopy);
+ void GetCurrentStats(TExecutorThreadStats& statsCopy) const {
+ Ctx.GetCurrentStats(statsCopy);
}
- TThreadId GetThreadId() const; // blocks, must be called after Start()
- TWorkerId GetWorkerId() const { return Ctx.WorkerId; }
-
+ TThreadId GetThreadId() const; // blocks, must be called after Start()
+ TWorkerId GetWorkerId() const { return Ctx.WorkerId; }
+
private:
void* ThreadProc();
@@ -76,37 +76,37 @@ namespace NActors {
TActorSystem* const ActorSystem;
private:
- // Pool-specific
+ // Pool-specific
IExecutorPool* const ExecutorPool;
- // Event-specific (currently executing)
+ // Event-specific (currently executing)
TVector<THolder<IActor>> DyingActors;
TActorId CurrentRecipient;
- ui64 CurrentActorScheduledEventsCounter = 0;
+ ui64 CurrentActorScheduledEventsCounter = 0;
- // Thread-specific
- TWorkerContext Ctx;
- ui64 RevolvingReadCounter = 0;
- ui64 RevolvingWriteCounter = 0;
+ // Thread-specific
+ TWorkerContext Ctx;
+ ui64 RevolvingReadCounter = 0;
+ ui64 RevolvingWriteCounter = 0;
const TString ThreadName;
- volatile TThreadId ThreadId = UnknownThreadId;
+ volatile TThreadId ThreadId = UnknownThreadId;
};
template <typename TMailbox>
- void UnlockFromExecution(TMailbox* mailbox, IExecutorPool* executorPool, bool asFree, ui32 hint, TWorkerId workerId, ui64& revolvingWriteCounter) {
+ void UnlockFromExecution(TMailbox* mailbox, IExecutorPool* executorPool, bool asFree, ui32 hint, TWorkerId workerId, ui64& revolvingWriteCounter) {
mailbox->UnlockFromExecution1();
const bool needReschedule1 = (nullptr != mailbox->Head());
if (!asFree) {
if (mailbox->UnlockFromExecution2(needReschedule1)) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivationEx(hint, ++revolvingWriteCounter);
}
} else {
if (mailbox->UnlockAsFree(needReschedule1)) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivationEx(hint, ++revolvingWriteCounter);
}
- executorPool->ReclaimMailbox(TMailbox::MailboxType, hint, workerId, ++revolvingWriteCounter);
+ executorPool->ReclaimMailbox(TMailbox::MailboxType, hint, workerId, ++revolvingWriteCounter);
}
}
}
diff --git a/library/cpp/actors/core/lease.h b/library/cpp/actors/core/lease.h
index 650ae7b122..3bde281960 100644
--- a/library/cpp/actors/core/lease.h
+++ b/library/cpp/actors/core/lease.h
@@ -1,56 +1,56 @@
-#pragma once
-
-#include "defs.h"
-
-namespace NActors {
- // Value representing specific worker's permission for exclusive use of CPU till specific deadline
- struct TLease {
- // Lower WorkerBits store current fast worker id
- // All other higher bits store expiration (hard preemption) timestamp
- using TValue = ui64;
- TValue Value;
-
- static constexpr ui64 WorkerIdMask = ui64((1ull << WorkerBits) - 1);
- static constexpr ui64 ExpireTsMask = ~WorkerIdMask;
-
- explicit constexpr TLease(ui64 value)
- : Value(value)
- {}
-
- constexpr TLease(TWorkerId workerId, ui64 expireTs)
- : Value((workerId & WorkerIdMask) | (expireTs & ExpireTsMask))
- {}
-
- TWorkerId GetWorkerId() const {
- return Value & WorkerIdMask;
- }
-
- TLease NeverExpire() const {
- return TLease(Value | ExpireTsMask);
- }
-
- bool IsNeverExpiring() const {
- return (Value & ExpireTsMask) == ExpireTsMask;
- }
-
- ui64 GetExpireTs() const {
- // Do not truncate worker id
- // NOTE: it decrease accuracy, but improves performance
- return Value;
- }
-
- ui64 GetPreciseExpireTs() const {
- return Value & ExpireTsMask;
- }
-
- operator TValue() const {
- return Value;
- }
- };
-
- // Special expire timestamp values
- static constexpr ui64 NeverExpire = ui64(-1);
-
- // Special hard-preemption-in-progress lease
- static constexpr TLease HardPreemptionLease = TLease(TLease::WorkerIdMask, NeverExpire);
-}
+#pragma once
+
+#include "defs.h"
+
+namespace NActors {
+ // Value representing specific worker's permission for exclusive use of CPU till specific deadline
+ struct TLease {
+ // Lower WorkerBits store current fast worker id
+ // All other higher bits store expiration (hard preemption) timestamp
+ using TValue = ui64;
+ TValue Value;
+
+ static constexpr ui64 WorkerIdMask = ui64((1ull << WorkerBits) - 1);
+ static constexpr ui64 ExpireTsMask = ~WorkerIdMask;
+
+ explicit constexpr TLease(ui64 value)
+ : Value(value)
+ {}
+
+ constexpr TLease(TWorkerId workerId, ui64 expireTs)
+ : Value((workerId & WorkerIdMask) | (expireTs & ExpireTsMask))
+ {}
+
+ TWorkerId GetWorkerId() const {
+ return Value & WorkerIdMask;
+ }
+
+ TLease NeverExpire() const {
+ return TLease(Value | ExpireTsMask);
+ }
+
+ bool IsNeverExpiring() const {
+ return (Value & ExpireTsMask) == ExpireTsMask;
+ }
+
+ ui64 GetExpireTs() const {
+ // Do not truncate worker id
+ // NOTE: it decrease accuracy, but improves performance
+ return Value;
+ }
+
+ ui64 GetPreciseExpireTs() const {
+ return Value & ExpireTsMask;
+ }
+
+ operator TValue() const {
+ return Value;
+ }
+ };
+
+ // Special expire timestamp values
+ static constexpr ui64 NeverExpire = ui64(-1);
+
+ // Special hard-preemption-in-progress lease
+ static constexpr TLease HardPreemptionLease = TLease(TLease::WorkerIdMask, NeverExpire);
+}
diff --git a/library/cpp/actors/core/log.cpp b/library/cpp/actors/core/log.cpp
index 5f63b5af58..c05a32f020 100644
--- a/library/cpp/actors/core/log.cpp
+++ b/library/cpp/actors/core/log.cpp
@@ -311,13 +311,13 @@ namespace NActors {
void TLoggerActor::RenderComponentPriorities(IOutputStream& str) {
using namespace NLog;
- HTML(str) {
+ HTML(str) {
H4() {
str << "Priority Settings for the Components";
}
- TABLE_SORTABLE_CLASS("table") {
- TABLEHEAD() {
- TABLER() {
+ TABLE_SORTABLE_CLASS("table") {
+ TABLEHEAD() {
+ TABLER() {
TABLEH() {
str << "Component";
}
@@ -330,16 +330,16 @@ namespace NActors {
TABLEH() {
str << "Sampling Rate";
}
- }
- }
- TABLEBODY() {
+ }
+ }
+ TABLEBODY() {
for (EComponent i = Settings->MinVal; i < Settings->MaxVal; i++) {
auto name = Settings->ComponentName(i);
if (!*name)
continue;
NLog::TComponentSettings componentSettings = Settings->GetComponentSettings(i);
- TABLER() {
+ TABLER() {
TABLED() {
str << "<a href='logger?c=" << i << "'>" << name << "</a>";
}
@@ -352,11 +352,11 @@ namespace NActors {
TABLED() {
str << componentSettings.Raw.X.SamplingRate;
}
- }
+ }
}
- }
- }
- }
+ }
+ }
+ }
}
/*
@@ -412,53 +412,53 @@ namespace NActors {
if (hasComponent && !hasPriority && !hasSamplingPriority && !hasSamplingRate) {
NLog::TComponentSettings componentSettings = Settings->GetComponentSettings(component);
ui32 samplingRate = componentSettings.Raw.X.SamplingRate;
- HTML(str) {
- DIV_CLASS("row") {
- DIV_CLASS("col-md-12") {
+ HTML(str) {
+ DIV_CLASS("row") {
+ DIV_CLASS("col-md-12") {
H4() {
str << "Current log settings for " << Settings->ComponentName(component) << Endl;
}
- UL() {
- LI() {
+ UL() {
+ LI() {
str << "Priority: "
<< NLog::PriorityToString(NLog::EPrio(componentSettings.Raw.X.Level));
- }
- LI() {
+ }
+ LI() {
str << "Sampling priority: "
<< NLog::PriorityToString(NLog::EPrio(componentSettings.Raw.X.SamplingLevel));
- }
- LI() {
+ }
+ LI() {
str << "Sampling rate: "
<< samplingRate;
- }
- }
- }
- }
+ }
+ }
+ }
+ }
- DIV_CLASS("row") {
- DIV_CLASS("col-md-12") {
+ DIV_CLASS("row") {
+ DIV_CLASS("col-md-12") {
H4() {
str << "Change priority" << Endl;
}
- UL() {
+ UL() {
for (int p = NLog::PRI_EMERG; p <= NLog::PRI_TRACE; ++p) {
- LI() {
+ LI() {
str << "<a href='logger?c=" << component << "&p=" << p << "'>"
<< NLog::PriorityToString(NLog::EPrio(p)) << "</a>";
- }
+ }
}
- }
+ }
H4() {
str << "Change sampling priority" << Endl;
}
- UL() {
+ UL() {
for (int p = NLog::PRI_EMERG; p <= NLog::PRI_TRACE; ++p) {
- LI() {
+ LI() {
str << "<a href='logger?c=" << component << "&sp=" << p << "'>"
<< NLog::PriorityToString(NLog::EPrio(p)) << "</a>";
- }
+ }
}
- }
+ }
H4() {
str << "Change sampling rate" << Endl;
}
@@ -470,9 +470,9 @@ namespace NActors {
H4() {
str << "<a href='logger'>Cancel</a>" << Endl;
}
- }
- }
- }
+ }
+ }
+ }
} else {
TString explanation;
@@ -489,64 +489,64 @@ namespace NActors {
Settings->SetAllowDrop(allowDrop);
}
- HTML(str) {
+ HTML(str) {
if (!explanation.empty()) {
- DIV_CLASS("row") {
+ DIV_CLASS("row") {
DIV_CLASS("col-md-12 alert alert-info") {
str << explanation;
}
- }
+ }
}
- DIV_CLASS("row") {
- DIV_CLASS("col-md-6") {
+ DIV_CLASS("row") {
+ DIV_CLASS("col-md-6") {
RenderComponentPriorities(str);
}
DIV_CLASS("col-md-6") {
H4() {
str << "Change priority for all components";
}
- TABLE_CLASS("table table-condensed") {
- TABLEHEAD() {
- TABLER() {
+ TABLE_CLASS("table table-condensed") {
+ TABLEHEAD() {
+ TABLER() {
TABLEH() {
str << "Priority";
}
- }
- }
- TABLEBODY() {
+ }
+ }
+ TABLEBODY() {
for (int p = NLog::PRI_EMERG; p <= NLog::PRI_TRACE; ++p) {
- TABLER() {
+ TABLER() {
TABLED() {
str << "<a href = 'logger?c=-1&p=" << p << "'>"
<< NLog::PriorityToString(NLog::EPrio(p)) << "</a>";
- }
- }
+ }
+ }
}
- }
- }
+ }
+ }
H4() {
str << "Change sampling priority for all components";
}
- TABLE_CLASS("table table-condensed") {
- TABLEHEAD() {
- TABLER() {
+ TABLE_CLASS("table table-condensed") {
+ TABLEHEAD() {
+ TABLER() {
TABLEH() {
str << "Priority";
}
- }
- }
- TABLEBODY() {
+ }
+ }
+ TABLEBODY() {
for (int p = NLog::PRI_EMERG; p <= NLog::PRI_TRACE; ++p) {
- TABLER() {
+ TABLER() {
TABLED() {
str << "<a href = 'logger?c=-1&sp=" << p << "'>"
<< NLog::PriorityToString(NLog::EPrio(p)) << "</a>";
- }
- }
+ }
+ }
}
- }
- }
+ }
+ }
H4() {
str << "Change sampling rate for all components";
}
@@ -563,27 +563,27 @@ namespace NActors {
str << "<input type=\"hidden\" name=\"allowdrop\" value=\"" << (Settings->AllowDrop ? "0" : "1") << "\"/>" << Endl;
str << "<input class=\"btn btn-primary\" type=\"submit\" value=\"" << (Settings->AllowDrop ? "Disable" : "Enable") << "\"/>" << Endl;
str << "</form>" << Endl;
- }
- }
+ }
+ }
Metrics->GetOutputHtml(str);
- }
+ }
}
ctx.Send(ev->Sender, new NMon::TEvHttpInfoRes(str.Str()));
}
- constexpr size_t TimeBufSize = 512;
-
+ constexpr size_t TimeBufSize = 512;
+
bool TLoggerActor::OutputRecord(TInstant time, NLog::EPrio priority, NLog::EComponent component,
const TString& formatted) noexcept try {
const auto logPrio = ::ELogPriority(ui16(priority));
- char buf[TimeBufSize];
+ char buf[TimeBufSize];
switch (Settings->Format) {
case NActors::NLog::TSettings::PLAIN_FULL_FORMAT: {
TStringBuilder logRecord;
if (Settings->UseLocalTimestamps) {
- logRecord << FormatLocalTimestamp(time, buf);
+ logRecord << FormatLocalTimestamp(time, buf);
} else {
logRecord << time;
}
@@ -649,12 +649,12 @@ namespace NActors {
Become(&TThis::StateFunc);
}
- const char* TLoggerActor::FormatLocalTimestamp(TInstant time, char* buf) {
+ const char* TLoggerActor::FormatLocalTimestamp(TInstant time, char* buf) {
struct tm localTime;
time.LocalTime(&localTime);
- int r = strftime(buf, TimeBufSize, "%Y-%m-%d-%H-%M-%S", &localTime);
- Y_VERIFY(r != 0);
- return buf;
+ int r = strftime(buf, TimeBufSize, "%Y-%m-%d-%H-%M-%S", &localTime);
+ Y_VERIFY(r != 0);
+ return buf;
}
TAutoPtr<TLogBackend> CreateSysLogBackend(const TString& ident,
diff --git a/library/cpp/actors/core/log.h b/library/cpp/actors/core/log.h
index c11a7cf3c1..32a5abfed2 100644
--- a/library/cpp/actors/core/log.h
+++ b/library/cpp/actors/core/log.h
@@ -255,7 +255,7 @@ namespace NActors {
void RenderComponentPriorities(IOutputStream& str);
void LogIgnoredCount(TInstant now);
void WriteMessageStat(const NLog::TEvLog& ev);
- static const char* FormatLocalTimestamp(TInstant time, char* buf);
+ static const char* FormatLocalTimestamp(TInstant time, char* buf);
};
////////////////////////////////////////////////////////////////////////////////
diff --git a/library/cpp/actors/core/mailbox.cpp b/library/cpp/actors/core/mailbox.cpp
index d84b4f9e46..92763dbb1e 100644
--- a/library/cpp/actors/core/mailbox.cpp
+++ b/library/cpp/actors/core/mailbox.cpp
@@ -1,8 +1,8 @@
#include "mailbox.h"
#include "actorsystem.h"
-#include <library/cpp/actors/util/datetime.h>
-
+#include <library/cpp/actors/util/datetime.h>
+
#include <util/system/sanitizers.h>
namespace NActors {
@@ -183,7 +183,7 @@ namespace NActors {
#endif
mailbox->Queue.Push(ev.Release());
if (mailbox->MarkForSchedule()) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivation(hint);
}
}
@@ -207,7 +207,7 @@ namespace NActors {
#endif
mailbox->QueueWriter.Push(ev.Release());
if (mailbox->MarkForSchedule()) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivation(hint);
}
}
@@ -219,7 +219,7 @@ namespace NActors {
#endif
mailbox->Queue.Push(ev.Release());
if (mailbox->MarkForSchedule()) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivation(hint);
}
}
@@ -234,7 +234,7 @@ namespace NActors {
#endif
mailbox->Queue.Push(ev.Release());
if (mailbox->MarkForSchedule()) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivation(hint);
}
}
@@ -249,7 +249,7 @@ namespace NActors {
#endif
mailbox->Queue.Push(ev.Release());
if (mailbox->MarkForSchedule()) {
- RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
+ RelaxedStore<NHPTimer::STime>(&mailbox->ScheduleMoment, GetCycleCountFast());
executorPool->ScheduleActivation(hint);
}
}
@@ -347,7 +347,7 @@ namespace NActors {
TMailboxHeader::TMailboxHeader(TMailboxType::EType type)
: ExecutionState(TExecutionState::Free)
- , Reserved(0)
+ , Reserved(0)
, Type(type)
, ActorPack(TMailboxActorPack::Simple)
, Knobs(0)
diff --git a/library/cpp/actors/core/mailbox.h b/library/cpp/actors/core/mailbox.h
index 0bd9c4d314..4022915e1d 100644
--- a/library/cpp/actors/core/mailbox.h
+++ b/library/cpp/actors/core/mailbox.h
@@ -54,7 +54,7 @@ namespace NActors {
};
volatile ui32 ExecutionState;
- ui32 Reserved : 4; // never changes, always zero
+ ui32 Reserved : 4; // never changes, always zero
ui32 Type : 4; // never changes
ui32 ActorPack : 2;
ui32 Knobs : 22;
diff --git a/library/cpp/actors/core/mon_stats.h b/library/cpp/actors/core/mon_stats.h
index d55552af0c..e2db1e32e6 100644
--- a/library/cpp/actors/core/mon_stats.h
+++ b/library/cpp/actors/core/mon_stats.h
@@ -63,15 +63,15 @@ namespace NActors {
};
struct TExecutorThreadStats {
- ui64 SentEvents = 0;
- ui64 ReceivedEvents = 0;
- ui64 PreemptedEvents = 0; // Number of events experienced hard preemption
- ui64 NonDeliveredEvents = 0;
- ui64 EmptyMailboxActivation = 0;
- ui64 CpuNs = 0; // nanoseconds thread was executing on CPU (accounts for preemtion)
- NHPTimer::STime ElapsedTicks = 0;
- NHPTimer::STime ParkedTicks = 0;
- NHPTimer::STime BlockedTicks = 0;
+ ui64 SentEvents = 0;
+ ui64 ReceivedEvents = 0;
+ ui64 PreemptedEvents = 0; // Number of events experienced hard preemption
+ ui64 NonDeliveredEvents = 0;
+ ui64 EmptyMailboxActivation = 0;
+ ui64 CpuNs = 0; // nanoseconds thread was executing on CPU (accounts for preemtion)
+ NHPTimer::STime ElapsedTicks = 0;
+ NHPTimer::STime ParkedTicks = 0;
+ NHPTimer::STime BlockedTicks = 0;
TLogHistogram ActivationTimeHistogram;
TLogHistogram EventDeliveryTimeHistogram;
TLogHistogram EventProcessingCountHistogram;
@@ -80,19 +80,19 @@ namespace NActors {
TVector<ui64> ReceivedEventsByActivity;
TVector<i64> ActorsAliveByActivity; // the sum should be positive, but per-thread might be negative
TVector<ui64> ScheduledEventsByActivity;
- ui64 PoolActorRegistrations = 0;
- ui64 PoolDestroyedActors = 0;
- ui64 PoolAllocatedMailboxes = 0;
- ui64 MailboxPushedOutBySoftPreemption = 0;
- ui64 MailboxPushedOutByTime = 0;
- ui64 MailboxPushedOutByEventCount = 0;
+ ui64 PoolActorRegistrations = 0;
+ ui64 PoolDestroyedActors = 0;
+ ui64 PoolAllocatedMailboxes = 0;
+ ui64 MailboxPushedOutBySoftPreemption = 0;
+ ui64 MailboxPushedOutByTime = 0;
+ ui64 MailboxPushedOutByEventCount = 0;
TExecutorThreadStats(size_t activityVecSize = 1) // must be not empty as 0 used as default
- : ElapsedTicksByActivity(activityVecSize)
+ : ElapsedTicksByActivity(activityVecSize)
, ReceivedEventsByActivity(activityVecSize)
, ActorsAliveByActivity(activityVecSize)
, ScheduledEventsByActivity(activityVecSize)
- {}
+ {}
template <typename T>
static void AggregateOne(TVector<T>& self, const TVector<T>& other) {
@@ -107,14 +107,14 @@ namespace NActors {
void Aggregate(const TExecutorThreadStats& other) {
SentEvents += RelaxedLoad(&other.SentEvents);
ReceivedEvents += RelaxedLoad(&other.ReceivedEvents);
- PreemptedEvents += RelaxedLoad(&other.PreemptedEvents);
+ PreemptedEvents += RelaxedLoad(&other.PreemptedEvents);
NonDeliveredEvents += RelaxedLoad(&other.NonDeliveredEvents);
EmptyMailboxActivation += RelaxedLoad(&other.EmptyMailboxActivation);
- CpuNs += RelaxedLoad(&other.CpuNs);
+ CpuNs += RelaxedLoad(&other.CpuNs);
ElapsedTicks += RelaxedLoad(&other.ElapsedTicks);
ParkedTicks += RelaxedLoad(&other.ParkedTicks);
BlockedTicks += RelaxedLoad(&other.BlockedTicks);
- MailboxPushedOutBySoftPreemption += RelaxedLoad(&other.MailboxPushedOutBySoftPreemption);
+ MailboxPushedOutBySoftPreemption += RelaxedLoad(&other.MailboxPushedOutBySoftPreemption);
MailboxPushedOutByTime += RelaxedLoad(&other.MailboxPushedOutByTime);
MailboxPushedOutByEventCount += RelaxedLoad(&other.MailboxPushedOutByEventCount);
diff --git a/library/cpp/actors/core/probes.cpp b/library/cpp/actors/core/probes.cpp
index 7ace83e102..0a9b256f70 100644
--- a/library/cpp/actors/core/probes.cpp
+++ b/library/cpp/actors/core/probes.cpp
@@ -1,28 +1,28 @@
#include "probes.h"
-#include "actorsystem.h"
-
-#include <util/string/builder.h>
-
+#include "actorsystem.h"
+
+#include <util/string/builder.h>
+
LWTRACE_DEFINE_PROVIDER(ACTORLIB_PROVIDER);
-
-namespace NActors {
- TVector<NLWTrace::TDashboard> LWTraceDashboards(TActorSystemSetup* setup) {
- TVector<NLWTrace::TDashboard> result;
-
- NLWTrace::TDashboard slowDash;
- ui32 pools = setup->GetExecutorsCount();
- size_t top = 30;
- slowDash.SetName("ActorSystem slow events");
- slowDash.SetDescription(TStringBuilder() << "TOP" << top << " slow event executions >1M cycles for every pool (refresh page to update)");
- for (ui32 pool = 0; pool < pools; pool++) {
- auto* row = slowDash.AddRows();
- auto* cell = row->AddCells();
- cell->SetTitle(TStringBuilder() << pool << ":" << setup->GetPoolName(pool));
- cell->SetUrl(TStringBuilder() << "?mode=log&id=.ACTORLIB_PROVIDER.SlowEvent.ppoolId=" << pool << "&s=eventMs&reverse=y&head=30");
- }
- result.push_back(slowDash);
-
- return result;
- }
-}
+
+namespace NActors {
+ TVector<NLWTrace::TDashboard> LWTraceDashboards(TActorSystemSetup* setup) {
+ TVector<NLWTrace::TDashboard> result;
+
+ NLWTrace::TDashboard slowDash;
+ ui32 pools = setup->GetExecutorsCount();
+ size_t top = 30;
+ slowDash.SetName("ActorSystem slow events");
+ slowDash.SetDescription(TStringBuilder() << "TOP" << top << " slow event executions >1M cycles for every pool (refresh page to update)");
+ for (ui32 pool = 0; pool < pools; pool++) {
+ auto* row = slowDash.AddRows();
+ auto* cell = row->AddCells();
+ cell->SetTitle(TStringBuilder() << pool << ":" << setup->GetPoolName(pool));
+ cell->SetUrl(TStringBuilder() << "?mode=log&id=.ACTORLIB_PROVIDER.SlowEvent.ppoolId=" << pool << "&s=eventMs&reverse=y&head=30");
+ }
+ result.push_back(slowDash);
+
+ return result;
+ }
+}
diff --git a/library/cpp/actors/core/probes.h b/library/cpp/actors/core/probes.h
index 4912d6dd26..0733cd010d 100644
--- a/library/cpp/actors/core/probes.h
+++ b/library/cpp/actors/core/probes.h
@@ -1,12 +1,12 @@
#pragma once
#include <library/cpp/lwtrace/all.h>
-#include <util/generic/vector.h>
-
-#define LWACTORID(x) (x).RawX1(), (x).RawX2(), (x).NodeId(), (x).PoolID()
-#define LWTYPE_ACTORID ui64, ui64, ui32, ui32
-#define LWNAME_ACTORID(n) n "Raw1", n "Raw2", n "NodeId", n "PoolId"
+#include <util/generic/vector.h>
+#define LWACTORID(x) (x).RawX1(), (x).RawX2(), (x).NodeId(), (x).PoolID()
+#define LWTYPE_ACTORID ui64, ui64, ui32, ui32
+#define LWNAME_ACTORID(n) n "Raw1", n "Raw2", n "NodeId", n "PoolId"
+
#define ACTORLIB_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
PROBE(SlowEvent, GROUPS("ActorLibSlow"), \
TYPES(ui32, double, TString, TString, TString), \
@@ -23,27 +23,27 @@
PROBE(SlowRegisterAdd, GROUPS("ActorLibSlow"), \
TYPES(ui32, double), \
NAMES("poolId", "registerAddMs")) \
- PROBE(MailboxPushedOutBySoftPreemption, GROUPS("ActorLibMailbox", "ActorLibMailboxPushedOut"), \
- TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
- NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
- PROBE(MailboxPushedOutByTime, GROUPS("ActorLibMailbox", "ActorLibMailboxPushedOut"), \
- TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
- NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
- PROBE(MailboxPushedOutByEventCount, GROUPS("ActorLibMailbox", "ActorLibMailboxPushedOut"), \
- TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
- NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
- PROBE(MailboxEmpty, GROUPS("ActorLibMailbox"), \
- TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
- NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
- PROBE(ActivationBegin, GROUPS(), \
- TYPES(ui32, ui32, ui32, double), \
- NAMES("cpu", "poolId", "workerId", "expireMs")) \
- PROBE(ActivationEnd, GROUPS(), \
- TYPES(ui32, ui32, ui32), \
- NAMES("cpu", "poolId", "workerId")) \
+ PROBE(MailboxPushedOutBySoftPreemption, GROUPS("ActorLibMailbox", "ActorLibMailboxPushedOut"), \
+ TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
+ NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
+ PROBE(MailboxPushedOutByTime, GROUPS("ActorLibMailbox", "ActorLibMailboxPushedOut"), \
+ TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
+ NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
+ PROBE(MailboxPushedOutByEventCount, GROUPS("ActorLibMailbox", "ActorLibMailboxPushedOut"), \
+ TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
+ NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
+ PROBE(MailboxEmpty, GROUPS("ActorLibMailbox"), \
+ TYPES(ui32, TString, ui32, TDuration, ui64, TString, TString), \
+ NAMES("poolId", "pool", "eventsProcessed", "procTimeMs", "workerId", "actorId", "actorType")) \
+ PROBE(ActivationBegin, GROUPS(), \
+ TYPES(ui32, ui32, ui32, double), \
+ NAMES("cpu", "poolId", "workerId", "expireMs")) \
+ PROBE(ActivationEnd, GROUPS(), \
+ TYPES(ui32, ui32, ui32), \
+ NAMES("cpu", "poolId", "workerId")) \
PROBE(ExecutorThreadStats, GROUPS("ActorLibStats"), \
- TYPES(ui32, TString, ui64, ui64, ui64, double, double), \
- NAMES("poolId", "pool", "workerId", "execCount", "readyActivationCount", "execMs", "nonExecMs")) \
+ TYPES(ui32, TString, ui64, ui64, ui64, double, double), \
+ NAMES("poolId", "pool", "workerId", "execCount", "readyActivationCount", "execMs", "nonExecMs")) \
PROBE(SlowICReadLoopAdjustSize, GROUPS("ActorLibSlowIC"), \
TYPES(double), \
NAMES("icReadLoopAdjustSizeMs")) \
@@ -75,102 +75,102 @@
TYPES(ui64, ui64, ui32, ui32, ui64, ui64), \
NAMES("timeUs", "timerfd_expirations", "eventsGottenFromQueues", "eventsSent", \
"eventsInSendQueue", "eventSchedulingErrorUs")) \
- PROBE(ForwardEvent, GROUPS("Orbit", "InterconnectSessionTCP"), \
- TYPES(ui32, ui32, ui32, LWTYPE_ACTORID, LWTYPE_ACTORID, ui64, ui32), \
- NAMES("peerId", "type", "flags", LWNAME_ACTORID("r"), LWNAME_ACTORID("s"), \
- "cookie", "eventSerializedSize")) \
- PROBE(EnqueueEvent, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui64, TDuration, ui16, ui64, ui64), \
- NAMES("peerId", "numEventsInReadyChannels", "enqueueBlockedTotalMs", "channelId", "queueSizeInEvents", "queueSizeInBytes")) \
- PROBE(SerializeToPacketBegin, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui16, ui64), \
- NAMES("peerId", "channelId", "outputQueueSize")) \
- PROBE(SerializeToPacketEnd, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui16, ui64, ui64), \
- NAMES("peerId", "channelId", "outputQueueSize", "offsetInPacket")) \
- PROBE(FillSendingBuffer, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui32, ui64, TDuration), \
- NAMES("peerId", "taskBytesGenerated", "numEventsInReadyChannelsBehind", "fillBlockedTotalMs")) \
- PROBE(PacketGenerated, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui64, ui64, ui64, ui64), \
- NAMES("peerId", "bytesUnwritten", "inflightBytes", "packetsGenerated", "packetSize")) \
- PROBE(PacketWrittenToSocket, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui64, bool, ui64, ui64, TDuration, int), \
- NAMES("peerId", "packetsWrittenToSocket", "triedWriting", "packetDataSize", "bytesUnwritten", "writeBlockedTotalMs", "fd")) \
- PROBE(GenerateTraffic, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double, ui64, ui32, ui64), \
- NAMES("peerId", "generateTrafficMs", "dataBytesSent", "generatedPackets", "generatedBytes")) \
- PROBE(WriteToSocket, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui64, ui64, ui64, ui64, TDuration, int), \
- NAMES("peerId", "bytesWritten", "packetsWritten", "packetsWrittenToSocket", "bytesUnwritten", "writeBlockedTotalMs", "fd")) \
- PROBE(UpdateFromInputSession, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double), \
- NAMES("peerId", "pingMs")) \
- PROBE(UnblockByDropConfirmed, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double), \
- NAMES("peerId", "updateDeliveryMs")) \
- PROBE(DropConfirmed, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, ui64, ui64), \
- NAMES("peerId", "droppedBytes", "inflightBytes")) \
- PROBE(StartRam, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32), \
- NAMES("peerId")) \
- PROBE(FinishRam, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double), \
- NAMES("peerId", "ramMs")) \
- PROBE(SkipGenerateTraffic, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double), \
- NAMES("peerId", "elapsedSinceRamMs")) \
- PROBE(StartBatching, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double), \
- NAMES("peerId", "batchPeriodMs")) \
- PROBE(FinishBatching, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double), \
- NAMES("peerId", "finishBatchDeliveryMs")) \
- PROBE(BlockedWrite, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double, ui64), \
- NAMES("peerId", "sendQueueSize", "writtenBytes")) \
- PROBE(ReadyWrite, GROUPS("InterconnectSessionTCP"), \
- TYPES(ui32, double, double), \
- NAMES("peerId", "readyWriteDeliveryMs", "blockMs")) \
- PROBE(EpollStartWaitIn, GROUPS("EpollThread"), \
- TYPES(), \
- NAMES()) \
- PROBE(EpollFinishWaitIn, GROUPS("EpollThread"), \
- TYPES(i32), \
- NAMES("eventsCount")) \
- PROBE(EpollWaitOut, GROUPS("EpollThread"), \
- TYPES(i32), \
- NAMES("eventsCount")) \
- PROBE(EpollSendReadyRead, GROUPS("EpollThread"), \
- TYPES(bool, bool, int), \
- NAMES("hangup", "event", "fd")) \
- PROBE(EpollSendReadyWrite, GROUPS("EpollThread"), \
- TYPES(bool, bool, int), \
- NAMES("hangup", "event", "fd")) \
- PROBE(HardPreemption, GROUPS("UnitedWorker"), \
- TYPES(ui32, ui32, ui32, ui32), \
- NAMES("cpu", "prevPoolId", "prevWorkerId", "nextWorkerId")) \
- PROBE(SetPreemptionTimer, GROUPS("UnitedWorker", "PreemptionTimer"), \
- TYPES(ui32, ui32, int, double, double), \
- NAMES("cpu", "workerId", "fd", "nowMs", "preemptMs")) \
- PROBE(ResetPreemptionTimer, GROUPS("UnitedWorker", "PreemptionTimer"), \
- TYPES(ui32, ui32, int, double, double), \
- NAMES("cpu", "workerId", "fd", "nowMs", "preemptMs")) \
- PROBE(SlowWorkerActionRace, GROUPS("UnitedWorker"), \
- TYPES(ui32, ui32, ui64), \
- NAMES("cpu", "poolId", "slowPoolsMask")) \
- PROBE(PoolStats, GROUPS("PoolCpuBalancer"), \
- TYPES(ui32, TString, ui64, ui8, ui8, double, double, double, ui64, ui64, ui64), \
- NAMES("poolId", "pool", "currentCpus", "loadClass", "priority", "scaleFactor", "cpuIdle", "cpuLoad", "importance", "addImportance", "subImportance")) \
- PROBE(MoveCpu, GROUPS("PoolCpuBalancer"), \
- TYPES(ui32, ui64, TString, TString, ui32), \
- NAMES("fromPoolId", "toPoolId", "fromPool", "toPool", "cpu")) \
+ PROBE(ForwardEvent, GROUPS("Orbit", "InterconnectSessionTCP"), \
+ TYPES(ui32, ui32, ui32, LWTYPE_ACTORID, LWTYPE_ACTORID, ui64, ui32), \
+ NAMES("peerId", "type", "flags", LWNAME_ACTORID("r"), LWNAME_ACTORID("s"), \
+ "cookie", "eventSerializedSize")) \
+ PROBE(EnqueueEvent, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui64, TDuration, ui16, ui64, ui64), \
+ NAMES("peerId", "numEventsInReadyChannels", "enqueueBlockedTotalMs", "channelId", "queueSizeInEvents", "queueSizeInBytes")) \
+ PROBE(SerializeToPacketBegin, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui16, ui64), \
+ NAMES("peerId", "channelId", "outputQueueSize")) \
+ PROBE(SerializeToPacketEnd, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui16, ui64, ui64), \
+ NAMES("peerId", "channelId", "outputQueueSize", "offsetInPacket")) \
+ PROBE(FillSendingBuffer, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui32, ui64, TDuration), \
+ NAMES("peerId", "taskBytesGenerated", "numEventsInReadyChannelsBehind", "fillBlockedTotalMs")) \
+ PROBE(PacketGenerated, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui64, ui64, ui64, ui64), \
+ NAMES("peerId", "bytesUnwritten", "inflightBytes", "packetsGenerated", "packetSize")) \
+ PROBE(PacketWrittenToSocket, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui64, bool, ui64, ui64, TDuration, int), \
+ NAMES("peerId", "packetsWrittenToSocket", "triedWriting", "packetDataSize", "bytesUnwritten", "writeBlockedTotalMs", "fd")) \
+ PROBE(GenerateTraffic, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double, ui64, ui32, ui64), \
+ NAMES("peerId", "generateTrafficMs", "dataBytesSent", "generatedPackets", "generatedBytes")) \
+ PROBE(WriteToSocket, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui64, ui64, ui64, ui64, TDuration, int), \
+ NAMES("peerId", "bytesWritten", "packetsWritten", "packetsWrittenToSocket", "bytesUnwritten", "writeBlockedTotalMs", "fd")) \
+ PROBE(UpdateFromInputSession, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double), \
+ NAMES("peerId", "pingMs")) \
+ PROBE(UnblockByDropConfirmed, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double), \
+ NAMES("peerId", "updateDeliveryMs")) \
+ PROBE(DropConfirmed, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, ui64, ui64), \
+ NAMES("peerId", "droppedBytes", "inflightBytes")) \
+ PROBE(StartRam, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32), \
+ NAMES("peerId")) \
+ PROBE(FinishRam, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double), \
+ NAMES("peerId", "ramMs")) \
+ PROBE(SkipGenerateTraffic, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double), \
+ NAMES("peerId", "elapsedSinceRamMs")) \
+ PROBE(StartBatching, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double), \
+ NAMES("peerId", "batchPeriodMs")) \
+ PROBE(FinishBatching, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double), \
+ NAMES("peerId", "finishBatchDeliveryMs")) \
+ PROBE(BlockedWrite, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double, ui64), \
+ NAMES("peerId", "sendQueueSize", "writtenBytes")) \
+ PROBE(ReadyWrite, GROUPS("InterconnectSessionTCP"), \
+ TYPES(ui32, double, double), \
+ NAMES("peerId", "readyWriteDeliveryMs", "blockMs")) \
+ PROBE(EpollStartWaitIn, GROUPS("EpollThread"), \
+ TYPES(), \
+ NAMES()) \
+ PROBE(EpollFinishWaitIn, GROUPS("EpollThread"), \
+ TYPES(i32), \
+ NAMES("eventsCount")) \
+ PROBE(EpollWaitOut, GROUPS("EpollThread"), \
+ TYPES(i32), \
+ NAMES("eventsCount")) \
+ PROBE(EpollSendReadyRead, GROUPS("EpollThread"), \
+ TYPES(bool, bool, int), \
+ NAMES("hangup", "event", "fd")) \
+ PROBE(EpollSendReadyWrite, GROUPS("EpollThread"), \
+ TYPES(bool, bool, int), \
+ NAMES("hangup", "event", "fd")) \
+ PROBE(HardPreemption, GROUPS("UnitedWorker"), \
+ TYPES(ui32, ui32, ui32, ui32), \
+ NAMES("cpu", "prevPoolId", "prevWorkerId", "nextWorkerId")) \
+ PROBE(SetPreemptionTimer, GROUPS("UnitedWorker", "PreemptionTimer"), \
+ TYPES(ui32, ui32, int, double, double), \
+ NAMES("cpu", "workerId", "fd", "nowMs", "preemptMs")) \
+ PROBE(ResetPreemptionTimer, GROUPS("UnitedWorker", "PreemptionTimer"), \
+ TYPES(ui32, ui32, int, double, double), \
+ NAMES("cpu", "workerId", "fd", "nowMs", "preemptMs")) \
+ PROBE(SlowWorkerActionRace, GROUPS("UnitedWorker"), \
+ TYPES(ui32, ui32, ui64), \
+ NAMES("cpu", "poolId", "slowPoolsMask")) \
+ PROBE(PoolStats, GROUPS("PoolCpuBalancer"), \
+ TYPES(ui32, TString, ui64, ui8, ui8, double, double, double, ui64, ui64, ui64), \
+ NAMES("poolId", "pool", "currentCpus", "loadClass", "priority", "scaleFactor", "cpuIdle", "cpuLoad", "importance", "addImportance", "subImportance")) \
+ PROBE(MoveCpu, GROUPS("PoolCpuBalancer"), \
+ TYPES(ui32, ui64, TString, TString, ui32), \
+ NAMES("fromPoolId", "toPoolId", "fromPool", "toPool", "cpu")) \
/**/
LWTRACE_DECLARE_PROVIDER(ACTORLIB_PROVIDER)
-
-namespace NActors {
- struct TActorSystemSetup;
- TVector<NLWTrace::TDashboard> LWTraceDashboards(TActorSystemSetup* setup);
-}
+
+namespace NActors {
+ struct TActorSystemSetup;
+ TVector<NLWTrace::TDashboard> LWTraceDashboards(TActorSystemSetup* setup);
+}
diff --git a/library/cpp/actors/core/scheduler_actor.cpp b/library/cpp/actors/core/scheduler_actor.cpp
index febc5e40dd..7e38a41e30 100644
--- a/library/cpp/actors/core/scheduler_actor.cpp
+++ b/library/cpp/actors/core/scheduler_actor.cpp
@@ -116,11 +116,11 @@ namespace NActors {
void TryUpdateTime(NHPTimer::STime* lastTimeUpdate) {
NHPTimer::STime hpnow;
- GetTimeFast(&hpnow);
+ GetTimeFast(&hpnow);
const ui64 elapsedCycles = hpnow > *lastTimeUpdate ? hpnow - *lastTimeUpdate : 0;
if (elapsedCycles > Cfg.ResolutionMicroseconds * (NHPTimer::GetCyclesPerSecond() / IntrasecondThreshold)) {
UpdateTime();
- GetTimeFast(lastTimeUpdate);
+ GetTimeFast(lastTimeUpdate);
}
}
diff --git a/library/cpp/actors/core/scheduler_basic.cpp b/library/cpp/actors/core/scheduler_basic.cpp
index fba200e16b..715cfb787d 100644
--- a/library/cpp/actors/core/scheduler_basic.cpp
+++ b/library/cpp/actors/core/scheduler_basic.cpp
@@ -1,9 +1,9 @@
#include "scheduler_basic.h"
#include "scheduler_queue.h"
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <library/cpp/actors/util/thread.h>
-
+
#ifdef BALLOC
#include <library/cpp/balloc/optional/operators.h>
#endif
@@ -61,7 +61,7 @@ namespace NActors {
ui64 activeTick = AlignUp<ui64>(throttledMonotonic, IntrasecondThreshold);
TAutoPtr<TMomentMap> activeSec;
- NHPTimer::STime hpprev = GetCycleCountFast();
+ NHPTimer::STime hpprev = GetCycleCountFast();
ui64 nextTimestamp = TInstant::Now().MicroSeconds();
ui64 nextMonotonic = Max(currentMonotonic, GetMonotonicMicroSeconds());
@@ -170,7 +170,7 @@ namespace NActors {
}
}
- NHPTimer::STime hpnow = GetCycleCountFast();
+ NHPTimer::STime hpnow = GetCycleCountFast();
if (MonCounters) {
*MonCounters->QueueSize -= eventsSent + eventsDropped;
@@ -202,7 +202,7 @@ namespace NActors {
NanoSleep(delta * 1000); // ok, looks like we should sleep a bit.
// Don't count sleep in elapsed microseconds
- hpprev = GetCycleCountFast();
+ hpprev = GetCycleCountFast();
nextTimestamp = TInstant::Now().MicroSeconds();
nextMonotonic = Max(currentMonotonic, GetMonotonicMicroSeconds());
}
@@ -218,7 +218,7 @@ namespace NActors {
*CurrentMonotonic = GetMonotonicMicroSeconds();
}
- void TBasicSchedulerThread::PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) {
+ void TBasicSchedulerThread::PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) {
Y_VERIFY(scheduleReadersCount > 0);
TotalReaders = scheduleReadersCount;
Readers.Reset(new NSchedulerQueue::TReader*[scheduleReadersCount]);
diff --git a/library/cpp/actors/core/scheduler_basic.h b/library/cpp/actors/core/scheduler_basic.h
index 2ccde39235..16a5b005bd 100644
--- a/library/cpp/actors/core/scheduler_basic.h
+++ b/library/cpp/actors/core/scheduler_basic.h
@@ -42,7 +42,7 @@ namespace NActors {
~TBasicSchedulerThread();
void Prepare(TActorSystem* actorSystem, volatile ui64* currentTimestamp, volatile ui64* currentMonotonic) override;
- void PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) override;
+ void PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) override;
void PrepareStart() override;
void Start() override;
@@ -61,7 +61,7 @@ namespace NActors {
*currentMonotonic = GetMonotonicMicroSeconds();
}
- void PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) override {
+ void PrepareSchedules(NSchedulerQueue::TReader** readers, ui32 scheduleReadersCount) override {
Y_UNUSED(readers);
Y_UNUSED(scheduleReadersCount);
}
diff --git a/library/cpp/actors/core/ut/ya.make b/library/cpp/actors/core/ut/ya.make
index 3ee28d5850..64ab864b4a 100644
--- a/library/cpp/actors/core/ut/ya.make
+++ b/library/cpp/actors/core/ut/ya.make
@@ -33,11 +33,11 @@ SRCS(
actor_ut.cpp
actorsystem_ut.cpp
ask_ut.cpp
- balancer_ut.cpp
+ balancer_ut.cpp
event_pb_payload_ut.cpp
event_pb_ut.cpp
executor_pool_basic_ut.cpp
- executor_pool_united_ut.cpp
+ executor_pool_united_ut.cpp
log_ut.cpp
memory_tracker_ut.cpp
scheduler_actor_ut.cpp
diff --git a/library/cpp/actors/core/worker_context.cpp b/library/cpp/actors/core/worker_context.cpp
index ada6c997d4..55b50f4708 100644
--- a/library/cpp/actors/core/worker_context.cpp
+++ b/library/cpp/actors/core/worker_context.cpp
@@ -1,7 +1,7 @@
-#include "worker_context.h"
-#include "probes.h"
-
-namespace NActors {
- LWTRACE_USING(ACTORLIB_PROVIDER);
-
-}
+#include "worker_context.h"
+#include "probes.h"
+
+namespace NActors {
+ LWTRACE_USING(ACTORLIB_PROVIDER);
+
+}
diff --git a/library/cpp/actors/core/worker_context.h b/library/cpp/actors/core/worker_context.h
index b4c37a7629..d4a9a5e6ee 100644
--- a/library/cpp/actors/core/worker_context.h
+++ b/library/cpp/actors/core/worker_context.h
@@ -1,175 +1,175 @@
-#pragma once
-
-#include "defs.h"
-
-#include "actorsystem.h"
-#include "event.h"
-#include "lease.h"
-#include "mailbox.h"
-#include "mon_stats.h"
-
-#include <library/cpp/actors/util/datetime.h>
-#include <library/cpp/actors/util/intrinsics.h>
-#include <library/cpp/actors/util/thread.h>
-
-#include <library/cpp/lwtrace/shuttle.h>
-
-namespace NActors {
- struct TWorkerContext {
- const TWorkerId WorkerId;
- const TCpuId CpuId;
- TLease Lease;
- IExecutorPool* Executor = nullptr;
- TMailboxTable* MailboxTable = nullptr;
- ui64 TimePerMailboxTs = 0;
- ui32 EventsPerMailbox = 0;
- ui64 SoftDeadlineTs = ui64(-1);
- TExecutorThreadStats* Stats = &WorkerStats; // pool stats
- TExecutorThreadStats WorkerStats;
- TPoolId PoolId = MaxPools;
- mutable NLWTrace::TOrbit Orbit;
-
- TWorkerContext(TWorkerId workerId, TCpuId cpuId, size_t activityVecSize)
- : WorkerId(workerId)
- , CpuId(cpuId)
- , Lease(WorkerId, NeverExpire)
- , WorkerStats(activityVecSize)
- {}
-
-#ifdef ACTORSLIB_COLLECT_EXEC_STATS
- void GetCurrentStats(TExecutorThreadStats& statsCopy) const {
- statsCopy = TExecutorThreadStats();
- statsCopy.Aggregate(*Stats);
- }
-
- void AddElapsedCycles(ui32 activityType, i64 elapsed) {
- Y_VERIFY_DEBUG(activityType < Stats->MaxActivityType());
- RelaxedStore(&Stats->ElapsedTicks, RelaxedLoad(&Stats->ElapsedTicks) + elapsed);
- RelaxedStore(&Stats->ElapsedTicksByActivity[activityType], RelaxedLoad(&Stats->ElapsedTicksByActivity[activityType]) + elapsed);
- }
-
- void AddParkedCycles(i64 elapsed) {
- RelaxedStore(&Stats->ParkedTicks, RelaxedLoad(&Stats->ParkedTicks) + elapsed);
- }
-
- void AddBlockedCycles(i64 elapsed) {
- RelaxedStore(&Stats->BlockedTicks, RelaxedLoad(&Stats->BlockedTicks) + elapsed);
- }
-
- void IncrementSentEvents() {
- RelaxedStore(&Stats->SentEvents, RelaxedLoad(&Stats->SentEvents) + 1);
- }
-
- void IncrementPreemptedEvents() {
- RelaxedStore(&Stats->PreemptedEvents, RelaxedLoad(&Stats->PreemptedEvents) + 1);
- }
-
- void DecrementActorsAliveByActivity(ui32 activityType) {
- if (activityType >= Stats->MaxActivityType()) {
- activityType = 0;
- }
- RelaxedStore(&Stats->ActorsAliveByActivity[activityType], Stats->ActorsAliveByActivity[activityType] - 1);
- }
-
- inline void IncrementNonDeliveredEvents() {
- RelaxedStore(&Stats->NonDeliveredEvents, RelaxedLoad(&Stats->NonDeliveredEvents) + 1);
- }
-
- inline void IncrementMailboxPushedOutBySoftPreemption() {
- RelaxedStore(&Stats->MailboxPushedOutBySoftPreemption, RelaxedLoad(&Stats->MailboxPushedOutBySoftPreemption) + 1);
- }
-
- inline void IncrementMailboxPushedOutByTime() {
- RelaxedStore(&Stats->MailboxPushedOutByTime, RelaxedLoad(&Stats->MailboxPushedOutByTime) + 1);
- }
-
- inline void IncrementMailboxPushedOutByEventCount() {
- RelaxedStore(&Stats->MailboxPushedOutByEventCount, RelaxedLoad(&Stats->MailboxPushedOutByEventCount) + 1);
- }
-
- inline void IncrementEmptyMailboxActivation() {
- RelaxedStore(&Stats->EmptyMailboxActivation, RelaxedLoad(&Stats->EmptyMailboxActivation) + 1);
- }
-
- double AddActivationStats(i64 scheduleTs, i64 deliveredTs) {
- i64 ts = deliveredTs > scheduleTs ? deliveredTs - scheduleTs : 0;
- double usec = NHPTimer::GetSeconds(ts) * 1000000.0;
- Stats->ActivationTimeHistogram.Add(usec);
- return usec;
- }
-
- ui64 AddEventDeliveryStats(i64 sentTs, i64 deliveredTs) {
- ui64 usecDeliv = deliveredTs > sentTs ? NHPTimer::GetSeconds(deliveredTs - sentTs) * 1000000 : 0;
- Stats->EventDeliveryTimeHistogram.Add(usecDeliv);
- return usecDeliv;
- }
-
- i64 AddEventProcessingStats(i64 deliveredTs, i64 processedTs, ui32 activityType, ui64 scheduled) {
- i64 elapsed = processedTs - deliveredTs;
- ui64 usecElapsed = NHPTimer::GetSeconds(elapsed) * 1000000;
- activityType = (activityType >= Stats->MaxActivityType()) ? 0 : activityType;
- Stats->EventProcessingCountHistogram.Add(usecElapsed);
- Stats->EventProcessingTimeHistogram.Add(usecElapsed, elapsed);
- RelaxedStore(&Stats->ReceivedEvents, RelaxedLoad(&Stats->ReceivedEvents) + 1);
- RelaxedStore(&Stats->ReceivedEventsByActivity[activityType], RelaxedLoad(&Stats->ReceivedEventsByActivity[activityType]) + 1);
- RelaxedStore(&Stats->ScheduledEventsByActivity[activityType], RelaxedLoad(&Stats->ScheduledEventsByActivity[activityType]) + scheduled);
- AddElapsedCycles(activityType, elapsed);
- return elapsed;
- }
-
- void UpdateActorsStats(size_t dyingActorsCnt) {
- if (dyingActorsCnt) {
- AtomicAdd(Executor->DestroyedActors, dyingActorsCnt);
- }
- RelaxedStore(&Stats->PoolDestroyedActors, (ui64)RelaxedLoad(&Executor->DestroyedActors));
- RelaxedStore(&Stats->PoolActorRegistrations, (ui64)RelaxedLoad(&Executor->ActorRegistrations));
- RelaxedStore(&Stats->PoolAllocatedMailboxes, MailboxTable->GetAllocatedMailboxCount());
- }
-
- void UpdateThreadTime() {
- RelaxedStore(&WorkerStats.CpuNs, ThreadCPUTime() * 1000);
- }
-#else
- void GetCurrentStats(TExecutorThreadStats&) const {}
- inline void AddElapsedCycles(ui32, i64) {}
- inline void AddParkedCycles(i64) {}
- inline void AddBlockedCycles(i64) {}
- inline void IncrementSentEvents() {}
- inline void IncrementPreemptedEvents() {}
- inline void IncrementMailboxPushedOutBySoftPreemption() {}
- inline void IncrementMailboxPushedOutByTime() {}
- inline void IncrementMailboxPushedOutByEventCount() {}
- inline void IncrementEmptyMailboxActivation() {}
- void DecrementActorsAliveByActivity(ui32) {}
- void IncrementNonDeliveredEvents() {}
- double AddActivationStats(i64, i64) { return 0; }
- ui64 AddEventDeliveryStats(i64, i64) { return 0; }
- i64 AddEventProcessingStats(i64, i64, ui32, ui64) { return 0; }
- void UpdateActorsStats(size_t, IExecutorPool*) {}
- void UpdateThreadTime() {}
-#endif
-
- void Switch(IExecutorPool* executor,
- TMailboxTable* mailboxTable,
- ui64 timePerMailboxTs,
- ui32 eventsPerMailbox,
- ui64 softDeadlineTs,
- TExecutorThreadStats* stats)
- {
- Executor = executor;
- MailboxTable = mailboxTable;
- TimePerMailboxTs = timePerMailboxTs;
- EventsPerMailbox = eventsPerMailbox;
- SoftDeadlineTs = softDeadlineTs;
- Stats = stats;
- PoolId = Executor ? Executor->PoolId : MaxPools;
- }
-
- void SwitchToIdle() {
- Executor = nullptr;
- MailboxTable = nullptr;
- //Stats = &WorkerStats; // TODO: in actorsystem 2.0 idle stats cannot be related to specific pool
- PoolId = MaxPools;
- }
- };
-}
+#pragma once
+
+#include "defs.h"
+
+#include "actorsystem.h"
+#include "event.h"
+#include "lease.h"
+#include "mailbox.h"
+#include "mon_stats.h"
+
+#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/intrinsics.h>
+#include <library/cpp/actors/util/thread.h>
+
+#include <library/cpp/lwtrace/shuttle.h>
+
+namespace NActors {
+ struct TWorkerContext {
+ const TWorkerId WorkerId;
+ const TCpuId CpuId;
+ TLease Lease;
+ IExecutorPool* Executor = nullptr;
+ TMailboxTable* MailboxTable = nullptr;
+ ui64 TimePerMailboxTs = 0;
+ ui32 EventsPerMailbox = 0;
+ ui64 SoftDeadlineTs = ui64(-1);
+ TExecutorThreadStats* Stats = &WorkerStats; // pool stats
+ TExecutorThreadStats WorkerStats;
+ TPoolId PoolId = MaxPools;
+ mutable NLWTrace::TOrbit Orbit;
+
+ TWorkerContext(TWorkerId workerId, TCpuId cpuId, size_t activityVecSize)
+ : WorkerId(workerId)
+ , CpuId(cpuId)
+ , Lease(WorkerId, NeverExpire)
+ , WorkerStats(activityVecSize)
+ {}
+
+#ifdef ACTORSLIB_COLLECT_EXEC_STATS
+ void GetCurrentStats(TExecutorThreadStats& statsCopy) const {
+ statsCopy = TExecutorThreadStats();
+ statsCopy.Aggregate(*Stats);
+ }
+
+ void AddElapsedCycles(ui32 activityType, i64 elapsed) {
+ Y_VERIFY_DEBUG(activityType < Stats->MaxActivityType());
+ RelaxedStore(&Stats->ElapsedTicks, RelaxedLoad(&Stats->ElapsedTicks) + elapsed);
+ RelaxedStore(&Stats->ElapsedTicksByActivity[activityType], RelaxedLoad(&Stats->ElapsedTicksByActivity[activityType]) + elapsed);
+ }
+
+ void AddParkedCycles(i64 elapsed) {
+ RelaxedStore(&Stats->ParkedTicks, RelaxedLoad(&Stats->ParkedTicks) + elapsed);
+ }
+
+ void AddBlockedCycles(i64 elapsed) {
+ RelaxedStore(&Stats->BlockedTicks, RelaxedLoad(&Stats->BlockedTicks) + elapsed);
+ }
+
+ void IncrementSentEvents() {
+ RelaxedStore(&Stats->SentEvents, RelaxedLoad(&Stats->SentEvents) + 1);
+ }
+
+ void IncrementPreemptedEvents() {
+ RelaxedStore(&Stats->PreemptedEvents, RelaxedLoad(&Stats->PreemptedEvents) + 1);
+ }
+
+ void DecrementActorsAliveByActivity(ui32 activityType) {
+ if (activityType >= Stats->MaxActivityType()) {
+ activityType = 0;
+ }
+ RelaxedStore(&Stats->ActorsAliveByActivity[activityType], Stats->ActorsAliveByActivity[activityType] - 1);
+ }
+
+ inline void IncrementNonDeliveredEvents() {
+ RelaxedStore(&Stats->NonDeliveredEvents, RelaxedLoad(&Stats->NonDeliveredEvents) + 1);
+ }
+
+ inline void IncrementMailboxPushedOutBySoftPreemption() {
+ RelaxedStore(&Stats->MailboxPushedOutBySoftPreemption, RelaxedLoad(&Stats->MailboxPushedOutBySoftPreemption) + 1);
+ }
+
+ inline void IncrementMailboxPushedOutByTime() {
+ RelaxedStore(&Stats->MailboxPushedOutByTime, RelaxedLoad(&Stats->MailboxPushedOutByTime) + 1);
+ }
+
+ inline void IncrementMailboxPushedOutByEventCount() {
+ RelaxedStore(&Stats->MailboxPushedOutByEventCount, RelaxedLoad(&Stats->MailboxPushedOutByEventCount) + 1);
+ }
+
+ inline void IncrementEmptyMailboxActivation() {
+ RelaxedStore(&Stats->EmptyMailboxActivation, RelaxedLoad(&Stats->EmptyMailboxActivation) + 1);
+ }
+
+ double AddActivationStats(i64 scheduleTs, i64 deliveredTs) {
+ i64 ts = deliveredTs > scheduleTs ? deliveredTs - scheduleTs : 0;
+ double usec = NHPTimer::GetSeconds(ts) * 1000000.0;
+ Stats->ActivationTimeHistogram.Add(usec);
+ return usec;
+ }
+
+ ui64 AddEventDeliveryStats(i64 sentTs, i64 deliveredTs) {
+ ui64 usecDeliv = deliveredTs > sentTs ? NHPTimer::GetSeconds(deliveredTs - sentTs) * 1000000 : 0;
+ Stats->EventDeliveryTimeHistogram.Add(usecDeliv);
+ return usecDeliv;
+ }
+
+ i64 AddEventProcessingStats(i64 deliveredTs, i64 processedTs, ui32 activityType, ui64 scheduled) {
+ i64 elapsed = processedTs - deliveredTs;
+ ui64 usecElapsed = NHPTimer::GetSeconds(elapsed) * 1000000;
+ activityType = (activityType >= Stats->MaxActivityType()) ? 0 : activityType;
+ Stats->EventProcessingCountHistogram.Add(usecElapsed);
+ Stats->EventProcessingTimeHistogram.Add(usecElapsed, elapsed);
+ RelaxedStore(&Stats->ReceivedEvents, RelaxedLoad(&Stats->ReceivedEvents) + 1);
+ RelaxedStore(&Stats->ReceivedEventsByActivity[activityType], RelaxedLoad(&Stats->ReceivedEventsByActivity[activityType]) + 1);
+ RelaxedStore(&Stats->ScheduledEventsByActivity[activityType], RelaxedLoad(&Stats->ScheduledEventsByActivity[activityType]) + scheduled);
+ AddElapsedCycles(activityType, elapsed);
+ return elapsed;
+ }
+
+ void UpdateActorsStats(size_t dyingActorsCnt) {
+ if (dyingActorsCnt) {
+ AtomicAdd(Executor->DestroyedActors, dyingActorsCnt);
+ }
+ RelaxedStore(&Stats->PoolDestroyedActors, (ui64)RelaxedLoad(&Executor->DestroyedActors));
+ RelaxedStore(&Stats->PoolActorRegistrations, (ui64)RelaxedLoad(&Executor->ActorRegistrations));
+ RelaxedStore(&Stats->PoolAllocatedMailboxes, MailboxTable->GetAllocatedMailboxCount());
+ }
+
+ void UpdateThreadTime() {
+ RelaxedStore(&WorkerStats.CpuNs, ThreadCPUTime() * 1000);
+ }
+#else
+ void GetCurrentStats(TExecutorThreadStats&) const {}
+ inline void AddElapsedCycles(ui32, i64) {}
+ inline void AddParkedCycles(i64) {}
+ inline void AddBlockedCycles(i64) {}
+ inline void IncrementSentEvents() {}
+ inline void IncrementPreemptedEvents() {}
+ inline void IncrementMailboxPushedOutBySoftPreemption() {}
+ inline void IncrementMailboxPushedOutByTime() {}
+ inline void IncrementMailboxPushedOutByEventCount() {}
+ inline void IncrementEmptyMailboxActivation() {}
+ void DecrementActorsAliveByActivity(ui32) {}
+ void IncrementNonDeliveredEvents() {}
+ double AddActivationStats(i64, i64) { return 0; }
+ ui64 AddEventDeliveryStats(i64, i64) { return 0; }
+ i64 AddEventProcessingStats(i64, i64, ui32, ui64) { return 0; }
+ void UpdateActorsStats(size_t, IExecutorPool*) {}
+ void UpdateThreadTime() {}
+#endif
+
+ void Switch(IExecutorPool* executor,
+ TMailboxTable* mailboxTable,
+ ui64 timePerMailboxTs,
+ ui32 eventsPerMailbox,
+ ui64 softDeadlineTs,
+ TExecutorThreadStats* stats)
+ {
+ Executor = executor;
+ MailboxTable = mailboxTable;
+ TimePerMailboxTs = timePerMailboxTs;
+ EventsPerMailbox = eventsPerMailbox;
+ SoftDeadlineTs = softDeadlineTs;
+ Stats = stats;
+ PoolId = Executor ? Executor->PoolId : MaxPools;
+ }
+
+ void SwitchToIdle() {
+ Executor = nullptr;
+ MailboxTable = nullptr;
+ //Stats = &WorkerStats; // TODO: in actorsystem 2.0 idle stats cannot be related to specific pool
+ PoolId = MaxPools;
+ }
+ };
+}
diff --git a/library/cpp/actors/core/ya.make b/library/cpp/actors/core/ya.make
index 880a9d00db..9cb2e2d396 100644
--- a/library/cpp/actors/core/ya.make
+++ b/library/cpp/actors/core/ya.make
@@ -30,16 +30,16 @@ SRCS(
actorsystem.h
ask.cpp
ask.h
- balancer.h
- balancer.cpp
+ balancer.h
+ balancer.cpp
buffer.cpp
buffer.h
callstack.cpp
callstack.h
- config.h
- cpu_manager.cpp
- cpu_manager.h
- cpu_state.h
+ config.h
+ cpu_manager.cpp
+ cpu_manager.h
+ cpu_state.h
defs.h
event.cpp
event.h
@@ -56,8 +56,8 @@ SRCS(
executor_pool_basic.h
executor_pool_io.cpp
executor_pool_io.h
- executor_pool_united.cpp
- executor_pool_united.h
+ executor_pool_united.cpp
+ executor_pool_united.h
executor_thread.cpp
executor_thread.h
hfunc.h
@@ -66,7 +66,7 @@ SRCS(
invoke.h
io_dispatcher.cpp
io_dispatcher.h
- lease.h
+ lease.h
log.cpp
log.h
log_settings.cpp
@@ -82,9 +82,9 @@ SRCS(
mon.h
mon_stats.h
monotonic.cpp
- monotonic.h
- worker_context.cpp
- worker_context.h
+ monotonic.h
+ worker_context.cpp
+ worker_context.h
probes.cpp
probes.h
process_stats.cpp
diff --git a/library/cpp/actors/dnscachelib/dnscache.cpp b/library/cpp/actors/dnscachelib/dnscache.cpp
index 649339ddb2..026491bcf1 100644
--- a/library/cpp/actors/dnscachelib/dnscache.cpp
+++ b/library/cpp/actors/dnscachelib/dnscache.cpp
@@ -1,5 +1,5 @@
#include "dnscache.h"
-#include "probes.h"
+#include "probes.h"
#include "timekeeper.h"
#include <contrib/libs/c-ares/ares.h>
@@ -8,8 +8,8 @@
const TDnsCache::THost TDnsCache::NullHost;
-LWTRACE_USING(DNSCACHELIB_PROVIDER);
-
+LWTRACE_USING(DNSCACHELIB_PROVIDER);
+
static_assert(sizeof(ares_channel) == sizeof(void*), "expect sizeof(ares_channel) == sizeof(void *)");
TDnsCache::TDnsCache(bool allowIpv4, bool allowIpv6, time_t lifetime, time_t neg, ui32 timeout)
@@ -33,11 +33,11 @@ TDnsCache::TDnsCache(bool allowIpv4, bool allowIpv6, time_t lifetime, time_t neg
ares_channel chan;
if (ares_init(&chan) != ARES_SUCCESS) {
- LWPROBE(AresInitFailed);
+ LWPROBE(AresInitFailed);
ythrow yexception() << "ares_init() failed";
}
Channel = chan;
- LWPROBE(Created);
+ LWPROBE(Created);
}
TDnsCache::~TDnsCache(void) {
@@ -45,7 +45,7 @@ TDnsCache::~TDnsCache(void) {
ares_cancel(chan);
ares_destroy(chan);
- LWPROBE(Destroyed);
+ LWPROBE(Destroyed);
#ifdef _win_
ares_library_cleanup();
@@ -112,7 +112,7 @@ NAddr::IRemoteAddrPtr TDnsCache::GetAddr(
}
}
- LWPROBE(FamilyMismatch, family, AllowIpV4, AllowIpV6);
+ LWPROBE(FamilyMismatch, family, AllowIpV4, AllowIpV6);
return nullptr;
}
@@ -170,7 +170,7 @@ bool TDnsCache::THost::IsStale(int family, const TDnsCache* ctx) const noexcept
const TDnsCache::THost&
TDnsCache::Resolve(const TString& hostname, int family, bool cacheOnly) {
if (!ValidateHName(hostname)) {
- LWPROBE(ResolveNullHost, hostname, family);
+ LWPROBE(ResolveNullHost, hostname, family);
return NullHost;
}
@@ -185,15 +185,15 @@ TDnsCache::Resolve(const TString& hostname, int family, bool cacheOnly) {
if (!p->second.IsStale(family, this)) {
/* Recently resolved, just return cached value */
ACacheHits += 1;
- THost& host = p->second;
- LWPROBE(ResolveFromCache, hostname, family, host.AddrsV4ToString(), host.AddrsV6ToString(), ACacheHits);
- return host;
- } else {
- LWPROBE(ResolveCacheTimeout, hostname);
+ THost& host = p->second;
+ LWPROBE(ResolveFromCache, hostname, family, host.AddrsV4ToString(), host.AddrsV6ToString(), ACacheHits);
+ return host;
+ } else {
+ LWPROBE(ResolveCacheTimeout, hostname);
}
} else {
/* Never resolved, create cache entry */
- LWPROBE(ResolveCacheNew, hostname);
+ LWPROBE(ResolveCacheNew, hostname);
p = HostCache.insert(std::make_pair(hostname, THost())).first;
}
ACacheMisses += 1;
@@ -227,7 +227,7 @@ TDnsCache::Resolve(const TString& hostname, int family, bool cacheOnly) {
WaitTask(inprogress);
- LWPROBE(ResolveDone, hostname, family, p->second.AddrsV4ToString(), p->second.AddrsV6ToString());
+ LWPROBE(ResolveDone, hostname, family, p->second.AddrsV4ToString(), p->second.AddrsV6ToString());
return p->second;
}
@@ -415,31 +415,31 @@ void TDnsCache::GHBACallback(void* arg, int status, int, struct hostent* info) {
}
AtomicSet(p->second.InProgress, 0);
}
-
+
TString TDnsCache::THost::AddrsV4ToString() const {
- TStringStream ss;
- bool first = false;
- for (TIpHost addr : AddrsV4) {
+ TStringStream ss;
+ bool first = false;
+ for (TIpHost addr : AddrsV4) {
ss << (first ? "" : " ") << IpToString(addr);
- first = false;
- }
- return ss.Str();
-}
-
+ first = false;
+ }
+ return ss.Str();
+}
+
TString TDnsCache::THost::AddrsV6ToString() const {
- TStringStream ss;
- bool first = false;
- for (in6_addr addr : AddrsV6) {
- struct sockaddr_in6 sin6;
- Zero(sin6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = addr;
-
- NAddr::TIPv6Addr addr6(sin6);
+ TStringStream ss;
+ bool first = false;
+ for (in6_addr addr : AddrsV6) {
+ struct sockaddr_in6 sin6;
+ Zero(sin6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = addr;
+
+ NAddr::TIPv6Addr addr6(sin6);
ss << (first ? "" : " ") << NAddr::PrintHost(addr6);
- first = false;
- }
- return ss.Str();
-}
+ first = false;
+ }
+ return ss.Str();
+}
TDnsCache::TAresLibInit TDnsCache::InitAresLib;
diff --git a/library/cpp/actors/dnscachelib/dnscache.h b/library/cpp/actors/dnscachelib/dnscache.h
index 3313a251a1..03eec356d2 100644
--- a/library/cpp/actors/dnscachelib/dnscache.h
+++ b/library/cpp/actors/dnscachelib/dnscache.h
@@ -65,7 +65,7 @@ private:
time_t ResolvedV6 = 0;
time_t NotFoundV6 = 0;
TAtomic InProgressV6 = 0;
-
+
TString AddrsV4ToString() const;
TString AddrsV6ToString() const;
diff --git a/library/cpp/actors/dnscachelib/probes.cpp b/library/cpp/actors/dnscachelib/probes.cpp
index 07734ab20f..441e0609f9 100644
--- a/library/cpp/actors/dnscachelib/probes.cpp
+++ b/library/cpp/actors/dnscachelib/probes.cpp
@@ -1,3 +1,3 @@
-#include "probes.h"
-
-LWTRACE_DEFINE_PROVIDER(DNSCACHELIB_PROVIDER)
+#include "probes.h"
+
+LWTRACE_DEFINE_PROVIDER(DNSCACHELIB_PROVIDER)
diff --git a/library/cpp/actors/dnscachelib/probes.h b/library/cpp/actors/dnscachelib/probes.h
index 313b7b8712..6416e997b7 100644
--- a/library/cpp/actors/dnscachelib/probes.h
+++ b/library/cpp/actors/dnscachelib/probes.h
@@ -1,7 +1,7 @@
-#pragma once
-
+#pragma once
+
#include <library/cpp/lwtrace/all.h>
-
+
#define DNSCACHELIB_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
PROBE(Created, GROUPS(), TYPES(), NAMES()) \
PROBE(Destroyed, GROUPS(), TYPES(), NAMES()) \
@@ -30,6 +30,6 @@
GROUPS(), \
TYPES(TString), \
NAMES("hostname")) \
- /**/
-
-LWTRACE_DECLARE_PROVIDER(DNSCACHELIB_PROVIDER)
+ /**/
+
+LWTRACE_DECLARE_PROVIDER(DNSCACHELIB_PROVIDER)
diff --git a/library/cpp/actors/dnscachelib/ya.make b/library/cpp/actors/dnscachelib/ya.make
index e3a6ad6202..3ee25102c1 100644
--- a/library/cpp/actors/dnscachelib/ya.make
+++ b/library/cpp/actors/dnscachelib/ya.make
@@ -11,8 +11,8 @@ OWNER(
SRCS(
dnscache.cpp
dnscache.h
- probes.cpp
- probes.h
+ probes.cpp
+ probes.h
timekeeper.h
)
diff --git a/library/cpp/actors/helpers/flow_controlled_queue.cpp b/library/cpp/actors/helpers/flow_controlled_queue.cpp
index d75cc54023..46addfa708 100644
--- a/library/cpp/actors/helpers/flow_controlled_queue.cpp
+++ b/library/cpp/actors/helpers/flow_controlled_queue.cpp
@@ -2,7 +2,7 @@
#include <library/cpp/actors/core/interconnect.h>
#include <library/cpp/actors/core/hfunc.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <util/generic/deque.h>
#include <util/datetime/cputimer.h>
@@ -29,7 +29,7 @@ public:
, Source(source)
, Cookie(cookie)
, Flags(flags)
- , StartCounter(GetCycleCountFast())
+ , StartCounter(GetCycleCountFast())
{}
STATEFN(StateWait) {
@@ -41,7 +41,7 @@ public:
}
TDuration AccumulatedLatency() const {
- const ui64 cc = GetCycleCountFast() - StartCounter;
+ const ui64 cc = GetCycleCountFast() - StartCounter;
return CyclesToDuration(cc);
}
diff --git a/library/cpp/actors/interconnect/interconnect_channel.cpp b/library/cpp/actors/interconnect/interconnect_channel.cpp
index a66ba2a154..9aee8fd5a2 100644
--- a/library/cpp/actors/interconnect/interconnect_channel.cpp
+++ b/library/cpp/actors/interconnect/interconnect_channel.cpp
@@ -3,13 +3,13 @@
#include <library/cpp/actors/core/events.h>
#include <library/cpp/actors/core/executor_thread.h>
#include <library/cpp/actors/core/log.h>
-#include <library/cpp/actors/core/probes.h>
+#include <library/cpp/actors/core/probes.h>
#include <library/cpp/actors/protos/services_common.pb.h>
#include <library/cpp/actors/prof/tag.h>
#include <library/cpp/digest/crc32c/crc32c.h>
-LWTRACE_USING(ACTORLIB_PROVIDER);
-
+LWTRACE_USING(ACTORLIB_PROVIDER);
+
namespace NActors {
DECLARE_WILSON_EVENT(EventSentToSocket);
DECLARE_WILSON_EVENT(EventReceivedFromSocket);
@@ -25,8 +25,8 @@ namespace NActors {
// WILSON_TRACE(*ctx, &traceId, EventSentToSocket);
// }
traceId.Serialize(&event.Descr.TraceId);
- LWTRACK(SerializeToPacketEnd, event.Orbit, PeerNodeId, ChannelId, OutputQueueSize, task.GetDataSize());
- task.Orbit.Take(event.Orbit);
+ LWTRACK(SerializeToPacketEnd, event.Orbit, PeerNodeId, ChannelId, OutputQueueSize, task.GetDataSize());
+ task.Orbit.Take(event.Orbit);
event.Descr.Flags = (event.Descr.Flags & ~IEventHandle::FlagForwardOnNondelivery) |
(ExtendedFormat ? IEventHandle::FlagExtendedFormat : 0);
@@ -58,7 +58,7 @@ namespace NActors {
switch (State) {
case EState::INITIAL:
event.InitChecksum();
- LWTRACK(SerializeToPacketBegin, event.Orbit, PeerNodeId, ChannelId, OutputQueueSize);
+ LWTRACK(SerializeToPacketBegin, event.Orbit, PeerNodeId, ChannelId, OutputQueueSize);
if (event.Event) {
State = EState::CHUNKER;
IEventBase *base = event.Event.Get();
diff --git a/library/cpp/actors/interconnect/interconnect_channel.h b/library/cpp/actors/interconnect/interconnect_channel.h
index e4a0ae3cda..a26cb7a92c 100644
--- a/library/cpp/actors/interconnect/interconnect_channel.h
+++ b/library/cpp/actors/interconnect/interconnect_channel.h
@@ -42,11 +42,11 @@ namespace NActors {
class TEventOutputChannel : public TInterconnectLoggingBase {
public:
- TEventOutputChannel(TEventHolderPool& pool, ui16 id, ui32 peerNodeId, ui32 maxSerializedEventSize,
+ TEventOutputChannel(TEventHolderPool& pool, ui16 id, ui32 peerNodeId, ui32 maxSerializedEventSize,
std::shared_ptr<IInterconnectMetrics> metrics, TSessionParams params)
- : TInterconnectLoggingBase(Sprintf("OutputChannel %" PRIu16 " [node %" PRIu32 "]", id, peerNodeId))
+ : TInterconnectLoggingBase(Sprintf("OutputChannel %" PRIu16 " [node %" PRIu32 "]", id, peerNodeId))
, Pool(pool)
- , PeerNodeId(peerNodeId)
+ , PeerNodeId(peerNodeId)
, ChannelId(id)
, Metrics(std::move(metrics))
, Params(std::move(params))
@@ -56,11 +56,11 @@ namespace NActors {
~TEventOutputChannel() {
}
- std::pair<ui32, TEventHolder*> Push(IEventHandle& ev) {
+ std::pair<ui32, TEventHolder*> Push(IEventHandle& ev) {
TEventHolder& event = Pool.Allocate(Queue);
const ui32 bytes = event.Fill(ev) + sizeof(TEventDescr);
OutputQueueSize += bytes;
- return std::make_pair(bytes, &event);
+ return std::make_pair(bytes, &event);
}
void DropConfirmed(ui64 confirm);
@@ -86,7 +86,7 @@ namespace NActors {
void NotifyUndelivered();
TEventHolderPool& Pool;
- const ui32 PeerNodeId;
+ const ui32 PeerNodeId;
const ui16 ChannelId;
std::shared_ptr<IInterconnectMetrics> Metrics;
const TSessionParams Params;
diff --git a/library/cpp/actors/interconnect/interconnect_common.h b/library/cpp/actors/interconnect/interconnect_common.h
index 285709a00c..104573daaa 100644
--- a/library/cpp/actors/interconnect/interconnect_common.h
+++ b/library/cpp/actors/interconnect/interconnect_common.h
@@ -2,7 +2,7 @@
#include <library/cpp/actors/core/actorid.h>
#include <library/cpp/actors/core/actorsystem.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <library/cpp/monlib/dynamic_counters/counters.h>
#include <library/cpp/monlib/metrics/metric_registry.h>
#include <util/generic/map.h>
@@ -82,7 +82,7 @@ namespace NActors {
TAtomicBase MaxDestructorQueueSize = 1024 * 1024 * 1024;
TString ClusterUUID;
TVector<TString> AcceptUUID;
- ui64 StartTime = GetCycleCountFast();
+ ui64 StartTime = GetCycleCountFast();
TString TechnicalSelfHostName;
TInitWhiteboardCallback InitWhiteboard;
TUpdateWhiteboardCallback UpdateWhiteboard;
diff --git a/library/cpp/actors/interconnect/interconnect_tcp_input_session.cpp b/library/cpp/actors/interconnect/interconnect_tcp_input_session.cpp
index 0abe9fe659..e445c42f70 100644
--- a/library/cpp/actors/interconnect/interconnect_tcp_input_session.cpp
+++ b/library/cpp/actors/interconnect/interconnect_tcp_input_session.cpp
@@ -1,7 +1,7 @@
#include "interconnect_tcp_session.h"
#include "interconnect_tcp_proxy.h"
#include <library/cpp/actors/core/probes.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
namespace NActors {
LWTRACE_USING(ACTORLIB_PROVIDER);
@@ -195,7 +195,7 @@ namespace NActors {
ConfirmedByInput = HeaderConfirm;
if (AtomicGet(Context->ControlPacketId) <= HeaderConfirm && !NewPingProtocol) {
ui64 sendTime = AtomicGet(Context->ControlPacketSendTimer);
- TDuration duration = CyclesToDuration(GetCycleCountFast() - sendTime);
+ TDuration duration = CyclesToDuration(GetCycleCountFast() - sendTime);
const auto durationUs = duration.MicroSeconds();
Metrics->UpdateLegacyPingTimeHist(durationUs);
PingQ.push_back(duration);
@@ -217,7 +217,7 @@ namespace NActors {
Send(SessionId, new TEvProcessPingRequest(HeaderSerial & ~TTcpPacketBuf::PingRequestMask));
} else if (HeaderSerial & TTcpPacketBuf::PingResponseMask) {
const ui64 sent = HeaderSerial & ~TTcpPacketBuf::PingResponseMask;
- const ui64 received = GetCycleCountFast();
+ const ui64 received = GetCycleCountFast();
HandlePingResponse(CyclesToDuration(received - sent));
} else if (HeaderSerial & TTcpPacketBuf::ClockMask) {
HandleClock(TInstant::MicroSeconds(HeaderSerial & ~TTcpPacketBuf::ClockMask));
diff --git a/library/cpp/actors/interconnect/interconnect_tcp_session.cpp b/library/cpp/actors/interconnect/interconnect_tcp_session.cpp
index 2ded7f9f53..8da77bcd1d 100644
--- a/library/cpp/actors/interconnect/interconnect_tcp_session.cpp
+++ b/library/cpp/actors/interconnect/interconnect_tcp_session.cpp
@@ -5,7 +5,7 @@
#include <library/cpp/actors/core/probes.h>
#include <library/cpp/actors/core/log.h>
#include <library/cpp/actors/core/interconnect.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <library/cpp/actors/protos/services_common.pb.h>
#include <library/cpp/monlib/service/pages/templates.h>
@@ -128,20 +128,20 @@ namespace NActors {
auto& oChannel = ChannelScheduler->GetOutputChannel(evChannel);
const bool wasWorking = oChannel.IsWorking();
- const auto [dataSize, event] = oChannel.Push(*ev);
- LWTRACK(ForwardEvent, event->Orbit, Proxy->PeerNodeId, event->Descr.Type, event->Descr.Flags, LWACTORID(event->Descr.Recipient), LWACTORID(event->Descr.Sender), event->Descr.Cookie, event->EventSerializedSize);
-
- TotalOutputQueueSize += dataSize;
+ const auto [dataSize, event] = oChannel.Push(*ev);
+ LWTRACK(ForwardEvent, event->Orbit, Proxy->PeerNodeId, event->Descr.Type, event->Descr.Flags, LWACTORID(event->Descr.Recipient), LWACTORID(event->Descr.Sender), event->Descr.Cookie, event->EventSerializedSize);
+
+ TotalOutputQueueSize += dataSize;
Proxy->Metrics->AddOutputBuffersTotalSize(dataSize);
- if (!wasWorking) {
- // this channel has returned to work -- it was empty and this we have just put first event in the queue
- ChannelScheduler->AddToHeap(oChannel, EqualizeCounter);
+ if (!wasWorking) {
+ // this channel has returned to work -- it was empty and this we have just put first event in the queue
+ ChannelScheduler->AddToHeap(oChannel, EqualizeCounter);
}
SetOutputStuckFlag(true);
++NumEventsInReadyChannels;
- LWTRACK(EnqueueEvent, event->Orbit, Proxy->PeerNodeId, NumEventsInReadyChannels, GetWriteBlockedTotal(), evChannel, oChannel.GetQueueSize(), oChannel.GetBufferedAmountOfData());
+ LWTRACK(EnqueueEvent, event->Orbit, Proxy->PeerNodeId, NumEventsInReadyChannels, GetWriteBlockedTotal(), evChannel, oChannel.GetQueueSize(), oChannel.GetBufferedAmountOfData());
WILSON_TRACE(*TlsActivationContext, &ev->TraceId, OutputQueuePush,
QueueSizeInEvents = oChannel.GetQueueSize(),
QueueSizeInBytes = oChannel.GetBufferedAmountOfData());
@@ -179,7 +179,7 @@ namespace NActors {
} else {
TActivationContext::Send(ev);
}
- LWPROBE(StartBatching, Proxy->PeerNodeId, batchPeriod.MillisecondsFloat());
+ LWPROBE(StartBatching, Proxy->PeerNodeId, batchPeriod.MillisecondsFloat());
LOG_DEBUG_IC_SESSION("ICS17", "batching started");
}
}
@@ -315,7 +315,7 @@ namespace NActors {
// update ping time
Ping = msg.Ping;
- LWPROBE(UpdateFromInputSession, Proxy->PeerNodeId, Ping.MillisecondsFloat());
+ LWPROBE(UpdateFromInputSession, Proxy->PeerNodeId, Ping.MillisecondsFloat());
bool needConfirm = false;
@@ -342,7 +342,7 @@ namespace NActors {
// generate more traffic if we have unblocked state now
if (unblockedSomething) {
- LWPROBE(UnblockByDropConfirmed, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - ev->SendTime) * 1000.0);
+ LWPROBE(UnblockByDropConfirmed, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - ev->SendTime) * 1000.0);
GenerateTraffic();
}
@@ -380,7 +380,7 @@ namespace NActors {
void TInterconnectSessionTCP::HandleRam(TEvRam::TPtr& ev) {
if (ev->Get() == RamInQueue) {
- LWPROBE(FinishRam, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - ev->SendTime) * 1000.0);
+ LWPROBE(FinishRam, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - ev->SendTime) * 1000.0);
RamInQueue = nullptr;
GenerateTraffic();
}
@@ -391,7 +391,7 @@ namespace NActors {
IssuePingRequest();
if (RamInQueue && !RamInQueue->Batching) {
- LWPROBE(SkipGenerateTraffic, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - RamStartedCycles) * 1000.0);
+ LWPROBE(SkipGenerateTraffic, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - RamStartedCycles) * 1000.0);
return; // we'll do it a bit later
} else {
RamInQueue = nullptr;
@@ -399,51 +399,51 @@ namespace NActors {
LOG_DEBUG_IC_SESSION("ICS19", "GenerateTraffic");
- // There is a tradeoff between fairness and efficiency.
- // The less traffic is generated here, the less buffering is after fair scheduler,
- // the more fair system is, the less latency is present.
- // The more traffic is generated here, the less syscalls and actor-system overhead occurs,
- // the less cpu is consumed.
- static const ui64 generateLimit = 64 * 1024;
-
+ // There is a tradeoff between fairness and efficiency.
+ // The less traffic is generated here, the less buffering is after fair scheduler,
+ // the more fair system is, the less latency is present.
+ // The more traffic is generated here, the less syscalls and actor-system overhead occurs,
+ // the less cpu is consumed.
+ static const ui64 generateLimit = 64 * 1024;
+
const ui64 sizeBefore = TotalOutputQueueSize;
- ui32 generatedPackets = 0;
- ui64 generatedBytes = 0;
- ui64 generateStarted = GetCycleCountFast();
+ ui32 generatedPackets = 0;
+ ui64 generatedBytes = 0;
+ ui64 generateStarted = GetCycleCountFast();
// apply traffic changes
auto accountTraffic = [&] { ChannelScheduler->ForEach([](TEventOutputChannel& channel) { channel.AccountTraffic(); }); };
- // first, we create as many data packets as we can generate under certain conditions; they include presence
- // of events in channels queues and in flight fitting into requested limit; after we hit one of these conditions
- // we exit cycle
- while (Socket && NumEventsInReadyChannels && InflightDataAmount < GetTotalInflightAmountOfData() && !ReceiveContext->WriteBlockedByFullSendBuffer) {
- if (generatedBytes >= generateLimit) {
- // resume later but ensure that we have issued at least one packet
+ // first, we create as many data packets as we can generate under certain conditions; they include presence
+ // of events in channels queues and in flight fitting into requested limit; after we hit one of these conditions
+ // we exit cycle
+ while (Socket && NumEventsInReadyChannels && InflightDataAmount < GetTotalInflightAmountOfData() && !ReceiveContext->WriteBlockedByFullSendBuffer) {
+ if (generatedBytes >= generateLimit) {
+ // resume later but ensure that we have issued at least one packet
RamInQueue = new TEvRam(false);
Send(SelfId(), RamInQueue);
- RamStartedCycles = GetCycleCountFast();
- LWPROBE(StartRam, Proxy->PeerNodeId);
- break;
+ RamStartedCycles = GetCycleCountFast();
+ LWPROBE(StartRam, Proxy->PeerNodeId);
+ break;
}
- try {
- generatedBytes += MakePacket(true);
- ++generatedPackets;
- } catch (const TExSerializedEventTooLarge& ex) {
- // terminate session if the event can't be serialized properly
- accountTraffic();
- LOG_CRIT_IC("ICS31", "serialized event Type# 0x%08" PRIx32 " is too large", ex.Type);
- return Terminate(TDisconnectReason::EventTooLarge());
+ try {
+ generatedBytes += MakePacket(true);
+ ++generatedPackets;
+ } catch (const TExSerializedEventTooLarge& ex) {
+ // terminate session if the event can't be serialized properly
+ accountTraffic();
+ LOG_CRIT_IC("ICS31", "serialized event Type# 0x%08" PRIx32 " is too large", ex.Type);
+ return Terminate(TDisconnectReason::EventTooLarge());
}
}
- if (Socket) {
- WriteData();
- }
-
- LWPROBE(GenerateTraffic, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - generateStarted) * 1000.0, sizeBefore - TotalOutputQueueSize, generatedPackets, generatedBytes);
-
+ if (Socket) {
+ WriteData();
+ }
+
+ LWPROBE(GenerateTraffic, Proxy->PeerNodeId, NHPTimer::GetSeconds(GetCycleCountFast() - generateStarted) * 1000.0, sizeBefore - TotalOutputQueueSize, generatedPackets, generatedBytes);
+
accountTraffic();
EqualizeCounter += ChannelScheduler->Equalize();
}
@@ -520,10 +520,10 @@ namespace NActors {
ReceiveContext->WriteBlockedByFullSendBuffer ? "true" : "false");
if (std::exchange(ReceiveContext->WriteBlockedByFullSendBuffer, false)) {
Proxy->Metrics->IncUsefulWriteWakeups();
- ui64 nowCycles = GetCycleCountFast();
- double blockedUs = NHPTimer::GetSeconds(nowCycles - WriteBlockedCycles) * 1000000.0;
- LWPROBE(ReadyWrite, Proxy->PeerNodeId, NHPTimer::GetSeconds(nowCycles - ev->SendTime) * 1000.0, blockedUs / 1000.0);
- WriteBlockedTotal += TDuration::MicroSeconds(blockedUs);
+ ui64 nowCycles = GetCycleCountFast();
+ double blockedUs = NHPTimer::GetSeconds(nowCycles - WriteBlockedCycles) * 1000000.0;
+ LWPROBE(ReadyWrite, Proxy->PeerNodeId, NHPTimer::GetSeconds(nowCycles - ev->SendTime) * 1000.0, blockedUs / 1000.0);
+ WriteBlockedTotal += TDuration::MicroSeconds(blockedUs);
GenerateTraffic();
} else if (!ev->Cookie) {
Proxy->Metrics->IncSpuriousWriteWakeups();
@@ -602,7 +602,7 @@ namespace NActors {
Y_VERIFY(static_cast<size_t>(r) <= BytesUnwritten);
BytesUnwritten -= r;
written += r;
- ui64 packets = 0;
+ ui64 packets = 0;
// advance SendQueuePos to eat all processed items
for (size_t amount = r; amount && SendQueuePos->DropBufs(amount); ++SendQueuePos) {
@@ -610,11 +610,11 @@ namespace NActors {
LastSentSerial = Max(LastSentSerial, SendQueuePos->GetSerial());
}
++PacketsWrittenToSocket;
- ++packets;
- LWTRACK(PacketWrittenToSocket, SendQueuePos->Orbit, Proxy->PeerNodeId, PacketsWrittenToSocket, SendQueuePos->TriedWriting, SendQueuePos->GetDataSize(), BytesUnwritten, GetWriteBlockedTotal(), (SOCKET)*Socket);
+ ++packets;
+ LWTRACK(PacketWrittenToSocket, SendQueuePos->Orbit, Proxy->PeerNodeId, PacketsWrittenToSocket, SendQueuePos->TriedWriting, SendQueuePos->GetDataSize(), BytesUnwritten, GetWriteBlockedTotal(), (SOCKET)*Socket);
}
-
- LWPROBE(WriteToSocket, Proxy->PeerNodeId, r, packets, PacketsWrittenToSocket, BytesUnwritten, GetWriteBlockedTotal(), (SOCKET)*Socket);
+
+ LWPROBE(WriteToSocket, Proxy->PeerNodeId, r, packets, PacketsWrittenToSocket, BytesUnwritten, GetWriteBlockedTotal(), (SOCKET)*Socket);
} else if (-r != EAGAIN && -r != EWOULDBLOCK) {
const TString message = r == 0 ? "connection closed by peer"
: err ? err
@@ -635,8 +635,8 @@ namespace NActors {
// TEvPollerReadyWrite event from poller; set up flag meaning this and wait for that event
Y_VERIFY(!ReceiveContext->WriteBlockedByFullSendBuffer);
ReceiveContext->WriteBlockedByFullSendBuffer = true;
- WriteBlockedCycles = GetCycleCountFast();
- LWPROBE(BlockedWrite, Proxy->PeerNodeId, SendQueue.size(), written);
+ WriteBlockedCycles = GetCycleCountFast();
+ LWPROBE(BlockedWrite, Proxy->PeerNodeId, SendQueue.size(), written);
LOG_DEBUG_IC_SESSION("ICS18", "hit send buffer limit");
if (PollerToken) {
@@ -718,7 +718,7 @@ namespace NActors {
}
}
- ui64 TInterconnectSessionTCP::MakePacket(bool data, TMaybe<ui64> pingMask) {
+ ui64 TInterconnectSessionTCP::MakePacket(bool data, TMaybe<ui64> pingMask) {
Y_VERIFY(Socket);
TSendQueue::iterator packet;
@@ -759,7 +759,7 @@ namespace NActors {
}
if (AtomicGet(ReceiveContext->ControlPacketId) == 0) {
- AtomicSet(ReceiveContext->ControlPacketSendTimer, GetCycleCountFast());
+ AtomicSet(ReceiveContext->ControlPacketSendTimer, GetCycleCountFast());
AtomicSet(ReceiveContext->ControlPacketId, OutputCounter);
}
@@ -788,8 +788,8 @@ namespace NActors {
packet->Sign();
// count number of bytes pending for write
- ui64 packetSize = (Params.UseModernFrame ? sizeof(TTcpPacketHeader_v2) : sizeof(TTcpPacketHeader_v1)) + packet->GetDataSize();
- BytesUnwritten += packetSize;
+ ui64 packetSize = (Params.UseModernFrame ? sizeof(TTcpPacketHeader_v2) : sizeof(TTcpPacketHeader_v1)) + packet->GetDataSize();
+ BytesUnwritten += packetSize;
LOG_DEBUG_IC_SESSION("ICS22", "outgoing packet Serial# %" PRIu64 " Confirm# %" PRIu64 " DataSize# %zu"
" InflightDataAmount# %" PRIu64 " BytesUnwritten# %" PRIu64, serial, lastInputSerial, packet->GetDataSize(),
@@ -799,13 +799,13 @@ namespace NActors {
ResetFlushLogic();
++PacketsGenerated;
- LWTRACK(PacketGenerated, packet->Orbit, Proxy->PeerNodeId, BytesUnwritten, InflightDataAmount, PacketsGenerated, packetSize);
+ LWTRACK(PacketGenerated, packet->Orbit, Proxy->PeerNodeId, BytesUnwritten, InflightDataAmount, PacketsGenerated, packetSize);
if (!data) {
WriteData();
}
-
- return packetSize;
+
+ return packetSize;
}
bool TInterconnectSessionTCP::DropConfirmed(ui64 confirm) {
@@ -836,14 +836,14 @@ namespace NActors {
channel.DropConfirmed(lastDroppedSerial);
});
- const ui64 current = InflightDataAmount;
- const ui64 limit = GetTotalInflightAmountOfData();
- const bool unblockedSomething = current >= limit && current < limit + droppedDataAmount;
+ const ui64 current = InflightDataAmount;
+ const ui64 limit = GetTotalInflightAmountOfData();
+ const bool unblockedSomething = current >= limit && current < limit + droppedDataAmount;
PacketsConfirmed += numDropped;
InflightDataAmount -= droppedDataAmount;
Proxy->Metrics->SubInflightDataAmount(droppedDataAmount);
- LWPROBE(DropConfirmed, Proxy->PeerNodeId, droppedDataAmount, InflightDataAmount);
+ LWPROBE(DropConfirmed, Proxy->PeerNodeId, droppedDataAmount, InflightDataAmount);
LOG_DEBUG_IC_SESSION("ICS24", "exit InflightDataAmount: %" PRIu64 " bytes droppedDataAmount: %" PRIu64 " bytes"
" dropped %" PRIu32 " packets", InflightDataAmount, droppedDataAmount, numDropped);
@@ -896,7 +896,7 @@ namespace NActors {
}
}
- LWTRACK(FillSendingBuffer, task.Orbit, Proxy->PeerNodeId, bytesGenerated, NumEventsInReadyChannels, WriteBlockedTotal);
+ LWTRACK(FillSendingBuffer, task.Orbit, Proxy->PeerNodeId, bytesGenerated, NumEventsInReadyChannels, WriteBlockedTotal);
Y_VERIFY(bytesGenerated); // ensure we are not stalled in serialization
}
@@ -967,15 +967,15 @@ namespace NActors {
auto& lastpair = OutputQueueUtilization.Last();
if (state)
- lastpair.first -= GetCycleCountFast();
+ lastpair.first -= GetCycleCountFast();
else
- lastpair.first += GetCycleCountFast();
+ lastpair.first += GetCycleCountFast();
OutputStuckFlag = state;
}
void TInterconnectSessionTCP::SwitchStuckPeriod() {
- auto now = GetCycleCountFast();
+ auto now = GetCycleCountFast();
if (OutputQueueUtilization.Size() != 0) {
auto& lastpair = OutputQueueUtilization.Last();
lastpair.second = now - lastpair.second;
@@ -1005,7 +1005,7 @@ namespace NActors {
}
ui64 TInterconnectSessionTCP::GetMaxCyclesPerEvent() const {
- return DurationToCycles(TDuration::MicroSeconds(50));
+ return DurationToCycles(TDuration::MicroSeconds(50));
}
void TInterconnectSessionTCP::IssuePingRequest() {
@@ -1013,7 +1013,7 @@ namespace NActors {
if (now >= LastPingTimestamp + PingPeriodicity) {
LOG_DEBUG_IC_SESSION("ICS22", "Issuing ping request");
if (Socket) {
- MakePacket(false, GetCycleCountFast() | TTcpPacketBuf::PingRequestMask);
+ MakePacket(false, GetCycleCountFast() | TTcpPacketBuf::PingRequestMask);
}
if (Socket) {
MakePacket(false, TInstant::Now().MicroSeconds() | TTcpPacketBuf::ClockMask);
diff --git a/library/cpp/actors/interconnect/interconnect_tcp_session.h b/library/cpp/actors/interconnect/interconnect_tcp_session.h
index 7fc00dbcc5..e347d9b799 100644
--- a/library/cpp/actors/interconnect/interconnect_tcp_session.h
+++ b/library/cpp/actors/interconnect/interconnect_tcp_session.h
@@ -6,7 +6,7 @@
#include <library/cpp/actors/core/log.h>
#include <library/cpp/actors/helpers/mon_histogram_helper.h>
#include <library/cpp/actors/protos/services_common.pb.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <library/cpp/actors/util/rope.h>
#include <library/cpp/actors/util/funnel_queue.h>
#include <library/cpp/actors/util/recentwnd.h>
@@ -38,12 +38,12 @@ namespace NActors {
public:
TSlowPathChecker(TTraceCallback&& callback)
: Callback(std::move(callback))
- , Start(GetCycleCountFast())
+ , Start(GetCycleCountFast())
{
}
~TSlowPathChecker() {
- const NHPTimer::STime end = GetCycleCountFast();
+ const NHPTimer::STime end = GetCycleCountFast();
const NHPTimer::STime elapsed = end - Start;
if (elapsed > 1000000) {
Callback(NHPTimer::GetSeconds(elapsed) * 1000);
@@ -63,7 +63,7 @@ namespace NActors {
class TTimeLimit {
public:
TTimeLimit(ui64 limitInCycles)
- : UpperLimit(limitInCycles == 0 ? 0 : GetCycleCountFast() + limitInCycles)
+ : UpperLimit(limitInCycles == 0 ? 0 : GetCycleCountFast() + limitInCycles)
{
}
@@ -73,7 +73,7 @@ namespace NActors {
}
bool CheckExceeded() {
- return UpperLimit != 0 && GetCycleCountFast() > UpperLimit;
+ return UpperLimit != 0 && GetCycleCountFast() > UpperLimit;
}
const ui64 UpperLimit;
@@ -125,7 +125,7 @@ namespace NActors {
std::unordered_map<ui16, TRope> ChannelMap;
TReceiveContext() {
- GetTimeFast(&StartTime);
+ GetTimeFast(&StartTime);
}
// returns false if sessions needs to be terminated and packet not to be processed
@@ -378,7 +378,7 @@ namespace NActors {
void SetNewConnection(TEvHandshakeDone::TPtr& ev);
TEvRam* RamInQueue = nullptr;
- ui64 RamStartedCycles = 0;
+ ui64 RamStartedCycles = 0;
void HandleRam(TEvRam::TPtr& ev);
void GenerateTraffic();
@@ -389,7 +389,7 @@ namespace NActors {
void Handle(TEvPollerRegisterResult::TPtr ev);
void WriteData();
- ui64 MakePacket(bool data, TMaybe<ui64> pingMask = {});
+ ui64 MakePacket(bool data, TMaybe<ui64> pingMask = {});
void FillSendingBuffer(TTcpPacketOutTask& packet, ui64 serial);
bool DropConfirmed(ui64 confirm);
void ShutdownSocket(TDisconnectReason reason);
@@ -452,21 +452,21 @@ namespace NActors {
TSendQueue SendQueue;
TSendQueue SendQueueCache;
TSendQueue::iterator SendQueuePos;
- ui64 WriteBlockedCycles = 0; // start of current block period
- TDuration WriteBlockedTotal; // total incremental duration that session has been blocked
+ ui64 WriteBlockedCycles = 0; // start of current block period
+ TDuration WriteBlockedTotal; // total incremental duration that session has been blocked
ui64 BytesUnwritten = 0;
void TrimSendQueueCache();
- TDuration GetWriteBlockedTotal() const {
+ TDuration GetWriteBlockedTotal() const {
if (ReceiveContext->WriteBlockedByFullSendBuffer) {
- double blockedUs = NHPTimer::GetSeconds(GetCycleCountFast() - WriteBlockedCycles) * 1000000.0;
- return WriteBlockedTotal + TDuration::MicroSeconds(blockedUs); // append current blocking period if any
- } else {
- return WriteBlockedTotal;
- }
- }
-
+ double blockedUs = NHPTimer::GetSeconds(GetCycleCountFast() - WriteBlockedCycles) * 1000000.0;
+ return WriteBlockedTotal + TDuration::MicroSeconds(blockedUs); // append current blocking period if any
+ } else {
+ return WriteBlockedTotal;
+ }
+ }
+
ui64 OutputCounter;
ui64 LastSentSerial = 0;
diff --git a/library/cpp/actors/interconnect/packet.cpp b/library/cpp/actors/interconnect/packet.cpp
index e2c289ed59..55c9679414 100644
--- a/library/cpp/actors/interconnect/packet.cpp
+++ b/library/cpp/actors/interconnect/packet.cpp
@@ -1,11 +1,11 @@
#include "packet.h"
-#include <library/cpp/actors/core/probes.h>
-
+#include <library/cpp/actors/core/probes.h>
+
#include <util/system/datetime.h>
-LWTRACE_USING(ACTORLIB_PROVIDER);
-
+LWTRACE_USING(ACTORLIB_PROVIDER);
+
ui32 TEventHolder::Fill(IEventHandle& ev) {
Serial = 0;
Descr.Type = ev.Type;
@@ -27,6 +27,6 @@ ui32 TEventHolder::Fill(IEventHandle& ev) {
} else {
EventSerializedSize = 0;
}
-
+
return EventSerializedSize;
}
diff --git a/library/cpp/actors/interconnect/packet.h b/library/cpp/actors/interconnect/packet.h
index 4ba50a2b5f..f062633b0b 100644
--- a/library/cpp/actors/interconnect/packet.h
+++ b/library/cpp/actors/interconnect/packet.h
@@ -8,7 +8,7 @@
#include <library/cpp/actors/util/rope.h>
#include <library/cpp/actors/prof/tag.h>
#include <library/cpp/digest/crc32c/crc32c.h>
-#include <library/cpp/lwtrace/shuttle.h>
+#include <library/cpp/lwtrace/shuttle.h>
#include <util/generic/string.h>
#include <util/generic/list.h>
@@ -108,7 +108,7 @@ struct TEventHolder : TNonCopyable {
ui64 Serial;
ui32 EventSerializedSize;
ui32 EventActuallySerialized;
- mutable NLWTrace::TOrbit Orbit;
+ mutable NLWTrace::TOrbit Orbit;
ui32 Fill(IEventHandle& ev);
@@ -136,7 +136,7 @@ struct TEventHolder : TNonCopyable {
void Clear() {
Event.Reset();
Buffer.Reset();
- Orbit.Reset();
+ Orbit.Reset();
}
};
@@ -154,7 +154,7 @@ struct TTcpPacketOutTask : TNonCopyable {
bool TriedWriting;
char *FreeArea;
char *End;
- mutable NLWTrace::TOrbit Orbit;
+ mutable NLWTrace::TOrbit Orbit;
public:
TTcpPacketOutTask(const TSessionParams& params)
@@ -189,7 +189,7 @@ public:
TriedWriting = false;
FreeArea = Params.UseModernFrame ? Packet.v2.Data : Packet.v1.Data;
End = FreeArea + TTcpPacketBuf::PacketDataLen;
- Orbit.Reset();
+ Orbit.Reset();
}
bool IsEmpty() const {
diff --git a/library/cpp/actors/interconnect/poller_actor.cpp b/library/cpp/actors/interconnect/poller_actor.cpp
index e75cbcaef4..ef363b208e 100644
--- a/library/cpp/actors/interconnect/poller_actor.cpp
+++ b/library/cpp/actors/interconnect/poller_actor.cpp
@@ -5,7 +5,7 @@
#include <library/cpp/actors/core/actorsystem.h>
#include <library/cpp/actors/core/hfunc.h>
#include <library/cpp/actors/core/log.h>
-#include <library/cpp/actors/core/probes.h>
+#include <library/cpp/actors/core/probes.h>
#include <library/cpp/actors/protos/services_common.pb.h>
#include <library/cpp/actors/util/funnel_queue.h>
@@ -17,9 +17,9 @@
#include <variant>
namespace NActors {
-
- LWTRACE_USING(ACTORLIB_PROVIDER);
-
+
+ LWTRACE_USING(ACTORLIB_PROVIDER);
+
namespace {
int LastSocketError() {
#if defined(_win_)
diff --git a/library/cpp/actors/interconnect/profiler.h b/library/cpp/actors/interconnect/profiler.h
index 77a59e3179..d9192e1559 100644
--- a/library/cpp/actors/interconnect/profiler.h
+++ b/library/cpp/actors/interconnect/profiler.h
@@ -1,7 +1,7 @@
#pragma once
-#include <library/cpp/actors/util/datetime.h>
-
+#include <library/cpp/actors/util/datetime.h>
+
namespace NActors {
class TProfiled {
@@ -14,7 +14,7 @@ namespace NActors {
EType Type; // entry kind
int Line;
const char *Marker; // name of the profiled function/part
- ui64 Timestamp; // cycles
+ ui64 Timestamp; // cycles
};
bool Enable = false;
@@ -44,7 +44,7 @@ namespace NActors {
type,
line,
marker,
- GetCycleCountFast()
+ GetCycleCountFast()
});
}
}
diff --git a/library/cpp/actors/memory_log/memlog.cpp b/library/cpp/actors/memory_log/memlog.cpp
index 8e6b46727d..a7ffa24623 100644
--- a/library/cpp/actors/memory_log/memlog.cpp
+++ b/library/cpp/actors/memory_log/memlog.cpp
@@ -1,7 +1,7 @@
#include "memlog.h"
-#include <library/cpp/actors/util/datetime.h>
-
+#include <library/cpp/actors/util/datetime.h>
+
#include <util/system/info.h>
#include <util/system/atomic.h>
#include <util/system/align.h>
@@ -270,7 +270,7 @@ bool MemLogWrite(const char* begin, size_t msgSize, bool addLF) noexcept {
Y_VERIFY(AlignDown(&prolog, TMemoryLog::MemcpyAlignment) == &prolog);
int snprintfResult = snprintf(prolog, prologSize + 1,
- "TS %020" PRIu64 " TI %020" PRIu64 " ", GetCycleCountFast(), threadId);
+ "TS %020" PRIu64 " TI %020" PRIu64 " ", GetCycleCountFast(), threadId);
if (snprintfResult < 0) {
return false;
@@ -341,7 +341,7 @@ bool MemLogVPrintF(const char* format, va_list params) noexcept {
int prologSize = snprintf(buf,
TMemoryLog::MAX_MESSAGE_SIZE - 2,
"TS %020" PRIu64 " TI %020" PRIu64 " ",
- GetCycleCountFast(),
+ GetCycleCountFast(),
threadId);
if (Y_UNLIKELY(prologSize < 0)) {
diff --git a/library/cpp/actors/testlib/test_runtime.cpp b/library/cpp/actors/testlib/test_runtime.cpp
index 6fa25b9965..008e25b416 100644
--- a/library/cpp/actors/testlib/test_runtime.cpp
+++ b/library/cpp/actors/testlib/test_runtime.cpp
@@ -6,7 +6,7 @@
#include <library/cpp/actors/core/executor_pool_io.h>
#include <library/cpp/actors/core/log.h>
#include <library/cpp/actors/core/scheduler_basic.h>
-#include <library/cpp/actors/util/datetime.h>
+#include <library/cpp/actors/util/datetime.h>
#include <library/cpp/actors/protos/services_common.pb.h>
#include <library/cpp/random_provider/random_provider.h>
#include <library/cpp/actors/interconnect/interconnect.h>
@@ -248,7 +248,7 @@ namespace NActors {
Node->ActorSystemMonotonic = currentMonotonic;
}
- void PrepareSchedules(NSchedulerQueue::TReader **readers, ui32 scheduleReadersCount) override {
+ void PrepareSchedules(NSchedulerQueue::TReader **readers, ui32 scheduleReadersCount) override {
Y_UNUSED(readers);
Y_UNUSED(scheduleReadersCount);
}
@@ -282,33 +282,33 @@ namespace NActors {
}
// for threads
- ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override {
- Y_UNUSED(wctx);
+ ui32 GetReadyActivation(TWorkerContext& wctx, ui64 revolvingCounter) override {
+ Y_UNUSED(wctx);
Y_UNUSED(revolvingCounter);
Y_FAIL();
}
- void ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingCounter) override {
- Y_UNUSED(workerId);
+ void ReclaimMailbox(TMailboxType::EType mailboxType, ui32 hint, TWorkerId workerId, ui64 revolvingCounter) override {
+ Y_UNUSED(workerId);
Node->MailboxTable->ReclaimMailbox(mailboxType, hint, revolvingCounter);
}
- void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) override {
- DoSchedule(deadline, ev, cookie, workerId);
+ void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) override {
+ DoSchedule(deadline, ev, cookie, workerId);
}
- void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) override {
- DoSchedule(TInstant::FromValue(deadline.GetValue()), ev, cookie, workerId);
+ void Schedule(TMonotonic deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) override {
+ DoSchedule(TInstant::FromValue(deadline.GetValue()), ev, cookie, workerId);
}
- void Schedule(TDuration delay, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) override {
+ void Schedule(TDuration delay, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) override {
TInstant deadline = Runtime->GetTimeProvider()->Now() + delay;
- DoSchedule(deadline, ev, cookie, workerId);
+ DoSchedule(deadline, ev, cookie, workerId);
}
- void DoSchedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) {
- Y_UNUSED(workerId);
-
+ void DoSchedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie *cookie, TWorkerId workerId) {
+ Y_UNUSED(workerId);
+
TGuard<TMutex> guard(Runtime->Mutex);
bool verbose = (Runtime->CurrentDispatchContext ? !Runtime->CurrentDispatchContext->Options->Quiet : true) && VERBOSE;
if (Runtime->BlockedOutput.find(ev->Sender) != Runtime->BlockedOutput.end()) {
@@ -372,7 +372,7 @@ namespace NActors {
TMailboxHeader* mailbox = node->MailboxTable->Get(mailboxHint);
IActor* recipientActor = mailbox->FindActor(ev->GetRecipientRewrite().LocalId());
if (recipientActor) {
- TActorContext ctx(*mailbox, *node->ExecutorThread, GetCycleCountFast(), ev->GetRecipientRewrite());
+ TActorContext ctx(*mailbox, *node->ExecutorThread, GetCycleCountFast(), ev->GetRecipientRewrite());
TActivationContext *prevTlsActivationContext = TlsActivationContext;
TlsActivationContext = &ctx;
recipientActor->Receive(ev, ctx);
@@ -412,7 +412,7 @@ namespace NActors {
}
// lifecycle stuff
- void Prepare(TActorSystem *actorSystem, NSchedulerQueue::TReader **scheduleReaders, ui32 *scheduleSz) override {
+ void Prepare(TActorSystem *actorSystem, NSchedulerQueue::TReader **scheduleReaders, ui32 *scheduleSz) override {
Y_UNUSED(actorSystem);
Y_UNUSED(scheduleReaders);
Y_UNUSED(scheduleSz);
@@ -507,7 +507,7 @@ namespace NActors {
node->SchedulerPool.Reset(CreateExecutorPoolStub(this, nodeIndex, node, 0));
node->MailboxTable.Reset(new TMailboxTable());
node->ActorSystem = MakeActorSystem(nodeIndex, node);
- node->ExecutorThread.Reset(new TExecutorThread(0, 0, node->ActorSystem.Get(), node->SchedulerPool.Get(), node->MailboxTable.Get(), "TestExecutor"));
+ node->ExecutorThread.Reset(new TExecutorThread(0, 0, node->ActorSystem.Get(), node->SchedulerPool.Get(), node->MailboxTable.Get(), "TestExecutor"));
} else {
node->ActorSystem = MakeActorSystem(nodeIndex, node);
}
@@ -904,19 +904,19 @@ namespace NActors {
switch (mailboxType) {
case TMailboxType::Simple:
- UnlockFromExecution((TMailboxTable::TSimpleMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
+ UnlockFromExecution((TMailboxTable::TSimpleMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
break;
case TMailboxType::Revolving:
- UnlockFromExecution((TMailboxTable::TRevolvingMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
+ UnlockFromExecution((TMailboxTable::TRevolvingMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
break;
case TMailboxType::HTSwap:
- UnlockFromExecution((TMailboxTable::THTSwapMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
+ UnlockFromExecution((TMailboxTable::THTSwapMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
break;
case TMailboxType::ReadAsFilled:
- UnlockFromExecution((TMailboxTable::TReadAsFilledMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
+ UnlockFromExecution((TMailboxTable::TReadAsFilledMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
break;
case TMailboxType::TinyReadAsFilled:
- UnlockFromExecution((TMailboxTable::TTinyReadAsFilledMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
+ UnlockFromExecution((TMailboxTable::TTinyReadAsFilledMailbox *)mailbox, node->ExecutorPools[0], false, hint, MaxWorkers, ++revolvingCounter);
break;
default:
Y_FAIL("Unsupported mailbox type");
@@ -1029,13 +1029,13 @@ namespace NActors {
}
bool TTestActorRuntimeBase::DispatchEvents(const TDispatchOptions& options) {
- return DispatchEvents(options, TInstant::Max());
- }
-
+ return DispatchEvents(options, TInstant::Max());
+ }
+
bool TTestActorRuntimeBase::DispatchEvents(const TDispatchOptions& options, TDuration simTimeout) {
- return DispatchEvents(options, TInstant::MicroSeconds(CurrentTimestamp) + simTimeout);
- }
-
+ return DispatchEvents(options, TInstant::MicroSeconds(CurrentTimestamp) + simTimeout);
+ }
+
bool TTestActorRuntimeBase::DispatchEvents(const TDispatchOptions& options, TInstant simDeadline) {
TGuard<TMutex> guard(Mutex);
return DispatchEventsInternal(options, simDeadline);
@@ -1251,7 +1251,7 @@ namespace NActors {
}
if (!localContext.FoundNonEmptyMailboxes.empty())
- return true;
+ return true;
if (options.CustomFinalCondition && options.CustomFinalCondition())
return true;
@@ -1266,15 +1266,15 @@ namespace NActors {
Cerr << "Dispatch complete with non-empty queue at " << TInstant::MicroSeconds(CurrentTimestamp) << "\n";
}
- return true;
+ return true;
}
}
}
- if (TInstant::MicroSeconds(CurrentTimestamp) > simDeadline) {
- return false;
- }
-
+ if (TInstant::MicroSeconds(CurrentTimestamp) > simDeadline) {
+ return false;
+ }
+
if (dispatchTime >= deadline) {
if (verbose) {
Cerr << "Reach deadline at " << TInstant::MicroSeconds(CurrentTimestamp) << "\n";
@@ -1333,7 +1333,7 @@ namespace NActors {
Cerr << "Process selected events at " << TInstant::MicroSeconds(CurrentTimestamp) << "\n";
}
- deadline = dispatchTime + DispatchTimeout;
+ deadline = dispatchTime + DispatchTimeout;
continue;
}
@@ -1351,7 +1351,7 @@ namespace NActors {
dispatchTime += waitDelay;
MailboxesHasEvents.WaitT(Mutex, waitDelay);
}
- return false;
+ return false;
}
void TTestActorRuntimeBase::HandleNonEmptyMailboxesForEachContext(TEventMailboxId mboxId) {
@@ -1452,8 +1452,8 @@ namespace NActors {
++dispatchCount;
{
if (!DispatchEventsInternal(TDispatchOptions(), deadline)) {
- return; // Timed out; event was not found
- }
+ return; // Timed out; event was not found
+ }
}
Y_VERIFY(dispatchCount < 1000, "Hard limit to prevent endless loop");
@@ -1572,7 +1572,7 @@ namespace NActors {
// Save actorId by value in order to prevent ctx from being invalidated during another Send call.
TActorId actorId = ev->GetRecipientRewrite();
node->ActorToActorId[recipientActor] = ev->GetRecipientRewrite();
- TActorContext ctx(*mailbox, *node->ExecutorThread, GetCycleCountFast(), actorId);
+ TActorContext ctx(*mailbox, *node->ExecutorThread, GetCycleCountFast(), actorId);
TActivationContext *prevTlsActivationContext = TlsActivationContext;
TlsActivationContext = &ctx;
CurrentRecipient = actorId;
diff --git a/library/cpp/actors/testlib/test_runtime.h b/library/cpp/actors/testlib/test_runtime.h
index 26e3b45c98..863e2cdb49 100644
--- a/library/cpp/actors/testlib/test_runtime.h
+++ b/library/cpp/actors/testlib/test_runtime.h
@@ -253,9 +253,9 @@ namespace NActors {
void PushEventsFront(TEventsList& events);
void PushMailboxEventsFront(ui32 hint, ui32 nodeId, TEventsList& events);
// doesn't dispatch events for edge actors
- bool DispatchEvents(const TDispatchOptions& options = TDispatchOptions());
- bool DispatchEvents(const TDispatchOptions& options, TDuration simTimeout);
- bool DispatchEvents(const TDispatchOptions& options, TInstant simDeadline);
+ bool DispatchEvents(const TDispatchOptions& options = TDispatchOptions());
+ bool DispatchEvents(const TDispatchOptions& options, TDuration simTimeout);
+ bool DispatchEvents(const TDispatchOptions& options, TInstant simDeadline);
void Send(IEventHandle* ev, ui32 senderNodeIndex = 0, bool viaActorSystem = false);
void Schedule(IEventHandle* ev, const TDuration& duration, ui32 nodeIndex = 0);
void ClearCounters();
@@ -288,7 +288,7 @@ namespace NActors {
TActorSystem* GetAnyNodeActorSystem();
TActorSystem* GetActorSystem(ui32 nodeId);
template <typename TEvent>
- TEvent* GrabEdgeEventIf(TAutoPtr<IEventHandle>& handle, std::function<bool(const TEvent&)> predicate, TDuration simTimeout = TDuration::Max()) {
+ TEvent* GrabEdgeEventIf(TAutoPtr<IEventHandle>& handle, std::function<bool(const TEvent&)> predicate, TDuration simTimeout = TDuration::Max()) {
handle.Destroy();
const ui32 eventType = TEvent::EventType;
WaitForEdgeEvents([&](TTestActorRuntimeBase& runtime, TAutoPtr<IEventHandle>& event) {
@@ -305,14 +305,14 @@ namespace NActors {
return false;
}, {}, simTimeout);
- if (simTimeout == TDuration::Max())
+ if (simTimeout == TDuration::Max())
Y_VERIFY(handle);
-
- if (handle) {
- return reinterpret_cast<TAutoPtr<TEventHandle<TEvent>>&>(handle)->Get();
- } else {
- return nullptr;
- }
+
+ if (handle) {
+ return reinterpret_cast<TAutoPtr<TEventHandle<TEvent>>&>(handle)->Get();
+ } else {
+ return nullptr;
+ }
}
template<class TEvent>
@@ -354,9 +354,9 @@ namespace NActors {
}
template <typename TEvent>
- TEvent* GrabEdgeEvent(TAutoPtr<IEventHandle>& handle, TDuration simTimeout = TDuration::Max()) {
+ TEvent* GrabEdgeEvent(TAutoPtr<IEventHandle>& handle, TDuration simTimeout = TDuration::Max()) {
std::function<bool(const TEvent&)> truth = [](const TEvent&) { return true; };
- return GrabEdgeEventIf(handle, truth, simTimeout);
+ return GrabEdgeEventIf(handle, truth, simTimeout);
}
template <typename TEvent>
@@ -400,9 +400,9 @@ namespace NActors {
}
template <typename TEvent>
- TEvent* GrabEdgeEventRethrow(TAutoPtr<IEventHandle>& handle, TDuration simTimeout = TDuration::Max()) {
+ TEvent* GrabEdgeEventRethrow(TAutoPtr<IEventHandle>& handle, TDuration simTimeout = TDuration::Max()) {
try {
- return GrabEdgeEvent<TEvent>(handle, simTimeout);
+ return GrabEdgeEvent<TEvent>(handle, simTimeout);
} catch (...) {
ythrow TWithBackTrace<yexception>() << "Exception occured while waiting for " << TypeName<TEvent>() << ": " << CurrentExceptionMessage();
}
diff --git a/library/cpp/actors/util/affinity.cpp b/library/cpp/actors/util/affinity.cpp
index cc1b6e70ec..69f9048ec1 100644
--- a/library/cpp/actors/util/affinity.cpp
+++ b/library/cpp/actors/util/affinity.cpp
@@ -16,17 +16,17 @@ public:
#endif
}
- explicit TImpl(const ui8* cpus, ui32 size) {
+ explicit TImpl(const ui8* cpus, ui32 size) {
#ifdef _linux_
CPU_ZERO(&Mask);
- for (ui32 i = 0; i != size; ++i) {
- if (cpus[i]) {
- CPU_SET(i, &Mask);
- }
- }
+ for (ui32 i = 0; i != size; ++i) {
+ if (cpus[i]) {
+ CPU_SET(i, &Mask);
+ }
+ }
#else
- Y_UNUSED(cpus);
- Y_UNUSED(size);
+ Y_UNUSED(cpus);
+ Y_UNUSED(size);
#endif
}
@@ -36,18 +36,18 @@ public:
Y_VERIFY_DEBUG(ar == 0);
#endif
}
-
- operator TCpuMask() const {
- TCpuMask result;
-#ifdef _linux_
- for (ui32 i = 0; i != CPU_SETSIZE; ++i) {
- result.Cpus.emplace_back(CPU_ISSET(i, &Mask));
- }
- result.RemoveTrailingZeros();
-#endif
- return result;
- }
-
+
+ operator TCpuMask() const {
+ TCpuMask result;
+#ifdef _linux_
+ for (ui32 i = 0; i != CPU_SETSIZE; ++i) {
+ result.Cpus.emplace_back(CPU_ISSET(i, &Mask));
+ }
+ result.RemoveTrailingZeros();
+#endif
+ return result;
+ }
+
};
TAffinity::TAffinity() {
@@ -57,37 +57,37 @@ TAffinity::~TAffinity() {
}
TAffinity::TAffinity(const ui8* x, ui32 sz) {
- if (x && sz) {
- Impl.Reset(new TImpl(x, sz));
- }
-}
-
-TAffinity::TAffinity(const TCpuMask& mask) {
- if (!mask.IsEmpty()) {
- static_assert(sizeof(ui8) == sizeof(mask.Cpus[0]));
- const ui8* x = reinterpret_cast<const ui8*>(&mask.Cpus[0]);
- const ui32 sz = mask.Size();
+ if (x && sz) {
Impl.Reset(new TImpl(x, sz));
- }
+ }
}
+TAffinity::TAffinity(const TCpuMask& mask) {
+ if (!mask.IsEmpty()) {
+ static_assert(sizeof(ui8) == sizeof(mask.Cpus[0]));
+ const ui8* x = reinterpret_cast<const ui8*>(&mask.Cpus[0]);
+ const ui32 sz = mask.Size();
+ Impl.Reset(new TImpl(x, sz));
+ }
+}
+
void TAffinity::Current() {
Impl.Reset(new TImpl());
}
void TAffinity::Set() const {
- if (!!Impl) {
+ if (!!Impl) {
Impl->Set();
- }
+ }
}
bool TAffinity::Empty() const {
- return !Impl;
-}
-
-TAffinity::operator TCpuMask() const {
- if (!!Impl) {
- return *Impl;
- }
- return TCpuMask();
+ return !Impl;
}
+
+TAffinity::operator TCpuMask() const {
+ if (!!Impl) {
+ return *Impl;
+ }
+ return TCpuMask();
+}
diff --git a/library/cpp/actors/util/affinity.h b/library/cpp/actors/util/affinity.h
index ae106ed180..c807d03b76 100644
--- a/library/cpp/actors/util/affinity.h
+++ b/library/cpp/actors/util/affinity.h
@@ -1,27 +1,27 @@
#pragma once
#include "defs.h"
-#include "cpumask.h"
+#include "cpumask.h"
-// Platform-specific class to set or get thread affinity
+// Platform-specific class to set or get thread affinity
class TAffinity: public TThrRefBase, TNonCopyable {
class TImpl;
THolder<TImpl> Impl;
public:
TAffinity();
- TAffinity(const ui8* cpus, ui32 size);
- explicit TAffinity(const TCpuMask& mask);
+ TAffinity(const ui8* cpus, ui32 size);
+ explicit TAffinity(const TCpuMask& mask);
~TAffinity();
void Current();
void Set() const;
bool Empty() const;
-
- operator TCpuMask() const;
+
+ operator TCpuMask() const;
};
-// Scoped affinity setter
+// Scoped affinity setter
class TAffinityGuard : TNonCopyable {
bool Stacked;
TAffinity OldAffinity;
diff --git a/library/cpp/actors/util/cpumask.h b/library/cpp/actors/util/cpumask.h
index 29741aa1d6..1f72ae3895 100644
--- a/library/cpp/actors/util/cpumask.h
+++ b/library/cpp/actors/util/cpumask.h
@@ -1,133 +1,133 @@
-#pragma once
-
-#include "defs.h"
-
-#include <library/cpp/containers/stack_vector/stack_vec.h>
-
-#include <util/string/split.h>
-#include <util/generic/yexception.h>
-
-using TCpuId = ui32;
-
-// Simple data structure to operate with set of cpus
-struct TCpuMask {
- TStackVec<bool, 1024> Cpus;
-
- // Creates empty mask
- TCpuMask() {}
-
- // Creates mask with single cpu set
- explicit TCpuMask(TCpuId cpuId) {
- Set(cpuId);
- }
-
- // Initialize mask from raw boolean array
- template <class T>
- TCpuMask(const T* cpus, TCpuId size) {
- Cpus.reserve(size);
- for (TCpuId i = 0; i != size; ++i) {
- Cpus.emplace_back(bool(cpus[i]));
- }
- }
-
- // Parse a numerical list of processors. The numbers are separated by commas and may include ranges. For example: 0,5,7,9-11
- explicit TCpuMask(const TString& cpuList) {
- try {
- for (TStringBuf s : StringSplitter(cpuList).Split(',')) {
- TCpuId l, r;
- if (s.find('-') != TString::npos) {
- StringSplitter(s).Split('-').CollectInto(&l, &r);
- } else {
- l = r = FromString<TCpuId>(s);
- }
- if (r >= Cpus.size()) {
- Cpus.resize(r + 1, false);
- }
- for (TCpuId cpu = l; cpu <= r; cpu++) {
- Cpus[cpu] = true;
- }
- }
- } catch (...) {
- ythrow TWithBackTrace<yexception>() << "Exception occured while parsing cpu list '" << cpuList << "': " << CurrentExceptionMessage();
- }
- }
-
- // Returns size of underlying vector
- TCpuId Size() const {
- return Cpus.size();
- }
-
- // Returns number of set bits in mask
- TCpuId CpuCount() const {
- TCpuId result = 0;
- for (bool value : Cpus) {
- result += value;
- }
- return result;
- }
-
- bool IsEmpty() const {
- for (bool value : Cpus) {
- if (value) {
- return false;
- }
- }
- return true;
- }
-
- bool IsSet(TCpuId cpu) const {
- return cpu < Cpus.size() && Cpus[cpu];
- }
-
- void Set(TCpuId cpu) {
- if (cpu >= Cpus.size()) {
- Cpus.resize(cpu + 1, false);
- }
- Cpus[cpu] = true;
- }
-
- void Reset(TCpuId cpu) {
- if (cpu < Cpus.size()) {
- Cpus[cpu] = false;
- }
- }
-
- void RemoveTrailingZeros() {
- while (!Cpus.empty() && !Cpus.back()) {
- Cpus.pop_back();
- }
- }
-
- explicit operator bool() const {
- return !IsEmpty();
- }
-
- TCpuMask operator &(const TCpuMask& rhs) const {
- TCpuMask result;
- TCpuId size = Max(Size(), rhs.Size());
- result.Cpus.reserve(size);
- for (TCpuId cpu = 0; cpu < size; cpu++) {
- result.Cpus.emplace_back(IsSet(cpu) && rhs.IsSet(cpu));
- }
- return result;
- }
-
- TCpuMask operator |(const TCpuMask& rhs) const {
- TCpuMask result;
- TCpuId size = Max(Size(), rhs.Size());
- result.Cpus.reserve(size);
- for (TCpuId cpu = 0; cpu < size; cpu++) {
- result.Cpus.emplace_back(IsSet(cpu) || rhs.IsSet(cpu));
- }
- return result;
- }
-
- TCpuMask operator -(const TCpuMask& rhs) const {
- TCpuMask result;
- result.Cpus.reserve(Size());
- for (TCpuId cpu = 0; cpu < Size(); cpu++) {
- result.Cpus.emplace_back(IsSet(cpu) && !rhs.IsSet(cpu));
- }
- return result;
- }
-};
+#pragma once
+
+#include "defs.h"
+
+#include <library/cpp/containers/stack_vector/stack_vec.h>
+
+#include <util/string/split.h>
+#include <util/generic/yexception.h>
+
+using TCpuId = ui32;
+
+// Simple data structure to operate with set of cpus
+struct TCpuMask {
+ TStackVec<bool, 1024> Cpus;
+
+ // Creates empty mask
+ TCpuMask() {}
+
+ // Creates mask with single cpu set
+ explicit TCpuMask(TCpuId cpuId) {
+ Set(cpuId);
+ }
+
+ // Initialize mask from raw boolean array
+ template <class T>
+ TCpuMask(const T* cpus, TCpuId size) {
+ Cpus.reserve(size);
+ for (TCpuId i = 0; i != size; ++i) {
+ Cpus.emplace_back(bool(cpus[i]));
+ }
+ }
+
+ // Parse a numerical list of processors. The numbers are separated by commas and may include ranges. For example: 0,5,7,9-11
+ explicit TCpuMask(const TString& cpuList) {
+ try {
+ for (TStringBuf s : StringSplitter(cpuList).Split(',')) {
+ TCpuId l, r;
+ if (s.find('-') != TString::npos) {
+ StringSplitter(s).Split('-').CollectInto(&l, &r);
+ } else {
+ l = r = FromString<TCpuId>(s);
+ }
+ if (r >= Cpus.size()) {
+ Cpus.resize(r + 1, false);
+ }
+ for (TCpuId cpu = l; cpu <= r; cpu++) {
+ Cpus[cpu] = true;
+ }
+ }
+ } catch (...) {
+ ythrow TWithBackTrace<yexception>() << "Exception occured while parsing cpu list '" << cpuList << "': " << CurrentExceptionMessage();
+ }
+ }
+
+ // Returns size of underlying vector
+ TCpuId Size() const {
+ return Cpus.size();
+ }
+
+ // Returns number of set bits in mask
+ TCpuId CpuCount() const {
+ TCpuId result = 0;
+ for (bool value : Cpus) {
+ result += value;
+ }
+ return result;
+ }
+
+ bool IsEmpty() const {
+ for (bool value : Cpus) {
+ if (value) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool IsSet(TCpuId cpu) const {
+ return cpu < Cpus.size() && Cpus[cpu];
+ }
+
+ void Set(TCpuId cpu) {
+ if (cpu >= Cpus.size()) {
+ Cpus.resize(cpu + 1, false);
+ }
+ Cpus[cpu] = true;
+ }
+
+ void Reset(TCpuId cpu) {
+ if (cpu < Cpus.size()) {
+ Cpus[cpu] = false;
+ }
+ }
+
+ void RemoveTrailingZeros() {
+ while (!Cpus.empty() && !Cpus.back()) {
+ Cpus.pop_back();
+ }
+ }
+
+ explicit operator bool() const {
+ return !IsEmpty();
+ }
+
+ TCpuMask operator &(const TCpuMask& rhs) const {
+ TCpuMask result;
+ TCpuId size = Max(Size(), rhs.Size());
+ result.Cpus.reserve(size);
+ for (TCpuId cpu = 0; cpu < size; cpu++) {
+ result.Cpus.emplace_back(IsSet(cpu) && rhs.IsSet(cpu));
+ }
+ return result;
+ }
+
+ TCpuMask operator |(const TCpuMask& rhs) const {
+ TCpuMask result;
+ TCpuId size = Max(Size(), rhs.Size());
+ result.Cpus.reserve(size);
+ for (TCpuId cpu = 0; cpu < size; cpu++) {
+ result.Cpus.emplace_back(IsSet(cpu) || rhs.IsSet(cpu));
+ }
+ return result;
+ }
+
+ TCpuMask operator -(const TCpuMask& rhs) const {
+ TCpuMask result;
+ result.Cpus.reserve(Size());
+ for (TCpuId cpu = 0; cpu < Size(); cpu++) {
+ result.Cpus.emplace_back(IsSet(cpu) && !rhs.IsSet(cpu));
+ }
+ return result;
+ }
+};
diff --git a/library/cpp/actors/util/datetime.h b/library/cpp/actors/util/datetime.h
index cbec5965d6..4bdf57bbde 100644
--- a/library/cpp/actors/util/datetime.h
+++ b/library/cpp/actors/util/datetime.h
@@ -1,82 +1,82 @@
-#pragma once
-
-#include <util/system/defaults.h>
-#include <util/system/hp_timer.h>
-#include <util/system/platform.h>
-
-#if defined(_win_)
-#include <intrin.h>
-#pragma intrinsic(__rdtsc)
-#endif // _win_
-
-#if defined(_darwin_) && !defined(_x86_)
-#include <mach/mach_time.h>
-#endif
-
-// GetCycleCount() from util/system/datetime.h uses rdtscp, which is more accurate than rdtsc,
-// but rdtscp disables processor's out-of-order execution, so it can be slow
-Y_FORCE_INLINE ui64 GetCycleCountFast() {
-#if defined(_MSC_VER)
- // Generates the rdtsc instruction, which returns the processor time stamp.
- // The processor time stamp records the number of clock cycles since the last reset.
- return __rdtsc();
-#elif defined(__clang__) && !defined(_arm64_)
- return __builtin_readcyclecounter();
-#elif defined(_x86_64_)
- unsigned hi, lo;
- __asm__ __volatile__("rdtsc"
- : "=a"(lo), "=d"(hi));
- return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
-#elif defined(_i386_)
- ui64 x;
- __asm__ volatile("rdtsc\n\t"
- : "=A"(x));
- return x;
-#elif defined(_darwin_)
- return mach_absolute_time();
-#elif defined(_arm32_)
- return MicroSeconds();
-#elif defined(_arm64_)
- ui64 x;
-
- __asm__ __volatile__("isb; mrs %0, cntvct_el0"
- : "=r"(x));
-
- return x;
-#else
-#error "unsupported arch"
-#endif
-}
-
-// NHPTimer::GetTime fast analog
-Y_FORCE_INLINE void GetTimeFast(NHPTimer::STime* pTime) noexcept {
- *pTime = GetCycleCountFast();
-}
-
-namespace NActors {
- inline double Ts2Ns(ui64 ts) {
- return NHPTimer::GetSeconds(ts) * 1e9;
- }
-
- inline double Ts2Us(ui64 ts) {
- return NHPTimer::GetSeconds(ts) * 1e6;
- }
-
- inline double Ts2Ms(ui64 ts) {
- return NHPTimer::GetSeconds(ts) * 1e3;
- }
-
- inline ui64 Us2Ts(double us) {
- return ui64(NHPTimer::GetClockRate() * us / 1e6);
- }
-
- struct TTimeTracker {
- ui64 Ts;
- TTimeTracker(): Ts(GetCycleCountFast()) {}
- ui64 Elapsed() {
- ui64 ts = GetCycleCountFast();
- std::swap(Ts, ts);
- return Ts - ts;
- }
- };
-}
+#pragma once
+
+#include <util/system/defaults.h>
+#include <util/system/hp_timer.h>
+#include <util/system/platform.h>
+
+#if defined(_win_)
+#include <intrin.h>
+#pragma intrinsic(__rdtsc)
+#endif // _win_
+
+#if defined(_darwin_) && !defined(_x86_)
+#include <mach/mach_time.h>
+#endif
+
+// GetCycleCount() from util/system/datetime.h uses rdtscp, which is more accurate than rdtsc,
+// but rdtscp disables processor's out-of-order execution, so it can be slow
+Y_FORCE_INLINE ui64 GetCycleCountFast() {
+#if defined(_MSC_VER)
+ // Generates the rdtsc instruction, which returns the processor time stamp.
+ // The processor time stamp records the number of clock cycles since the last reset.
+ return __rdtsc();
+#elif defined(__clang__) && !defined(_arm64_)
+ return __builtin_readcyclecounter();
+#elif defined(_x86_64_)
+ unsigned hi, lo;
+ __asm__ __volatile__("rdtsc"
+ : "=a"(lo), "=d"(hi));
+ return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
+#elif defined(_i386_)
+ ui64 x;
+ __asm__ volatile("rdtsc\n\t"
+ : "=A"(x));
+ return x;
+#elif defined(_darwin_)
+ return mach_absolute_time();
+#elif defined(_arm32_)
+ return MicroSeconds();
+#elif defined(_arm64_)
+ ui64 x;
+
+ __asm__ __volatile__("isb; mrs %0, cntvct_el0"
+ : "=r"(x));
+
+ return x;
+#else
+#error "unsupported arch"
+#endif
+}
+
+// NHPTimer::GetTime fast analog
+Y_FORCE_INLINE void GetTimeFast(NHPTimer::STime* pTime) noexcept {
+ *pTime = GetCycleCountFast();
+}
+
+namespace NActors {
+ inline double Ts2Ns(ui64 ts) {
+ return NHPTimer::GetSeconds(ts) * 1e9;
+ }
+
+ inline double Ts2Us(ui64 ts) {
+ return NHPTimer::GetSeconds(ts) * 1e6;
+ }
+
+ inline double Ts2Ms(ui64 ts) {
+ return NHPTimer::GetSeconds(ts) * 1e3;
+ }
+
+ inline ui64 Us2Ts(double us) {
+ return ui64(NHPTimer::GetClockRate() * us / 1e6);
+ }
+
+ struct TTimeTracker {
+ ui64 Ts;
+ TTimeTracker(): Ts(GetCycleCountFast()) {}
+ ui64 Elapsed() {
+ ui64 ts = GetCycleCountFast();
+ std::swap(Ts, ts);
+ return Ts - ts;
+ }
+ };
+}
diff --git a/library/cpp/actors/util/thread.h b/library/cpp/actors/util/thread.h
index d742c8c585..4cab922647 100644
--- a/library/cpp/actors/util/thread.h
+++ b/library/cpp/actors/util/thread.h
@@ -5,7 +5,7 @@
#include <util/system/execpath.h>
#include <util/system/thread.h>
#include <util/system/thread.h>
-#include <time.h>
+#include <time.h>
inline void SetCurrentThreadName(const TString& name,
const ui32 maxCharsFromProcessName = 8) {
diff --git a/library/cpp/actors/util/timerfd.h b/library/cpp/actors/util/timerfd.h
index 3189e2a672..a9b35ff9e7 100644
--- a/library/cpp/actors/util/timerfd.h
+++ b/library/cpp/actors/util/timerfd.h
@@ -1,65 +1,65 @@
-#pragma once
-
-#include "datetime.h"
-
-#include <util/generic/noncopyable.h>
-
-#ifdef _linux_
-
-#include <util/system/yassert.h>
-#include <errno.h>
-#include <sys/timerfd.h>
-
-struct TTimerFd: public TNonCopyable {
- int Fd;
-
- TTimerFd() {
- Fd = timerfd_create(CLOCK_MONOTONIC, 0);
- Y_VERIFY(Fd != -1, "timerfd_create(CLOCK_MONOTONIC, 0) -> -1; errno:%d: %s", int(errno), strerror(errno));
- }
-
- ~TTimerFd() {
- close(Fd);
- }
-
- void Set(ui64 ts) {
- ui64 now = GetCycleCountFast();
- Arm(now >= ts? 1: NHPTimer::GetSeconds(ts - now) * 1e9);
- }
-
- void Reset() {
- Arm(0); // disarm timer
- }
-
- void Wait() {
- ui64 expirations;
- ssize_t s = read(Fd, &expirations, sizeof(ui64));
- Y_UNUSED(s); // Y_VERIFY(s == sizeof(ui64));
- }
-
- void Wake() {
- Arm(1);
- }
-private:
- void Arm(ui64 ns) {
- struct itimerspec spec;
- spec.it_value.tv_sec = ns / 1'000'000'000;
- spec.it_value.tv_nsec = ns % 1'000'000'000;
- spec.it_interval.tv_sec = 0;
- spec.it_interval.tv_nsec = 0;
- int ret = timerfd_settime(Fd, 0, &spec, nullptr);
- Y_VERIFY(ret != -1, "timerfd_settime(%d, 0, %" PRIu64 "ns, 0) -> %d; errno:%d: %s", Fd, ns, ret, int(errno), strerror(errno));
- }
-};
-
-#else
-
-struct TTimerFd: public TNonCopyable {
- int Fd = 0;
- void Set(ui64) {}
- void Reset() {}
- void Wait() {}
- void Wake() {}
-};
-
-#endif
+#pragma once
+
+#include "datetime.h"
+
+#include <util/generic/noncopyable.h>
+
+#ifdef _linux_
+
+#include <util/system/yassert.h>
+#include <errno.h>
+#include <sys/timerfd.h>
+
+struct TTimerFd: public TNonCopyable {
+ int Fd;
+
+ TTimerFd() {
+ Fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ Y_VERIFY(Fd != -1, "timerfd_create(CLOCK_MONOTONIC, 0) -> -1; errno:%d: %s", int(errno), strerror(errno));
+ }
+
+ ~TTimerFd() {
+ close(Fd);
+ }
+
+ void Set(ui64 ts) {
+ ui64 now = GetCycleCountFast();
+ Arm(now >= ts? 1: NHPTimer::GetSeconds(ts - now) * 1e9);
+ }
+
+ void Reset() {
+ Arm(0); // disarm timer
+ }
+
+ void Wait() {
+ ui64 expirations;
+ ssize_t s = read(Fd, &expirations, sizeof(ui64));
+ Y_UNUSED(s); // Y_VERIFY(s == sizeof(ui64));
+ }
+
+ void Wake() {
+ Arm(1);
+ }
+private:
+ void Arm(ui64 ns) {
+ struct itimerspec spec;
+ spec.it_value.tv_sec = ns / 1'000'000'000;
+ spec.it_value.tv_nsec = ns % 1'000'000'000;
+ spec.it_interval.tv_sec = 0;
+ spec.it_interval.tv_nsec = 0;
+ int ret = timerfd_settime(Fd, 0, &spec, nullptr);
+ Y_VERIFY(ret != -1, "timerfd_settime(%d, 0, %" PRIu64 "ns, 0) -> %d; errno:%d: %s", Fd, ns, ret, int(errno), strerror(errno));
+ }
+};
+
+#else
+
+struct TTimerFd: public TNonCopyable {
+ int Fd = 0;
+ void Set(ui64) {}
+ void Reset() {}
+ void Wait() {}
+ void Wake() {}
+};
+
+#endif
diff --git a/library/cpp/actors/util/ya.make b/library/cpp/actors/util/ya.make
index 37488c3962..a8bfd05d5a 100644
--- a/library/cpp/actors/util/ya.make
+++ b/library/cpp/actors/util/ya.make
@@ -8,8 +8,8 @@ OWNER(
SRCS(
affinity.cpp
affinity.h
- cpumask.h
- datetime.h
+ cpumask.h
+ datetime.h
defs.h
funnel_queue.h
futex.h
@@ -26,7 +26,7 @@ SRCS(
threadparkpad.cpp
threadparkpad.h
ticket_lock.h
- timerfd.h
+ timerfd.h
unordered_cache.h
)
diff --git a/library/cpp/bucket_quoter/bucket_quoter.h b/library/cpp/bucket_quoter/bucket_quoter.h
index 3d92ef8450..74eeee2601 100644
--- a/library/cpp/bucket_quoter/bucket_quoter.h
+++ b/library/cpp/bucket_quoter/bucket_quoter.h
@@ -2,7 +2,7 @@
#include <util/datetime/base.h>
#include <util/system/mutex.h>
-#include <util/system/hp_timer.h>
+#include <util/system/hp_timer.h>
/* Token bucket.
* Makes flow of *inflow* units per second in average, with up to *capacity* bursts.
@@ -39,54 +39,54 @@
*/
-struct TInstantTimerMs {
- using TTime = TInstant;
- static constexpr ui64 Resolution = 1000ull; // milliseconds
- static TTime Now() {
- return TInstant::Now();
- }
- static ui64 Duration(TTime from, TTime to) {
- return (to - from).MilliSeconds();
- }
-};
-
-struct THPTimerUs {
- using TTime = NHPTimer::STime;
+struct TInstantTimerMs {
+ using TTime = TInstant;
+ static constexpr ui64 Resolution = 1000ull; // milliseconds
+ static TTime Now() {
+ return TInstant::Now();
+ }
+ static ui64 Duration(TTime from, TTime to) {
+ return (to - from).MilliSeconds();
+ }
+};
+
+struct THPTimerUs {
+ using TTime = NHPTimer::STime;
static constexpr ui64 Resolution = 1000000ull; // microseconds
- static TTime Now() {
- NHPTimer::STime ret;
- NHPTimer::GetTime(&ret);
- return ret;
- }
- static ui64 Duration(TTime from, TTime to) {
- i64 cycles = to - from;
- if (cycles > 0) {
- return ui64(double(cycles) * double(Resolution) / NHPTimer::GetClockRate());
- } else {
- return 0;
- }
- }
-};
-
-template <typename StatCounter, typename Lock = TMutex, typename Timer = TInstantTimerMs>
+ static TTime Now() {
+ NHPTimer::STime ret;
+ NHPTimer::GetTime(&ret);
+ return ret;
+ }
+ static ui64 Duration(TTime from, TTime to) {
+ i64 cycles = to - from;
+ if (cycles > 0) {
+ return ui64(double(cycles) * double(Resolution) / NHPTimer::GetClockRate());
+ } else {
+ return 0;
+ }
+ }
+};
+
+template <typename StatCounter, typename Lock = TMutex, typename Timer = TInstantTimerMs>
class TBucketQuoter {
public:
- using TTime = typename Timer::TTime;
-
- struct TResult {
- i64 Before;
- i64 After;
- ui64 Seqno;
- };
-
+ using TTime = typename Timer::TTime;
+
+ struct TResult {
+ i64 Before;
+ i64 After;
+ ui64 Seqno;
+ };
+
/* fixed quota */
- TBucketQuoter(ui64 inflow, ui64 capacity, StatCounter* msgPassed = nullptr,
- StatCounter* bucketUnderflows = nullptr, StatCounter* tokensUsed = nullptr,
+ TBucketQuoter(ui64 inflow, ui64 capacity, StatCounter* msgPassed = nullptr,
+ StatCounter* bucketUnderflows = nullptr, StatCounter* tokensUsed = nullptr,
StatCounter* usecWaited = nullptr, bool fill = false, StatCounter* aggregateInflow = nullptr)
: MsgPassed(msgPassed)
, BucketUnderflows(bucketUnderflows)
, TokensUsed(tokensUsed)
- , UsecWaited(usecWaited)
+ , UsecWaited(usecWaited)
, AggregateInflow(aggregateInflow)
, Bucket(fill ? capacity : 0)
, LastAdd(Timer::Now())
@@ -99,13 +99,13 @@ public:
}
/* adjustable quotas */
- TBucketQuoter(TAtomic* inflow, TAtomic* capacity, StatCounter* msgPassed = nullptr,
- StatCounter* bucketUnderflows = nullptr, StatCounter* tokensUsed = nullptr,
+ TBucketQuoter(TAtomic* inflow, TAtomic* capacity, StatCounter* msgPassed = nullptr,
+ StatCounter* bucketUnderflows = nullptr, StatCounter* tokensUsed = nullptr,
StatCounter* usecWaited = nullptr, bool fill = false, StatCounter* aggregateInflow = nullptr)
: MsgPassed(msgPassed)
, BucketUnderflows(bucketUnderflows)
, TokensUsed(tokensUsed)
- , UsecWaited(usecWaited)
+ , UsecWaited(usecWaited)
, AggregateInflow(aggregateInflow)
, Bucket(fill ? AtomicGet(*capacity) : 0)
, LastAdd(Timer::Now())
@@ -116,22 +116,22 @@ public:
}
bool IsAvail() {
- TGuard<Lock> g(BucketMutex);
- FillBucket();
- if (Bucket < 0) {
- if (BucketUnderflows) {
- (*BucketUnderflows)++;
- }
- }
- return (Bucket >= 0);
- }
-
- bool IsAvail(TResult& res) {
- TGuard<Lock> g(BucketMutex);
- res.Before = Bucket;
+ TGuard<Lock> g(BucketMutex);
+ FillBucket();
+ if (Bucket < 0) {
+ if (BucketUnderflows) {
+ (*BucketUnderflows)++;
+ }
+ }
+ return (Bucket >= 0);
+ }
+
+ bool IsAvail(TResult& res) {
+ TGuard<Lock> g(BucketMutex);
+ res.Before = Bucket;
FillBucket();
- res.After = Bucket;
- res.Seqno = ++Seqno;
+ res.After = Bucket;
+ res.Seqno = ++Seqno;
if (Bucket < 0) {
if (BucketUnderflows) {
(*BucketUnderflows)++;
@@ -140,58 +140,58 @@ public:
return (Bucket >= 0);
}
- ui64 GetAvail() {
- TGuard<Lock> g(BucketMutex);
- FillBucket();
- return Max<i64>(0, Bucket);
- }
-
- ui64 GetAvail(TResult& res) {
- TGuard<Lock> g(BucketMutex);
- res.Before = Bucket;
- FillBucket();
- res.After = Bucket;
- res.Seqno = ++Seqno;
- return Max<i64>(0, Bucket);
- }
-
+ ui64 GetAvail() {
+ TGuard<Lock> g(BucketMutex);
+ FillBucket();
+ return Max<i64>(0, Bucket);
+ }
+
+ ui64 GetAvail(TResult& res) {
+ TGuard<Lock> g(BucketMutex);
+ res.Before = Bucket;
+ FillBucket();
+ res.After = Bucket;
+ res.Seqno = ++Seqno;
+ return Max<i64>(0, Bucket);
+ }
+
void Use(ui64 tokens, bool sleep = false) {
- TGuard<Lock> g(BucketMutex);
- UseNoLock(tokens, sleep);
- }
-
- void Use(ui64 tokens, TResult& res, bool sleep = false) {
- TGuard<Lock> g(BucketMutex);
- res.Before = Bucket;
- UseNoLock(tokens, sleep);
- res.After = Bucket;
- res.Seqno = ++Seqno;
+ TGuard<Lock> g(BucketMutex);
+ UseNoLock(tokens, sleep);
}
- i64 UseAndFill(ui64 tokens) {
- TGuard<Lock> g(BucketMutex);
- UseNoLock(tokens);
- FillBucket();
- return Bucket;
- }
-
- void Add(ui64 tokens) {
- TGuard<Lock> g(BucketMutex);
- AddNoLock(tokens);
- }
-
- void Add(ui64 tokens, TResult& res) {
- TGuard<Lock> g(BucketMutex);
- res.Before = Bucket;
- AddNoLock(tokens);
- res.After = Bucket;
- res.Seqno = ++Seqno;
- }
-
- ui32 GetWaitTime() {
- TGuard<Lock> g(BucketMutex);
-
+ void Use(ui64 tokens, TResult& res, bool sleep = false) {
+ TGuard<Lock> g(BucketMutex);
+ res.Before = Bucket;
+ UseNoLock(tokens, sleep);
+ res.After = Bucket;
+ res.Seqno = ++Seqno;
+ }
+
+ i64 UseAndFill(ui64 tokens) {
+ TGuard<Lock> g(BucketMutex);
+ UseNoLock(tokens);
FillBucket();
+ return Bucket;
+ }
+
+ void Add(ui64 tokens) {
+ TGuard<Lock> g(BucketMutex);
+ AddNoLock(tokens);
+ }
+
+ void Add(ui64 tokens, TResult& res) {
+ TGuard<Lock> g(BucketMutex);
+ res.Before = Bucket;
+ AddNoLock(tokens);
+ res.After = Bucket;
+ res.Seqno = ++Seqno;
+ }
+
+ ui32 GetWaitTime() {
+ TGuard<Lock> g(BucketMutex);
+
+ FillBucket();
if (Bucket >= 0) {
return 0;
}
@@ -200,37 +200,37 @@ public:
return usec;
}
- ui32 GetWaitTime(TResult& res) {
- TGuard<Lock> g(BucketMutex);
- res.Before = Bucket;
- FillBucket();
- res.After = Bucket;
- res.Seqno = ++Seqno;
- if (Bucket >= 0) {
- return 0;
- }
- ui32 usec = (-Bucket * 1000000) / (*InflowTokensPerSecond);
- return usec;
- }
-
+ ui32 GetWaitTime(TResult& res) {
+ TGuard<Lock> g(BucketMutex);
+ res.Before = Bucket;
+ FillBucket();
+ res.After = Bucket;
+ res.Seqno = ++Seqno;
+ if (Bucket >= 0) {
+ return 0;
+ }
+ ui32 usec = (-Bucket * 1000000) / (*InflowTokensPerSecond);
+ return usec;
+ }
+
void Sleep() {
while (!IsAvail()) {
ui32 delay = GetWaitTime();
if (delay != 0) {
usleep(delay);
- if (UsecWaited) {
- (*UsecWaited) += delay;
- }
+ if (UsecWaited) {
+ (*UsecWaited) += delay;
+ }
}
}
}
private:
void FillBucket() {
- TTime now = Timer::Now();
+ TTime now = Timer::Now();
- ui64 elapsed = Timer::Duration(LastAdd, now);
- if (*InflowTokensPerSecond * elapsed >= Timer::Resolution) {
+ ui64 elapsed = Timer::Duration(LastAdd, now);
+ if (*InflowTokensPerSecond * elapsed >= Timer::Resolution) {
ui64 inflow = *InflowTokensPerSecond * elapsed / Timer::Resolution;
if (AggregateInflow) {
*AggregateInflow += inflow;
@@ -244,35 +244,35 @@ private:
}
}
- void UseNoLock(ui64 tokens, bool sleep = false) {
- if (sleep)
- Sleep();
- Bucket -= tokens;
- if (TokensUsed) {
- (*TokensUsed) += tokens;
- }
- if (MsgPassed) {
- (*MsgPassed)++;
- }
- }
-
- void AddNoLock(ui64 tokens) {
- Bucket += tokens;
- if (Bucket > *BucketTokensCapacity) {
- Bucket = *BucketTokensCapacity;
- }
- }
-
+ void UseNoLock(ui64 tokens, bool sleep = false) {
+ if (sleep)
+ Sleep();
+ Bucket -= tokens;
+ if (TokensUsed) {
+ (*TokensUsed) += tokens;
+ }
+ if (MsgPassed) {
+ (*MsgPassed)++;
+ }
+ }
+
+ void AddNoLock(ui64 tokens) {
+ Bucket += tokens;
+ if (Bucket > *BucketTokensCapacity) {
+ Bucket = *BucketTokensCapacity;
+ }
+ }
+
StatCounter* MsgPassed;
StatCounter* BucketUnderflows;
StatCounter* TokensUsed;
- StatCounter* UsecWaited;
+ StatCounter* UsecWaited;
StatCounter* AggregateInflow;
i64 Bucket;
- TTime LastAdd;
- Lock BucketMutex;
- ui64 Seqno = 0;
+ TTime LastAdd;
+ Lock BucketMutex;
+ ui64 Seqno = 0;
TAtomic* InflowTokensPerSecond;
TAtomic* BucketTokensCapacity;
diff --git a/library/cpp/containers/stack_vector/stack_vec.h b/library/cpp/containers/stack_vector/stack_vec.h
index fcc5d9a2a5..5b4d370e1f 100644
--- a/library/cpp/containers/stack_vector/stack_vec.h
+++ b/library/cpp/containers/stack_vector/stack_vec.h
@@ -41,7 +41,7 @@ namespace NPrivate {
using typename Alloc::value_type;
template <class U>
- struct rebind: public ::NPrivate::TRebind<Alloc, TSelf, T, U> {
+ struct rebind: public ::NPrivate::TRebind<Alloc, TSelf, T, U> {
};
public:
@@ -82,7 +82,7 @@ namespace NPrivate {
private:
std::aligned_storage_t<sizeof(T), alignof(T)> StackBasedStorage[CountOnStack];
- bool IsStorageUsed = false;
+ bool IsStorageUsed = false;
private:
Alloc& FallbackAllocator() noexcept {
diff --git a/library/cpp/http/server/http.cpp b/library/cpp/http/server/http.cpp
index 128583bdd7..b461c242ab 100644
--- a/library/cpp/http/server/http.cpp
+++ b/library/cpp/http/server/http.cpp
@@ -456,7 +456,7 @@ public:
TOptions Options_;
ICallBack* Cb_ = nullptr;
THttpServer* Parent_ = nullptr;
- TWakeupPollAble WakeupPollAble;
+ TWakeupPollAble WakeupPollAble;
TMutex StopMutex;
private:
diff --git a/library/cpp/lwtrace/all.h b/library/cpp/lwtrace/all.h
index d7aa57c49d..c086bede4a 100644
--- a/library/cpp/lwtrace/all.h
+++ b/library/cpp/lwtrace/all.h
@@ -1,195 +1,195 @@
-#pragma once
-
-#include "control.h"
-#include "event.h"
+#pragma once
+
+#include "control.h"
+#include "event.h"
#include "preprocessor.h"
-#include "probe.h"
+#include "probe.h"
#include "start.h"
-
-//
+
+//
// Full documentation: https://wiki.yandex-team.ru/development/poisk/arcadia/library/lwtrace/
-//
-// Short usage instruction:
-//
-// 1. Declare probes provider in header file 'probes.h':
-// #include <yweb/robot/kiwi/lwtrace/all.h>
-// #define MY_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \ // name of your provider
-// PROBE(MyProbe, GROUPS("MyGroup1", "MyGroup2"), TYPES(), NAMES()) \ // probe specification w/o argiments
+//
+// Short usage instruction:
+//
+// 1. Declare probes provider in header file 'probes.h':
+// #include <yweb/robot/kiwi/lwtrace/all.h>
+// #define MY_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \ // name of your provider
+// PROBE(MyProbe, GROUPS("MyGroup1", "MyGroup2"), TYPES(), NAMES()) \ // probe specification w/o argiments
// PROBE(MyAnotherProbe, GROUPS("MyGroup2"), TYPES(int, TString), NAMES("arg1", "arg2")) \ // another probe with arguments
-// PROBE(MyScopedProbe, GROUPS(), TYPES(ui64, int), NAMES("duration", "stage")) \ // scoped probe with argument
-// /**/
-// LWTRACE_DECLARE_PROVIDER(MY_PROVIDER)
-//
-// 2. Define provider in source file 'provider.cpp':
-// #include "probes.h"
-// LWTRACE_DEFINE_PROVIDER(MY_PROVIDER)
-//
-// 3. Call probes from provider in your code:
-// #include "probes.h"
-// int main() {
-// GLOBAL_LWPROBE(MY_PROVIDER, MyProbe);
-// GLOBAL_LWPROBE(MY_PROVIDER, MyAnotherProbe, 123, stroka);
-// ... or ...
-// LWTRACE_USING(MY_PROVIDER); // expands into using namespace
-// LWPROBE(MyProbe);
-// LWPROBE(MyAnotherProbe, 123, stroka);
-// }
-//
-// 4. Attach provider to your monitoring service:
-// #include <yweb/robot/kiwi/util/monservice.h>
-// #include "probes.h"
-// class TMyMonSrvc: public NKiwi::TMonService {
-// TMyMonSrvc(TProbeRegistry& probes)
-// {
-// THolder<NKiwi::TTraceMonPage> tr(new NKiwi::TTraceMonPage());
-// tr->GetProbes().AddProbesList(LWTRACE_GET_PROBES(MY_PROVIDER));
-// Register(tr.Release());
-// }
-// };
-//
-// 5. Compile and run application
-//
-// 6. Create file 'mysuper.tr' with trace query:
-// Blocks { # Log all calls to probes from MyGroup1
-// ProbeDesc { Group: "MyGroup1" }
-// Action {
-// LogAction { LogTimestamp: true }
-// }
-// }
-// Blocks { # Log first 10 calls to MyAnother with arg1 > 1000
-// ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
-// Predicate {
-// Operators { Type: OT_GT; Param: "arg1"; Value: "1000" }
-// }
-// Action {
-// LogAction { MaxRecords: 10 }
-// }
-// }
-// Blocks { # Start following executon of all 4 blocks each time MyAnotherProbe was called with arg2 == "start"
-// ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
-// Predicate {
-// Operators { Type: OT_EQ; Param: "arg2"; Value: "start" }
-// }
-// Action { StartAction {} }
-// }
-// Blocks { # Stop following executon of all 4 blocks each time MyAnotherProbe was called with arg2 == "stop"
-// ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
-// Predicate {
-// Operators { Type: OT_EQ; Param: "arg2"; Value: "stop" }
-// }
-// Action { StopAction {} }
-// }
-//
-// 7. Send trace query to the server with HTTP POST:
-// yweb/robot/kiwi/scripts/trace.sh new uniq-id-for-my-trace hostname:monport < mysuper.tr
-//
-// 8. With browser go to: http://hostname:monport/trace
-//
-// 9. Delete query from server:
-// yweb/robot/kiwi/scripts/trace.sh delete uniq-id-for-my-trace hostname:monport
-//
-//
-// CONFIGURATION AND SUPPORT:
-// 1. Turning off all calls to probes.
-// Add to project's CMakeLists.txt: add_definitions(-DLWTRACE_DISABLE_PROBES)
-//
-// 2. Turning off all calls to events.
-// Add to project's CMakeLists.txt: add_definitions(-DLWTRACE_DISABLE_EVENTS)
-//
-// 3. Increasing maximum number of probe parameters:
-// Add more lines in FOREACH_PARAMNUM macro definition in preprocessor.h
-//
-//
-// ISSUES
-// 1. Note that executors for different blocks are attached in order of their declaration in trace script.
-// Executor can be called by a program as soon as it is attached, therefore there is no guarantee that
-// all blocks are started simultaneously
-//
-
-#ifndef LWTRACE_DISABLE
-
-// Declare user provider (see USAGE INSTRUCTION)
-#define LWTRACE_DECLARE_PROVIDER(provider) LWTRACE_DECLARE_PROVIDER_I(provider)
-
-// Define user provider (see USAGE INSTRUCTION)
-#define LWTRACE_DEFINE_PROVIDER(provider) LWTRACE_DEFINE_PROVIDER_I(provider)
-
-// Import names from provider
-#define LWTRACE_USING(provider) using namespace LWTRACE_GET_NAMESPACE(provider);
-
-// Probes and events list accessor
-#define LWTRACE_GET_PROBES(provider) LWTRACE_GET_PROBES_I(provider)
-#define LWTRACE_GET_EVENTS(provider) LWTRACE_GET_EVENTS_I(provider)
-
-#ifndef LWTRACE_DISABLE_PROBES
-
-// Call a probe
-// NOTE: LWPROBE() should be used in source files only with previous call to LWTRACE_USING(MY_PROVIDER)
-// NOTE: in header files GLOBAL_LWPROBE() should be used instead
-// NOTE: if lots of calls needed in header file, it's convenient to define/undef the following macro:
-// NOTE: #define MY_PROBE(name, ...) GLOBAL_LWPROBE(MY_PROVIDER, name, ## __VA_ARGS__)
-#define GLOBAL_LWPROBE(provider, probe, ...) LWPROBE_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
-#define LWPROBE(probe, ...) LWPROBE_I(LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
+// PROBE(MyScopedProbe, GROUPS(), TYPES(ui64, int), NAMES("duration", "stage")) \ // scoped probe with argument
+// /**/
+// LWTRACE_DECLARE_PROVIDER(MY_PROVIDER)
+//
+// 2. Define provider in source file 'provider.cpp':
+// #include "probes.h"
+// LWTRACE_DEFINE_PROVIDER(MY_PROVIDER)
+//
+// 3. Call probes from provider in your code:
+// #include "probes.h"
+// int main() {
+// GLOBAL_LWPROBE(MY_PROVIDER, MyProbe);
+// GLOBAL_LWPROBE(MY_PROVIDER, MyAnotherProbe, 123, stroka);
+// ... or ...
+// LWTRACE_USING(MY_PROVIDER); // expands into using namespace
+// LWPROBE(MyProbe);
+// LWPROBE(MyAnotherProbe, 123, stroka);
+// }
+//
+// 4. Attach provider to your monitoring service:
+// #include <yweb/robot/kiwi/util/monservice.h>
+// #include "probes.h"
+// class TMyMonSrvc: public NKiwi::TMonService {
+// TMyMonSrvc(TProbeRegistry& probes)
+// {
+// THolder<NKiwi::TTraceMonPage> tr(new NKiwi::TTraceMonPage());
+// tr->GetProbes().AddProbesList(LWTRACE_GET_PROBES(MY_PROVIDER));
+// Register(tr.Release());
+// }
+// };
+//
+// 5. Compile and run application
+//
+// 6. Create file 'mysuper.tr' with trace query:
+// Blocks { # Log all calls to probes from MyGroup1
+// ProbeDesc { Group: "MyGroup1" }
+// Action {
+// LogAction { LogTimestamp: true }
+// }
+// }
+// Blocks { # Log first 10 calls to MyAnother with arg1 > 1000
+// ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
+// Predicate {
+// Operators { Type: OT_GT; Param: "arg1"; Value: "1000" }
+// }
+// Action {
+// LogAction { MaxRecords: 10 }
+// }
+// }
+// Blocks { # Start following executon of all 4 blocks each time MyAnotherProbe was called with arg2 == "start"
+// ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
+// Predicate {
+// Operators { Type: OT_EQ; Param: "arg2"; Value: "start" }
+// }
+// Action { StartAction {} }
+// }
+// Blocks { # Stop following executon of all 4 blocks each time MyAnotherProbe was called with arg2 == "stop"
+// ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
+// Predicate {
+// Operators { Type: OT_EQ; Param: "arg2"; Value: "stop" }
+// }
+// Action { StopAction {} }
+// }
+//
+// 7. Send trace query to the server with HTTP POST:
+// yweb/robot/kiwi/scripts/trace.sh new uniq-id-for-my-trace hostname:monport < mysuper.tr
+//
+// 8. With browser go to: http://hostname:monport/trace
+//
+// 9. Delete query from server:
+// yweb/robot/kiwi/scripts/trace.sh delete uniq-id-for-my-trace hostname:monport
+//
+//
+// CONFIGURATION AND SUPPORT:
+// 1. Turning off all calls to probes.
+// Add to project's CMakeLists.txt: add_definitions(-DLWTRACE_DISABLE_PROBES)
+//
+// 2. Turning off all calls to events.
+// Add to project's CMakeLists.txt: add_definitions(-DLWTRACE_DISABLE_EVENTS)
+//
+// 3. Increasing maximum number of probe parameters:
+// Add more lines in FOREACH_PARAMNUM macro definition in preprocessor.h
+//
+//
+// ISSUES
+// 1. Note that executors for different blocks are attached in order of their declaration in trace script.
+// Executor can be called by a program as soon as it is attached, therefore there is no guarantee that
+// all blocks are started simultaneously
+//
+
+#ifndef LWTRACE_DISABLE
+
+// Declare user provider (see USAGE INSTRUCTION)
+#define LWTRACE_DECLARE_PROVIDER(provider) LWTRACE_DECLARE_PROVIDER_I(provider)
+
+// Define user provider (see USAGE INSTRUCTION)
+#define LWTRACE_DEFINE_PROVIDER(provider) LWTRACE_DEFINE_PROVIDER_I(provider)
+
+// Import names from provider
+#define LWTRACE_USING(provider) using namespace LWTRACE_GET_NAMESPACE(provider);
+
+// Probes and events list accessor
+#define LWTRACE_GET_PROBES(provider) LWTRACE_GET_PROBES_I(provider)
+#define LWTRACE_GET_EVENTS(provider) LWTRACE_GET_EVENTS_I(provider)
+
+#ifndef LWTRACE_DISABLE_PROBES
+
+// Call a probe
+// NOTE: LWPROBE() should be used in source files only with previous call to LWTRACE_USING(MY_PROVIDER)
+// NOTE: in header files GLOBAL_LWPROBE() should be used instead
+// NOTE: if lots of calls needed in header file, it's convenient to define/undef the following macro:
+// NOTE: #define MY_PROBE(name, ...) GLOBAL_LWPROBE(MY_PROVIDER, name, ## __VA_ARGS__)
+#define GLOBAL_LWPROBE(provider, probe, ...) LWPROBE_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
+#define LWPROBE(probe, ...) LWPROBE_I(LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
#define GLOBAL_LWPROBE_ENABLED(provider, probe) LWPROBE_ENABLED_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe))
#define LWPROBE_ENABLED(probe) LWPROBE_ENABLED_I(LWTRACE_GET_NAME(probe))
-#define LWPROBE_OBJ(probe, ...) LWPROBE_I(probe, ##__VA_ARGS__)
-
-// Calls a probe when scope is beeing left
-// NOTE: arguments are passed by value and stored until scope exit
-// NOTE: probe should be declared with first params of type ui64, argument for which is automaticaly generated (duration in microseconds)
-// NOTE: *_DURATION() macros take through "..." all arguments except the first one
-#define GLOBAL_LWPROBE_DURATION(provider, probe, ...) LWPROBE_DURATION_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_TYPE(probe), lwtrace_scoped_##provider##probe, LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
-#define LWPROBE_DURATION(probe, ...) LWPROBE_DURATION_I(LWTRACE_GET_TYPE(probe), lwtrace_scoped_##probe, LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
-
-// Probe with orbit support
-#define GLOBAL_LWTRACK(provider, probe, orbit, ...) LWTRACK_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), orbit, ##__VA_ARGS__)
-#define LWTRACK(probe, orbit, ...) LWTRACK_I(LWTRACE_GET_NAME(probe), orbit, ##__VA_ARGS__)
-#define LWTRACK_OBJ(probe, orbit, ...) LWTRACK_I(probe, orbit, ##__VA_ARGS__)
-
-#else
-#define GLOBAL_LWPROBE(provider, probe, ...)
-#define LWPROBE(probe, ...)
+#define LWPROBE_OBJ(probe, ...) LWPROBE_I(probe, ##__VA_ARGS__)
+
+// Calls a probe when scope is beeing left
+// NOTE: arguments are passed by value and stored until scope exit
+// NOTE: probe should be declared with first params of type ui64, argument for which is automaticaly generated (duration in microseconds)
+// NOTE: *_DURATION() macros take through "..." all arguments except the first one
+#define GLOBAL_LWPROBE_DURATION(provider, probe, ...) LWPROBE_DURATION_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_TYPE(probe), lwtrace_scoped_##provider##probe, LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
+#define LWPROBE_DURATION(probe, ...) LWPROBE_DURATION_I(LWTRACE_GET_TYPE(probe), lwtrace_scoped_##probe, LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
+
+// Probe with orbit support
+#define GLOBAL_LWTRACK(provider, probe, orbit, ...) LWTRACK_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), orbit, ##__VA_ARGS__)
+#define LWTRACK(probe, orbit, ...) LWTRACK_I(LWTRACE_GET_NAME(probe), orbit, ##__VA_ARGS__)
+#define LWTRACK_OBJ(probe, orbit, ...) LWTRACK_I(probe, orbit, ##__VA_ARGS__)
+
+#else
+#define GLOBAL_LWPROBE(provider, probe, ...)
+#define LWPROBE(probe, ...)
#define GLOBAL_LWPROBE_ENABLED(provider, probe) false
#define LWPROBE_ENABLED(probe) false
-#define LWPROBE_OBJ(probe, ...) Y_UNUSED(probe)
-#define GLOBAL_LWPROBE_DURATION(provider, probe, ...)
-#define LWPROBE_DURATION(probe, ...)
-#define GLOBAL_LWTRACK(provider, probe, orbit, ...)
-#define LWTRACK(probe, orbit, ...)
-#define LWTRACK_OBJ(probe, orbit, ...) Y_UNUSED(probe)
-#endif
-
-#ifndef LWTRACE_DISABLE_EVENTS
-
-// Call an event
-// NOTE: LWEVENT() should be used in source files only with previous call to LWTRACE_USING(MY_PROVIDER)
-// NOTE: in header files GLOBAL_LWEVENT() should be used instead
-// NOTE: if lots of calls needed in header file, it's convenient to define/undef the following macro:
-// NOTE: #define MY_EVENT(name, ...) GLOBAL_LWEVENT(MY_PROVIDER, name, ## __VA_ARGS__)
-#define GLOBAL_LWEVENT(provider, event, ...) LWEVENT_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(event), ##__VA_ARGS__)
-#define LWEVENT(event, ...) LWEVENT_I(LWTRACE_GET_NAME(event), ##__VA_ARGS__)
-
-#else
-#define GLOBAL_LWEVENT(provider, event, ...)
-#define LWEVENT(event, ...)
-#endif
-
-#else
-
-#define LWTRACE_DECLARE_PROVIDER(provider)
-#define LWTRACE_DEFINE_PROVIDER(provider)
-#define LWTRACE_USING(provider)
-#define LWTRACE_GET_PROBES(provider) NULL
-#define LWTRACE_GET_EVENTS(provider) NULL
-#define GLOBAL_LWPROBE(provider, probe, ...)
-#define LWPROBE(probe, ...)
+#define LWPROBE_OBJ(probe, ...) Y_UNUSED(probe)
+#define GLOBAL_LWPROBE_DURATION(provider, probe, ...)
+#define LWPROBE_DURATION(probe, ...)
+#define GLOBAL_LWTRACK(provider, probe, orbit, ...)
+#define LWTRACK(probe, orbit, ...)
+#define LWTRACK_OBJ(probe, orbit, ...) Y_UNUSED(probe)
+#endif
+
+#ifndef LWTRACE_DISABLE_EVENTS
+
+// Call an event
+// NOTE: LWEVENT() should be used in source files only with previous call to LWTRACE_USING(MY_PROVIDER)
+// NOTE: in header files GLOBAL_LWEVENT() should be used instead
+// NOTE: if lots of calls needed in header file, it's convenient to define/undef the following macro:
+// NOTE: #define MY_EVENT(name, ...) GLOBAL_LWEVENT(MY_PROVIDER, name, ## __VA_ARGS__)
+#define GLOBAL_LWEVENT(provider, event, ...) LWEVENT_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(event), ##__VA_ARGS__)
+#define LWEVENT(event, ...) LWEVENT_I(LWTRACE_GET_NAME(event), ##__VA_ARGS__)
+
+#else
+#define GLOBAL_LWEVENT(provider, event, ...)
+#define LWEVENT(event, ...)
+#endif
+
+#else
+
+#define LWTRACE_DECLARE_PROVIDER(provider)
+#define LWTRACE_DEFINE_PROVIDER(provider)
+#define LWTRACE_USING(provider)
+#define LWTRACE_GET_PROBES(provider) NULL
+#define LWTRACE_GET_EVENTS(provider) NULL
+#define GLOBAL_LWPROBE(provider, probe, ...)
+#define LWPROBE(probe, ...)
#define GLOBAL_LWPROBE_ENABLED(provider, probe) false
#define LWPROBE_ENABLED(probe) false
-#define GLOBAL_LWPROBE_DURATION(provider, probe, ...)
-#define LWPROBE_DURATION(probe, ...)
-#define GLOBAL_LWTRACK(provider, probe, orbit, ...)
-#define LWTRACK(probe, orbit, ...)
-#define GLOBAL_LWEVENT(provider, event, ...)
-#define LWEVENT(event, ...)
-
-#endif
+#define GLOBAL_LWPROBE_DURATION(provider, probe, ...)
+#define LWPROBE_DURATION(probe, ...)
+#define GLOBAL_LWTRACK(provider, probe, orbit, ...)
+#define LWTRACK(probe, orbit, ...)
+#define GLOBAL_LWEVENT(provider, event, ...)
+#define LWEVENT(event, ...)
+
+#endif
diff --git a/library/cpp/lwtrace/check.cpp b/library/cpp/lwtrace/check.cpp
index 4e34fc5d49..5f4da9712e 100644
--- a/library/cpp/lwtrace/check.cpp
+++ b/library/cpp/lwtrace/check.cpp
@@ -1,18 +1,18 @@
-#include "check.h"
+#include "check.h"
#include <util/stream/output.h>
-#include <util/string/cast.h>
-
-namespace NLWTrace {
- int TCheck::ObjCount = 0;
-}
-
-template <>
-NLWTrace::TCheck FromStringImpl(const char* data, size_t len) {
- return NLWTrace::TCheck(FromString<int, char>(data, len));
-}
-
-template <>
-void Out<NLWTrace::TCheck>(IOutputStream& o, TTypeTraits<NLWTrace::TCheck>::TFuncParam t) {
- Out<int>(o, t.Value);
-}
+#include <util/string/cast.h>
+
+namespace NLWTrace {
+ int TCheck::ObjCount = 0;
+}
+
+template <>
+NLWTrace::TCheck FromStringImpl(const char* data, size_t len) {
+ return NLWTrace::TCheck(FromString<int, char>(data, len));
+}
+
+template <>
+void Out<NLWTrace::TCheck>(IOutputStream& o, TTypeTraits<NLWTrace::TCheck>::TFuncParam t) {
+ Out<int>(o, t.Value);
+}
diff --git a/library/cpp/lwtrace/check.h b/library/cpp/lwtrace/check.h
index 71503cbc7b..e346e04dfb 100644
--- a/library/cpp/lwtrace/check.h
+++ b/library/cpp/lwtrace/check.h
@@ -1,78 +1,78 @@
-#pragma once
+#pragma once
+
+namespace NLWTrace {
+ struct TCheck {
+ int Value;
+ static int ObjCount;
+
+ TCheck()
+ : Value(0)
+ {
+ ObjCount++;
+ }
+
+ explicit TCheck(int value)
+ : Value(value)
+ {
+ ObjCount++;
+ }
+
+ TCheck(const TCheck& o)
+ : Value(o.Value)
+ {
+ ObjCount++;
+ }
+
+ ~TCheck() {
+ ObjCount--;
+ }
+
+ bool operator<(const TCheck& rhs) const {
+ return Value < rhs.Value;
+ }
+ bool operator>(const TCheck& rhs) const {
+ return Value > rhs.Value;
+ }
+ bool operator<=(const TCheck& rhs) const {
+ return Value <= rhs.Value;
+ }
+ bool operator>=(const TCheck& rhs) const {
+ return Value >= rhs.Value;
+ }
+ bool operator==(const TCheck& rhs) const {
+ return Value == rhs.Value;
+ }
+ bool operator!=(const TCheck& rhs) const {
+ return Value != rhs.Value;
+ }
+ TCheck operator+(const TCheck& rhs) const {
+ return TCheck(Value + rhs.Value);
+ }
+ TCheck operator-(const TCheck& rhs) const {
+ return TCheck(Value - rhs.Value);
+ }
+ TCheck operator*(const TCheck& rhs) const {
+ return TCheck(Value * rhs.Value);
+ }
+ TCheck operator/(const TCheck& rhs) const {
+ return TCheck(Value / rhs.Value);
+ }
+ TCheck operator%(const TCheck& rhs) const {
+ return TCheck(Value % rhs.Value);
+ }
+
+ void Add(const TCheck rhs) {
+ Value += rhs.Value;
+ }
+ void Sub(const TCheck rhs) {
+ Value -= rhs.Value;
+ }
+ void Inc() {
+ ++Value;
+ }
+ void Dec() {
+ --Value;
+ }
+ };
-namespace NLWTrace {
- struct TCheck {
- int Value;
- static int ObjCount;
-
- TCheck()
- : Value(0)
- {
- ObjCount++;
- }
-
- explicit TCheck(int value)
- : Value(value)
- {
- ObjCount++;
- }
-
- TCheck(const TCheck& o)
- : Value(o.Value)
- {
- ObjCount++;
- }
-
- ~TCheck() {
- ObjCount--;
- }
-
- bool operator<(const TCheck& rhs) const {
- return Value < rhs.Value;
- }
- bool operator>(const TCheck& rhs) const {
- return Value > rhs.Value;
- }
- bool operator<=(const TCheck& rhs) const {
- return Value <= rhs.Value;
- }
- bool operator>=(const TCheck& rhs) const {
- return Value >= rhs.Value;
- }
- bool operator==(const TCheck& rhs) const {
- return Value == rhs.Value;
- }
- bool operator!=(const TCheck& rhs) const {
- return Value != rhs.Value;
- }
- TCheck operator+(const TCheck& rhs) const {
- return TCheck(Value + rhs.Value);
- }
- TCheck operator-(const TCheck& rhs) const {
- return TCheck(Value - rhs.Value);
- }
- TCheck operator*(const TCheck& rhs) const {
- return TCheck(Value * rhs.Value);
- }
- TCheck operator/(const TCheck& rhs) const {
- return TCheck(Value / rhs.Value);
- }
- TCheck operator%(const TCheck& rhs) const {
- return TCheck(Value % rhs.Value);
- }
-
- void Add(const TCheck rhs) {
- Value += rhs.Value;
- }
- void Sub(const TCheck rhs) {
- Value -= rhs.Value;
- }
- void Inc() {
- ++Value;
- }
- void Dec() {
- --Value;
- }
- };
-
-}
+}
diff --git a/library/cpp/lwtrace/control.h b/library/cpp/lwtrace/control.h
index 16b24eafd2..478488e653 100644
--- a/library/cpp/lwtrace/control.h
+++ b/library/cpp/lwtrace/control.h
@@ -1,5 +1,5 @@
-#pragma once
-
+#pragma once
+
#include "custom_action.h"
#include "event.h"
#include "log.h"
@@ -10,199 +10,199 @@
#include <google/protobuf/repeated_field.h>
-#include <util/generic/deque.h>
-#include <util/generic/hash.h>
-#include <util/generic/noncopyable.h>
-#include <util/generic/ptr.h>
-#include <util/generic/set.h>
-#include <util/generic/vector.h>
-
-namespace NLWTrace {
+#include <util/generic/deque.h>
+#include <util/generic/hash.h>
+#include <util/generic/noncopyable.h>
+#include <util/generic/ptr.h>
+#include <util/generic/set.h>
+#include <util/generic/vector.h>
+
+namespace NLWTrace {
using TProbeMap = THashMap<std::pair<TString, TString>, TProbe*>;
- // Interface for probe ownership management
- class IBox: public virtual TThrRefBase {
- private:
- bool Owns;
+ // Interface for probe ownership management
+ class IBox: public virtual TThrRefBase {
+ private:
+ bool Owns;
- public:
- explicit IBox(bool ownsProbe = false)
- : Owns(ownsProbe)
+ public:
+ explicit IBox(bool ownsProbe = false)
+ : Owns(ownsProbe)
{
}
-
- bool OwnsProbe() {
- return Owns;
- }
-
- virtual TProbe* GetProbe() = 0;
- };
-
- using TBoxPtr = TIntrusivePtr<IBox>;
-
- // Simple not-owning box, that just holds pointer to static/global probe (e.g. created by LWTRACE_DEFINE_PROVIDER)
- class TStaticBox: public IBox {
- private:
- TProbe* Probe;
-
- public:
- explicit TStaticBox(TProbe* probe)
- : IBox(false)
- , Probe(probe)
+
+ bool OwnsProbe() {
+ return Owns;
+ }
+
+ virtual TProbe* GetProbe() = 0;
+ };
+
+ using TBoxPtr = TIntrusivePtr<IBox>;
+
+ // Simple not-owning box, that just holds pointer to static/global probe (e.g. created by LWTRACE_DEFINE_PROVIDER)
+ class TStaticBox: public IBox {
+ private:
+ TProbe* Probe;
+
+ public:
+ explicit TStaticBox(TProbe* probe)
+ : IBox(false)
+ , Probe(probe)
{
}
-
- TProbe* GetProbe() override {
- return Probe;
- }
- };
-
- // Just a set of unique probes
- // TODO[serxa]: get rid of different ProbeRegistries, use unique one (singleton) with auto registration
- class TProbeRegistry: public TNonCopyable {
- private:
- TMutex Mutex;
-
- // Probe* pointer uniquely identifies a probe and boxptr actually owns TProbe object (if required)
- using TProbes = THashMap<TProbe*, TBoxPtr>;
- TProbes Probes;
-
- // Probe provider-name pairs must be unique, keep track of them
- using TIds = TSet<std::pair<TString, TString>>;
- TIds Ids;
-
- public:
- // Add probes from null-terminated array of probe pointers. Probe can be added multiple times. Thread-safe.
- // Implies probes you pass will live forever (e.g. created by LWTRACE_DEFINE_PROVIDER)
- void AddProbesList(TProbe** reg);
-
- // Manage probes that are created/destructed dynamically
- void AddProbe(const TBoxPtr& box);
- void RemoveProbe(TProbe* probe);
-
- // Helper class to make thread-safe iteration over probes
- class TProbesAccessor {
- private:
- TGuard<TMutex> Guard;
- TProbes& Probes;
- public:
- explicit TProbesAccessor(TProbeRegistry* registry)
- : Guard(registry->Mutex)
- , Probes(registry->Probes)
- {}
-
- explicit TProbesAccessor(TProbeRegistry& registry)
- : TProbesAccessor(&registry)
- {}
-
- auto begin() { return Probes.begin(); }
- auto end() { return Probes.end(); }
- };
-
- friend class TProbesAccessor;
-
- private:
- void AddProbeNoLock(const TBoxPtr& box);
- void RemoveProbeNoLock(TProbe* probe);
- };
-
- // Represents a compiled trace query, holds executors attached to probes
- class TSession: public TNonCopyable {
- public:
- typedef THashMap<TString, TAtomicBase> TTraceVariables;
-
- private:
- const TInstant StartTime;
- const ui64 TraceIdx;
- TProbeRegistry& Registry;
- TDuration StoreDuration;
- TDuration ReadDuration;
- TCyclicLog CyclicLog;
- TDurationLog DurationLog;
- TCyclicDepot CyclicDepot;
- TDurationDepot DurationDepot;
- TAtomic LastTrackId;
+
+ TProbe* GetProbe() override {
+ return Probe;
+ }
+ };
+
+ // Just a set of unique probes
+ // TODO[serxa]: get rid of different ProbeRegistries, use unique one (singleton) with auto registration
+ class TProbeRegistry: public TNonCopyable {
+ private:
+ TMutex Mutex;
+
+ // Probe* pointer uniquely identifies a probe and boxptr actually owns TProbe object (if required)
+ using TProbes = THashMap<TProbe*, TBoxPtr>;
+ TProbes Probes;
+
+ // Probe provider-name pairs must be unique, keep track of them
+ using TIds = TSet<std::pair<TString, TString>>;
+ TIds Ids;
+
+ public:
+ // Add probes from null-terminated array of probe pointers. Probe can be added multiple times. Thread-safe.
+ // Implies probes you pass will live forever (e.g. created by LWTRACE_DEFINE_PROVIDER)
+ void AddProbesList(TProbe** reg);
+
+ // Manage probes that are created/destructed dynamically
+ void AddProbe(const TBoxPtr& box);
+ void RemoveProbe(TProbe* probe);
+
+ // Helper class to make thread-safe iteration over probes
+ class TProbesAccessor {
+ private:
+ TGuard<TMutex> Guard;
+ TProbes& Probes;
+ public:
+ explicit TProbesAccessor(TProbeRegistry* registry)
+ : Guard(registry->Mutex)
+ , Probes(registry->Probes)
+ {}
+
+ explicit TProbesAccessor(TProbeRegistry& registry)
+ : TProbesAccessor(&registry)
+ {}
+
+ auto begin() { return Probes.begin(); }
+ auto end() { return Probes.end(); }
+ };
+
+ friend class TProbesAccessor;
+
+ private:
+ void AddProbeNoLock(const TBoxPtr& box);
+ void RemoveProbeNoLock(TProbe* probe);
+ };
+
+ // Represents a compiled trace query, holds executors attached to probes
+ class TSession: public TNonCopyable {
+ public:
+ typedef THashMap<TString, TAtomicBase> TTraceVariables;
+
+ private:
+ const TInstant StartTime;
+ const ui64 TraceIdx;
+ TProbeRegistry& Registry;
+ TDuration StoreDuration;
+ TDuration ReadDuration;
+ TCyclicLog CyclicLog;
+ TDurationLog DurationLog;
+ TCyclicDepot CyclicDepot;
+ TDurationDepot DurationDepot;
+ TAtomic LastTrackId;
TAtomic LastSpanId;
- typedef TVector<std::pair<TProbe*, IExecutor*>> TProbes;
- TProbes Probes;
- bool Attached;
- NLWTrace::TQuery Query;
- TTraceVariables TraceVariables;
- TTraceResources TraceResources;
- void InsertExecutor(TTraceVariables& traceVariables,
- size_t bi, const NLWTrace::TPredicate* pred,
- const google::protobuf::RepeatedPtrField<NLWTrace::TAction>& actions,
- TProbe* probe, const bool destructiveActionsAllowed,
- const TCustomActionFactory& customActionFactory);
-
- private:
- void Destroy();
-
- public:
- TSession(ui64 traceIdx,
- TProbeRegistry& registry,
- const NLWTrace::TQuery& query,
- const bool destructiveActionsAllowed,
- const TCustomActionFactory& customActionFactory);
- ~TSession();
- void Detach();
- size_t GetEventsCount() const;
- size_t GetThreadsCount() const;
- const NLWTrace::TQuery& GetQuery() const {
- return Query;
- }
- TInstant GetStartTime() const {
- return StartTime;
- }
- ui64 GetTraceIdx() const {
- return TraceIdx;
- }
- TTraceResources& Resources() {
- return TraceResources;
- }
- const TTraceResources& Resources() const {
- return TraceResources;
- }
-
- template <class TReader>
- void ReadThreads(TReader& r) const {
- CyclicLog.ReadThreads(r);
- DurationLog.ReadThreads(r);
- }
-
- template <class TReader>
- void ReadItems(TReader& r) const {
- CyclicLog.ReadItems(r);
- DurationLog.ReadItems(GetCycleCount(), DurationToCycles(ReadDuration), r);
- }
-
- template <class TReader>
- void ReadItems(ui64 now, ui64 duration, TReader& r) const {
- CyclicLog.ReadItems(r);
- DurationLog.ReadItems(now, duration, r);
- }
-
- template <class TReader>
- void ReadDepotThreads(TReader& r) const {
- CyclicDepot.ReadThreads(r);
- DurationDepot.ReadThreads(r);
- }
-
- template <class TReader>
- void ReadDepotItems(TReader& r) const {
- CyclicDepot.ReadItems(r);
- DurationDepot.ReadItems(GetCycleCount(), DurationToCycles(ReadDuration), r);
- }
-
- template <class TReader>
- void ReadDepotItems(ui64 now, ui64 duration, TReader& r) const {
- CyclicDepot.ReadItems(r);
- DurationDepot.ReadItems(now, duration, r);
- }
- void ToProtobuf(TLogPb& pb) const;
- };
-
+ typedef TVector<std::pair<TProbe*, IExecutor*>> TProbes;
+ TProbes Probes;
+ bool Attached;
+ NLWTrace::TQuery Query;
+ TTraceVariables TraceVariables;
+ TTraceResources TraceResources;
+ void InsertExecutor(TTraceVariables& traceVariables,
+ size_t bi, const NLWTrace::TPredicate* pred,
+ const google::protobuf::RepeatedPtrField<NLWTrace::TAction>& actions,
+ TProbe* probe, const bool destructiveActionsAllowed,
+ const TCustomActionFactory& customActionFactory);
+
+ private:
+ void Destroy();
+
+ public:
+ TSession(ui64 traceIdx,
+ TProbeRegistry& registry,
+ const NLWTrace::TQuery& query,
+ const bool destructiveActionsAllowed,
+ const TCustomActionFactory& customActionFactory);
+ ~TSession();
+ void Detach();
+ size_t GetEventsCount() const;
+ size_t GetThreadsCount() const;
+ const NLWTrace::TQuery& GetQuery() const {
+ return Query;
+ }
+ TInstant GetStartTime() const {
+ return StartTime;
+ }
+ ui64 GetTraceIdx() const {
+ return TraceIdx;
+ }
+ TTraceResources& Resources() {
+ return TraceResources;
+ }
+ const TTraceResources& Resources() const {
+ return TraceResources;
+ }
+
+ template <class TReader>
+ void ReadThreads(TReader& r) const {
+ CyclicLog.ReadThreads(r);
+ DurationLog.ReadThreads(r);
+ }
+
+ template <class TReader>
+ void ReadItems(TReader& r) const {
+ CyclicLog.ReadItems(r);
+ DurationLog.ReadItems(GetCycleCount(), DurationToCycles(ReadDuration), r);
+ }
+
+ template <class TReader>
+ void ReadItems(ui64 now, ui64 duration, TReader& r) const {
+ CyclicLog.ReadItems(r);
+ DurationLog.ReadItems(now, duration, r);
+ }
+
+ template <class TReader>
+ void ReadDepotThreads(TReader& r) const {
+ CyclicDepot.ReadThreads(r);
+ DurationDepot.ReadThreads(r);
+ }
+
+ template <class TReader>
+ void ReadDepotItems(TReader& r) const {
+ CyclicDepot.ReadItems(r);
+ DurationDepot.ReadItems(GetCycleCount(), DurationToCycles(ReadDuration), r);
+ }
+
+ template <class TReader>
+ void ReadDepotItems(ui64 now, ui64 duration, TReader& r) const {
+ CyclicDepot.ReadItems(r);
+ DurationDepot.ReadItems(now, duration, r);
+ }
+ void ToProtobuf(TLogPb& pb) const;
+ };
+
// Deserialization result.
// Either IsSuccess is true or FailedEventNames contains event names
// we were not able to deserialize.
@@ -218,112 +218,112 @@ namespace NLWTrace {
}
};
- // Just a registry of all active trace queries
- // Facade for all interactions with probes/traces
- class TManager: public TNonCopyable {
- private:
- TProbeRegistry& Registry;
- TMutex Mtx;
+ // Just a registry of all active trace queries
+ // Facade for all interactions with probes/traces
+ class TManager: public TNonCopyable {
+ private:
+ TProbeRegistry& Registry;
+ TMutex Mtx;
ui64 LastTraceIdx = 1;
- typedef THashMap<TString, TSession*> TTraces; // traceId -> TSession
- TTraces Traces;
- bool DestructiveActionsAllowed;
- TCustomActionFactory CustomActionFactory;
+ typedef THashMap<TString, TSession*> TTraces; // traceId -> TSession
+ TTraces Traces;
+ bool DestructiveActionsAllowed;
+ TCustomActionFactory CustomActionFactory;
THolder<TRunLogShuttleActionExecutor<TCyclicDepot>> SerializingExecutor;
-
- public:
+
+ public:
static constexpr ui64 RemoteTraceIdx = 0;
public:
- TManager(TProbeRegistry& registry, bool allowDestructiveActions);
- ~TManager();
- bool HasTrace(const TString& id) const;
- const TSession* GetTrace(const TString& id) const;
- void New(const TString& id, const NLWTrace::TQuery& query);
- void Delete(const TString& id);
- void Stop(const TString& id);
-
- template <class TReader>
- void ReadProbes(TReader& reader) const {
- TProbeRegistry::TProbesAccessor probes(Registry);
- for (auto& kv : probes) {
- TProbe* probe = kv.first;
- reader.Push(probe);
- }
- }
-
- template <class TReader>
- void ReadTraces(TReader& reader) const {
- TGuard<TMutex> g(Mtx);
- for (const auto& Trace : Traces) {
- const TString& id = Trace.first;
- const TSession* trace = Trace.second;
- reader.Push(id, trace);
- }
- }
-
- template <class TReader>
- void ReadLog(const TString& id, TReader& reader) {
- TGuard<TMutex> g(Mtx);
- TTraces::iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- TSession* trace = it->second;
- trace->ReadItems(reader);
- }
- }
-
- template <class TReader>
- void ReadLog(const TString& id, ui64 now, TReader& reader) {
- TGuard<TMutex> g(Mtx);
- TTraces::iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- TSession* trace = it->second;
- trace->ReadItems(now, reader);
- }
- }
-
- template <class TReader>
- void ReadDepot(const TString& id, TReader& reader) {
- TGuard<TMutex> g(Mtx);
- TTraces::iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- TSession* trace = it->second;
- trace->ReadDepotItems(reader);
- }
- }
-
- template <class TReader>
- void ReadDepot(const TString& id, ui64 now, TReader& reader) {
- TGuard<TMutex> g(Mtx);
- TTraces::iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- TSession* trace = it->second;
- trace->ReadDepotItems(now, reader);
- }
- }
-
- bool GetDestructiveActionsAllowed() {
- return DestructiveActionsAllowed;
- }
-
- void RegisterCustomAction(const TString& name, const TCustomActionFactory::TCallback& callback) {
- CustomActionFactory.Register(name, callback);
- }
-
- template <class T>
- void RegisterCustomAction() {
- CustomActionFactory.Register(T::GetActionName(), [=](TProbe* probe, const TCustomAction& action, TSession* trace) {
- return new T(probe, action, trace);
- });
- }
+ TManager(TProbeRegistry& registry, bool allowDestructiveActions);
+ ~TManager();
+ bool HasTrace(const TString& id) const;
+ const TSession* GetTrace(const TString& id) const;
+ void New(const TString& id, const NLWTrace::TQuery& query);
+ void Delete(const TString& id);
+ void Stop(const TString& id);
+
+ template <class TReader>
+ void ReadProbes(TReader& reader) const {
+ TProbeRegistry::TProbesAccessor probes(Registry);
+ for (auto& kv : probes) {
+ TProbe* probe = kv.first;
+ reader.Push(probe);
+ }
+ }
+
+ template <class TReader>
+ void ReadTraces(TReader& reader) const {
+ TGuard<TMutex> g(Mtx);
+ for (const auto& Trace : Traces) {
+ const TString& id = Trace.first;
+ const TSession* trace = Trace.second;
+ reader.Push(id, trace);
+ }
+ }
+
+ template <class TReader>
+ void ReadLog(const TString& id, TReader& reader) {
+ TGuard<TMutex> g(Mtx);
+ TTraces::iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ TSession* trace = it->second;
+ trace->ReadItems(reader);
+ }
+ }
+
+ template <class TReader>
+ void ReadLog(const TString& id, ui64 now, TReader& reader) {
+ TGuard<TMutex> g(Mtx);
+ TTraces::iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ TSession* trace = it->second;
+ trace->ReadItems(now, reader);
+ }
+ }
+
+ template <class TReader>
+ void ReadDepot(const TString& id, TReader& reader) {
+ TGuard<TMutex> g(Mtx);
+ TTraces::iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ TSession* trace = it->second;
+ trace->ReadDepotItems(reader);
+ }
+ }
+
+ template <class TReader>
+ void ReadDepot(const TString& id, ui64 now, TReader& reader) {
+ TGuard<TMutex> g(Mtx);
+ TTraces::iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ TSession* trace = it->second;
+ trace->ReadDepotItems(now, reader);
+ }
+ }
+
+ bool GetDestructiveActionsAllowed() {
+ return DestructiveActionsAllowed;
+ }
+
+ void RegisterCustomAction(const TString& name, const TCustomActionFactory::TCallback& callback) {
+ CustomActionFactory.Register(name, callback);
+ }
+
+ template <class T>
+ void RegisterCustomAction() {
+ CustomActionFactory.Register(T::GetActionName(), [=](TProbe* probe, const TCustomAction& action, TSession* trace) {
+ return new T(probe, action, trace);
+ });
+ }
TProbeMap GetProbesMap();
@@ -347,5 +347,5 @@ namespace NLWTrace {
bool IsTraced(TOrbit& orbit) {
return orbit.HasShuttle(TManager::RemoteTraceIdx);
}
- };
-}
+ };
+}
diff --git a/library/cpp/lwtrace/custom_action.cpp b/library/cpp/lwtrace/custom_action.cpp
index a379b34ec0..dc97b44ac0 100644
--- a/library/cpp/lwtrace/custom_action.cpp
+++ b/library/cpp/lwtrace/custom_action.cpp
@@ -1,21 +1,21 @@
-#include "custom_action.h"
+#include "custom_action.h"
#include "control.h"
using namespace NLWTrace;
-TCustomActionExecutor* TCustomActionFactory::Create(TProbe* probe, const TCustomAction& action, TSession* trace) const {
- auto iter = Callbacks.find(action.GetName());
- if (iter != Callbacks.end()) {
- return iter->second(probe, action, trace);
- } else {
- return nullptr;
- }
+TCustomActionExecutor* TCustomActionFactory::Create(TProbe* probe, const TCustomAction& action, TSession* trace) const {
+ auto iter = Callbacks.find(action.GetName());
+ if (iter != Callbacks.end()) {
+ return iter->second(probe, action, trace);
+ } else {
+ return nullptr;
+ }
}
-
-void TCustomActionFactory::Register(const TString& name, const TCustomActionFactory::TCallback& callback) {
+
+void TCustomActionFactory::Register(const TString& name, const TCustomActionFactory::TCallback& callback) {
if (Callbacks.contains(name)) {
- ythrow yexception() << "duplicate custom action '" << name << "'";
- }
- Callbacks[name] = callback;
-}
+ ythrow yexception() << "duplicate custom action '" << name << "'";
+ }
+ Callbacks[name] = callback;
+}
diff --git a/library/cpp/lwtrace/custom_action.h b/library/cpp/lwtrace/custom_action.h
index 92a3c66b84..6d950a39e1 100644
--- a/library/cpp/lwtrace/custom_action.h
+++ b/library/cpp/lwtrace/custom_action.h
@@ -8,68 +8,68 @@
#include <functional>
-namespace NLWTrace {
- class TSession;
+namespace NLWTrace {
+ class TSession;
- // Custom action can save any stuff (derived from IResource) in TSession object
- // IMPORTANT: Derived class will be used from multiple threads! (see example3)
- class IResource: public TAtomicRefCount<IResource> {
- public:
- virtual ~IResource() {
- }
- };
- using TResourcePtr = TIntrusivePtr<IResource>;
+ // Custom action can save any stuff (derived from IResource) in TSession object
+ // IMPORTANT: Derived class will be used from multiple threads! (see example3)
+ class IResource: public TAtomicRefCount<IResource> {
+ public:
+ virtual ~IResource() {
+ }
+ };
+ using TResourcePtr = TIntrusivePtr<IResource>;
+
+ // Trace resources that is used to hold/get/create any stuff
+ class TTraceResources: public THashMap<TString, TResourcePtr> {
+ public:
+ template <class T>
+ T& Get(const TString& name) {
+ auto iter = find(name);
+ if (iter == end()) {
+ iter = insert(value_type(name, TResourcePtr(new T()))).first;
+ }
+ return *static_cast<T*>(iter->second.Get());
+ }
+
+ template <class T>
+ const T* GetOrNull(const TString& name) const {
+ auto iter = find(name);
+ if (iter == end()) {
+ return nullptr;
+ }
+ return *iter->second;
+ }
+ };
+
+ // Base class of all custom actions
+ class TCustomActionExecutor: public IExecutor {
+ protected:
+ TProbe* const Probe;
+ bool Destructive;
+
+ public:
+ TCustomActionExecutor(TProbe* probe, bool destructive)
+ : IExecutor()
+ , Probe(probe)
+ , Destructive(destructive)
+ {
+ }
+
+ bool IsDestructive() {
+ return Destructive;
+ }
+ };
- // Trace resources that is used to hold/get/create any stuff
- class TTraceResources: public THashMap<TString, TResourcePtr> {
- public:
- template <class T>
- T& Get(const TString& name) {
- auto iter = find(name);
- if (iter == end()) {
- iter = insert(value_type(name, TResourcePtr(new T()))).first;
- }
- return *static_cast<T*>(iter->second.Get());
- }
-
- template <class T>
- const T* GetOrNull(const TString& name) const {
- auto iter = find(name);
- if (iter == end()) {
- return nullptr;
- }
- return *iter->second;
- }
- };
-
- // Base class of all custom actions
- class TCustomActionExecutor: public IExecutor {
- protected:
- TProbe* const Probe;
- bool Destructive;
-
- public:
- TCustomActionExecutor(TProbe* probe, bool destructive)
- : IExecutor()
- , Probe(probe)
- , Destructive(destructive)
- {
- }
-
- bool IsDestructive() {
- return Destructive;
- }
- };
-
- // Factory to produce custom action executors
- class TCustomActionFactory {
- public:
- using TCallback = std::function<TCustomActionExecutor*(TProbe* probe, const TCustomAction& action, TSession* trace)>;
- TCustomActionExecutor* Create(TProbe* probe, const TCustomAction& action, TSession* trace) const;
- void Register(const TString& name, const TCallback& callback);
-
- private:
- THashMap<TString, TCallback> Callbacks;
- };
-
-}
+ // Factory to produce custom action executors
+ class TCustomActionFactory {
+ public:
+ using TCallback = std::function<TCustomActionExecutor*(TProbe* probe, const TCustomAction& action, TSession* trace)>;
+ TCustomActionExecutor* Create(TProbe* probe, const TCustomAction& action, TSession* trace) const;
+ void Register(const TString& name, const TCallback& callback);
+
+ private:
+ THashMap<TString, TCallback> Callbacks;
+ };
+
+}
diff --git a/library/cpp/lwtrace/event.h b/library/cpp/lwtrace/event.h
index e53a620c45..417ec823d8 100644
--- a/library/cpp/lwtrace/event.h
+++ b/library/cpp/lwtrace/event.h
@@ -1,29 +1,29 @@
-#pragma once
-
+#pragma once
+
#include "preprocessor.h"
-#include "signature.h"
+#include "signature.h"
#include "param_traits.h"
#include <library/cpp/lwtrace/protos/lwtrace.pb.h>
-
-namespace NLWTrace {
- // Common class for all events
- struct TEvent {
- const char* Name;
- const char* Groups[LWTRACE_MAX_GROUPS + 1];
- TSignature Signature;
-
- const char* GetProvider() const {
- return Groups[0];
- }
-
- void ToProtobuf(TEventPb& pb) const {
- pb.SetName(Name);
- for (const char* const* gi = Groups; *gi != nullptr; gi++) {
- pb.AddGroups(*gi);
- }
- Signature.ToProtobuf(pb);
- }
- };
-
-}
+
+namespace NLWTrace {
+ // Common class for all events
+ struct TEvent {
+ const char* Name;
+ const char* Groups[LWTRACE_MAX_GROUPS + 1];
+ TSignature Signature;
+
+ const char* GetProvider() const {
+ return Groups[0];
+ }
+
+ void ToProtobuf(TEventPb& pb) const {
+ pb.SetName(Name);
+ for (const char* const* gi = Groups; *gi != nullptr; gi++) {
+ pb.AddGroups(*gi);
+ }
+ Signature.ToProtobuf(pb);
+ }
+ };
+
+}
diff --git a/library/cpp/lwtrace/example1/lwtrace_example1.cpp b/library/cpp/lwtrace/example1/lwtrace_example1.cpp
index 6b32c405ee..ff6891ec18 100644
--- a/library/cpp/lwtrace/example1/lwtrace_example1.cpp
+++ b/library/cpp/lwtrace/example1/lwtrace_example1.cpp
@@ -1,6 +1,6 @@
#include <library/cpp/lwtrace/all.h>
-#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
+#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
PROBE(IterationProbe, GROUPS(), TYPES(i32, double), NAMES("n", "result")) \
/**/
@@ -11,7 +11,7 @@ void InitLWTrace() {
NLWTrace::StartLwtraceFromEnv();
}
-long double Fact(int n) {
+long double Fact(int n) {
if (n < 0) {
ythrow yexception() << "N! is undefined for negative N (" << n << ")";
}
diff --git a/library/cpp/lwtrace/example2/lwtrace_example2.cpp b/library/cpp/lwtrace/example2/lwtrace_example2.cpp
index 7a4f7a1daf..faf95a7c61 100644
--- a/library/cpp/lwtrace/example2/lwtrace_example2.cpp
+++ b/library/cpp/lwtrace/example2/lwtrace_example2.cpp
@@ -5,18 +5,18 @@
#include <google/protobuf/text_format.h>
#include <util/stream/file.h>
-#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
- PROBE(StartupProbe, GROUPS(), TYPES(), NAMES()) \
- PROBE(IterationProbe, GROUPS(), TYPES(i64, double), NAMES("n", "result")) \
+#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
+ PROBE(StartupProbe, GROUPS(), TYPES(), NAMES()) \
+ PROBE(IterationProbe, GROUPS(), TYPES(i64, double), NAMES("n", "result")) \
PROBE(DurationProbe, GROUPS(), TYPES(ui64, i64, double), NAMES("duration", "n", "result")) \
- PROBE(ResultProbe, GROUPS(), TYPES(double), NAMES("factN")) \
- PROBE(AfterInputProbe, GROUPS(), TYPES(i32), NAMES("n")) \
+ PROBE(ResultProbe, GROUPS(), TYPES(double), NAMES("factN")) \
+ PROBE(AfterInputProbe, GROUPS(), TYPES(i32), NAMES("n")) \
/**/
LWTRACE_DECLARE_PROVIDER(LWTRACE_EXAMPLE_PROVIDER)
LWTRACE_DEFINE_PROVIDER(LWTRACE_EXAMPLE_PROVIDER)
-THolder<NLWTrace::TManager> traceManager;
+THolder<NLWTrace::TManager> traceManager;
struct TConfig {
bool UnsafeLWTrace;
@@ -24,7 +24,7 @@ struct TConfig {
};
void InitLWTrace(TConfig& cfg) {
- traceManager.Reset(new NLWTrace::TManager(*Singleton<NLWTrace::TProbeRegistry>(), cfg.UnsafeLWTrace));
+ traceManager.Reset(new NLWTrace::TManager(*Singleton<NLWTrace::TProbeRegistry>(), cfg.UnsafeLWTrace));
}
void AddLWTraceRequest(TConfig& cfg) {
@@ -36,7 +36,7 @@ void AddLWTraceRequest(TConfig& cfg) {
class TLogReader {
public:
- void Push(TThread::TId tid, const NLWTrace::TCyclicLog::TItem& item) {
+ void Push(TThread::TId tid, const NLWTrace::TCyclicLog::TItem& item) {
Cout << "tid=" << tid << " probe=" << item.Probe->Event.Name;
if (item.Timestamp != TInstant::Zero()) {
Cout << " time=" << item.Timestamp;
@@ -59,7 +59,7 @@ void DisplayLWTraceLog() {
traceManager->ReadLog("TraceRequest1", reader);
}
-long double Fact(i64 n) {
+long double Fact(i64 n) {
if (n < 0) {
ythrow yexception() << "N! is undefined for negative N (" << n << ")";
}
@@ -94,14 +94,14 @@ int main(int argc, char** argv) {
using namespace NLastGetopt;
TOpts opts = NLastGetopt::TOpts::Default();
opts.AddLongOption('u', "unsafe-lwtrace",
- "allow destructive LWTrace actions")
- .OptionalValue(ToString(true))
- .DefaultValue(ToString(false))
- .StoreResult(&cfg.UnsafeLWTrace);
+ "allow destructive LWTrace actions")
+ .OptionalValue(ToString(true))
+ .DefaultValue(ToString(false))
+ .StoreResult(&cfg.UnsafeLWTrace);
opts.AddLongOption('f', "trace-request",
- "specify a file containing LWTrace request")
- .DefaultValue("example_query.tr")
- .StoreResult(&cfg.TraceRequestPath);
+ "specify a file containing LWTrace request")
+ .DefaultValue("example_query.tr")
+ .StoreResult(&cfg.TraceRequestPath);
opts.AddHelpOption('h');
TOptsParseResult res(&opts, argc, argv);
diff --git a/library/cpp/lwtrace/example3/example_query.tr b/library/cpp/lwtrace/example3/example_query.tr
index 1f841b0932..e53c21c02d 100644
--- a/library/cpp/lwtrace/example3/example_query.tr
+++ b/library/cpp/lwtrace/example3/example_query.tr
@@ -4,10 +4,10 @@ Blocks {
Provider: "LWTRACE_EXAMPLE_PROVIDER"
}
Action {
- CustomAction {
- Name: "MyAction"
- Opts: "/dev/stdout"
- }
+ CustomAction {
+ Name: "MyAction"
+ Opts: "/dev/stdout"
+ }
}
}
diff --git a/library/cpp/lwtrace/example3/lwtrace_example3.cpp b/library/cpp/lwtrace/example3/lwtrace_example3.cpp
index 4493dc0077..2fa2976a69 100644
--- a/library/cpp/lwtrace/example3/lwtrace_example3.cpp
+++ b/library/cpp/lwtrace/example3/lwtrace_example3.cpp
@@ -1,8 +1,8 @@
#include <library/cpp/lwtrace/all.h>
#include <google/protobuf/text_format.h>
-#include "my_action.h"
+#include "my_action.h"
-#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
+#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
PROBE(IterationProbe, GROUPS(), TYPES(i32, double), NAMES("n", "result")) \
/**/
@@ -10,12 +10,12 @@ LWTRACE_DECLARE_PROVIDER(LWTRACE_EXAMPLE_PROVIDER)
LWTRACE_DEFINE_PROVIDER(LWTRACE_EXAMPLE_PROVIDER)
void InitLWTrace() {
- NLWTrace::StartLwtraceFromEnv([=](NLWTrace::TManager& mngr) {
- mngr.RegisterCustomAction<TMyActionExecutor>();
- });
+ NLWTrace::StartLwtraceFromEnv([=](NLWTrace::TManager& mngr) {
+ mngr.RegisterCustomAction<TMyActionExecutor>();
+ });
}
-long double Fact(int n) {
+long double Fact(int n) {
if (n < 0) {
ythrow yexception() << "N! is undefined for negative N (" << n << ")";
}
diff --git a/library/cpp/lwtrace/example3/my_action.h b/library/cpp/lwtrace/example3/my_action.h
index 9a04293ba2..80a34ecca8 100644
--- a/library/cpp/lwtrace/example3/my_action.h
+++ b/library/cpp/lwtrace/example3/my_action.h
@@ -1,85 +1,85 @@
-#pragma once
-
+#pragma once
+
#include <library/cpp/lwtrace/all.h>
-#include <util/stream/file.h>
-
-// Example of custom state for custom executors
-// Holds file for output from TMyActionExecutor
-class TMyFile: public NLWTrace::IResource {
-private:
- TMutex Mutex;
+#include <util/stream/file.h>
+
+// Example of custom state for custom executors
+// Holds file for output from TMyActionExecutor
+class TMyFile: public NLWTrace::IResource {
+private:
+ TMutex Mutex;
THolder<TUnbufferedFileOutput> File;
-
-public:
- // Note that this class must have default ctor (it's declared here just for clearness)
- TMyFile() {
- }
-
- // Note that dtor will be called by TManager::Delete() after detachment and destruction of all executors
- ~TMyFile() {
- }
-
- // Some kind of state initialization
- // Can be called only from executor constructor, and should not be thread-safe
- void Open(const TString& path) {
- if (File) {
- // We must avoid double open because each executor will call Open() on the same object
- // if the same file was specified in Opts
- return;
- }
+
+public:
+ // Note that this class must have default ctor (it's declared here just for clearness)
+ TMyFile() {
+ }
+
+ // Note that dtor will be called by TManager::Delete() after detachment and destruction of all executors
+ ~TMyFile() {
+ }
+
+ // Some kind of state initialization
+ // Can be called only from executor constructor, and should not be thread-safe
+ void Open(const TString& path) {
+ if (File) {
+ // We must avoid double open because each executor will call Open() on the same object
+ // if the same file was specified in Opts
+ return;
+ }
File.Reset(new TUnbufferedFileOutput(path));
- }
-
- // Outputs a line to opened file
- // Can be called from DoExecute() and must be thread-safe
- void Output(const TString& line) {
- Y_VERIFY(File);
- TGuard<TMutex> g(Mutex); // Because DoExecute() call can come from any thread
- *File << line << Endl;
- }
-};
-
-// Action that prints events to specified file
-class TMyActionExecutor: public NLWTrace::TCustomActionExecutor {
-private:
- TMyFile& File;
-
-public:
- TMyActionExecutor(NLWTrace::TProbe* probe, const NLWTrace::TCustomAction& action, NLWTrace::TSession* session)
- : NLWTrace::TCustomActionExecutor(probe, false /* not destructive */)
- , File(session->Resources().Get<TMyFile>("FileHolder/" + action.GetOpts(0))) // unique state id must include your d
- {
- if (action.GetOpts().size() != 1) {
- yexception() << "wrong number of Opts in MyAction";
- }
- File.Open(action.GetOpts(0));
- }
-
- static const char* GetActionName() {
- static const char name[] = "MyAction";
- return name;
- }
-
-private:
- virtual bool DoExecute(NLWTrace::TOrbit&, const NLWTrace::TParams& params) {
- // Serialize param values to strings
+ }
+
+ // Outputs a line to opened file
+ // Can be called from DoExecute() and must be thread-safe
+ void Output(const TString& line) {
+ Y_VERIFY(File);
+ TGuard<TMutex> g(Mutex); // Because DoExecute() call can come from any thread
+ *File << line << Endl;
+ }
+};
+
+// Action that prints events to specified file
+class TMyActionExecutor: public NLWTrace::TCustomActionExecutor {
+private:
+ TMyFile& File;
+
+public:
+ TMyActionExecutor(NLWTrace::TProbe* probe, const NLWTrace::TCustomAction& action, NLWTrace::TSession* session)
+ : NLWTrace::TCustomActionExecutor(probe, false /* not destructive */)
+ , File(session->Resources().Get<TMyFile>("FileHolder/" + action.GetOpts(0))) // unique state id must include your d
+ {
+ if (action.GetOpts().size() != 1) {
+ yexception() << "wrong number of Opts in MyAction";
+ }
+ File.Open(action.GetOpts(0));
+ }
+
+ static const char* GetActionName() {
+ static const char name[] = "MyAction";
+ return name;
+ }
+
+private:
+ virtual bool DoExecute(NLWTrace::TOrbit&, const NLWTrace::TParams& params) {
+ // Serialize param values to strings
TString paramValues[LWTRACE_MAX_PARAMS];
- Probe->Event.Signature.SerializeParams(params, paramValues);
-
- // Generate output line
- TStringStream ss;
- ss << "TMyActionExecutor>>> ";
- ss << Probe->Event.Name;
- for (ui32 i = 0; i < Probe->Event.Signature.ParamCount; ++i) {
- ss << " " << Probe->Event.Signature.ParamNames[i] << "=" << paramValues[i];
- }
-
- // Write line to file
- File.Output(ss.Str());
-
- // Executors can chain if you specify multiple actions in one block (in trace query).
- // So return true to continue execution of actions for given trace query block (on current triggered event)
- // or return false if this action is the last for this block
- return true;
- }
-};
+ Probe->Event.Signature.SerializeParams(params, paramValues);
+
+ // Generate output line
+ TStringStream ss;
+ ss << "TMyActionExecutor>>> ";
+ ss << Probe->Event.Name;
+ for (ui32 i = 0; i < Probe->Event.Signature.ParamCount; ++i) {
+ ss << " " << Probe->Event.Signature.ParamNames[i] << "=" << paramValues[i];
+ }
+
+ // Write line to file
+ File.Output(ss.Str());
+
+ // Executors can chain if you specify multiple actions in one block (in trace query).
+ // So return true to continue execution of actions for given trace query block (on current triggered event)
+ // or return false if this action is the last for this block
+ return true;
+ }
+};
diff --git a/library/cpp/lwtrace/example3/start_with_query.sh b/library/cpp/lwtrace/example3/start_with_query.sh
index 5cd221856f..09f4395f7c 100755
--- a/library/cpp/lwtrace/example3/start_with_query.sh
+++ b/library/cpp/lwtrace/example3/start_with_query.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-echo "Executing program with following trace query:"
-cat example_query.tr
-echo -n "Press any key to start program"
-read
-LWTRACE="example_query.tr" ./lwtrace-example3
+echo "Executing program with following trace query:"
+cat example_query.tr
+echo -n "Press any key to start program"
+read
+LWTRACE="example_query.tr" ./lwtrace-example3
diff --git a/library/cpp/lwtrace/example3/ya.make b/library/cpp/lwtrace/example3/ya.make
index c5b31586e9..e3a16da2b2 100644
--- a/library/cpp/lwtrace/example3/ya.make
+++ b/library/cpp/lwtrace/example3/ya.make
@@ -1,9 +1,9 @@
-PROGRAM(lwtrace-example3)
+PROGRAM(lwtrace-example3)
-OWNER(serxa)
+OWNER(serxa)
SRCS(
- lwtrace_example3.cpp
+ lwtrace_example3.cpp
)
PEERDIR(
diff --git a/library/cpp/lwtrace/example4/example_query.tr b/library/cpp/lwtrace/example4/example_query.tr
index 46cd25ce91..54441f9082 100644
--- a/library/cpp/lwtrace/example4/example_query.tr
+++ b/library/cpp/lwtrace/example4/example_query.tr
@@ -1,6 +1,6 @@
Blocks {
ProbeDesc {
- Name: "BackTrack"
+ Name: "BackTrack"
Provider: "LWTRACE_EXAMPLE_PROVIDER"
}
Action {
diff --git a/library/cpp/lwtrace/example4/lwtrace_example4.cpp b/library/cpp/lwtrace/example4/lwtrace_example4.cpp
index 7b55a07c75..1e99923d22 100644
--- a/library/cpp/lwtrace/example4/lwtrace_example4.cpp
+++ b/library/cpp/lwtrace/example4/lwtrace_example4.cpp
@@ -1,37 +1,37 @@
#include <library/cpp/lwtrace/all.h>
-#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
- PROBE(BackTrack, GROUPS(), TYPES(NLWTrace::TSymbol), NAMES("frame")) \
+#define LWTRACE_EXAMPLE_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
+ PROBE(BackTrack, GROUPS(), TYPES(NLWTrace::TSymbol), NAMES("frame")) \
/**/
LWTRACE_DECLARE_PROVIDER(LWTRACE_EXAMPLE_PROVIDER)
LWTRACE_DEFINE_PROVIDER(LWTRACE_EXAMPLE_PROVIDER)
-LWTRACE_USING(LWTRACE_EXAMPLE_PROVIDER);
-
-#define MY_BACKTRACK() LWPROBE(BackTrack, LWTRACE_LOCATION_SYMBOL)
-
+LWTRACE_USING(LWTRACE_EXAMPLE_PROVIDER);
+
+#define MY_BACKTRACK() LWPROBE(BackTrack, LWTRACE_LOCATION_SYMBOL)
+
void InitLWTrace() {
NLWTrace::StartLwtraceFromEnv();
}
-long double Fact(int n) {
- MY_BACKTRACK();
+long double Fact(int n) {
+ MY_BACKTRACK();
if (n < 0) {
- MY_BACKTRACK();
+ MY_BACKTRACK();
ythrow yexception() << "N! is undefined for negative N (" << n << ")";
}
double result = 1;
for (; n > 1; --n) {
- MY_BACKTRACK();
+ MY_BACKTRACK();
result *= n;
}
- MY_BACKTRACK();
+ MY_BACKTRACK();
return result;
}
void FactorialCalculator() {
- MY_BACKTRACK();
+ MY_BACKTRACK();
i32 n;
Cout << "Enter a number: ";
TString str;
@@ -42,8 +42,8 @@ void FactorialCalculator() {
int main() {
InitLWTrace();
- MY_BACKTRACK();
+ MY_BACKTRACK();
FactorialCalculator();
- MY_BACKTRACK();
+ MY_BACKTRACK();
return 0;
}
diff --git a/library/cpp/lwtrace/example4/start_with_query.sh b/library/cpp/lwtrace/example4/start_with_query.sh
index 5bc195c1ae..17cf93f3b0 100755
--- a/library/cpp/lwtrace/example4/start_with_query.sh
+++ b/library/cpp/lwtrace/example4/start_with_query.sh
@@ -1,3 +1,3 @@
#!/bin/bash
export LWTRACE="example_query.tr"
-./lwtrace-example4
+./lwtrace-example4
diff --git a/library/cpp/lwtrace/example4/ya.make b/library/cpp/lwtrace/example4/ya.make
index a3004340a8..22dd209068 100644
--- a/library/cpp/lwtrace/example4/ya.make
+++ b/library/cpp/lwtrace/example4/ya.make
@@ -1,9 +1,9 @@
-PROGRAM(lwtrace-example4)
+PROGRAM(lwtrace-example4)
-OWNER(serxa)
+OWNER(serxa)
SRCS(
- lwtrace_example4.cpp
+ lwtrace_example4.cpp
)
PEERDIR(
diff --git a/library/cpp/lwtrace/example5/example_query.tr b/library/cpp/lwtrace/example5/example_query.tr
index 90887d4ddf..34f872d7ee 100644
--- a/library/cpp/lwtrace/example5/example_query.tr
+++ b/library/cpp/lwtrace/example5/example_query.tr
@@ -1,9 +1,9 @@
-Blocks {
- ProbeDesc {
- Group: "LWTRACE_EXAMPLE_PROVIDER"
- }
- Action {
- PrintToStderrAction { }
- }
-}
-
+Blocks {
+ ProbeDesc {
+ Group: "LWTRACE_EXAMPLE_PROVIDER"
+ }
+ Action {
+ PrintToStderrAction { }
+ }
+}
+
diff --git a/library/cpp/lwtrace/example5/lwtrace_example5.cpp b/library/cpp/lwtrace/example5/lwtrace_example5.cpp
index 1c324473c2..3a5e3def30 100644
--- a/library/cpp/lwtrace/example5/lwtrace_example5.cpp
+++ b/library/cpp/lwtrace/example5/lwtrace_example5.cpp
@@ -1,30 +1,30 @@
#include <library/cpp/lwtrace/all.h>
#include <library/cpp/lwtrace/lwprobe.h>
-
-template <ui64 N>
-ui64 Fact() {
+
+template <ui64 N>
+ui64 Fact() {
ui64 result = N * Fact<N - 1>();
-
+
#ifndef LWTRACE_DISABLE
- // Note that probe is create on the first pass
- // LWTRACE_DECLARE_PROVIDER and LWTRACE_DEFINE_PROVIDER are not needed
- // (Provider is created implicitly)
- static NLWTrace::TLWProbe<ui64> factProbe(
- "LWTRACE_EXAMPLE_PROVIDER", "FactProbe_" + ToString(N), {}, {"result"});
-
- LWPROBE_OBJ(factProbe, result);
+ // Note that probe is create on the first pass
+ // LWTRACE_DECLARE_PROVIDER and LWTRACE_DEFINE_PROVIDER are not needed
+ // (Provider is created implicitly)
+ static NLWTrace::TLWProbe<ui64> factProbe(
+ "LWTRACE_EXAMPLE_PROVIDER", "FactProbe_" + ToString(N), {}, {"result"});
+
+ LWPROBE_OBJ(factProbe, result);
#endif // LWTRACE_DISABLE
- return result;
-}
-
-template <>
-ui64 Fact<0>() {
- return 1;
-}
-
-int main() {
+ return result;
+}
+
+template <>
+ui64 Fact<0>() {
+ return 1;
+}
+
+int main() {
Fact<6>(); // First run is required to create probes we can use later in trace query
- NLWTrace::StartLwtraceFromEnv(); // parse trace query and create trace session
+ NLWTrace::StartLwtraceFromEnv(); // parse trace query and create trace session
Cout << Fact<6>() << Endl; // actually trigger probes
- return 0;
-}
+ return 0;
+}
diff --git a/library/cpp/lwtrace/example5/start_with_query.sh b/library/cpp/lwtrace/example5/start_with_query.sh
index 4df5e4e47c..9802100f5b 100755
--- a/library/cpp/lwtrace/example5/start_with_query.sh
+++ b/library/cpp/lwtrace/example5/start_with_query.sh
@@ -1,3 +1,3 @@
-#!/bin/bash
-export LWTRACE="example_query.tr"
-./lwtrace-example5
+#!/bin/bash
+export LWTRACE="example_query.tr"
+./lwtrace-example5
diff --git a/library/cpp/lwtrace/example5/ya.make b/library/cpp/lwtrace/example5/ya.make
index 06dd4dc569..04ee4d29f2 100644
--- a/library/cpp/lwtrace/example5/ya.make
+++ b/library/cpp/lwtrace/example5/ya.make
@@ -1,13 +1,13 @@
-PROGRAM(lwtrace-example5)
-
-OWNER(serxa)
-
-SRCS(
- lwtrace_example5.cpp
-)
-
-PEERDIR(
+PROGRAM(lwtrace-example5)
+
+OWNER(serxa)
+
+SRCS(
+ lwtrace_example5.cpp
+)
+
+PEERDIR(
library/cpp/lwtrace
-)
-
-END()
+)
+
+END()
diff --git a/library/cpp/lwtrace/kill_action.cpp b/library/cpp/lwtrace/kill_action.cpp
index 2b74dc4587..dad8b9afa4 100644
--- a/library/cpp/lwtrace/kill_action.cpp
+++ b/library/cpp/lwtrace/kill_action.cpp
@@ -10,12 +10,12 @@
using namespace NLWTrace;
using namespace NLWTrace::NPrivate;
-bool TKillActionExecutor::DoExecute(TOrbit&, const TParams&) {
+bool TKillActionExecutor::DoExecute(TOrbit&, const TParams&) {
#ifdef _win_
abort();
#else
int r = kill(getpid(), SIGABRT);
Y_VERIFY(r == 0, "kill failed");
- return true;
+ return true;
#endif
}
diff --git a/library/cpp/lwtrace/kill_action.h b/library/cpp/lwtrace/kill_action.h
index 14da9ffd50..1544e339e1 100644
--- a/library/cpp/lwtrace/kill_action.h
+++ b/library/cpp/lwtrace/kill_action.h
@@ -2,14 +2,14 @@
#include "probe.h"
-namespace NLWTrace {
- namespace NPrivate {
- class TKillActionExecutor: public IExecutor {
- public:
- explicit TKillActionExecutor(const TProbe*) {
- }
- bool DoExecute(TOrbit& orbit, const TParams& params) override;
- };
+namespace NLWTrace {
+ namespace NPrivate {
+ class TKillActionExecutor: public IExecutor {
+ public:
+ explicit TKillActionExecutor(const TProbe*) {
+ }
+ bool DoExecute(TOrbit& orbit, const TParams& params) override;
+ };
- }
-}
+ }
+}
diff --git a/library/cpp/lwtrace/log.h b/library/cpp/lwtrace/log.h
index 56981a97f8..b226a1534c 100644
--- a/library/cpp/lwtrace/log.h
+++ b/library/cpp/lwtrace/log.h
@@ -1,906 +1,906 @@
-#pragma once
-
+#pragma once
+
#include "probe.h"
#include <util/datetime/base.h>
#include <util/generic/algorithm.h>
#include <util/generic/deque.h>
-#include <util/generic/noncopyable.h>
-#include <util/generic/vector.h>
+#include <util/generic/noncopyable.h>
+#include <util/generic/vector.h>
#include <util/string/printf.h>
#include <util/system/atomic.h>
#include <util/system/hp_timer.h>
-#include <util/system/mutex.h>
-#include <util/system/spinlock.h>
-#include <util/system/thread.h>
+#include <util/system/mutex.h>
+#include <util/system/spinlock.h>
+#include <util/system/thread.h>
#include <util/system/tls.h>
-
-namespace NLWTrace {
- // Cyclic buffer that pushes items to its back and pop item from front on overflow
- template <class TItem>
- class TCyclicBuffer: public TNonCopyable {
- private:
- TVector<TItem> Data;
- TItem* Front; // Points to the first item (valid iff Size > 0)
- TItem* Back; // Points to the last item (valid iff Size > 0)
- size_t Size; // Number of items in the buffer
-
- TItem* First() {
- return &*Data.begin();
- }
-
- TItem* Last() {
- return &*Data.end();
- }
-
- const TItem* First() const {
- return &*Data.begin();
- }
-
- const TItem* Last() const {
- return &*Data.end();
- }
-
- public:
- explicit TCyclicBuffer(size_t capacity)
- : Data(capacity)
- , Size(0)
- {
- }
-
- TItem* Add() {
- if (Size != 0) {
- Inc(Back);
- if (Back == Front) {
- Inc(Front); // Forget (pop_front) old items
- } else {
- Size++;
- }
- } else {
- Front = Back = First();
- Size = 1;
- }
- Back->Clear();
- return Back;
- }
-
- TItem* GetFront() {
- return Front;
- }
-
- TItem* GetBack() {
- return Back;
- }
-
- const TItem* GetFront() const {
- return Front;
- }
-
- const TItem* GetBack() const {
- return Back;
- }
-
- size_t GetSize() const {
- return Size;
- }
-
- bool IsFull() const {
- return Size == Data.size();
- }
-
- void Inc(TItem*& it) {
- it++;
- if (it == Last()) {
- it = First();
- }
- }
-
- void Inc(const TItem*& it) const {
- it++;
- if (it == Last()) {
- it = First();
- }
- }
-
- void Destroy() {
- Data.clear();
- Size = 0;
- }
-
- void Clear() {
- Size = 0;
- }
-
- void Swap(TCyclicBuffer& other) {
- Data.swap(other.Data);
- std::swap(Front, other.Front);
- std::swap(Back, other.Back);
- std::swap(Size, other.Size);
- }
- };
-
- // Buffer that pushes items to its back and pop item from front on expire
- template <class TItem>
- class TDurationBuffer: public TNonCopyable {
- protected:
- TDeque<TItem> Data;
- ui64 StoreDuration;
- ui8 CleanupCounter = 0;
-
- public:
- explicit TDurationBuffer(TDuration duration)
- : StoreDuration(DurationToCycles(duration))
- {
- }
-
- TItem* Add() {
- if (!CleanupCounter) {
- Cleanup();
- CleanupCounter = 128; // Make cleanup after every 128 additions
- }
- CleanupCounter--;
- Data.emplace_back();
- return &Data.back();
- }
-
- TItem* GetFront() {
- return &Data.front();
- }
-
- TItem* GetBack() {
- return &Data.back();
- }
-
- const TItem* GetFront() const {
- return &Data.front();
- }
-
- const TItem* GetBack() const {
- return &Data.back();
- }
-
- size_t GetSize() const {
- return Data.size();
- }
-
- bool Empty() const {
- return Data.empty();
- }
-
- void Destroy() {
- Data.clear();
- }
-
- void Swap(TDurationBuffer& other) {
- Data.swap(other.Data);
- std::swap(StoreDuration, other.StoreDuration);
- }
-
- private:
- void Cleanup() {
- ui64 cutoff = GetCycleCount();
- if (cutoff > StoreDuration) {
- cutoff -= StoreDuration;
- while (!Data.empty() && Data.front().GetTimestampCycles() < cutoff) {
- Data.pop_front();
- }
- }
- }
- };
-
- struct TLogItem {
- TProbe* Probe = nullptr;
- TParams Params;
- size_t SavedParamsCount;
- TInstant Timestamp;
- ui64 TimestampCycles;
-
- TLogItem() {
- }
-
- TLogItem(const TLogItem& other)
- : Probe(other.Probe)
- , SavedParamsCount(other.SavedParamsCount)
- , Timestamp(other.Timestamp)
- , TimestampCycles(other.TimestampCycles)
- {
- Clone(other);
- }
-
- ~TLogItem() {
- Destroy();
- }
-
- TLogItem& operator=(const TLogItem& other) {
- Destroy();
- Probe = other.Probe;
- SavedParamsCount = other.SavedParamsCount;
- Timestamp = other.Timestamp;
- TimestampCycles = other.TimestampCycles;
- Clone(other);
- return *this;
- }
-
- void Clear() {
- Destroy();
- Probe = nullptr;
- }
-
- void ToProtobuf(TLogItemPb& pb) const {
- pb.SetName(Probe->Event.Name);
- pb.SetProvider(Probe->Event.GetProvider());
- if (SavedParamsCount > 0) {
- TString paramValues[LWTRACE_MAX_PARAMS];
- Probe->Event.Signature.SerializeParams(Params, paramValues);
- for (size_t pi = 0; pi < SavedParamsCount; pi++) {
- pb.AddParams(paramValues[pi]);
- }
- }
- pb.SetTimestamp(Timestamp.GetValue());
- pb.SetTimestampCycles(TimestampCycles);
- }
-
- TTypedParam GetParam(const TString& param) const {
- if (SavedParamsCount == 0) {
- return TTypedParam();
- } else {
- size_t idx = Probe->Event.Signature.FindParamIndex(param);
- if (idx >= SavedParamsCount) { // Also covers idx=-1 case (not found)
- return TTypedParam();
- } else {
- EParamTypePb type = ParamTypeToProtobuf(Probe->Event.Signature.ParamTypes[idx]);
- return TTypedParam(type, Params.Param[idx]);
- }
- }
- }
-
- ui64 GetTimestampCycles() const {
- return TimestampCycles;
- }
-
- private:
- void Clone(const TLogItem& other) {
- if (Probe && SavedParamsCount > 0) {
- Probe->Event.Signature.CloneParams(Params, other.Params);
- }
- }
-
- void Destroy() {
- if (Probe && SavedParamsCount > 0) {
- Probe->Event.Signature.DestroyParams(Params);
- }
- }
- };
-
- struct TTrackLog {
- struct TItem : TLogItem {
- TThread::TId ThreadId;
-
+
+namespace NLWTrace {
+ // Cyclic buffer that pushes items to its back and pop item from front on overflow
+ template <class TItem>
+ class TCyclicBuffer: public TNonCopyable {
+ private:
+ TVector<TItem> Data;
+ TItem* Front; // Points to the first item (valid iff Size > 0)
+ TItem* Back; // Points to the last item (valid iff Size > 0)
+ size_t Size; // Number of items in the buffer
+
+ TItem* First() {
+ return &*Data.begin();
+ }
+
+ TItem* Last() {
+ return &*Data.end();
+ }
+
+ const TItem* First() const {
+ return &*Data.begin();
+ }
+
+ const TItem* Last() const {
+ return &*Data.end();
+ }
+
+ public:
+ explicit TCyclicBuffer(size_t capacity)
+ : Data(capacity)
+ , Size(0)
+ {
+ }
+
+ TItem* Add() {
+ if (Size != 0) {
+ Inc(Back);
+ if (Back == Front) {
+ Inc(Front); // Forget (pop_front) old items
+ } else {
+ Size++;
+ }
+ } else {
+ Front = Back = First();
+ Size = 1;
+ }
+ Back->Clear();
+ return Back;
+ }
+
+ TItem* GetFront() {
+ return Front;
+ }
+
+ TItem* GetBack() {
+ return Back;
+ }
+
+ const TItem* GetFront() const {
+ return Front;
+ }
+
+ const TItem* GetBack() const {
+ return Back;
+ }
+
+ size_t GetSize() const {
+ return Size;
+ }
+
+ bool IsFull() const {
+ return Size == Data.size();
+ }
+
+ void Inc(TItem*& it) {
+ it++;
+ if (it == Last()) {
+ it = First();
+ }
+ }
+
+ void Inc(const TItem*& it) const {
+ it++;
+ if (it == Last()) {
+ it = First();
+ }
+ }
+
+ void Destroy() {
+ Data.clear();
+ Size = 0;
+ }
+
+ void Clear() {
+ Size = 0;
+ }
+
+ void Swap(TCyclicBuffer& other) {
+ Data.swap(other.Data);
+ std::swap(Front, other.Front);
+ std::swap(Back, other.Back);
+ std::swap(Size, other.Size);
+ }
+ };
+
+ // Buffer that pushes items to its back and pop item from front on expire
+ template <class TItem>
+ class TDurationBuffer: public TNonCopyable {
+ protected:
+ TDeque<TItem> Data;
+ ui64 StoreDuration;
+ ui8 CleanupCounter = 0;
+
+ public:
+ explicit TDurationBuffer(TDuration duration)
+ : StoreDuration(DurationToCycles(duration))
+ {
+ }
+
+ TItem* Add() {
+ if (!CleanupCounter) {
+ Cleanup();
+ CleanupCounter = 128; // Make cleanup after every 128 additions
+ }
+ CleanupCounter--;
+ Data.emplace_back();
+ return &Data.back();
+ }
+
+ TItem* GetFront() {
+ return &Data.front();
+ }
+
+ TItem* GetBack() {
+ return &Data.back();
+ }
+
+ const TItem* GetFront() const {
+ return &Data.front();
+ }
+
+ const TItem* GetBack() const {
+ return &Data.back();
+ }
+
+ size_t GetSize() const {
+ return Data.size();
+ }
+
+ bool Empty() const {
+ return Data.empty();
+ }
+
+ void Destroy() {
+ Data.clear();
+ }
+
+ void Swap(TDurationBuffer& other) {
+ Data.swap(other.Data);
+ std::swap(StoreDuration, other.StoreDuration);
+ }
+
+ private:
+ void Cleanup() {
+ ui64 cutoff = GetCycleCount();
+ if (cutoff > StoreDuration) {
+ cutoff -= StoreDuration;
+ while (!Data.empty() && Data.front().GetTimestampCycles() < cutoff) {
+ Data.pop_front();
+ }
+ }
+ }
+ };
+
+ struct TLogItem {
+ TProbe* Probe = nullptr;
+ TParams Params;
+ size_t SavedParamsCount;
+ TInstant Timestamp;
+ ui64 TimestampCycles;
+
+ TLogItem() {
+ }
+
+ TLogItem(const TLogItem& other)
+ : Probe(other.Probe)
+ , SavedParamsCount(other.SavedParamsCount)
+ , Timestamp(other.Timestamp)
+ , TimestampCycles(other.TimestampCycles)
+ {
+ Clone(other);
+ }
+
+ ~TLogItem() {
+ Destroy();
+ }
+
+ TLogItem& operator=(const TLogItem& other) {
+ Destroy();
+ Probe = other.Probe;
+ SavedParamsCount = other.SavedParamsCount;
+ Timestamp = other.Timestamp;
+ TimestampCycles = other.TimestampCycles;
+ Clone(other);
+ return *this;
+ }
+
+ void Clear() {
+ Destroy();
+ Probe = nullptr;
+ }
+
+ void ToProtobuf(TLogItemPb& pb) const {
+ pb.SetName(Probe->Event.Name);
+ pb.SetProvider(Probe->Event.GetProvider());
+ if (SavedParamsCount > 0) {
+ TString paramValues[LWTRACE_MAX_PARAMS];
+ Probe->Event.Signature.SerializeParams(Params, paramValues);
+ for (size_t pi = 0; pi < SavedParamsCount; pi++) {
+ pb.AddParams(paramValues[pi]);
+ }
+ }
+ pb.SetTimestamp(Timestamp.GetValue());
+ pb.SetTimestampCycles(TimestampCycles);
+ }
+
+ TTypedParam GetParam(const TString& param) const {
+ if (SavedParamsCount == 0) {
+ return TTypedParam();
+ } else {
+ size_t idx = Probe->Event.Signature.FindParamIndex(param);
+ if (idx >= SavedParamsCount) { // Also covers idx=-1 case (not found)
+ return TTypedParam();
+ } else {
+ EParamTypePb type = ParamTypeToProtobuf(Probe->Event.Signature.ParamTypes[idx]);
+ return TTypedParam(type, Params.Param[idx]);
+ }
+ }
+ }
+
+ ui64 GetTimestampCycles() const {
+ return TimestampCycles;
+ }
+
+ private:
+ void Clone(const TLogItem& other) {
+ if (Probe && SavedParamsCount > 0) {
+ Probe->Event.Signature.CloneParams(Params, other.Params);
+ }
+ }
+
+ void Destroy() {
+ if (Probe && SavedParamsCount > 0) {
+ Probe->Event.Signature.DestroyParams(Params);
+ }
+ }
+ };
+
+ struct TTrackLog {
+ struct TItem : TLogItem {
+ TThread::TId ThreadId;
+
TItem() = default;
-
- TItem(TThread::TId tid, const TLogItem& item)
- : TLogItem(item)
- , ThreadId(tid)
- {
- }
- };
-
- using TItems = TVector<TItem>;
- TItems Items;
- bool Truncated = false;
- ui64 Id = 0;
-
- void Clear() {
- Items.clear();
- Truncated = false;
- }
-
- ui64 GetTimestampCycles() const {
- return Items.empty() ? 0 : Items.front().GetTimestampCycles();
- }
- };
-
- // Log that uses per-thread cyclic buffers to store items
- template <class T>
- class TCyclicLogImpl: public TNonCopyable {
- public:
- using TLog = TCyclicLogImpl;
- using TItem = T;
-
- private:
- using TBuffer = TCyclicBuffer<TItem>;
-
- class TStorage {
- private:
- // Data that can be accessed in lock-free way from reader/writer
- TAtomic Writers = 0;
- mutable TBuffer* volatile CurBuffer = nullptr;
-
- // Data that can be accessed only from reader
- // NOTE: multiple readers are serialized by TCyclicLogImpl::Lock
- mutable TBuffer* OldBuffer = nullptr;
- mutable TBuffer* NewBuffer = nullptr;
-
- TLog* volatile Log = nullptr;
-
- TThread::TId ThreadId = 0;
- TAtomic EventsCount = 0;
-
- public:
- TStorage() {
- }
-
- explicit TStorage(TLog* log)
- : CurBuffer(new TBuffer(log->GetCapacity()))
- , OldBuffer(new TBuffer(log->GetCapacity()))
- , NewBuffer(new TBuffer(log->GetCapacity()))
- , Log(log)
- , ThreadId(TThread::CurrentThreadId())
- {
- Log->RegisterThread(this);
- }
-
- ~TStorage() {
- if (TLog* log = AtomicSwap(&Log, nullptr)) {
- AtomicBarrier(); // Serialize `Log' and TCyclicLogImpl::Lock memory order
- // NOTE: the following function swaps `this' with `new TStorage()'
- log->UnregisterThreadAndMakeOrphan(this);
- } else {
- // NOTE: `Log' can be nullptr if either it is orphan storage or TryDismiss() succeeded
- // NOTE: in both cases it is ok to call these deletes
- delete CurBuffer;
- delete OldBuffer;
- delete NewBuffer;
- }
- }
-
- bool TryDismiss() {
- // TCyclicLogImpl::Lock implied (no readers)
- if (TLog* log = AtomicSwap(&Log, nullptr)) {
- TBuffer* curBuffer = AtomicSwap(&CurBuffer, nullptr);
- WaitForWriters();
- // At this point we guarantee that there is no and wont be active writer
- delete curBuffer;
- delete OldBuffer;
- delete NewBuffer;
- OldBuffer = nullptr;
- NewBuffer = nullptr;
- return true;
- } else {
- // ~TStorage() is in progress
- return false;
- }
- }
-
- void WaitForWriters() const {
- while (AtomicGet(Writers) > 0) {
- SpinLockPause();
- }
- }
-
- TThread::TId GetThreadId() const {
- // TCyclicLogImpl::Lock implied (no readers)
- return ThreadId;
- }
-
- size_t GetEventsCount() const {
- // TCyclicLogImpl::Lock implied (no readers)
- return AtomicGet(EventsCount);
- }
-
- void Swap(TStorage& other) {
- // TCyclicLogImpl::Lock implied (no readers)
- std::swap(CurBuffer, other.CurBuffer);
- std::swap(OldBuffer, other.OldBuffer);
- std::swap(NewBuffer, other.NewBuffer);
- std::swap(Log, other.Log);
- std::swap(ThreadId, other.ThreadId);
- std::swap(EventsCount, other.EventsCount);
- }
-
- TBuffer* StartWriter() {
- AtomicIncrement(Writers);
- return const_cast<TBuffer*>(AtomicGet(CurBuffer));
- }
-
- void StopWriter() {
- AtomicDecrement(Writers);
- }
-
- void IncEventsCount() {
- AtomicIncrement(EventsCount);
- }
-
- template <class TReader>
- void ReadItems(TReader& r) const {
- // TCyclicLogImpl::Lock implied
- NewBuffer = AtomicSwap(&CurBuffer, NewBuffer);
- WaitForWriters();
-
- // Merge new buffer into old buffer
- if (NewBuffer->IsFull()) {
- std::swap(NewBuffer, OldBuffer);
- } else {
- if (NewBuffer->GetSize() > 0) {
- for (const TItem *i = NewBuffer->GetFront(), *e = NewBuffer->GetBack();; NewBuffer->Inc(i)) {
- TItem* oldSlot = OldBuffer->Add();
- *oldSlot = *i;
- if (i == e) {
- break;
- }
- }
- }
- }
-
- NewBuffer->Clear();
-
- // Iterate over old buffer
- if (OldBuffer->GetSize() > 0) {
- for (const TItem *i = OldBuffer->GetFront(), *e = OldBuffer->GetBack();; OldBuffer->Inc(i)) {
- r.Push(ThreadId, *i);
- if (i == e) {
- break;
- }
- }
- }
- }
- };
-
- size_t Capacity;
- Y_THREAD(TStorage)
- PerThreadStorage;
- TSpinLock Lock;
- // If thread exits its storage is destroyed, so we move it into OrphanStorages before destruction
- TVector<TAtomicSharedPtr<TStorage>> OrphanStorages;
- typedef TVector<TStorage*> TStoragesVec;
- TStoragesVec StoragesVec;
- TAtomic ThreadsCount;
-
- public:
- explicit TCyclicLogImpl(size_t capacity)
- : Capacity(capacity)
- , PerThreadStorage(this)
- , ThreadsCount(0)
- {
- }
-
- ~TCyclicLogImpl() {
- for (bool again = true; again;) {
- TGuard<TSpinLock> g(Lock);
- AtomicBarrier(); // Serialize `storage->Log' and Lock memory order
- again = false;
- while (!StoragesVec.empty()) {
- TStorage* storage = StoragesVec.back();
- // TStorage destructor can be called when TCyclicLogImpl is already destructed
- // So we ensure this does not lead to problems
- // NOTE: Y_THREAD(TStorage) destructs TStorage object for a specific thread only on that thread exit
- // NOTE: this issue can lead to memleaks if threads never exit and many TCyclicLogImpl are created
- if (storage->TryDismiss()) {
- StoragesVec.pop_back();
- } else {
- // Rare case when another thread is running ~TStorage() -- let it finish
- again = true;
- SpinLockPause();
- break;
- }
- }
- }
- }
-
- size_t GetCapacity() const {
- return Capacity;
- }
-
- size_t GetEventsCount() const {
- size_t events = 0;
- TGuard<TSpinLock> g(Lock);
- for (auto i : StoragesVec) {
- events += i->GetEventsCount();
- }
- for (const auto& orphanStorage : OrphanStorages) {
- events += orphanStorage->GetEventsCount();
- }
- return events;
- }
-
- size_t GetThreadsCount() const {
- return AtomicGet(ThreadsCount);
- }
-
- void RegisterThread(TStorage* storage) {
- TGuard<TSpinLock> g(Lock);
- StoragesVec.push_back(storage);
- AtomicIncrement(ThreadsCount);
- }
-
- void UnregisterThreadAndMakeOrphan(TStorage* storage) {
- TGuard<TSpinLock> g(Lock);
- // `storage' writers are not possible at this scope because
- // UnregisterThreadAndMakeOrphan is only called from exiting threads.
- // `storage' readers are not possible at this scope due to Lock guard.
-
- Erase(StoragesVec, storage);
- TAtomicSharedPtr<TStorage> orphan(new TStorage());
- orphan->Swap(*storage); // Swap is required because we cannot take ownership from Y_THREAD(TStorage) object
- OrphanStorages.push_back(orphan);
- }
-
- template <class TReader>
- void ReadThreads(TReader& r) const {
- TGuard<TSpinLock> g(Lock);
- for (auto i : StoragesVec) {
- r.PushThread(i->GetThreadId());
- }
- for (const auto& orphanStorage : OrphanStorages) {
- r.PushThread(orphanStorage->GetThreadId());
- }
- }
-
- template <class TReader>
- void ReadItems(TReader& r) const {
- TGuard<TSpinLock> g(Lock);
- for (auto i : StoragesVec) {
- i->ReadItems(r);
- }
- for (const auto& orphanStorage : OrphanStorages) {
- orphanStorage->ReadItems(r);
- }
- }
-
- class TAccessor {
- private:
- TStorage& Storage;
- TBuffer* Buffer;
-
- public:
- explicit TAccessor(TLog& log)
- : Storage(log.PerThreadStorage.Get())
- , Buffer(Storage.StartWriter())
- {
- }
-
- ~TAccessor() {
- Storage.StopWriter();
- }
-
- TItem* Add() {
- if (Buffer) {
- Storage.IncEventsCount();
- return Buffer->Add();
- } else {
- // TStorage detached from trace due to trace destruction
- // so we should not try log anything
- return nullptr;
- }
- }
- };
-
- friend class TAccessor;
- };
-
- using TCyclicLog = TCyclicLogImpl<TLogItem>;
- using TCyclicDepot = TCyclicLogImpl<TTrackLog>;
-
- // Log that uses per-thread buffers to store items up to given duration
- template <class T>
- class TDurationLogImpl: public TNonCopyable {
- public:
- using TLog = TDurationLogImpl;
- using TItem = T;
-
- class TAccessor;
- friend class TAccessor;
- class TAccessor: public TGuard<TSpinLock> {
- private:
- TLog& Log;
-
- public:
- explicit TAccessor(TLog& log)
- : TGuard<TSpinLock>(log.PerThreadStorage.Get().Lock)
- , Log(log)
- {
- }
-
- TItem* Add() {
- return Log.PerThreadStorage.Get().Add();
- }
- };
-
- private:
- class TStorage: public TDurationBuffer<TItem> {
- private:
- TLog* Log;
- TThread::TId ThreadId;
- ui64 EventsCount;
-
- public:
- TSpinLock Lock;
-
- TStorage()
- : TDurationBuffer<TItem>(TDuration::Zero())
- , Log(nullptr)
- , ThreadId(0)
- , EventsCount(0)
- {
- }
-
- explicit TStorage(TLog* log)
- : TDurationBuffer<TItem>(log->GetDuration())
- , Log(log)
- , ThreadId(TThread::CurrentThreadId())
- , EventsCount(0)
- {
- Log->RegisterThread(this);
- }
-
- ~TStorage() {
- if (Log) {
- Log->UnregisterThread(this);
- }
- }
-
- void DetachFromTraceLog() {
- Log = nullptr;
- }
-
- TItem* Add() {
- EventsCount++;
- return TDurationBuffer<TItem>::Add();
- }
-
- bool Expired(ui64 now) const {
- return this->Empty() ? true : this->GetBack()->GetTimestampCycles() + this->StoreDuration < now;
- }
-
- TThread::TId GetThreadId() const {
- return ThreadId;
- }
-
- size_t GetEventsCount() const {
- return EventsCount;
- }
-
- void Swap(TStorage& other) {
- TDurationBuffer<TItem>::Swap(other);
- std::swap(Log, other.Log);
- std::swap(ThreadId, other.ThreadId);
- std::swap(EventsCount, other.EventsCount);
- }
-
- template <class TReader>
- void ReadItems(ui64 now, ui64 duration, TReader& r) const {
- TGuard<TSpinLock> g(Lock);
- if (now > duration) {
- ui64 cutoff = now - duration;
- for (const TItem& item : this->Data) {
- if (item.GetTimestampCycles() >= cutoff) {
- r.Push(ThreadId, item);
- }
- }
- } else {
- for (const TItem& item : this->Data) {
- r.Push(ThreadId, item);
- }
- }
- }
- };
-
- TDuration Duration;
- Y_THREAD(TStorage)
- PerThreadStorage;
- TSpinLock Lock;
- typedef TVector<TAtomicSharedPtr<TStorage>> TOrphanStorages;
- TOrphanStorages OrphanStorages; // if thread exits its storage is destroyed, so we move it into OrphanStorages before destruction
- TAtomic OrphanStoragesEventsCount = 0;
- typedef TVector<TStorage*> TStoragesVec;
- TStoragesVec StoragesVec;
- TAtomic ThreadsCount;
-
- public:
- explicit TDurationLogImpl(TDuration duration)
- : Duration(duration)
- , PerThreadStorage(this)
- , ThreadsCount(0)
- {
- }
-
- ~TDurationLogImpl() {
- for (auto storage : StoragesVec) {
- // NOTE: Y_THREAD(TStorage) destructs TStorage object for a specific thread only on that thread exit
- // NOTE: this issue can lead to memleaks if threads never exit and many TTraceLogs are created
- storage->Destroy();
-
- // TraceLogStorage destructor can be called when TTraceLog is already destructed
- // So we ensure this does not lead to problems
- storage->DetachFromTraceLog();
- }
- }
-
- TDuration GetDuration() const {
- return Duration;
- }
-
- size_t GetEventsCount() const {
- size_t events = AtomicGet(OrphanStoragesEventsCount);
- TGuard<TSpinLock> g(Lock);
- for (auto i : StoragesVec) {
- events += i->GetEventsCount();
- }
- return events;
- }
-
- size_t GetThreadsCount() const {
- return AtomicGet(ThreadsCount);
- }
-
- void RegisterThread(TStorage* storage) {
- TGuard<TSpinLock> g(Lock);
- StoragesVec.push_back(storage);
- AtomicIncrement(ThreadsCount);
- }
-
- void UnregisterThread(TStorage* storage) {
- TGuard<TSpinLock> g(Lock);
- for (auto i = StoragesVec.begin(), e = StoragesVec.end(); i != e; ++i) {
- if (*i == storage) {
- StoragesVec.erase(i);
- break;
- }
- }
- TAtomicSharedPtr<TStorage> orphan(new TStorage());
- orphan->Swap(*storage);
- orphan->DetachFromTraceLog();
- AtomicAdd(OrphanStoragesEventsCount, orphan->GetEventsCount());
- OrphanStorages.push_back(orphan);
- CleanOrphanStorages(GetCycleCount());
- }
-
- void CleanOrphanStorages(ui64 now) {
- EraseIf(OrphanStorages, [=](const TAtomicSharedPtr<TStorage>& ptr) {
- const TStorage& storage = *ptr;
- return storage.Expired(now);
- });
- }
-
- template <class TReader>
- void ReadThreads(TReader& r) const {
- TGuard<TSpinLock> g(Lock);
- for (TStorage* i : StoragesVec) {
- r.PushThread(i->GetThreadId());
- }
- for (const auto& orphanStorage : OrphanStorages) {
- r.PushThread(orphanStorage->GetThreadId());
- }
- }
-
- template <class TReader>
- void ReadItems(ui64 now, ui64 duration, TReader& r) const {
- TGuard<TSpinLock> g(Lock);
- for (TStorage* storage : StoragesVec) {
- storage->ReadItems(now, duration, r);
- }
- for (const auto& orphanStorage : OrphanStorages) {
- orphanStorage->ReadItems(now, duration, r);
- }
- }
- };
-
- using TDurationLog = TDurationLogImpl<TLogItem>;
- using TDurationDepot = TDurationLogImpl<TTrackLog>;
-
- // Log that uses one cyclic buffer to store items
- // Each item is a result of execution of some event
- class TInMemoryLog: public TNonCopyable {
- public:
- struct TItem {
- const TEvent* Event;
- TParams Params;
- TInstant Timestamp;
-
- TItem()
- : Event(nullptr)
- {
- }
-
- TItem(const TItem& other)
- : Event(other.Event)
- , Timestamp(other.Timestamp)
- {
- Clone(other);
- }
-
- ~TItem() {
- Destroy();
- }
-
- TItem& operator=(const TItem& other) {
- Destroy();
- Event = other.Event;
- Timestamp = other.Timestamp;
- Clone(other);
- return *this;
- }
-
- void Clear() {
- Destroy();
- Event = nullptr;
- }
-
- private:
- void Clone(const TItem& other) {
- if (Event && Event->Signature.ParamCount > 0) {
- Event->Signature.CloneParams(Params, other.Params);
- }
- }
-
- void Destroy() {
- if (Event && Event->Signature.ParamCount > 0) {
- Event->Signature.DestroyParams(Params);
- }
- }
- };
-
- class TAccessor;
- friend class TAccessor;
- class TAccessor: public TGuard<TMutex> {
- private:
- TInMemoryLog& Log;
-
- public:
- explicit TAccessor(TInMemoryLog& log)
- : TGuard<TMutex>(log.Lock)
- , Log(log)
- {
- }
-
- TItem* Add() {
- return Log.Storage.Add();
- }
- };
-
- private:
- TMutex Lock;
- TCyclicBuffer<TItem> Storage;
-
- public:
- explicit TInMemoryLog(size_t capacity)
- : Storage(capacity)
- {
- }
-
- template <class TReader>
- void ReadItems(TReader& r) const {
- TGuard<TMutex> g(Lock);
- if (Storage.GetSize() > 0) {
- for (const TItem *i = Storage.GetFront(), *e = Storage.GetBack();; Storage.Inc(i)) {
- r.Push(*i);
- if (i == e) {
- break;
- }
- }
- }
- }
- };
-
-#ifndef LWTRACE_DISABLE
-
- // Class representing a specific event
- template <LWTRACE_TEMPLATE_PARAMS>
- struct TUserEvent {
- TEvent Event;
-
- inline void operator()(TInMemoryLog& log, bool logTimestamp, LWTRACE_FUNCTION_PARAMS) const {
- TInMemoryLog::TAccessor la(log);
- if (TInMemoryLog::TItem* item = la.Add()) {
- item->Event = &Event;
- LWTRACE_PREPARE_PARAMS(item->Params);
- if (logTimestamp) {
- item->Timestamp = TInstant::Now();
- }
- }
- }
- };
-
-#endif
-
-}
+
+ TItem(TThread::TId tid, const TLogItem& item)
+ : TLogItem(item)
+ , ThreadId(tid)
+ {
+ }
+ };
+
+ using TItems = TVector<TItem>;
+ TItems Items;
+ bool Truncated = false;
+ ui64 Id = 0;
+
+ void Clear() {
+ Items.clear();
+ Truncated = false;
+ }
+
+ ui64 GetTimestampCycles() const {
+ return Items.empty() ? 0 : Items.front().GetTimestampCycles();
+ }
+ };
+
+ // Log that uses per-thread cyclic buffers to store items
+ template <class T>
+ class TCyclicLogImpl: public TNonCopyable {
+ public:
+ using TLog = TCyclicLogImpl;
+ using TItem = T;
+
+ private:
+ using TBuffer = TCyclicBuffer<TItem>;
+
+ class TStorage {
+ private:
+ // Data that can be accessed in lock-free way from reader/writer
+ TAtomic Writers = 0;
+ mutable TBuffer* volatile CurBuffer = nullptr;
+
+ // Data that can be accessed only from reader
+ // NOTE: multiple readers are serialized by TCyclicLogImpl::Lock
+ mutable TBuffer* OldBuffer = nullptr;
+ mutable TBuffer* NewBuffer = nullptr;
+
+ TLog* volatile Log = nullptr;
+
+ TThread::TId ThreadId = 0;
+ TAtomic EventsCount = 0;
+
+ public:
+ TStorage() {
+ }
+
+ explicit TStorage(TLog* log)
+ : CurBuffer(new TBuffer(log->GetCapacity()))
+ , OldBuffer(new TBuffer(log->GetCapacity()))
+ , NewBuffer(new TBuffer(log->GetCapacity()))
+ , Log(log)
+ , ThreadId(TThread::CurrentThreadId())
+ {
+ Log->RegisterThread(this);
+ }
+
+ ~TStorage() {
+ if (TLog* log = AtomicSwap(&Log, nullptr)) {
+ AtomicBarrier(); // Serialize `Log' and TCyclicLogImpl::Lock memory order
+ // NOTE: the following function swaps `this' with `new TStorage()'
+ log->UnregisterThreadAndMakeOrphan(this);
+ } else {
+ // NOTE: `Log' can be nullptr if either it is orphan storage or TryDismiss() succeeded
+ // NOTE: in both cases it is ok to call these deletes
+ delete CurBuffer;
+ delete OldBuffer;
+ delete NewBuffer;
+ }
+ }
+
+ bool TryDismiss() {
+ // TCyclicLogImpl::Lock implied (no readers)
+ if (TLog* log = AtomicSwap(&Log, nullptr)) {
+ TBuffer* curBuffer = AtomicSwap(&CurBuffer, nullptr);
+ WaitForWriters();
+ // At this point we guarantee that there is no and wont be active writer
+ delete curBuffer;
+ delete OldBuffer;
+ delete NewBuffer;
+ OldBuffer = nullptr;
+ NewBuffer = nullptr;
+ return true;
+ } else {
+ // ~TStorage() is in progress
+ return false;
+ }
+ }
+
+ void WaitForWriters() const {
+ while (AtomicGet(Writers) > 0) {
+ SpinLockPause();
+ }
+ }
+
+ TThread::TId GetThreadId() const {
+ // TCyclicLogImpl::Lock implied (no readers)
+ return ThreadId;
+ }
+
+ size_t GetEventsCount() const {
+ // TCyclicLogImpl::Lock implied (no readers)
+ return AtomicGet(EventsCount);
+ }
+
+ void Swap(TStorage& other) {
+ // TCyclicLogImpl::Lock implied (no readers)
+ std::swap(CurBuffer, other.CurBuffer);
+ std::swap(OldBuffer, other.OldBuffer);
+ std::swap(NewBuffer, other.NewBuffer);
+ std::swap(Log, other.Log);
+ std::swap(ThreadId, other.ThreadId);
+ std::swap(EventsCount, other.EventsCount);
+ }
+
+ TBuffer* StartWriter() {
+ AtomicIncrement(Writers);
+ return const_cast<TBuffer*>(AtomicGet(CurBuffer));
+ }
+
+ void StopWriter() {
+ AtomicDecrement(Writers);
+ }
+
+ void IncEventsCount() {
+ AtomicIncrement(EventsCount);
+ }
+
+ template <class TReader>
+ void ReadItems(TReader& r) const {
+ // TCyclicLogImpl::Lock implied
+ NewBuffer = AtomicSwap(&CurBuffer, NewBuffer);
+ WaitForWriters();
+
+ // Merge new buffer into old buffer
+ if (NewBuffer->IsFull()) {
+ std::swap(NewBuffer, OldBuffer);
+ } else {
+ if (NewBuffer->GetSize() > 0) {
+ for (const TItem *i = NewBuffer->GetFront(), *e = NewBuffer->GetBack();; NewBuffer->Inc(i)) {
+ TItem* oldSlot = OldBuffer->Add();
+ *oldSlot = *i;
+ if (i == e) {
+ break;
+ }
+ }
+ }
+ }
+
+ NewBuffer->Clear();
+
+ // Iterate over old buffer
+ if (OldBuffer->GetSize() > 0) {
+ for (const TItem *i = OldBuffer->GetFront(), *e = OldBuffer->GetBack();; OldBuffer->Inc(i)) {
+ r.Push(ThreadId, *i);
+ if (i == e) {
+ break;
+ }
+ }
+ }
+ }
+ };
+
+ size_t Capacity;
+ Y_THREAD(TStorage)
+ PerThreadStorage;
+ TSpinLock Lock;
+ // If thread exits its storage is destroyed, so we move it into OrphanStorages before destruction
+ TVector<TAtomicSharedPtr<TStorage>> OrphanStorages;
+ typedef TVector<TStorage*> TStoragesVec;
+ TStoragesVec StoragesVec;
+ TAtomic ThreadsCount;
+
+ public:
+ explicit TCyclicLogImpl(size_t capacity)
+ : Capacity(capacity)
+ , PerThreadStorage(this)
+ , ThreadsCount(0)
+ {
+ }
+
+ ~TCyclicLogImpl() {
+ for (bool again = true; again;) {
+ TGuard<TSpinLock> g(Lock);
+ AtomicBarrier(); // Serialize `storage->Log' and Lock memory order
+ again = false;
+ while (!StoragesVec.empty()) {
+ TStorage* storage = StoragesVec.back();
+ // TStorage destructor can be called when TCyclicLogImpl is already destructed
+ // So we ensure this does not lead to problems
+ // NOTE: Y_THREAD(TStorage) destructs TStorage object for a specific thread only on that thread exit
+ // NOTE: this issue can lead to memleaks if threads never exit and many TCyclicLogImpl are created
+ if (storage->TryDismiss()) {
+ StoragesVec.pop_back();
+ } else {
+ // Rare case when another thread is running ~TStorage() -- let it finish
+ again = true;
+ SpinLockPause();
+ break;
+ }
+ }
+ }
+ }
+
+ size_t GetCapacity() const {
+ return Capacity;
+ }
+
+ size_t GetEventsCount() const {
+ size_t events = 0;
+ TGuard<TSpinLock> g(Lock);
+ for (auto i : StoragesVec) {
+ events += i->GetEventsCount();
+ }
+ for (const auto& orphanStorage : OrphanStorages) {
+ events += orphanStorage->GetEventsCount();
+ }
+ return events;
+ }
+
+ size_t GetThreadsCount() const {
+ return AtomicGet(ThreadsCount);
+ }
+
+ void RegisterThread(TStorage* storage) {
+ TGuard<TSpinLock> g(Lock);
+ StoragesVec.push_back(storage);
+ AtomicIncrement(ThreadsCount);
+ }
+
+ void UnregisterThreadAndMakeOrphan(TStorage* storage) {
+ TGuard<TSpinLock> g(Lock);
+ // `storage' writers are not possible at this scope because
+ // UnregisterThreadAndMakeOrphan is only called from exiting threads.
+ // `storage' readers are not possible at this scope due to Lock guard.
+
+ Erase(StoragesVec, storage);
+ TAtomicSharedPtr<TStorage> orphan(new TStorage());
+ orphan->Swap(*storage); // Swap is required because we cannot take ownership from Y_THREAD(TStorage) object
+ OrphanStorages.push_back(orphan);
+ }
+
+ template <class TReader>
+ void ReadThreads(TReader& r) const {
+ TGuard<TSpinLock> g(Lock);
+ for (auto i : StoragesVec) {
+ r.PushThread(i->GetThreadId());
+ }
+ for (const auto& orphanStorage : OrphanStorages) {
+ r.PushThread(orphanStorage->GetThreadId());
+ }
+ }
+
+ template <class TReader>
+ void ReadItems(TReader& r) const {
+ TGuard<TSpinLock> g(Lock);
+ for (auto i : StoragesVec) {
+ i->ReadItems(r);
+ }
+ for (const auto& orphanStorage : OrphanStorages) {
+ orphanStorage->ReadItems(r);
+ }
+ }
+
+ class TAccessor {
+ private:
+ TStorage& Storage;
+ TBuffer* Buffer;
+
+ public:
+ explicit TAccessor(TLog& log)
+ : Storage(log.PerThreadStorage.Get())
+ , Buffer(Storage.StartWriter())
+ {
+ }
+
+ ~TAccessor() {
+ Storage.StopWriter();
+ }
+
+ TItem* Add() {
+ if (Buffer) {
+ Storage.IncEventsCount();
+ return Buffer->Add();
+ } else {
+ // TStorage detached from trace due to trace destruction
+ // so we should not try log anything
+ return nullptr;
+ }
+ }
+ };
+
+ friend class TAccessor;
+ };
+
+ using TCyclicLog = TCyclicLogImpl<TLogItem>;
+ using TCyclicDepot = TCyclicLogImpl<TTrackLog>;
+
+ // Log that uses per-thread buffers to store items up to given duration
+ template <class T>
+ class TDurationLogImpl: public TNonCopyable {
+ public:
+ using TLog = TDurationLogImpl;
+ using TItem = T;
+
+ class TAccessor;
+ friend class TAccessor;
+ class TAccessor: public TGuard<TSpinLock> {
+ private:
+ TLog& Log;
+
+ public:
+ explicit TAccessor(TLog& log)
+ : TGuard<TSpinLock>(log.PerThreadStorage.Get().Lock)
+ , Log(log)
+ {
+ }
+
+ TItem* Add() {
+ return Log.PerThreadStorage.Get().Add();
+ }
+ };
+
+ private:
+ class TStorage: public TDurationBuffer<TItem> {
+ private:
+ TLog* Log;
+ TThread::TId ThreadId;
+ ui64 EventsCount;
+
+ public:
+ TSpinLock Lock;
+
+ TStorage()
+ : TDurationBuffer<TItem>(TDuration::Zero())
+ , Log(nullptr)
+ , ThreadId(0)
+ , EventsCount(0)
+ {
+ }
+
+ explicit TStorage(TLog* log)
+ : TDurationBuffer<TItem>(log->GetDuration())
+ , Log(log)
+ , ThreadId(TThread::CurrentThreadId())
+ , EventsCount(0)
+ {
+ Log->RegisterThread(this);
+ }
+
+ ~TStorage() {
+ if (Log) {
+ Log->UnregisterThread(this);
+ }
+ }
+
+ void DetachFromTraceLog() {
+ Log = nullptr;
+ }
+
+ TItem* Add() {
+ EventsCount++;
+ return TDurationBuffer<TItem>::Add();
+ }
+
+ bool Expired(ui64 now) const {
+ return this->Empty() ? true : this->GetBack()->GetTimestampCycles() + this->StoreDuration < now;
+ }
+
+ TThread::TId GetThreadId() const {
+ return ThreadId;
+ }
+
+ size_t GetEventsCount() const {
+ return EventsCount;
+ }
+
+ void Swap(TStorage& other) {
+ TDurationBuffer<TItem>::Swap(other);
+ std::swap(Log, other.Log);
+ std::swap(ThreadId, other.ThreadId);
+ std::swap(EventsCount, other.EventsCount);
+ }
+
+ template <class TReader>
+ void ReadItems(ui64 now, ui64 duration, TReader& r) const {
+ TGuard<TSpinLock> g(Lock);
+ if (now > duration) {
+ ui64 cutoff = now - duration;
+ for (const TItem& item : this->Data) {
+ if (item.GetTimestampCycles() >= cutoff) {
+ r.Push(ThreadId, item);
+ }
+ }
+ } else {
+ for (const TItem& item : this->Data) {
+ r.Push(ThreadId, item);
+ }
+ }
+ }
+ };
+
+ TDuration Duration;
+ Y_THREAD(TStorage)
+ PerThreadStorage;
+ TSpinLock Lock;
+ typedef TVector<TAtomicSharedPtr<TStorage>> TOrphanStorages;
+ TOrphanStorages OrphanStorages; // if thread exits its storage is destroyed, so we move it into OrphanStorages before destruction
+ TAtomic OrphanStoragesEventsCount = 0;
+ typedef TVector<TStorage*> TStoragesVec;
+ TStoragesVec StoragesVec;
+ TAtomic ThreadsCount;
+
+ public:
+ explicit TDurationLogImpl(TDuration duration)
+ : Duration(duration)
+ , PerThreadStorage(this)
+ , ThreadsCount(0)
+ {
+ }
+
+ ~TDurationLogImpl() {
+ for (auto storage : StoragesVec) {
+ // NOTE: Y_THREAD(TStorage) destructs TStorage object for a specific thread only on that thread exit
+ // NOTE: this issue can lead to memleaks if threads never exit and many TTraceLogs are created
+ storage->Destroy();
+
+ // TraceLogStorage destructor can be called when TTraceLog is already destructed
+ // So we ensure this does not lead to problems
+ storage->DetachFromTraceLog();
+ }
+ }
+
+ TDuration GetDuration() const {
+ return Duration;
+ }
+
+ size_t GetEventsCount() const {
+ size_t events = AtomicGet(OrphanStoragesEventsCount);
+ TGuard<TSpinLock> g(Lock);
+ for (auto i : StoragesVec) {
+ events += i->GetEventsCount();
+ }
+ return events;
+ }
+
+ size_t GetThreadsCount() const {
+ return AtomicGet(ThreadsCount);
+ }
+
+ void RegisterThread(TStorage* storage) {
+ TGuard<TSpinLock> g(Lock);
+ StoragesVec.push_back(storage);
+ AtomicIncrement(ThreadsCount);
+ }
+
+ void UnregisterThread(TStorage* storage) {
+ TGuard<TSpinLock> g(Lock);
+ for (auto i = StoragesVec.begin(), e = StoragesVec.end(); i != e; ++i) {
+ if (*i == storage) {
+ StoragesVec.erase(i);
+ break;
+ }
+ }
+ TAtomicSharedPtr<TStorage> orphan(new TStorage());
+ orphan->Swap(*storage);
+ orphan->DetachFromTraceLog();
+ AtomicAdd(OrphanStoragesEventsCount, orphan->GetEventsCount());
+ OrphanStorages.push_back(orphan);
+ CleanOrphanStorages(GetCycleCount());
+ }
+
+ void CleanOrphanStorages(ui64 now) {
+ EraseIf(OrphanStorages, [=](const TAtomicSharedPtr<TStorage>& ptr) {
+ const TStorage& storage = *ptr;
+ return storage.Expired(now);
+ });
+ }
+
+ template <class TReader>
+ void ReadThreads(TReader& r) const {
+ TGuard<TSpinLock> g(Lock);
+ for (TStorage* i : StoragesVec) {
+ r.PushThread(i->GetThreadId());
+ }
+ for (const auto& orphanStorage : OrphanStorages) {
+ r.PushThread(orphanStorage->GetThreadId());
+ }
+ }
+
+ template <class TReader>
+ void ReadItems(ui64 now, ui64 duration, TReader& r) const {
+ TGuard<TSpinLock> g(Lock);
+ for (TStorage* storage : StoragesVec) {
+ storage->ReadItems(now, duration, r);
+ }
+ for (const auto& orphanStorage : OrphanStorages) {
+ orphanStorage->ReadItems(now, duration, r);
+ }
+ }
+ };
+
+ using TDurationLog = TDurationLogImpl<TLogItem>;
+ using TDurationDepot = TDurationLogImpl<TTrackLog>;
+
+ // Log that uses one cyclic buffer to store items
+ // Each item is a result of execution of some event
+ class TInMemoryLog: public TNonCopyable {
+ public:
+ struct TItem {
+ const TEvent* Event;
+ TParams Params;
+ TInstant Timestamp;
+
+ TItem()
+ : Event(nullptr)
+ {
+ }
+
+ TItem(const TItem& other)
+ : Event(other.Event)
+ , Timestamp(other.Timestamp)
+ {
+ Clone(other);
+ }
+
+ ~TItem() {
+ Destroy();
+ }
+
+ TItem& operator=(const TItem& other) {
+ Destroy();
+ Event = other.Event;
+ Timestamp = other.Timestamp;
+ Clone(other);
+ return *this;
+ }
+
+ void Clear() {
+ Destroy();
+ Event = nullptr;
+ }
+
+ private:
+ void Clone(const TItem& other) {
+ if (Event && Event->Signature.ParamCount > 0) {
+ Event->Signature.CloneParams(Params, other.Params);
+ }
+ }
+
+ void Destroy() {
+ if (Event && Event->Signature.ParamCount > 0) {
+ Event->Signature.DestroyParams(Params);
+ }
+ }
+ };
+
+ class TAccessor;
+ friend class TAccessor;
+ class TAccessor: public TGuard<TMutex> {
+ private:
+ TInMemoryLog& Log;
+
+ public:
+ explicit TAccessor(TInMemoryLog& log)
+ : TGuard<TMutex>(log.Lock)
+ , Log(log)
+ {
+ }
+
+ TItem* Add() {
+ return Log.Storage.Add();
+ }
+ };
+
+ private:
+ TMutex Lock;
+ TCyclicBuffer<TItem> Storage;
+
+ public:
+ explicit TInMemoryLog(size_t capacity)
+ : Storage(capacity)
+ {
+ }
+
+ template <class TReader>
+ void ReadItems(TReader& r) const {
+ TGuard<TMutex> g(Lock);
+ if (Storage.GetSize() > 0) {
+ for (const TItem *i = Storage.GetFront(), *e = Storage.GetBack();; Storage.Inc(i)) {
+ r.Push(*i);
+ if (i == e) {
+ break;
+ }
+ }
+ }
+ }
+ };
+
+#ifndef LWTRACE_DISABLE
+
+ // Class representing a specific event
+ template <LWTRACE_TEMPLATE_PARAMS>
+ struct TUserEvent {
+ TEvent Event;
+
+ inline void operator()(TInMemoryLog& log, bool logTimestamp, LWTRACE_FUNCTION_PARAMS) const {
+ TInMemoryLog::TAccessor la(log);
+ if (TInMemoryLog::TItem* item = la.Add()) {
+ item->Event = &Event;
+ LWTRACE_PREPARE_PARAMS(item->Params);
+ if (logTimestamp) {
+ item->Timestamp = TInstant::Now();
+ }
+ }
+ }
+ };
+
+#endif
+
+}
diff --git a/library/cpp/lwtrace/log_shuttle.cpp b/library/cpp/lwtrace/log_shuttle.cpp
index 695aa90b31..1e9c00d0ef 100644
--- a/library/cpp/lwtrace/log_shuttle.cpp
+++ b/library/cpp/lwtrace/log_shuttle.cpp
@@ -1,32 +1,32 @@
-#include "log_shuttle.h"
+#include "log_shuttle.h"
#include "probes.h"
-
-namespace NLWTrace {
+
+namespace NLWTrace {
LWTRACE_USING(LWTRACE_INTERNAL_PROVIDER);
#ifdef LWTRACE_DISABLE
template <class TDepot>
- bool TLogShuttle<TDepot>::DoFork(TShuttlePtr& child) {
- Y_UNUSED(child);
+ bool TLogShuttle<TDepot>::DoFork(TShuttlePtr& child) {
+ Y_UNUSED(child);
return false;
}
template <class TDepot>
- bool TLogShuttle<TDepot>::DoJoin(const TShuttlePtr& child) {
- Y_UNUSED(child);
+ bool TLogShuttle<TDepot>::DoJoin(const TShuttlePtr& child) {
+ Y_UNUSED(child);
return false;
}
#else
template <class TDepot>
- bool TLogShuttle<TDepot>::DoFork(TShuttlePtr& child) {
- if (child = Executor->RentShuttle()) {
- child->SetParentSpanId(GetSpanId());
- Executor->Cast(child)->SetIgnore(true);
+ bool TLogShuttle<TDepot>::DoFork(TShuttlePtr& child) {
+ if (child = Executor->RentShuttle()) {
+ child->SetParentSpanId(GetSpanId());
+ Executor->Cast(child)->SetIgnore(true);
TParams params;
- params.Param[0].CopyConstruct<ui64>(child->GetSpanId());
+ params.Param[0].CopyConstruct<ui64>(child->GetSpanId());
bool result = DoAddProbe(&LWTRACE_GET_NAME(Fork).Probe, params, 0);
TUserSignature<ui64>::DestroyParams(params);
return result;
@@ -64,4 +64,4 @@ namespace NLWTrace {
template class TLogShuttle<TDurationDepot>;
template class TLogShuttle<TCyclicDepot>;
-}
+}
diff --git a/library/cpp/lwtrace/log_shuttle.h b/library/cpp/lwtrace/log_shuttle.h
index 729a38615f..8c9dc3a587 100644
--- a/library/cpp/lwtrace/log_shuttle.h
+++ b/library/cpp/lwtrace/log_shuttle.h
@@ -1,160 +1,160 @@
-#pragma once
-
-#include "log.h"
-#include "probe.h"
-
+#pragma once
+
+#include "log.h"
+#include "probe.h"
+
#include <library/cpp/lwtrace/protos/lwtrace.pb.h>
#include <util/system/spinlock.h>
-namespace NLWTrace {
- template <class TDepot>
- class TRunLogShuttleActionExecutor;
-
- ////////////////////////////////////////////////////////////////////////////////
-
- struct THostTimeCalculator {
+namespace NLWTrace {
+ template <class TDepot>
+ class TRunLogShuttleActionExecutor;
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ struct THostTimeCalculator {
double K = 0;
ui64 B = 0;
- THostTimeCalculator() {
+ THostTimeCalculator() {
TInstant now = TInstant::Now();
ui64 tsNow = GetCycleCount();
K = 1000000000 / NHPTimer::GetClockRate();
B = now.NanoSeconds() - K * tsNow;
}
- ui64 CyclesToEpochNanoseconds(ui64 cycles) const {
+ ui64 CyclesToEpochNanoseconds(ui64 cycles) const {
return K*cycles + B;
}
- ui64 EpochNanosecondsToCycles(ui64 ns) const {
+ ui64 EpochNanosecondsToCycles(ui64 ns) const {
return (ns - B) / K;
}
};
- inline ui64 CyclesToEpochNanoseconds(ui64 cycles) {
+ inline ui64 CyclesToEpochNanoseconds(ui64 cycles) {
return Singleton<THostTimeCalculator>()->CyclesToEpochNanoseconds(cycles);
}
- inline ui64 EpochNanosecondsToCycles(ui64 ns) {
+ inline ui64 EpochNanosecondsToCycles(ui64 ns) {
return Singleton<THostTimeCalculator>()->EpochNanosecondsToCycles(ns);
}
////////////////////////////////////////////////////////////////////////////////
- template <class TDepot>
- class TLogShuttle: public IShuttle {
- private:
+ template <class TDepot>
+ class TLogShuttle: public IShuttle {
+ private:
using TExecutor = TRunLogShuttleActionExecutor<TDepot>;
- TTrackLog TrackLog;
+ TTrackLog TrackLog;
TExecutor* Executor;
- bool Ignore = false;
- size_t MaxTrackLength;
+ bool Ignore = false;
+ size_t MaxTrackLength;
TAdaptiveLock Lock;
TAtomic ForkFailed = 0;
-
- public:
+
+ public:
explicit TLogShuttle(TExecutor* executor)
: IShuttle(executor->GetTraceIdx(), executor->NewSpanId())
, Executor(executor)
, MaxTrackLength(Executor->GetAction().GetMaxTrackLength() ? Executor->GetAction().GetMaxTrackLength() : 100)
- {
- }
-
+ {
+ }
+
bool DoAddProbe(TProbe* probe, const TParams& params, ui64 timestamp) override;
- void DoEndOfTrack() override;
- void DoDrop() override;
+ void DoEndOfTrack() override;
+ void DoDrop() override;
void DoSerialize(TShuttleTrace& msg) override;
- bool DoFork(TShuttlePtr& child) override;
+ bool DoFork(TShuttlePtr& child) override;
bool DoJoin(const TShuttlePtr& child) override;
-
- void SetIgnore(bool ignore);
- void Clear();
-
- const TTrackLog& GetTrackLog() const {
- return TrackLog;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- class TLogShuttleActionBase: public IExecutor {
- private:
- const ui64 TraceIdx;
-
- public:
- explicit TLogShuttleActionBase(ui64 traceIdx)
- : TraceIdx(traceIdx)
- {
- }
- ui64 GetTraceIdx() const {
- return TraceIdx;
- }
-
- static TLogShuttle<TDepot>* Cast(const TShuttlePtr& shuttle);
- static TLogShuttle<TDepot>* Cast(IShuttle* shuttle);
- };
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- class TRunLogShuttleActionExecutor: public TLogShuttleActionBase<TDepot> {
- private:
- TSpinLock Lock;
- TVector<TShuttlePtr> AllShuttles;
- TVector<TShuttlePtr> Parking;
- TRunLogShuttleAction Action;
- TDepot* Depot;
-
- TAtomic MissedTracks = 0;
- TAtomic* LastTrackId;
+
+ void SetIgnore(bool ignore);
+ void Clear();
+
+ const TTrackLog& GetTrackLog() const {
+ return TrackLog;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ class TLogShuttleActionBase: public IExecutor {
+ private:
+ const ui64 TraceIdx;
+
+ public:
+ explicit TLogShuttleActionBase(ui64 traceIdx)
+ : TraceIdx(traceIdx)
+ {
+ }
+ ui64 GetTraceIdx() const {
+ return TraceIdx;
+ }
+
+ static TLogShuttle<TDepot>* Cast(const TShuttlePtr& shuttle);
+ static TLogShuttle<TDepot>* Cast(IShuttle* shuttle);
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ class TRunLogShuttleActionExecutor: public TLogShuttleActionBase<TDepot> {
+ private:
+ TSpinLock Lock;
+ TVector<TShuttlePtr> AllShuttles;
+ TVector<TShuttlePtr> Parking;
+ TRunLogShuttleAction Action;
+ TDepot* Depot;
+
+ TAtomic MissedTracks = 0;
+ TAtomic* LastTrackId;
TAtomic* LastSpanId;
-
- static constexpr int MaxShuttles = 100000;
-
- public:
+
+ static constexpr int MaxShuttles = 100000;
+
+ public:
TRunLogShuttleActionExecutor(ui64 traceIdx, const TRunLogShuttleAction& action, TDepot* depot, TAtomic* lastTrackId, TAtomic* lastSpanId);
- ~TRunLogShuttleActionExecutor();
- bool DoExecute(TOrbit& orbit, const TParams& params) override;
- void RecordShuttle(TLogShuttle<TDepot>* shuttle);
- void ParkShuttle(TLogShuttle<TDepot>* shuttle);
+ ~TRunLogShuttleActionExecutor();
+ bool DoExecute(TOrbit& orbit, const TParams& params) override;
+ void RecordShuttle(TLogShuttle<TDepot>* shuttle);
+ void ParkShuttle(TLogShuttle<TDepot>* shuttle);
void DiscardShuttle();
TShuttlePtr RentShuttle();
ui64 NewSpanId();
- const TRunLogShuttleAction& GetAction() const {
- return Action;
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- class TEditLogShuttleActionExecutor: public TLogShuttleActionBase<TDepot> {
- private:
- TEditLogShuttleAction Action;
-
- public:
- TEditLogShuttleActionExecutor(ui64 traceIdx, const TEditLogShuttleAction& action);
- bool DoExecute(TOrbit& orbit, const TParams& params) override;
- };
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- class TDropLogShuttleActionExecutor: public TLogShuttleActionBase<TDepot> {
- private:
- TDropLogShuttleAction Action;
-
- public:
- TDropLogShuttleActionExecutor(ui64 traceIdx, const TDropLogShuttleAction& action);
- bool DoExecute(TOrbit& orbit, const TParams& params) override;
- };
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
+ const TRunLogShuttleAction& GetAction() const {
+ return Action;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ class TEditLogShuttleActionExecutor: public TLogShuttleActionBase<TDepot> {
+ private:
+ TEditLogShuttleAction Action;
+
+ public:
+ TEditLogShuttleActionExecutor(ui64 traceIdx, const TEditLogShuttleAction& action);
+ bool DoExecute(TOrbit& orbit, const TParams& params) override;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ class TDropLogShuttleActionExecutor: public TLogShuttleActionBase<TDepot> {
+ private:
+ TDropLogShuttleAction Action;
+
+ public:
+ TDropLogShuttleActionExecutor(ui64 traceIdx, const TDropLogShuttleAction& action);
+ bool DoExecute(TOrbit& orbit, const TParams& params) override;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
bool TLogShuttle<TDepot>::DoAddProbe(TProbe* probe, const TParams& params, ui64 timestamp) {
with_lock (Lock) {
if (TrackLog.Items.size() >= MaxTrackLength) {
@@ -169,41 +169,41 @@ namespace NLWTrace {
probe->Event.Signature.CloneParams(item->Params, params);
}
item->TimestampCycles = timestamp ? timestamp : GetCycleCount();
- }
-
- return true;
- }
-
- template <class TDepot>
- void TLogShuttle<TDepot>::DoEndOfTrack() {
- // Record track log if not ignored
- if (!Ignore) {
+ }
+
+ return true;
+ }
+
+ template <class TDepot>
+ void TLogShuttle<TDepot>::DoEndOfTrack() {
+ // Record track log if not ignored
+ if (!Ignore) {
if (AtomicGet(ForkFailed)) {
Executor->DiscardShuttle();
} else {
Executor->RecordShuttle(this);
}
- }
+ }
Executor->ParkShuttle(this);
- }
-
- template <class TDepot>
- void TLogShuttle<TDepot>::DoDrop() {
- // Do not track log results of dropped shuttles
+ }
+
+ template <class TDepot>
+ void TLogShuttle<TDepot>::DoDrop() {
+ // Do not track log results of dropped shuttles
Executor->ParkShuttle(this);
- }
-
- template <class TDepot>
- void TLogShuttle<TDepot>::SetIgnore(bool ignore) {
- Ignore = ignore;
- }
-
- template <class TDepot>
- void TLogShuttle<TDepot>::Clear() {
- TrackLog.Clear();
- }
-
- template <class TDepot>
+ }
+
+ template <class TDepot>
+ void TLogShuttle<TDepot>::SetIgnore(bool ignore) {
+ Ignore = ignore;
+ }
+
+ template <class TDepot>
+ void TLogShuttle<TDepot>::Clear() {
+ TrackLog.Clear();
+ }
+
+ template <class TDepot>
void TLogShuttle<TDepot>::DoSerialize(TShuttleTrace& msg)
{
with_lock (Lock)
@@ -223,137 +223,137 @@ namespace NLWTrace {
}
template <class TDepot>
- TLogShuttle<TDepot>* TLogShuttleActionBase<TDepot>::Cast(const TShuttlePtr& shuttle) {
- return static_cast<TLogShuttle<TDepot>*>(shuttle.Get());
- }
-
- template <class TDepot>
- TLogShuttle<TDepot>* TLogShuttleActionBase<TDepot>::Cast(IShuttle* shuttle) {
- return static_cast<TLogShuttle<TDepot>*>(shuttle);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- TRunLogShuttleActionExecutor<TDepot>::TRunLogShuttleActionExecutor(
- ui64 traceIdx,
- const TRunLogShuttleAction& action,
- TDepot* depot,
+ TLogShuttle<TDepot>* TLogShuttleActionBase<TDepot>::Cast(const TShuttlePtr& shuttle) {
+ return static_cast<TLogShuttle<TDepot>*>(shuttle.Get());
+ }
+
+ template <class TDepot>
+ TLogShuttle<TDepot>* TLogShuttleActionBase<TDepot>::Cast(IShuttle* shuttle) {
+ return static_cast<TLogShuttle<TDepot>*>(shuttle);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ TRunLogShuttleActionExecutor<TDepot>::TRunLogShuttleActionExecutor(
+ ui64 traceIdx,
+ const TRunLogShuttleAction& action,
+ TDepot* depot,
TAtomic* lastTrackId,
TAtomic* lastSpanId)
- : TLogShuttleActionBase<TDepot>(traceIdx)
- , Action(action)
- , Depot(depot)
- , LastTrackId(lastTrackId)
+ : TLogShuttleActionBase<TDepot>(traceIdx)
+ , Action(action)
+ , Depot(depot)
+ , LastTrackId(lastTrackId)
, LastSpanId(lastSpanId)
- {
+ {
ui64 size = Min<ui64>(Action.GetShuttlesCount() ? Action.GetShuttlesCount() : 1000, MaxShuttles); // Do not allow to allocate too much memory
- AllShuttles.reserve(size);
- Parking.reserve(size);
- for (ui64 i = 0; i < size; i++) {
- TShuttlePtr shuttle(new TLogShuttle<TDepot>(this));
- AllShuttles.emplace_back(shuttle);
- Parking.emplace_back(shuttle);
- }
- }
-
- template <class TDepot>
- TRunLogShuttleActionExecutor<TDepot>::~TRunLogShuttleActionExecutor() {
- for (TShuttlePtr& shuttle : AllShuttles) {
- shuttle->Kill();
- }
- }
-
- template <class TDepot>
- bool TRunLogShuttleActionExecutor<TDepot>::DoExecute(TOrbit& orbit, const TParams& params) {
- Y_UNUSED(params);
- if (TShuttlePtr shuttle = RentShuttle()) {
- this->Cast(shuttle)->SetIgnore(Action.GetIgnore());
- orbit.AddShuttle(shuttle);
- } else {
- AtomicIncrement(MissedTracks);
- }
- return true;
- }
-
- template <class TDepot>
+ AllShuttles.reserve(size);
+ Parking.reserve(size);
+ for (ui64 i = 0; i < size; i++) {
+ TShuttlePtr shuttle(new TLogShuttle<TDepot>(this));
+ AllShuttles.emplace_back(shuttle);
+ Parking.emplace_back(shuttle);
+ }
+ }
+
+ template <class TDepot>
+ TRunLogShuttleActionExecutor<TDepot>::~TRunLogShuttleActionExecutor() {
+ for (TShuttlePtr& shuttle : AllShuttles) {
+ shuttle->Kill();
+ }
+ }
+
+ template <class TDepot>
+ bool TRunLogShuttleActionExecutor<TDepot>::DoExecute(TOrbit& orbit, const TParams& params) {
+ Y_UNUSED(params);
+ if (TShuttlePtr shuttle = RentShuttle()) {
+ this->Cast(shuttle)->SetIgnore(Action.GetIgnore());
+ orbit.AddShuttle(shuttle);
+ } else {
+ AtomicIncrement(MissedTracks);
+ }
+ return true;
+ }
+
+ template <class TDepot>
void TRunLogShuttleActionExecutor<TDepot>::DiscardShuttle() {
AtomicIncrement(MissedTracks);
}
template <class TDepot>
- void TRunLogShuttleActionExecutor<TDepot>::RecordShuttle(TLogShuttle<TDepot>* shuttle) {
+ void TRunLogShuttleActionExecutor<TDepot>::RecordShuttle(TLogShuttle<TDepot>* shuttle) {
if (Depot == nullptr) {
return;
}
- typename TDepot::TAccessor a(*Depot);
- if (TTrackLog* trackLog = a.Add()) {
- *trackLog = shuttle->GetTrackLog();
- trackLog->Id = AtomicIncrement(*LastTrackId); // Track id is assigned at reporting time
- }
- }
-
- template <class TDepot>
- TShuttlePtr TRunLogShuttleActionExecutor<TDepot>::RentShuttle() {
- TGuard<TSpinLock> g(Lock);
- if (Parking.empty()) {
- return TShuttlePtr();
- } else {
- TShuttlePtr shuttle = Parking.back();
- Parking.pop_back();
- return shuttle;
- }
- }
-
- template <class TDepot>
- void TRunLogShuttleActionExecutor<TDepot>::ParkShuttle(TLogShuttle<TDepot>* shuttle) {
- shuttle->Clear();
- TGuard<TSpinLock> g(Lock);
- Parking.emplace_back(shuttle);
- }
-
+ typename TDepot::TAccessor a(*Depot);
+ if (TTrackLog* trackLog = a.Add()) {
+ *trackLog = shuttle->GetTrackLog();
+ trackLog->Id = AtomicIncrement(*LastTrackId); // Track id is assigned at reporting time
+ }
+ }
+
+ template <class TDepot>
+ TShuttlePtr TRunLogShuttleActionExecutor<TDepot>::RentShuttle() {
+ TGuard<TSpinLock> g(Lock);
+ if (Parking.empty()) {
+ return TShuttlePtr();
+ } else {
+ TShuttlePtr shuttle = Parking.back();
+ Parking.pop_back();
+ return shuttle;
+ }
+ }
+
+ template <class TDepot>
+ void TRunLogShuttleActionExecutor<TDepot>::ParkShuttle(TLogShuttle<TDepot>* shuttle) {
+ shuttle->Clear();
+ TGuard<TSpinLock> g(Lock);
+ Parking.emplace_back(shuttle);
+ }
+
template <class TDepot>
ui64 TRunLogShuttleActionExecutor<TDepot>::NewSpanId()
{
return LastSpanId ? AtomicIncrement(*LastSpanId) : 0;
}
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- TEditLogShuttleActionExecutor<TDepot>::TEditLogShuttleActionExecutor(ui64 traceIdx, const TEditLogShuttleAction& action)
- : TLogShuttleActionBase<TDepot>(traceIdx)
- , Action(action)
- {
- }
-
- template <class TDepot>
- bool TEditLogShuttleActionExecutor<TDepot>::DoExecute(TOrbit& orbit, const TParams& params) {
- Y_UNUSED(params);
- bool ignore = Action.GetIgnore();
- orbit.ForEachShuttle(this->GetTraceIdx(), [=](IShuttle* shuttle) {
- this->Cast(shuttle)->SetIgnore(ignore);
- return true;
- });
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- template <class TDepot>
- TDropLogShuttleActionExecutor<TDepot>::TDropLogShuttleActionExecutor(ui64 traceIdx, const TDropLogShuttleAction& action)
- : TLogShuttleActionBase<TDepot>(traceIdx)
- , Action(action)
- {
- }
-
- template <class TDepot>
- bool TDropLogShuttleActionExecutor<TDepot>::DoExecute(TOrbit& orbit, const TParams& params) {
- Y_UNUSED(params);
- orbit.ForEachShuttle(this->GetTraceIdx(), [](IShuttle*) {
- return false; // Erase shuttle from orbit
- });
- return true;
- }
-
-}
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ TEditLogShuttleActionExecutor<TDepot>::TEditLogShuttleActionExecutor(ui64 traceIdx, const TEditLogShuttleAction& action)
+ : TLogShuttleActionBase<TDepot>(traceIdx)
+ , Action(action)
+ {
+ }
+
+ template <class TDepot>
+ bool TEditLogShuttleActionExecutor<TDepot>::DoExecute(TOrbit& orbit, const TParams& params) {
+ Y_UNUSED(params);
+ bool ignore = Action.GetIgnore();
+ orbit.ForEachShuttle(this->GetTraceIdx(), [=](IShuttle* shuttle) {
+ this->Cast(shuttle)->SetIgnore(ignore);
+ return true;
+ });
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class TDepot>
+ TDropLogShuttleActionExecutor<TDepot>::TDropLogShuttleActionExecutor(ui64 traceIdx, const TDropLogShuttleAction& action)
+ : TLogShuttleActionBase<TDepot>(traceIdx)
+ , Action(action)
+ {
+ }
+
+ template <class TDepot>
+ bool TDropLogShuttleActionExecutor<TDepot>::DoExecute(TOrbit& orbit, const TParams& params) {
+ Y_UNUSED(params);
+ orbit.ForEachShuttle(this->GetTraceIdx(), [](IShuttle*) {
+ return false; // Erase shuttle from orbit
+ });
+ return true;
+ }
+
+}
diff --git a/library/cpp/lwtrace/lwprobe.h b/library/cpp/lwtrace/lwprobe.h
index 801fc3861b..9149bb8519 100644
--- a/library/cpp/lwtrace/lwprobe.h
+++ b/library/cpp/lwtrace/lwprobe.h
@@ -1,110 +1,110 @@
-#pragma once
-
+#pragma once
+
#include "control.h"
#include "probe.h"
-#include <ctype.h>
-
-namespace NLWTrace {
-#ifndef LWTRACE_DISABLE
-
- // Box that holds dynamically created probe
- // NOTE: must be allocated on heap
- template <LWTRACE_TEMPLATE_PARAMS>
- class TLWProbe: public IBox, public TUserProbe<LWTRACE_TEMPLATE_ARGS> {
- private:
- // Storage for strings referenced by TEvent
- TString Name;
- TString Provider;
- TVector<TString> Groups;
- TVector<TString> Params;
- TVector<TProbeRegistry*> Registries; // Note that we assume that registry lives longer than probe
-
- public:
- TLWProbe(const TString& provider, const TString& name, const TVector<TString>& groups, const TVector<TString>& params)
- : IBox(true)
- , Name(name)
- , Provider(provider)
- , Groups(groups)
- , Params(params)
- {
- // initialize TProbe
- TProbe& probe = this->Probe;
- probe.Init();
-
- // initialize TEvent
+#include <ctype.h>
+
+namespace NLWTrace {
+#ifndef LWTRACE_DISABLE
+
+ // Box that holds dynamically created probe
+ // NOTE: must be allocated on heap
+ template <LWTRACE_TEMPLATE_PARAMS>
+ class TLWProbe: public IBox, public TUserProbe<LWTRACE_TEMPLATE_ARGS> {
+ private:
+ // Storage for strings referenced by TEvent
+ TString Name;
+ TString Provider;
+ TVector<TString> Groups;
+ TVector<TString> Params;
+ TVector<TProbeRegistry*> Registries; // Note that we assume that registry lives longer than probe
+
+ public:
+ TLWProbe(const TString& provider, const TString& name, const TVector<TString>& groups, const TVector<TString>& params)
+ : IBox(true)
+ , Name(name)
+ , Provider(provider)
+ , Groups(groups)
+ , Params(params)
+ {
+ // initialize TProbe
+ TProbe& probe = this->Probe;
+ probe.Init();
+
+ // initialize TEvent
Y_VERIFY(IsCppIdentifier(Name), "probe '%s' is not C++ identifier", Name.data());
Y_VERIFY(IsCppIdentifier(Provider), "provider '%s' is not C++ identifier in probe %s", Provider.data(), Name.data());
- probe.Event.Name = Name.c_str();
- Zero(probe.Event.Groups);
- probe.Event.Groups[0] = Provider.c_str();
- auto i = Groups.begin(), ie = Groups.end();
+ probe.Event.Name = Name.c_str();
+ Zero(probe.Event.Groups);
+ probe.Event.Groups[0] = Provider.c_str();
+ auto i = Groups.begin(), ie = Groups.end();
Y_VERIFY(Groups.size() < LWTRACE_MAX_GROUPS, "too many groups in probe %s", Name.data());
- for (size_t n = 1; n < LWTRACE_MAX_GROUPS && i != ie; n++, ++i) {
+ for (size_t n = 1; n < LWTRACE_MAX_GROUPS && i != ie; n++, ++i) {
Y_VERIFY(IsCppIdentifier(*i), "group '%s' is not C++ identifier in probe %s", i->data(), Name.data());
- probe.Event.Groups[n] = i->c_str();
- }
-
- // initialize TSignature
- using TUsrSign = TUserSignature<LWTRACE_TEMPLATE_ARGS>;
- Y_VERIFY(TUsrSign::ParamCount == (int)Params.size(), "param count mismatch in probe %s: %d != %d",
+ probe.Event.Groups[n] = i->c_str();
+ }
+
+ // initialize TSignature
+ using TUsrSign = TUserSignature<LWTRACE_TEMPLATE_ARGS>;
+ Y_VERIFY(TUsrSign::ParamCount == (int)Params.size(), "param count mismatch in probe %s: %d != %d",
Name.data(), int(Params.size()), TUsrSign::ParamCount);
- TSignature& signature = probe.Event.Signature;
- signature.ParamTypes = TUsrSign::ParamTypes;
- Zero(signature.ParamNames);
- auto j = Params.begin(), je = Params.end();
- for (size_t n = 0; n < LWTRACE_MAX_PARAMS && j != je; n++, ++j) {
+ TSignature& signature = probe.Event.Signature;
+ signature.ParamTypes = TUsrSign::ParamTypes;
+ Zero(signature.ParamNames);
+ auto j = Params.begin(), je = Params.end();
+ for (size_t n = 0; n < LWTRACE_MAX_PARAMS && j != je; n++, ++j) {
Y_VERIFY(IsCppIdentifier(*j), "param '%s' is not C++ identifier in probe %s", j->data(), Name.data());
- signature.ParamNames[n] = j->c_str();
- }
- signature.ParamCount = TUsrSign::ParamCount;
- signature.SerializeParamsFunc = &TUsrSign::SerializeParams;
- signature.CloneParamsFunc = &TUsrSign::CloneParams;
- signature.DestroyParamsFunc = &TUsrSign::DestroyParams;
+ signature.ParamNames[n] = j->c_str();
+ }
+ signature.ParamCount = TUsrSign::ParamCount;
+ signature.SerializeParamsFunc = &TUsrSign::SerializeParams;
+ signature.CloneParamsFunc = &TUsrSign::CloneParams;
+ signature.DestroyParamsFunc = &TUsrSign::DestroyParams;
signature.SerializeToPbFunc = &TUsrSign::SerializeToPb;
signature.DeserializeFromPbFunc = &TUsrSign::DeserializeFromPb;
-
- // register probe in global registry
- Register(*Singleton<NLWTrace::TProbeRegistry>());
- }
-
- ~TLWProbe() {
- Unregister();
- }
-
- void Register(TProbeRegistry& reg) {
- Registries.push_back(&reg);
- reg.AddProbe(TBoxPtr(this)); // NOTE: implied `this' object is created with new operator
- }
-
- void Unregister() {
- // TODO[serxa]: make sure registry never dies before probe it contain
- // TODO[serxa]: make sure probe never dies before TSession that uses it
- for (TProbeRegistry* reg : Registries) {
- reg->RemoveProbe(&this->Probe);
- }
- }
-
- TProbe* GetProbe() override {
- return &this->Probe;
- }
-
- private:
- static bool IsCppIdentifier(const TString& str) {
- bool first = true;
- for (char c : str) {
- if (first) {
- first = false;
- if (!(isalpha(c) || c == '_')) {
- return false;
- }
- } else if (!(isalnum(c) || c == '_')) {
- return false;
- }
- }
- return true;
- }
- };
-
-#endif
-}
+
+ // register probe in global registry
+ Register(*Singleton<NLWTrace::TProbeRegistry>());
+ }
+
+ ~TLWProbe() {
+ Unregister();
+ }
+
+ void Register(TProbeRegistry& reg) {
+ Registries.push_back(&reg);
+ reg.AddProbe(TBoxPtr(this)); // NOTE: implied `this' object is created with new operator
+ }
+
+ void Unregister() {
+ // TODO[serxa]: make sure registry never dies before probe it contain
+ // TODO[serxa]: make sure probe never dies before TSession that uses it
+ for (TProbeRegistry* reg : Registries) {
+ reg->RemoveProbe(&this->Probe);
+ }
+ }
+
+ TProbe* GetProbe() override {
+ return &this->Probe;
+ }
+
+ private:
+ static bool IsCppIdentifier(const TString& str) {
+ bool first = true;
+ for (char c : str) {
+ if (first) {
+ first = false;
+ if (!(isalpha(c) || c == '_')) {
+ return false;
+ }
+ } else if (!(isalnum(c) || c == '_')) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
+#endif
+}
diff --git a/library/cpp/lwtrace/mon/analytics/all.h b/library/cpp/lwtrace/mon/analytics/all.h
index 02ddfb83f2..93c8b950ca 100644
--- a/library/cpp/lwtrace/mon/analytics/all.h
+++ b/library/cpp/lwtrace/mon/analytics/all.h
@@ -1,5 +1,5 @@
-#pragma once
-
+#pragma once
+
#include "csv_output.h"
#include "data.h"
#include "html_output.h"
diff --git a/library/cpp/lwtrace/mon/analytics/analytics.cpp b/library/cpp/lwtrace/mon/analytics/analytics.cpp
index 1b25263386..107c939f15 100644
--- a/library/cpp/lwtrace/mon/analytics/analytics.cpp
+++ b/library/cpp/lwtrace/mon/analytics/analytics.cpp
@@ -1,5 +1,5 @@
-#include "all.h"
-
-namespace NAnalytics {
-
-}
+#include "all.h"
+
+namespace NAnalytics {
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/csv_output.h b/library/cpp/lwtrace/mon/analytics/csv_output.h
index 90ded32f5d..7e441d9e3f 100644
--- a/library/cpp/lwtrace/mon/analytics/csv_output.h
+++ b/library/cpp/lwtrace/mon/analytics/csv_output.h
@@ -1,52 +1,52 @@
-#pragma once
-
-#include <util/string/printf.h>
-#include <util/stream/str.h>
-#include <util/generic/set.h>
+#pragma once
+
+#include <util/string/printf.h>
+#include <util/stream/str.h>
+#include <util/generic/set.h>
#include "data.h"
-
-namespace NAnalytics {
-
+
+namespace NAnalytics {
+
inline TString ToCsv(const TTable& in, TString sep = TString("\t"), bool head = true)
-{
+{
TSet<TString> cols;
- bool hasName = false;
- for (const TRow& row : in) {
- hasName = hasName || !row.Name.empty();
- for (const auto& kv : row) {
- cols.insert(kv.first);
- }
- }
-
- TStringStream ss;
- if (head) {
- bool first = true;
- if (hasName) {
+ bool hasName = false;
+ for (const TRow& row : in) {
+ hasName = hasName || !row.Name.empty();
+ for (const auto& kv : row) {
+ cols.insert(kv.first);
+ }
+ }
+
+ TStringStream ss;
+ if (head) {
+ bool first = true;
+ if (hasName) {
ss << (first? TString(): sep) << "Name";
- first = false;
- }
+ first = false;
+ }
for (const TString& c : cols) {
ss << (first? TString(): sep) << c;
- first = false;
- }
- ss << Endl;
- }
-
- for (const TRow& row : in) {
- bool first = true;
- if (hasName) {
+ first = false;
+ }
+ ss << Endl;
+ }
+
+ for (const TRow& row : in) {
+ bool first = true;
+ if (hasName) {
ss << (first? TString(): sep) << row.Name;
- first = false;
- }
+ first = false;
+ }
for (const TString& c : cols) {
ss << (first? TString(): sep);
- first = false;
+ first = false;
TString value;
ss << (row.GetAsString(c, value) ? value : TString("-"));
- }
- ss << Endl;
- }
- return ss.Str();
-}
-
-}
+ }
+ ss << Endl;
+ }
+ return ss.Str();
+}
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/data.h b/library/cpp/lwtrace/mon/analytics/data.h
index 4b643fe20b..7aeedbdd5e 100644
--- a/library/cpp/lwtrace/mon/analytics/data.h
+++ b/library/cpp/lwtrace/mon/analytics/data.h
@@ -1,15 +1,15 @@
-#pragma once
-
+#pragma once
+
#include <util/generic/string.h>
-#include <util/generic/hash.h>
+#include <util/generic/hash.h>
#include <util/generic/vector.h>
#include <util/string/builder.h>
#include <util/string/cast.h>
-
+
#include <variant>
-namespace NAnalytics {
-
+namespace NAnalytics {
+
using TRowValue = std::variant<i64, ui64, double, TString>;
TString ToString(const TRowValue& val) {
@@ -22,7 +22,7 @@ TString ToString(const TRowValue& val) {
struct TRow : public THashMap<TString, TRowValue> {
TString Name;
-
+
template<typename T>
bool Get(const TString& name, T& value) const {
if constexpr (std::is_same_v<double, T>) {
@@ -30,9 +30,9 @@ struct TRow : public THashMap<TString, TRowValue> {
value = 1.0;
return true;
}
- }
- auto iter = find(name);
- if (iter != end()) {
+ }
+ auto iter = find(name);
+ if (iter != end()) {
try {
value = std::get<T>(iter->second);
return true;
@@ -51,58 +51,58 @@ struct TRow : public THashMap<TString, TRowValue> {
auto iter = find(name);
if (iter != end()) {
value = ToString(iter->second);
- return true;
- }
+ return true;
+ }
return false;
- }
-};
-
+ }
+};
+
using TAttributes = THashMap<TString, TString>;
-
+
struct TTable : public TVector<TRow> {
- TAttributes Attributes;
-};
-
+ TAttributes Attributes;
+};
+
struct TMatrix : public TVector<double> {
- size_t Rows;
- size_t Cols;
-
- explicit TMatrix(size_t rows = 0, size_t cols = 0)
+ size_t Rows;
+ size_t Cols;
+
+ explicit TMatrix(size_t rows = 0, size_t cols = 0)
: TVector<double>(rows * cols)
- , Rows(rows)
- , Cols(cols)
- {}
-
- void Reset(size_t rows, size_t cols)
- {
- Rows = rows;
- Cols = cols;
- clear();
- resize(rows * cols);
- }
-
- double& Cell(size_t row, size_t col)
- {
- Y_VERIFY(row < Rows);
- Y_VERIFY(col < Cols);
- return operator[](row * Cols + col);
- }
-
- double Cell(size_t row, size_t col) const
- {
- Y_VERIFY(row < Rows);
- Y_VERIFY(col < Cols);
- return operator[](row * Cols + col);
- }
-
- double CellSum() const
- {
- double sum = 0.0;
- for (double x : *this) {
- sum += x;
- }
- return sum;
- }
-};
-
-}
+ , Rows(rows)
+ , Cols(cols)
+ {}
+
+ void Reset(size_t rows, size_t cols)
+ {
+ Rows = rows;
+ Cols = cols;
+ clear();
+ resize(rows * cols);
+ }
+
+ double& Cell(size_t row, size_t col)
+ {
+ Y_VERIFY(row < Rows);
+ Y_VERIFY(col < Cols);
+ return operator[](row * Cols + col);
+ }
+
+ double Cell(size_t row, size_t col) const
+ {
+ Y_VERIFY(row < Rows);
+ Y_VERIFY(col < Cols);
+ return operator[](row * Cols + col);
+ }
+
+ double CellSum() const
+ {
+ double sum = 0.0;
+ for (double x : *this) {
+ sum += x;
+ }
+ return sum;
+ }
+};
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/html_output.h b/library/cpp/lwtrace/mon/analytics/html_output.h
index f775f216b9..37d9fe3724 100644
--- a/library/cpp/lwtrace/mon/analytics/html_output.h
+++ b/library/cpp/lwtrace/mon/analytics/html_output.h
@@ -1,86 +1,86 @@
-#pragma once
-
-#include <util/string/printf.h>
-#include <util/stream/str.h>
-#include <util/generic/set.h>
+#pragma once
+
+#include <util/string/printf.h>
+#include <util/stream/str.h>
+#include <util/generic/set.h>
#include "data.h"
-
-namespace NAnalytics {
-
+
+namespace NAnalytics {
+
inline TString ToHtml(const TTable& in)
-{
+{
TSet<TString> cols;
- bool hasName = false;
- for (const TRow& row : in) {
- hasName = hasName || !row.Name.empty();
- for (const auto& kv : row) {
- cols.insert(kv.first);
- }
- }
-
- TStringStream ss;
- ss << "<table>";
- ss << "<thead><tr>";
- if (hasName) {
- ss << "<th>Name</th>";
- }
+ bool hasName = false;
+ for (const TRow& row : in) {
+ hasName = hasName || !row.Name.empty();
+ for (const auto& kv : row) {
+ cols.insert(kv.first);
+ }
+ }
+
+ TStringStream ss;
+ ss << "<table>";
+ ss << "<thead><tr>";
+ if (hasName) {
+ ss << "<th>Name</th>";
+ }
for (const TString& c : cols) {
- ss << "<th>" << c << "</th>";
- }
- ss << "</tr></thead><tbody>";
-
- for (const TRow& row : in) {
- ss << "<tr>";
- if (hasName) {
- ss << "<th>" << row.Name << "</th>";
- }
+ ss << "<th>" << c << "</th>";
+ }
+ ss << "</tr></thead><tbody>";
+
+ for (const TRow& row : in) {
+ ss << "<tr>";
+ if (hasName) {
+ ss << "<th>" << row.Name << "</th>";
+ }
for (const TString& c : cols) {
TString value;
ss << "<td>" << (row.GetAsString(c, value) ? value : TString("-")) << "</td>";
- }
- ss << "</tr>";
- }
- ss << "</tbody></table>";
-
- return ss.Str();
-}
-
+ }
+ ss << "</tr>";
+ }
+ ss << "</tbody></table>";
+
+ return ss.Str();
+}
+
inline TString ToTransposedHtml(const TTable& in)
-{
+{
TSet<TString> cols;
- bool hasName = false;
- for (const TRow& row : in) {
- hasName = hasName || !row.Name.empty();
- for (const auto& kv : row) {
- cols.insert(kv.first);
- }
- }
-
- TStringStream ss;
- ss << "<table><thead>";
- if (hasName) {
- ss << "<tr>";
- ss << "<th>Name</th>";
- for (const TRow& row : in) {
- ss << "<th>" << row.Name << "</th>";
- }
- ss << "</tr>";
- }
-
- ss << "</thead><tbody>";
-
+ bool hasName = false;
+ for (const TRow& row : in) {
+ hasName = hasName || !row.Name.empty();
+ for (const auto& kv : row) {
+ cols.insert(kv.first);
+ }
+ }
+
+ TStringStream ss;
+ ss << "<table><thead>";
+ if (hasName) {
+ ss << "<tr>";
+ ss << "<th>Name</th>";
+ for (const TRow& row : in) {
+ ss << "<th>" << row.Name << "</th>";
+ }
+ ss << "</tr>";
+ }
+
+ ss << "</thead><tbody>";
+
for (const TString& c : cols) {
- ss << "<tr>";
- ss << "<th>" << c << "</th>";
- for (const TRow& row : in) {
+ ss << "<tr>";
+ ss << "<th>" << c << "</th>";
+ for (const TRow& row : in) {
TString value;
ss << "<td>" << (row.GetAsString(c, value) ? value : TString("-")) << "</td>";
- }
- ss << "</tr>";
- }
- ss << "</tbody></table>";
-
- return ss.Str();
-}
-
-}
+ }
+ ss << "</tr>";
+ }
+ ss << "</tbody></table>";
+
+ return ss.Str();
+}
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/json_output.h b/library/cpp/lwtrace/mon/analytics/json_output.h
index 189f9802d3..a857ccfa0c 100644
--- a/library/cpp/lwtrace/mon/analytics/json_output.h
+++ b/library/cpp/lwtrace/mon/analytics/json_output.h
@@ -1,98 +1,98 @@
-#pragma once
-
-#include <util/string/printf.h>
-#include <util/stream/str.h>
-#include <util/string/vector.h>
-#include <util/generic/set.h>
-#include <util/generic/hash_set.h>
+#pragma once
+
+#include <util/string/printf.h>
+#include <util/stream/str.h>
+#include <util/string/vector.h>
+#include <util/generic/set.h>
+#include <util/generic/hash_set.h>
#include "data.h"
#include "util.h"
-
-namespace NAnalytics {
-
+
+namespace NAnalytics {
+
inline TString ToJsonFlot(const TTable& in, const TString& xno, const TVector<TString>& ynos, const TString& opts = TString())
-{
- TStringStream ss;
- ss << "[ ";
- bool first = true;
-
+{
+ TStringStream ss;
+ ss << "[ ";
+ bool first = true;
+
TString xn;
THashSet<TString> xopts;
- ParseNameAndOpts(xno, xn, xopts);
+ ParseNameAndOpts(xno, xn, xopts);
bool xstack = xopts.contains("stack");
-
+
for (const TString& yno : ynos) {
TString yn;
THashSet<TString> yopts;
- ParseNameAndOpts(yno, yn, yopts);
+ ParseNameAndOpts(yno, yn, yopts);
bool ystackOpt = yopts.contains("stack");
-
- ss << (first? "": ",\n ") << "{ " << opts << (opts? ", ": "") << "\"label\": \"" << yn << "\", \"data\": [ ";
- bool first2 = true;
+
+ ss << (first? "": ",\n ") << "{ " << opts << (opts? ", ": "") << "\"label\": \"" << yn << "\", \"data\": [ ";
+ bool first2 = true;
using TPt = std::tuple<double, double, TString>;
- std::vector<TPt> pts;
- for (const TRow& row : in) {
- double x, y;
- if (row.Get(xn, x) && row.Get(yn, y)) {
- pts.emplace_back(x, y, row.Name);
- }
- }
-
- if (xstack) {
- std::sort(pts.begin(), pts.end(), [] (const TPt& a, const TPt& b) {
- // At first sort by Name, then by x, then by y
- return std::make_tuple(std::get<2>(a), std::get<0>(a), std::get<1>(a)) <
- std::make_tuple(std::get<2>(b), std::get<0>(b), std::get<1>(b));
- });
- } else {
- std::sort(pts.begin(), pts.end());
- }
-
- double x = 0.0, xsum = 0.0;
- double y = 0.0, ysum = 0.0;
- for (auto& pt : pts) {
- if (xstack) {
- x = xsum;
- xsum += std::get<0>(pt);
- } else {
- x = std::get<0>(pt);
- }
-
- if (ystackOpt) {
- y = ysum;
- ysum += std::get<1>(pt);
- } else {
- y = std::get<1>(pt);
- }
-
- ss << (first2? "": ", ") << "["
- << Sprintf("%.6lf", Finitize(x)) << ", " // x coordinate
- << Sprintf("%.6lf", Finitize(y)) << ", " // y coordinate
- << "\"" << std::get<2>(pt) << "\", " // label
- << Sprintf("%.6lf", std::get<0>(pt)) << ", " // x label (real value)
- << Sprintf("%.6lf", std::get<1>(pt)) // y label (real value)
- << "]";
- first2 = false;
- }
- // Add final point
- if (!first2 && (xstack || ystackOpt)) {
- if (xstack)
- x = xsum;
- if (ystackOpt)
- y = ysum;
- ss << (first2? "": ", ") << "["
- << Sprintf("%.6lf", Finitize(x)) << ", " // x coordinate
- << Sprintf("%.6lf", Finitize(y)) << ", " // y coordinate
- << "\"\", "
- << Sprintf("%.6lf", x) << ", " // x label (real value)
- << Sprintf("%.6lf", y) // y label (real value)
- << "]";
- }
- ss << " ] }";
- first = false;
- }
- ss << "\n]";
- return ss.Str();
-}
-
-}
+ std::vector<TPt> pts;
+ for (const TRow& row : in) {
+ double x, y;
+ if (row.Get(xn, x) && row.Get(yn, y)) {
+ pts.emplace_back(x, y, row.Name);
+ }
+ }
+
+ if (xstack) {
+ std::sort(pts.begin(), pts.end(), [] (const TPt& a, const TPt& b) {
+ // At first sort by Name, then by x, then by y
+ return std::make_tuple(std::get<2>(a), std::get<0>(a), std::get<1>(a)) <
+ std::make_tuple(std::get<2>(b), std::get<0>(b), std::get<1>(b));
+ });
+ } else {
+ std::sort(pts.begin(), pts.end());
+ }
+
+ double x = 0.0, xsum = 0.0;
+ double y = 0.0, ysum = 0.0;
+ for (auto& pt : pts) {
+ if (xstack) {
+ x = xsum;
+ xsum += std::get<0>(pt);
+ } else {
+ x = std::get<0>(pt);
+ }
+
+ if (ystackOpt) {
+ y = ysum;
+ ysum += std::get<1>(pt);
+ } else {
+ y = std::get<1>(pt);
+ }
+
+ ss << (first2? "": ", ") << "["
+ << Sprintf("%.6lf", Finitize(x)) << ", " // x coordinate
+ << Sprintf("%.6lf", Finitize(y)) << ", " // y coordinate
+ << "\"" << std::get<2>(pt) << "\", " // label
+ << Sprintf("%.6lf", std::get<0>(pt)) << ", " // x label (real value)
+ << Sprintf("%.6lf", std::get<1>(pt)) // y label (real value)
+ << "]";
+ first2 = false;
+ }
+ // Add final point
+ if (!first2 && (xstack || ystackOpt)) {
+ if (xstack)
+ x = xsum;
+ if (ystackOpt)
+ y = ysum;
+ ss << (first2? "": ", ") << "["
+ << Sprintf("%.6lf", Finitize(x)) << ", " // x coordinate
+ << Sprintf("%.6lf", Finitize(y)) << ", " // y coordinate
+ << "\"\", "
+ << Sprintf("%.6lf", x) << ", " // x label (real value)
+ << Sprintf("%.6lf", y) // y label (real value)
+ << "]";
+ }
+ ss << " ] }";
+ first = false;
+ }
+ ss << "\n]";
+ return ss.Str();
+}
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/transform.h b/library/cpp/lwtrace/mon/analytics/transform.h
index f7dc9adb5b..bd80d49d35 100644
--- a/library/cpp/lwtrace/mon/analytics/transform.h
+++ b/library/cpp/lwtrace/mon/analytics/transform.h
@@ -1,204 +1,204 @@
-#pragma once
-
+#pragma once
+
#include "data.h"
-
-namespace NAnalytics {
-
-template <class TSkip, class TX, class TY>
-inline TTable Histogram(const TTable& in, TSkip skip,
+
+namespace NAnalytics {
+
+template <class TSkip, class TX, class TY>
+inline TTable Histogram(const TTable& in, TSkip skip,
const TString& xn_out, TX x_in,
const TString& yn_out, TY y_in,
- double x1, double x2, double dx)
-{
- long buckets = (x2 - x1) / dx;
- TTable out;
+ double x1, double x2, double dx)
+{
+ long buckets = (x2 - x1) / dx;
+ TTable out;
TString yn_sum = yn_out + "_sum";
TString yn_share = yn_out + "_share";
- double ysum = 0.0;
- out.resize(buckets);
- for (size_t i = 0; i < out.size(); i++) {
- double lb = x1 + dx*i;
- double ub = lb + dx;
- out[i].Name = "[" + ToString(lb) + ";" + ToString(ub) + (ub==x2? "]": ")");
- out[i][xn_out] = (lb + ub) / 2;
- out[i][yn_sum] = 0.0;
- }
- for (const auto& row : in) {
- if (skip(row)) {
- continue;
- }
- double x = x_in(row);
- long i = (x - x1) / dx;
- if (x == x2) { // Special hack to include right edge
- i--;
- }
- double y = y_in(row);
- ysum += y;
- if (i >= 0 && i < buckets) {
+ double ysum = 0.0;
+ out.resize(buckets);
+ for (size_t i = 0; i < out.size(); i++) {
+ double lb = x1 + dx*i;
+ double ub = lb + dx;
+ out[i].Name = "[" + ToString(lb) + ";" + ToString(ub) + (ub==x2? "]": ")");
+ out[i][xn_out] = (lb + ub) / 2;
+ out[i][yn_sum] = 0.0;
+ }
+ for (const auto& row : in) {
+ if (skip(row)) {
+ continue;
+ }
+ double x = x_in(row);
+ long i = (x - x1) / dx;
+ if (x == x2) { // Special hack to include right edge
+ i--;
+ }
+ double y = y_in(row);
+ ysum += y;
+ if (i >= 0 && i < buckets) {
out[i][yn_sum] = y + out[i].GetOrDefault(yn_sum, 0.0);
- }
- }
- for (TRow& row : out) {
- if (ysum != 0.0) {
+ }
+ }
+ for (TRow& row : out) {
+ if (ysum != 0.0) {
row[yn_share] = row.GetOrDefault(yn_sum, 0.0) / ysum;
- }
- }
- return out;
-}
-
+ }
+ }
+ return out;
+}
+
inline TTable HistogramAll(const TTable& in, const TString& xn, double x1, double x2, double dx)
-{
- long buckets = (dx == 0.0? 1: (x2 - x1) / dx);
- TTable out;
+{
+ long buckets = (dx == 0.0? 1: (x2 - x1) / dx);
+ TTable out;
THashMap<TString, double> colSum;
- out.resize(buckets);
-
+ out.resize(buckets);
+
TSet<TString> cols;
- for (auto& row : in) {
- for (auto& kv : row) {
- cols.insert(kv.first);
- }
- }
- cols.insert("_count");
- cols.erase(xn);
-
+ for (auto& row : in) {
+ for (auto& kv : row) {
+ cols.insert(kv.first);
+ }
+ }
+ cols.insert("_count");
+ cols.erase(xn);
+
for (const TString& col : cols) {
- colSum[col] = 0.0;
- }
-
- for (size_t i = 0; i < out.size(); i++) {
- double lb = x1 + dx*i;
- double ub = lb + dx;
- TRow& row = out[i];
- row.Name = "[" + ToString(lb) + ";" + ToString(ub) + (ub==x2? "]": ")");
- row[xn] = (lb + ub) / 2;
+ colSum[col] = 0.0;
+ }
+
+ for (size_t i = 0; i < out.size(); i++) {
+ double lb = x1 + dx*i;
+ double ub = lb + dx;
+ TRow& row = out[i];
+ row.Name = "[" + ToString(lb) + ";" + ToString(ub) + (ub==x2? "]": ")");
+ row[xn] = (lb + ub) / 2;
for (const TString& col : cols) {
- row[col + "_sum"] = 0.0;
- }
- }
- for (const TRow& row_in : in) {
- double x;
- if (!row_in.Get(xn, x)) {
- continue;
- }
- long i = (dx == 0.0? 0: (x - x1) / dx);
- if (x == x2 && dx > 0.0) { // Special hack to include right edge
- i--;
- }
- for (const auto& kv : row_in) {
+ row[col + "_sum"] = 0.0;
+ }
+ }
+ for (const TRow& row_in : in) {
+ double x;
+ if (!row_in.Get(xn, x)) {
+ continue;
+ }
+ long i = (dx == 0.0? 0: (x - x1) / dx);
+ if (x == x2 && dx > 0.0) { // Special hack to include right edge
+ i--;
+ }
+ for (const auto& kv : row_in) {
const TString& yn = kv.first;
- if (yn == xn) {
- continue;
- }
+ if (yn == xn) {
+ continue;
+ }
double y;
if (!row_in.Get(yn, y)) {
continue;
}
- colSum[yn] += y;
- if (i >= 0 && i < buckets) {
+ colSum[yn] += y;
+ if (i >= 0 && i < buckets) {
out[i][yn + "_cnt"] = out[i].GetOrDefault(yn + "_cnt") + 1;
out[i][yn + "_sum"] = out[i].GetOrDefault(yn + "_sum") + y;
if (out[i].contains(yn + "_min")) {
out[i][yn + "_min"] = Min(y, out[i].GetOrDefault(yn + "_min"));
- } else {
- out[i][yn + "_min"] = y;
- }
+ } else {
+ out[i][yn + "_min"] = y;
+ }
if (out[i].contains(yn + "_max")) {
out[i][yn + "_max"] = Max(y, out[i].GetOrDefault(yn + "_max"));
- } else {
- out[i][yn + "_max"] = y;
- }
- }
- }
- colSum["_count"]++;
- if (i >= 0 && i < buckets) {
+ } else {
+ out[i][yn + "_max"] = y;
+ }
+ }
+ }
+ colSum["_count"]++;
+ if (i >= 0 && i < buckets) {
out[i]["_count_sum"] = out[i].GetOrDefault("_count_sum") + 1;
- }
- }
- for (TRow& row : out) {
+ }
+ }
+ for (TRow& row : out) {
for (const TString& col : cols) {
- double ysum = colSum[col];
- if (col != "_count") {
+ double ysum = colSum[col];
+ if (col != "_count") {
if (row.GetOrDefault(col + "_cnt") != 0.0) {
row[col + "_avg"] = row.GetOrDefault(col + "_sum") / row.GetOrDefault(col + "_cnt");
- }
- }
- if (ysum != 0.0) {
+ }
+ }
+ if (ysum != 0.0) {
row[col + "_share"] = row.GetOrDefault(col + "_sum") / ysum;
- }
- }
- }
- return out;
-}
-
-inline TMatrix CovarianceMatrix(const TTable& in)
-{
+ }
+ }
+ }
+ return out;
+}
+
+inline TMatrix CovarianceMatrix(const TTable& in)
+{
TSet<TString> cols;
- for (auto& row : in) {
- for (auto& kv : row) {
- cols.insert(kv.first);
- }
- }
-
- struct TAggregate {
- size_t Idx = 0;
- double Sum = 0;
- size_t Count = 0;
- double Mean = 0;
- };
-
+ for (auto& row : in) {
+ for (auto& kv : row) {
+ cols.insert(kv.first);
+ }
+ }
+
+ struct TAggregate {
+ size_t Idx = 0;
+ double Sum = 0;
+ size_t Count = 0;
+ double Mean = 0;
+ };
+
THashMap<TString, TAggregate> colAggr;
-
- size_t colCount = 0;
- for (const TString& col : cols) {
- TAggregate& aggr = colAggr[col];
- aggr.Idx = colCount++;
- }
-
- for (const TRow& row : in) {
- for (const auto& kv : row) {
- const TString& xn = kv.first;
+
+ size_t colCount = 0;
+ for (const TString& col : cols) {
+ TAggregate& aggr = colAggr[col];
+ aggr.Idx = colCount++;
+ }
+
+ for (const TRow& row : in) {
+ for (const auto& kv : row) {
+ const TString& xn = kv.first;
double x;
if (!row.Get(xn, x)) {
continue;
}
- TAggregate& aggr = colAggr[xn];
- aggr.Sum += x;
- aggr.Count++;
- }
- }
-
- for (auto& kv : colAggr) {
- TAggregate& aggr = kv.second;
- aggr.Mean = aggr.Sum / aggr.Count;
- }
-
- TMatrix covCount(cols.size(), cols.size());
- TMatrix cov(cols.size(), cols.size());
- for (const TRow& row : in) {
- for (const auto& kv1 : row) {
+ TAggregate& aggr = colAggr[xn];
+ aggr.Sum += x;
+ aggr.Count++;
+ }
+ }
+
+ for (auto& kv : colAggr) {
+ TAggregate& aggr = kv.second;
+ aggr.Mean = aggr.Sum / aggr.Count;
+ }
+
+ TMatrix covCount(cols.size(), cols.size());
+ TMatrix cov(cols.size(), cols.size());
+ for (const TRow& row : in) {
+ for (const auto& kv1 : row) {
double x;
if (!row.Get(kv1.first, x)) {
continue;
}
- TAggregate& xaggr = colAggr[kv1.first];
- for (const auto& kv2 : row) {
+ TAggregate& xaggr = colAggr[kv1.first];
+ for (const auto& kv2 : row) {
double y;
if (!row.Get(kv2.first, y)) {
continue;
}
- TAggregate& yaggr = colAggr[kv2.first];
- covCount.Cell(xaggr.Idx, yaggr.Idx)++;
- cov.Cell(xaggr.Idx, yaggr.Idx) += (x - xaggr.Mean) * (y - yaggr.Mean);
- }
- }
- }
-
- for (size_t idx = 0; idx < cov.size(); idx++) {
- cov[idx] /= covCount[idx];
- }
-
- return cov;
-}
-
-}
+ TAggregate& yaggr = colAggr[kv2.first];
+ covCount.Cell(xaggr.Idx, yaggr.Idx)++;
+ cov.Cell(xaggr.Idx, yaggr.Idx) += (x - xaggr.Mean) * (y - yaggr.Mean);
+ }
+ }
+ }
+
+ for (size_t idx = 0; idx < cov.size(); idx++) {
+ cov[idx] /= covCount[idx];
+ }
+
+ return cov;
+}
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/util.h b/library/cpp/lwtrace/mon/analytics/util.h
index e07d06cc43..891ef9ad25 100644
--- a/library/cpp/lwtrace/mon/analytics/util.h
+++ b/library/cpp/lwtrace/mon/analytics/util.h
@@ -1,122 +1,122 @@
-#pragma once
-
+#pragma once
+
#include "data.h"
-#include <util/generic/algorithm.h>
-#include <util/generic/hash_set.h>
-#include <util/string/vector.h>
-
-namespace NAnalytics {
-
-// Get rid of NaNs and INFs
+#include <util/generic/algorithm.h>
+#include <util/generic/hash_set.h>
+#include <util/string/vector.h>
+
+namespace NAnalytics {
+
+// Get rid of NaNs and INFs
inline double Finitize(double x, double notFiniteValue = 0.0)
-{
- return isfinite(x)? x: notFiniteValue;
-}
-
+{
+ return isfinite(x)? x: notFiniteValue;
+}
+
inline void ParseNameAndOpts(const TString& nameAndOpts, TString& name, THashSet<TString>& opts)
-{
- name.clear();
- opts.clear();
- bool first = true;
+{
+ name.clear();
+ opts.clear();
+ bool first = true;
auto vs = SplitString(nameAndOpts, "-");
- for (const auto& s : vs) {
- if (first) {
- name = s;
- first = false;
- } else {
- opts.insert(s);
- }
- }
-}
-
+ for (const auto& s : vs) {
+ if (first) {
+ name = s;
+ first = false;
+ } else {
+ opts.insert(s);
+ }
+ }
+}
+
inline TString ParseName(const TString& nameAndOpts)
-{
+{
auto vs = SplitString(nameAndOpts, "-");
- if (vs.empty()) {
+ if (vs.empty()) {
return TString();
- } else {
- return vs[0];
- }
-}
-
-template <class R, class T>
+ } else {
+ return vs[0];
+ }
+}
+
+template <class R, class T>
inline R AccumulateIfExist(const TString& name, const TTable& table, R r, T t)
-{
- ForEach(table.begin(), table.end(), [=,&r] (const TRow& row) {
- double value;
- if (row.Get(name, value)) {
- r = t(r, value);
- }
- });
- return r;
-}
-
+{
+ ForEach(table.begin(), table.end(), [=,&r] (const TRow& row) {
+ double value;
+ if (row.Get(name, value)) {
+ r = t(r, value);
+ }
+ });
+ return r;
+}
+
inline double MinValue(const TString& nameAndOpts, const TTable& table)
-{
+{
TString name;
THashSet<TString> opts;
- ParseNameAndOpts(nameAndOpts, name, opts);
+ ParseNameAndOpts(nameAndOpts, name, opts);
bool stack = opts.contains("stack");
- if (stack) {
- return 0.0;
- } else {
+ if (stack) {
+ return 0.0;
+ } else {
auto zero = 0.0;
return AccumulateIfExist(name, table, 1.0 / zero /*+inf*/, [] (double x, double y) {
- return Min(x, y);
- });
- }
-}
-
+ return Min(x, y);
+ });
+ }
+}
+
inline double MaxValue(const TString& nameAndOpts, const TTable& table)
-{
+{
TString name;
THashSet<TString> opts;
- ParseNameAndOpts(nameAndOpts, name, opts);
+ ParseNameAndOpts(nameAndOpts, name, opts);
bool stack = opts.contains("stack");
- if (stack) {
- return AccumulateIfExist(name, table, 0.0, [] (double x, double y) {
- return x + y;
- });
- } else {
+ if (stack) {
+ return AccumulateIfExist(name, table, 0.0, [] (double x, double y) {
+ return x + y;
+ });
+ } else {
auto zero = 0.0;
return AccumulateIfExist(name, table, -1.0 / zero /*-inf*/, [] (double x, double y) {
- return Max(x, y);
- });
- }
-}
-
-template <class T>
+ return Max(x, y);
+ });
+ }
+}
+
+template <class T>
inline void Map(TTable& table, const TString& rname, T t)
-{
- ForEach(table.begin(), table.end(), [=] (TRow& row) {
- row[rname] = t(row);
- });
-}
-
+{
+ ForEach(table.begin(), table.end(), [=] (TRow& row) {
+ row[rname] = t(row);
+ });
+}
+
inline std::function<bool(const TRow&)> HasNoValueFor(TString name)
-{
- return [=] (const TRow& row) -> bool {
- double value;
- return !row.Get(name, value);
- };
-}
-
-
+{
+ return [=] (const TRow& row) -> bool {
+ double value;
+ return !row.Get(name, value);
+ };
+}
+
+
inline std::function<double(const TRow&)> GetValueFor(TString name, double defVal = 0.0)
-{
- return [=] (const TRow& row) -> double {
- double value;
- return row.Get(name, value)? value: defVal;
- };
-}
-
-inline std::function<double(const TRow&)> Const(double defVal = 0.0)
-{
- return [=] (const TRow&) {
- return defVal;
- };
-}
-
-}
+{
+ return [=] (const TRow& row) -> double {
+ double value;
+ return row.Get(name, value)? value: defVal;
+ };
+}
+
+inline std::function<double(const TRow&)> Const(double defVal = 0.0)
+{
+ return [=] (const TRow&) {
+ return defVal;
+ };
+}
+
+}
diff --git a/library/cpp/lwtrace/mon/analytics/ya.make b/library/cpp/lwtrace/mon/analytics/ya.make
index c18e23c8e1..24a04070b7 100644
--- a/library/cpp/lwtrace/mon/analytics/ya.make
+++ b/library/cpp/lwtrace/mon/analytics/ya.make
@@ -1,15 +1,15 @@
-LIBRARY()
-
+LIBRARY()
+
OWNER(serxa g:kikimr)
-
+
PEERDIR(
)
-SRCS(
- analytics.cpp
-)
-
-END()
-
-RECURSE(
-)
+SRCS(
+ analytics.cpp
+)
+
+END()
+
+RECURSE(
+)
diff --git a/library/cpp/lwtrace/mon/mon_lwtrace.cpp b/library/cpp/lwtrace/mon/mon_lwtrace.cpp
index a61ee9ce22..b400103f58 100644
--- a/library/cpp/lwtrace/mon/mon_lwtrace.cpp
+++ b/library/cpp/lwtrace/mon/mon_lwtrace.cpp
@@ -1,8 +1,8 @@
#include "mon_lwtrace.h"
-#include <algorithm>
-#include <iterator>
-
+#include <algorithm>
+#include <iterator>
+
#include <google/protobuf/text_format.h>
#include <library/cpp/lwtrace/mon/analytics/all.h>
#include <library/cpp/lwtrace/all.h>
@@ -12,14 +12,14 @@
#include <library/cpp/resource/resource.h>
#include <library/cpp/string_utils/base64/base64.h>
#include <library/cpp/html/pcdata/pcdata.h>
-#include <util/string/escape.h>
-#include <util/system/condvar.h>
-#include <util/system/execpath.h>
+#include <util/string/escape.h>
+#include <util/system/condvar.h>
+#include <util/system/execpath.h>
#include <util/system/hostname.h>
using namespace NMonitoring;
-#define WWW_CHECK(cond, ...) \
+#define WWW_CHECK(cond, ...) \
do { \
if (!(cond)) { \
ythrow yexception() << Sprintf(__VA_ARGS__); \
@@ -27,1383 +27,1383 @@ using namespace NMonitoring;
} while (false) \
/**/
-#define WWW_HTML_INNER(out) HTML(out) WITH_SCOPED(tmp, TScopedHtmlInner(out))
-#define WWW_HTML(out) out << NMonitoring::HTTPOKHTML; WWW_HTML_INNER(out)
-
-namespace NLwTraceMonPage {
-
-struct TTrackLogRefs {
- struct TItem {
- const TThread::TId ThreadId;
- const NLWTrace::TLogItem* Ptr;
-
- TItem()
- : ThreadId(0)
- , Ptr(nullptr)
- {}
-
- TItem(TThread::TId tid, const NLWTrace::TLogItem& ref)
- : ThreadId(tid)
- , Ptr(&ref)
- {}
-
- TItem(const TItem& o)
- : ThreadId(o.ThreadId)
- , Ptr(o.Ptr)
- {}
-
- operator const NLWTrace::TLogItem&() const { return *Ptr; }
- };
-
+#define WWW_HTML_INNER(out) HTML(out) WITH_SCOPED(tmp, TScopedHtmlInner(out))
+#define WWW_HTML(out) out << NMonitoring::HTTPOKHTML; WWW_HTML_INNER(out)
+
+namespace NLwTraceMonPage {
+
+struct TTrackLogRefs {
+ struct TItem {
+ const TThread::TId ThreadId;
+ const NLWTrace::TLogItem* Ptr;
+
+ TItem()
+ : ThreadId(0)
+ , Ptr(nullptr)
+ {}
+
+ TItem(TThread::TId tid, const NLWTrace::TLogItem& ref)
+ : ThreadId(tid)
+ , Ptr(&ref)
+ {}
+
+ TItem(const TItem& o)
+ : ThreadId(o.ThreadId)
+ , Ptr(o.Ptr)
+ {}
+
+ operator const NLWTrace::TLogItem&() const { return *Ptr; }
+ };
+
using TItems = TVector<TItem>;
- TItems Items;
-
- TTrackLogRefs() {}
-
- TTrackLogRefs(const TTrackLogRefs& other)
- : Items(other.Items)
- {}
-
- void Clear()
- {
- Items.clear();
- }
-
- ui64 GetTimestampCycles() const
- {
- return Items.empty()? 0: Items.front().Ptr->GetTimestampCycles();
- }
-};
-
-//
-// Templates to treat both NLWTrace::TLogItem and NLWTrace::TTrackLog in the same way (e.g. in TLogQuery)
-//
-
-template <class TLog>
-struct TLogTraits {};
-
-template <>
-struct TLogTraits<NLWTrace::TLogItem> {
- using TLog = NLWTrace::TLogItem;
- using const_iterator = const NLWTrace::TLogItem*;
- using const_reverse_iterator = const NLWTrace::TLogItem*;
-
- static const_iterator begin(const TLog& log) { return &log; }
- static const_iterator end(const TLog& log) { return &log + 1; }
- static const_reverse_iterator rbegin(const TLog& log) { return &log; }
- static const_reverse_iterator rend(const TLog& log) { return &log + 1; }
- static bool empty(const TLog&) { return false; }
- static const NLWTrace::TLogItem& front(const TLog& log) { return log; }
- static const NLWTrace::TLogItem& back(const TLog& log) { return log; }
-};
-
-template <>
-struct TLogTraits<NLWTrace::TTrackLog> {
- using TLog = NLWTrace::TTrackLog;
- using const_iterator = NLWTrace::TTrackLog::TItems::const_iterator;
- using const_reverse_iterator = NLWTrace::TTrackLog::TItems::const_reverse_iterator;
-
- static const_iterator begin(const TLog& log) { return log.Items.begin(); }
- static const_iterator end(const TLog& log) { return log.Items.end(); }
- static const_reverse_iterator rbegin(const TLog& log) { return log.Items.rbegin(); }
- static const_reverse_iterator rend(const TLog& log) { return log.Items.rend(); }
- static bool empty(const TLog& log) { return log.Items.empty(); }
- static const NLWTrace::TLogItem& front(const TLog& log) { return log.Items.front(); }
- static const NLWTrace::TLogItem& back(const TLog& log) { return log.Items.back(); }
-};
-
-template <>
-struct TLogTraits<TTrackLogRefs> {
- using TLog = TTrackLogRefs;
- using const_iterator = TTrackLogRefs::TItems::const_iterator;
- using const_reverse_iterator = TTrackLogRefs::TItems::const_reverse_iterator;
-
- static const_iterator begin(const TLog& log) { return log.Items.begin(); }
- static const_iterator end(const TLog& log) { return log.Items.end(); }
- static const_reverse_iterator rbegin(const TLog& log) { return log.Items.rbegin(); }
- static const_reverse_iterator rend(const TLog& log) { return log.Items.rend(); }
- static bool empty(const TLog& log) { return log.Items.empty(); }
- static const NLWTrace::TLogItem& front(const TLog& log) { return log.Items.front(); }
- static const NLWTrace::TLogItem& back(const TLog& log) { return log.Items.back(); }
-};
-
-/*
- * Log Query Language:
- * Data expressions:
- * 1) myparam[0], myparam[-1] // the first and the last myparam in any probe/provider
- * 2) myparam // the first (the same as [0])
- * 3) PROVIDER..myparam // any probe with myparam in PROVIDER
- * 4) MyProbe._elapsedMs // Ms since track begin for the first MyProbe event
- * 5) PROVIDER.MyProbe._sliceUs // Us since previous event in track for the first PROVIDER.MyProbe event
- */
-
-struct TLogQuery {
-private:
- enum ESpecialParam {
- NotSpecial = 0,
- // The last '*' can be one of: Ms, Us, Ns, Min, Hours, (blank means seconds)
- // '*Time' can be one of: RTime (since cut ts for given dataset), NTime (negative time since now), Time (since machine start)
- TrackDuration = 1, // _track*
- TrackBeginTime = 2, // _begin*Time*
- TrackEndTime = 3, // _end*Time*
- ElapsedDuration = 4, // _elapsed*
- SliceDuration = 5, // _slice*
- ThreadTime = 6, // _thr*Time*
- };
-
- template <class TLog, class TTr = TLogTraits<TLog>>
- struct TExecuteQuery;
-
- template <class TLog, class TTr>
- friend struct TExecuteQuery;
-
- template <class TLog, class TTr>
- struct TExecuteQuery {
- const TLogQuery& Query;
- const TLog* Log = nullptr;
- bool Reversed;
-
- i64 Skip;
- const NLWTrace::TLogItem* Item = nullptr;
- typename TTr::const_iterator FwdIter;
- typename TTr::const_reverse_iterator RevIter;
-
- NLWTrace::TTypedParam Result;
-
- explicit TExecuteQuery(const TLogQuery& query, const TLog& log)
- : Query(query)
- , Log(&log)
- , Reversed(Query.Index < 0)
- , Skip(Reversed? -Query.Index - 1: Query.Index)
- , FwdIter()
- , RevIter()
- {}
-
- void ExecuteQuery()
- {
- if (!Reversed) {
- for (auto i = TTr::begin(*Log), e = TTr::end(*Log); i != e; ++i) {
- if (FwdIteration(i)) {
- return;
- }
- }
- } else {
- for (auto i = TTr::rbegin(*Log), e = TTr::rend(*Log); i != e; ++i) {
- if (RevIteration(i)) {
- return;
- }
- }
- }
- }
-
- bool FwdIteration(typename TTr::const_iterator it)
- {
- FwdIter = it;
- Item = &*it;
- return ProcessItem();
- }
-
- bool RevIteration(typename TTr::const_reverse_iterator it)
- {
- RevIter = it;
- Item = &*it;
- return ProcessItem();
- }
-
- bool ProcessItem()
- {
- if (Query.Provider && Query.Provider != Item->Probe->Event.GetProvider()) {
- return false;
- }
- if (Query.Probe && Query.Probe != Item->Probe->Event.Name) {
- return false;
- }
- switch (Query.SpecialParam) {
- case NotSpecial:
- if (Item->Probe->Event.Signature.FindParamIndex(Query.ParamName) != size_t(-1)) {
- break; // param found
- } else {
- return false; // param not found
- }
- case TrackDuration: Y_FAIL();
- case TrackBeginTime: Y_FAIL();
- case TrackEndTime: Y_FAIL();
- case ElapsedDuration: break;
- case SliceDuration: break;
- case ThreadTime: break;
- }
- if (Skip > 0) {
- Skip--;
- return false;
- }
- switch (Query.SpecialParam) {
- case NotSpecial:
- Result = NLWTrace::TTypedParam(Item->GetParam(Query.ParamName));
- return true;
- case TrackDuration: Y_FAIL();
- case TrackBeginTime: Y_FAIL();
- case TrackEndTime: Y_FAIL();
- case ElapsedDuration:
- Result = NLWTrace::TTypedParam(Query.Duration(
- Log->GetTimestampCycles(),
- Item->GetTimestampCycles()));
- return true;
- case SliceDuration:
- Result = NLWTrace::TTypedParam(Query.Duration(
- PrevOrSame().GetTimestampCycles(),
- Item->GetTimestampCycles()));
- return true;
- case ThreadTime:
- Result = NLWTrace::TTypedParam(Query.Instant(Item->GetTimestampCycles()));
- return true;
- }
- return true;
- }
-
- const NLWTrace::TLogItem& PrevOrSame() const
- {
- if (!Reversed) {
- auto i = FwdIter;
- if (i != TTr::begin(*Log)) {
- i--;
- }
- return *i;
- } else {
- auto j = RevIter + 1;
- if (j == TTr::rend(*Log)) {
- return *RevIter;
- }
- return *j;
- }
- }
- };
-
+ TItems Items;
+
+ TTrackLogRefs() {}
+
+ TTrackLogRefs(const TTrackLogRefs& other)
+ : Items(other.Items)
+ {}
+
+ void Clear()
+ {
+ Items.clear();
+ }
+
+ ui64 GetTimestampCycles() const
+ {
+ return Items.empty()? 0: Items.front().Ptr->GetTimestampCycles();
+ }
+};
+
+//
+// Templates to treat both NLWTrace::TLogItem and NLWTrace::TTrackLog in the same way (e.g. in TLogQuery)
+//
+
+template <class TLog>
+struct TLogTraits {};
+
+template <>
+struct TLogTraits<NLWTrace::TLogItem> {
+ using TLog = NLWTrace::TLogItem;
+ using const_iterator = const NLWTrace::TLogItem*;
+ using const_reverse_iterator = const NLWTrace::TLogItem*;
+
+ static const_iterator begin(const TLog& log) { return &log; }
+ static const_iterator end(const TLog& log) { return &log + 1; }
+ static const_reverse_iterator rbegin(const TLog& log) { return &log; }
+ static const_reverse_iterator rend(const TLog& log) { return &log + 1; }
+ static bool empty(const TLog&) { return false; }
+ static const NLWTrace::TLogItem& front(const TLog& log) { return log; }
+ static const NLWTrace::TLogItem& back(const TLog& log) { return log; }
+};
+
+template <>
+struct TLogTraits<NLWTrace::TTrackLog> {
+ using TLog = NLWTrace::TTrackLog;
+ using const_iterator = NLWTrace::TTrackLog::TItems::const_iterator;
+ using const_reverse_iterator = NLWTrace::TTrackLog::TItems::const_reverse_iterator;
+
+ static const_iterator begin(const TLog& log) { return log.Items.begin(); }
+ static const_iterator end(const TLog& log) { return log.Items.end(); }
+ static const_reverse_iterator rbegin(const TLog& log) { return log.Items.rbegin(); }
+ static const_reverse_iterator rend(const TLog& log) { return log.Items.rend(); }
+ static bool empty(const TLog& log) { return log.Items.empty(); }
+ static const NLWTrace::TLogItem& front(const TLog& log) { return log.Items.front(); }
+ static const NLWTrace::TLogItem& back(const TLog& log) { return log.Items.back(); }
+};
+
+template <>
+struct TLogTraits<TTrackLogRefs> {
+ using TLog = TTrackLogRefs;
+ using const_iterator = TTrackLogRefs::TItems::const_iterator;
+ using const_reverse_iterator = TTrackLogRefs::TItems::const_reverse_iterator;
+
+ static const_iterator begin(const TLog& log) { return log.Items.begin(); }
+ static const_iterator end(const TLog& log) { return log.Items.end(); }
+ static const_reverse_iterator rbegin(const TLog& log) { return log.Items.rbegin(); }
+ static const_reverse_iterator rend(const TLog& log) { return log.Items.rend(); }
+ static bool empty(const TLog& log) { return log.Items.empty(); }
+ static const NLWTrace::TLogItem& front(const TLog& log) { return log.Items.front(); }
+ static const NLWTrace::TLogItem& back(const TLog& log) { return log.Items.back(); }
+};
+
+/*
+ * Log Query Language:
+ * Data expressions:
+ * 1) myparam[0], myparam[-1] // the first and the last myparam in any probe/provider
+ * 2) myparam // the first (the same as [0])
+ * 3) PROVIDER..myparam // any probe with myparam in PROVIDER
+ * 4) MyProbe._elapsedMs // Ms since track begin for the first MyProbe event
+ * 5) PROVIDER.MyProbe._sliceUs // Us since previous event in track for the first PROVIDER.MyProbe event
+ */
+
+struct TLogQuery {
+private:
+ enum ESpecialParam {
+ NotSpecial = 0,
+ // The last '*' can be one of: Ms, Us, Ns, Min, Hours, (blank means seconds)
+ // '*Time' can be one of: RTime (since cut ts for given dataset), NTime (negative time since now), Time (since machine start)
+ TrackDuration = 1, // _track*
+ TrackBeginTime = 2, // _begin*Time*
+ TrackEndTime = 3, // _end*Time*
+ ElapsedDuration = 4, // _elapsed*
+ SliceDuration = 5, // _slice*
+ ThreadTime = 6, // _thr*Time*
+ };
+
+ template <class TLog, class TTr = TLogTraits<TLog>>
+ struct TExecuteQuery;
+
+ template <class TLog, class TTr>
+ friend struct TExecuteQuery;
+
+ template <class TLog, class TTr>
+ struct TExecuteQuery {
+ const TLogQuery& Query;
+ const TLog* Log = nullptr;
+ bool Reversed;
+
+ i64 Skip;
+ const NLWTrace::TLogItem* Item = nullptr;
+ typename TTr::const_iterator FwdIter;
+ typename TTr::const_reverse_iterator RevIter;
+
+ NLWTrace::TTypedParam Result;
+
+ explicit TExecuteQuery(const TLogQuery& query, const TLog& log)
+ : Query(query)
+ , Log(&log)
+ , Reversed(Query.Index < 0)
+ , Skip(Reversed? -Query.Index - 1: Query.Index)
+ , FwdIter()
+ , RevIter()
+ {}
+
+ void ExecuteQuery()
+ {
+ if (!Reversed) {
+ for (auto i = TTr::begin(*Log), e = TTr::end(*Log); i != e; ++i) {
+ if (FwdIteration(i)) {
+ return;
+ }
+ }
+ } else {
+ for (auto i = TTr::rbegin(*Log), e = TTr::rend(*Log); i != e; ++i) {
+ if (RevIteration(i)) {
+ return;
+ }
+ }
+ }
+ }
+
+ bool FwdIteration(typename TTr::const_iterator it)
+ {
+ FwdIter = it;
+ Item = &*it;
+ return ProcessItem();
+ }
+
+ bool RevIteration(typename TTr::const_reverse_iterator it)
+ {
+ RevIter = it;
+ Item = &*it;
+ return ProcessItem();
+ }
+
+ bool ProcessItem()
+ {
+ if (Query.Provider && Query.Provider != Item->Probe->Event.GetProvider()) {
+ return false;
+ }
+ if (Query.Probe && Query.Probe != Item->Probe->Event.Name) {
+ return false;
+ }
+ switch (Query.SpecialParam) {
+ case NotSpecial:
+ if (Item->Probe->Event.Signature.FindParamIndex(Query.ParamName) != size_t(-1)) {
+ break; // param found
+ } else {
+ return false; // param not found
+ }
+ case TrackDuration: Y_FAIL();
+ case TrackBeginTime: Y_FAIL();
+ case TrackEndTime: Y_FAIL();
+ case ElapsedDuration: break;
+ case SliceDuration: break;
+ case ThreadTime: break;
+ }
+ if (Skip > 0) {
+ Skip--;
+ return false;
+ }
+ switch (Query.SpecialParam) {
+ case NotSpecial:
+ Result = NLWTrace::TTypedParam(Item->GetParam(Query.ParamName));
+ return true;
+ case TrackDuration: Y_FAIL();
+ case TrackBeginTime: Y_FAIL();
+ case TrackEndTime: Y_FAIL();
+ case ElapsedDuration:
+ Result = NLWTrace::TTypedParam(Query.Duration(
+ Log->GetTimestampCycles(),
+ Item->GetTimestampCycles()));
+ return true;
+ case SliceDuration:
+ Result = NLWTrace::TTypedParam(Query.Duration(
+ PrevOrSame().GetTimestampCycles(),
+ Item->GetTimestampCycles()));
+ return true;
+ case ThreadTime:
+ Result = NLWTrace::TTypedParam(Query.Instant(Item->GetTimestampCycles()));
+ return true;
+ }
+ return true;
+ }
+
+ const NLWTrace::TLogItem& PrevOrSame() const
+ {
+ if (!Reversed) {
+ auto i = FwdIter;
+ if (i != TTr::begin(*Log)) {
+ i--;
+ }
+ return *i;
+ } else {
+ auto j = RevIter + 1;
+ if (j == TTr::rend(*Log)) {
+ return *RevIter;
+ }
+ return *j;
+ }
+ }
+ };
+
TString Text;
TString Provider;
TString Probe;
TString ParamName;
- ESpecialParam SpecialParam = NotSpecial;
- i64 Index = 0;
- double TimeUnitSec = 1.0;
- i64 ZeroTs = 0;
- i64 RTimeZeroTs = 0;
- i64 NTimeZeroTs = 0;
-
-public:
- TLogQuery() {}
-
+ ESpecialParam SpecialParam = NotSpecial;
+ i64 Index = 0;
+ double TimeUnitSec = 1.0;
+ i64 ZeroTs = 0;
+ i64 RTimeZeroTs = 0;
+ i64 NTimeZeroTs = 0;
+
+public:
+ TLogQuery() {}
+
explicit TLogQuery(const TString& text)
- : Text(text)
- {
- try {
- if (!Text.empty()) {
- ParseQuery(Text);
- }
- } catch (...) {
- ythrow yexception()
- << CurrentExceptionMessage()
- << " while parsing track log query: "
- << Text;
- }
- }
-
- operator bool() const
- {
- return !Text.empty();
- }
-
- template <class TLog>
- NLWTrace::TTypedParam ExecuteQuery(const TLog& log) const
- {
- using TTr = TLogTraits<TLog>;
-
- WWW_CHECK(Text, "execute of empty log query");
- if (TTr::empty(log)) {
- return NLWTrace::TTypedParam();
- }
-
- if (SpecialParam == TrackDuration) {
- return Duration(
- log.GetTimestampCycles(),
- TTr::back(log).GetTimestampCycles());
- } else if (SpecialParam == TrackBeginTime) {
- return Instant(log.GetTimestampCycles());
- } else if (SpecialParam == TrackEndTime) {
- return Instant(TTr::back(log).GetTimestampCycles());
- }
-
- TExecuteQuery<TLog, TTr> exec(*this, log);
- exec.ExecuteQuery();
- return exec.Result;
- }
-
-private:
- NLWTrace::TTypedParam Duration(ui64 ts1, ui64 ts2) const
- {
- double sec = NHPTimer::GetSeconds(ts1 < ts2? ts2 - ts1: 0);
- return NLWTrace::TTypedParam(sec / TimeUnitSec);
- }
-
- NLWTrace::TTypedParam Instant(ui64 ts) const
- {
- double sec = NHPTimer::GetSeconds(i64(ts) - ZeroTs);
- return NLWTrace::TTypedParam(sec / TimeUnitSec);
- }
-
+ : Text(text)
+ {
+ try {
+ if (!Text.empty()) {
+ ParseQuery(Text);
+ }
+ } catch (...) {
+ ythrow yexception()
+ << CurrentExceptionMessage()
+ << " while parsing track log query: "
+ << Text;
+ }
+ }
+
+ operator bool() const
+ {
+ return !Text.empty();
+ }
+
+ template <class TLog>
+ NLWTrace::TTypedParam ExecuteQuery(const TLog& log) const
+ {
+ using TTr = TLogTraits<TLog>;
+
+ WWW_CHECK(Text, "execute of empty log query");
+ if (TTr::empty(log)) {
+ return NLWTrace::TTypedParam();
+ }
+
+ if (SpecialParam == TrackDuration) {
+ return Duration(
+ log.GetTimestampCycles(),
+ TTr::back(log).GetTimestampCycles());
+ } else if (SpecialParam == TrackBeginTime) {
+ return Instant(log.GetTimestampCycles());
+ } else if (SpecialParam == TrackEndTime) {
+ return Instant(TTr::back(log).GetTimestampCycles());
+ }
+
+ TExecuteQuery<TLog, TTr> exec(*this, log);
+ exec.ExecuteQuery();
+ return exec.Result;
+ }
+
+private:
+ NLWTrace::TTypedParam Duration(ui64 ts1, ui64 ts2) const
+ {
+ double sec = NHPTimer::GetSeconds(ts1 < ts2? ts2 - ts1: 0);
+ return NLWTrace::TTypedParam(sec / TimeUnitSec);
+ }
+
+ NLWTrace::TTypedParam Instant(ui64 ts) const
+ {
+ double sec = NHPTimer::GetSeconds(i64(ts) - ZeroTs);
+ return NLWTrace::TTypedParam(sec / TimeUnitSec);
+ }
+
void ParseQuery(const TString& s)
- {
+ {
auto parts = SplitString(s, ".");
- WWW_CHECK(parts.size() <= 3, "too many name specifiers");
+ WWW_CHECK(parts.size() <= 3, "too many name specifiers");
ParseParamSelector(parts.back());
- if (parts.size() >= 2) {
- ParseProbeSelector(parts[parts.size() - 2]);
- }
- if (parts.size() >= 3) {
- ParseProviderSelector(parts[parts.size() - 3]);
- }
- }
-
+ if (parts.size() >= 2) {
+ ParseProbeSelector(parts[parts.size() - 2]);
+ }
+ if (parts.size() >= 3) {
+ ParseProviderSelector(parts[parts.size() - 3]);
+ }
+ }
+
void ParseParamSelector(const TString& s)
- {
- size_t bracket = s.find('[');
+ {
+ size_t bracket = s.find('[');
if (bracket == TString::npos) {
- ParseParamName(s);
- Index = 0;
- } else {
- ParseParamName(s.substr(0, bracket));
- size_t bracket2 = s.find(']', bracket);
+ ParseParamName(s);
+ Index = 0;
+ } else {
+ ParseParamName(s.substr(0, bracket));
+ size_t bracket2 = s.find(']', bracket);
WWW_CHECK(bracket2 != TString::npos, "closing braket ']' is missing");
- Index = FromString<i64>(s.substr(bracket + 1, bracket2 - bracket - 1));
- }
- }
-
+ Index = FromString<i64>(s.substr(bracket + 1, bracket2 - bracket - 1));
+ }
+ }
+
void ParseParamName(const TString& s)
- {
- ParamName = s;
+ {
+ ParamName = s;
TString paramName = s;
-
+
const static TVector<std::pair<TString, ESpecialParam>> specials = {
- { "_track", TrackDuration },
- { "_begin", TrackBeginTime },
- { "_end", TrackEndTime },
- { "_elapsed", ElapsedDuration },
- { "_slice", SliceDuration },
- { "_thr", ThreadTime }
- };
-
- // Check for special params
- SpecialParam = NotSpecial;
- for (const auto& p : specials) {
- if (paramName.StartsWith(p.first)) {
- SpecialParam = p.second;
+ { "_track", TrackDuration },
+ { "_begin", TrackBeginTime },
+ { "_end", TrackEndTime },
+ { "_elapsed", ElapsedDuration },
+ { "_slice", SliceDuration },
+ { "_thr", ThreadTime }
+ };
+
+ // Check for special params
+ SpecialParam = NotSpecial;
+ for (const auto& p : specials) {
+ if (paramName.StartsWith(p.first)) {
+ SpecialParam = p.second;
paramName.erase(0, p.first.size());
- break;
- }
- }
-
- if (SpecialParam == NotSpecial) {
- return;
- }
-
+ break;
+ }
+ }
+
+ if (SpecialParam == NotSpecial) {
+ return;
+ }
+
const static TVector<std::pair<TString, double>> timeUnits = {
- { "Ms", 1e-3 },
- { "Us", 1e-6 },
- { "Ns", 1e-9 },
- { "Min", 60.0 },
- { "Hours", 3600.0 }
- };
-
- // Parse units for special params
- TimeUnitSec = 1.0;
- for (const auto& p : timeUnits) {
- if (paramName.EndsWith(p.first)) {
- TimeUnitSec = p.second;
+ { "Ms", 1e-3 },
+ { "Us", 1e-6 },
+ { "Ns", 1e-9 },
+ { "Min", 60.0 },
+ { "Hours", 3600.0 }
+ };
+
+ // Parse units for special params
+ TimeUnitSec = 1.0;
+ for (const auto& p : timeUnits) {
+ if (paramName.EndsWith(p.first)) {
+ TimeUnitSec = p.second;
paramName.erase(paramName.size() - p.first.size());
- break;
- }
- }
-
- if (SpecialParam == ThreadTime ||
- SpecialParam == TrackBeginTime ||
- SpecialParam == TrackEndTime)
- {
- // Parse time zero for special instant params
+ break;
+ }
+ }
+
+ if (SpecialParam == ThreadTime ||
+ SpecialParam == TrackBeginTime ||
+ SpecialParam == TrackEndTime)
+ {
+ // Parse time zero for special instant params
const TVector<std::pair<TString, i64>> timeZeros = {
- { "RTime", RTimeZeroTs },
- { "NTime", NTimeZeroTs },
- { "Time", 0ll }
- };
- ZeroTs = -1;
- for (const auto& p : timeZeros) {
- if (paramName.EndsWith(p.first)) {
- ZeroTs = p.second;
+ { "RTime", RTimeZeroTs },
+ { "NTime", NTimeZeroTs },
+ { "Time", 0ll }
+ };
+ ZeroTs = -1;
+ for (const auto& p : timeZeros) {
+ if (paramName.EndsWith(p.first)) {
+ ZeroTs = p.second;
paramName.erase(paramName.size() - p.first.size());
- break;
- }
- }
+ break;
+ }
+ }
WWW_CHECK(ZeroTs != -1, "wrong special param name (postfix '*Time' required): %s", s.data());
- }
-
+ }
+
WWW_CHECK(paramName.empty(), "wrong special param name: %s", s.data());
- }
-
+ }
+
void ParseProbeSelector(const TString& s)
- {
- Probe = s;
- }
-
+ {
+ Probe = s;
+ }
+
void ParseProviderSelector(const TString& s)
- {
- Provider = s;
- }
-};
-
+ {
+ Provider = s;
+ }
+};
+
using TVariants = TVector<std::pair<TString, TString>>;
using TTags = TSet<TString>;
-
+
TString GetProbeName(const NLWTrace::TProbe* probe, const char* sep = ".")
-{
+{
return TString(probe->Event.GetProvider()) + sep + probe->Event.Name;
-}
-
-struct TAdHocTraceConfig {
- NLWTrace::TQuery Cfg;
-
- TAdHocTraceConfig() {} // Invalid config
-
- TAdHocTraceConfig(ui16 logSize, ui64 logDurationUs, bool logShuttle)
- {
- auto block = Cfg.AddBlocks(); // Create one block to distinguish valid config
- if (logSize) {
- Cfg.SetPerThreadLogSize(logSize);
- }
- if (logDurationUs) {
- Cfg.SetLogDurationUs(logDurationUs);
- }
- if (logShuttle) {
- block->AddAction()->MutableRunLogShuttleAction();
- }
- }
-
+}
+
+struct TAdHocTraceConfig {
+ NLWTrace::TQuery Cfg;
+
+ TAdHocTraceConfig() {} // Invalid config
+
+ TAdHocTraceConfig(ui16 logSize, ui64 logDurationUs, bool logShuttle)
+ {
+ auto block = Cfg.AddBlocks(); // Create one block to distinguish valid config
+ if (logSize) {
+ Cfg.SetPerThreadLogSize(logSize);
+ }
+ if (logDurationUs) {
+ Cfg.SetLogDurationUs(logDurationUs);
+ }
+ if (logShuttle) {
+ block->AddAction()->MutableRunLogShuttleAction();
+ }
+ }
+
TAdHocTraceConfig(const TString& provider, const TString& probe, ui16 logSize = 0, ui64 logDurationUs = 0, bool logShuttle = false)
- : TAdHocTraceConfig(logSize, logDurationUs, logShuttle)
- {
- auto block = Cfg.MutableBlocks(0);
- auto pdesc = block->MutableProbeDesc();
- pdesc->SetProvider(provider);
- pdesc->SetName(probe);
- }
-
+ : TAdHocTraceConfig(logSize, logDurationUs, logShuttle)
+ {
+ auto block = Cfg.MutableBlocks(0);
+ auto pdesc = block->MutableProbeDesc();
+ pdesc->SetProvider(provider);
+ pdesc->SetName(probe);
+ }
+
explicit TAdHocTraceConfig(const TString& group, ui16 logSize = 0, ui64 logDurationUs = 0, bool logShuttle = false)
- : TAdHocTraceConfig(logSize, logDurationUs, logShuttle)
- {
- auto block = Cfg.MutableBlocks(0);
- auto pdesc = block->MutableProbeDesc();
- pdesc->SetGroup(group);
- }
-
+ : TAdHocTraceConfig(logSize, logDurationUs, logShuttle)
+ {
+ auto block = Cfg.MutableBlocks(0);
+ auto pdesc = block->MutableProbeDesc();
+ pdesc->SetGroup(group);
+ }
+
TString Id() const
- {
- TStringStream ss;
- for (size_t blockIdx = 0; blockIdx < Cfg.BlocksSize(); blockIdx++) {
- if (!ss.Str().empty()) {
- ss << "/";
- }
- auto block = Cfg.GetBlocks(blockIdx);
- auto pdesc = block.GetProbeDesc();
+ {
+ TStringStream ss;
+ for (size_t blockIdx = 0; blockIdx < Cfg.BlocksSize(); blockIdx++) {
+ if (!ss.Str().empty()) {
+ ss << "/";
+ }
+ auto block = Cfg.GetBlocks(blockIdx);
+ auto pdesc = block.GetProbeDesc();
if (pdesc.GetProvider()) {
- ss << "." << pdesc.GetProvider() << "." << pdesc.GetName();
+ ss << "." << pdesc.GetProvider() << "." << pdesc.GetName();
} else if (pdesc.GetGroup()) {
- ss << ".Group." << pdesc.GetGroup();
- }
- // TODO[serxa]: handle predicate
- for (size_t actionIdx = 0; actionIdx < block.ActionSize(); actionIdx++) {
- const NLWTrace::TAction& action = block.GetAction(actionIdx);
- if (action.HasRunLogShuttleAction()) {
- auto ls = action.GetRunLogShuttleAction();
- ss << ".alsr";
- if (ls.GetIgnore()) {
- ss << "-i";
- }
+ ss << ".Group." << pdesc.GetGroup();
+ }
+ // TODO[serxa]: handle predicate
+ for (size_t actionIdx = 0; actionIdx < block.ActionSize(); actionIdx++) {
+ const NLWTrace::TAction& action = block.GetAction(actionIdx);
+ if (action.HasRunLogShuttleAction()) {
+ auto ls = action.GetRunLogShuttleAction();
+ ss << ".alsr";
+ if (ls.GetIgnore()) {
+ ss << "-i";
+ }
if (ls.GetShuttlesCount()) {
- ss << "-s" << ls.GetShuttlesCount();
- }
+ ss << "-s" << ls.GetShuttlesCount();
+ }
if (ls.GetMaxTrackLength()) {
- ss << "-t" << ls.GetMaxTrackLength();
- }
- } else if (action.HasEditLogShuttleAction()) {
- auto ls = action.GetEditLogShuttleAction();
- ss << ".alse";
- if (ls.GetIgnore()) {
- ss << "-i";
- }
- } else if (action.HasDropLogShuttleAction()) {
- ss << ".alsd";
- }
- }
- }
+ ss << "-t" << ls.GetMaxTrackLength();
+ }
+ } else if (action.HasEditLogShuttleAction()) {
+ auto ls = action.GetEditLogShuttleAction();
+ ss << ".alse";
+ if (ls.GetIgnore()) {
+ ss << "-i";
+ }
+ } else if (action.HasDropLogShuttleAction()) {
+ ss << ".alsd";
+ }
+ }
+ }
if (Cfg.GetPerThreadLogSize()) {
- ss << ".l" << Cfg.GetPerThreadLogSize();
- }
+ ss << ".l" << Cfg.GetPerThreadLogSize();
+ }
if (Cfg.GetLogDurationUs()) {
- ui64 logDurationUs = Cfg.GetLogDurationUs();
- if (logDurationUs % (60 * 1000 * 1000) == 0)
- ss << ".d" << logDurationUs / (60 * 1000 * 1000) << "m";
- if (logDurationUs % (1000 * 1000) == 0)
- ss << ".d" << logDurationUs / (1000 * 1000) << "s";
- else if (logDurationUs % 1000 == 0)
- ss << ".d" << logDurationUs / 1000 << "ms";
- else
- ss << ".d" << logDurationUs << "us";
- }
- return ss.Str();
- }
-
- bool IsValid() const
- {
- return Cfg.BlocksSize() > 0;
- }
-
- NLWTrace::TQuery Query() const
- {
- if (!IsValid()) {
- ythrow yexception() << "invalid adhoc trace config";
- }
- return Cfg;
- }
-
+ ui64 logDurationUs = Cfg.GetLogDurationUs();
+ if (logDurationUs % (60 * 1000 * 1000) == 0)
+ ss << ".d" << logDurationUs / (60 * 1000 * 1000) << "m";
+ if (logDurationUs % (1000 * 1000) == 0)
+ ss << ".d" << logDurationUs / (1000 * 1000) << "s";
+ else if (logDurationUs % 1000 == 0)
+ ss << ".d" << logDurationUs / 1000 << "ms";
+ else
+ ss << ".d" << logDurationUs << "us";
+ }
+ return ss.Str();
+ }
+
+ bool IsValid() const
+ {
+ return Cfg.BlocksSize() > 0;
+ }
+
+ NLWTrace::TQuery Query() const
+ {
+ if (!IsValid()) {
+ ythrow yexception() << "invalid adhoc trace config";
+ }
+ return Cfg;
+ }
+
bool ParseId(const TString& id)
- {
- if (IsAdHocId(id)) {
+ {
+ if (IsAdHocId(id)) {
for (const TString& block : SplitString(id, "/")) {
- if (block.empty()) {
- continue;
- }
- size_t cutPos = (block[0] == '.'? 1: 0);
+ if (block.empty()) {
+ continue;
+ }
+ size_t cutPos = (block[0] == '.'? 1: 0);
TVector<TString> parts = SplitString(block.substr(cutPos), ".");
WWW_CHECK(parts.size() >= 2, "too few parts in adhoc trace id '%s' block '%s'", id.data(), block.data());
- auto blockPb = Cfg.AddBlocks();
- auto pdescPb = blockPb->MutableProbeDesc();
- if (parts[0] == "Group") {
- pdescPb->SetGroup(parts[1]);
- } else {
- pdescPb->SetProvider(parts[0]);
- pdescPb->SetName(parts[1]);
- }
- bool defaultAction = true;
- for (auto i = parts.begin() + 2, e = parts.end(); i != e; ++i) {
+ auto blockPb = Cfg.AddBlocks();
+ auto pdescPb = blockPb->MutableProbeDesc();
+ if (parts[0] == "Group") {
+ pdescPb->SetGroup(parts[1]);
+ } else {
+ pdescPb->SetProvider(parts[0]);
+ pdescPb->SetName(parts[1]);
+ }
+ bool defaultAction = true;
+ for (auto i = parts.begin() + 2, e = parts.end(); i != e; ++i) {
const TString& part = *i;
- if (part.empty()) {
- continue;
- }
- switch (part[0]) {
- case 'l': Cfg.SetPerThreadLogSize(FromString<ui16>(part.substr(1))); break;
- case 'd': Cfg.SetLogDurationUs(ParseDuration(part.substr(1))); break;
- case 's': blockPb->MutablePredicate()->SetSampleRate(1.0 / Max<ui64>(1, FromString<ui64>(part.substr(1)))); break;
- case 'p': ParsePredicate(blockPb->MutablePredicate()->AddOperators(), part.substr(1)); break;
- case 'a': ParseAction(blockPb->AddAction(), part.substr(1)); defaultAction = false; break;
+ if (part.empty()) {
+ continue;
+ }
+ switch (part[0]) {
+ case 'l': Cfg.SetPerThreadLogSize(FromString<ui16>(part.substr(1))); break;
+ case 'd': Cfg.SetLogDurationUs(ParseDuration(part.substr(1))); break;
+ case 's': blockPb->MutablePredicate()->SetSampleRate(1.0 / Max<ui64>(1, FromString<ui64>(part.substr(1)))); break;
+ case 'p': ParsePredicate(blockPb->MutablePredicate()->AddOperators(), part.substr(1)); break;
+ case 'a': ParseAction(blockPb->AddAction(), part.substr(1)); defaultAction = false; break;
default: WWW_CHECK(false, "unknown adhoc trace part type '%s' in '%s'", part.data(), id.data());
- }
- }
- if (defaultAction) {
- blockPb->AddAction()->MutableLogAction();
- }
- }
- return true;
- }
- return false;
- }
-private:
+ }
+ }
+ if (defaultAction) {
+ blockPb->AddAction()->MutableLogAction();
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+private:
static bool IsAdHocId(const TString& id)
- {
- return !id.empty() && id[0] == '.';
- }
-
+ {
+ return !id.empty() && id[0] == '.';
+ }
+
void ParsePredicate(NLWTrace::TOperator* op, const TString& p)
- {
- size_t sign = p.find_first_of("=!><");
+ {
+ size_t sign = p.find_first_of("=!><");
WWW_CHECK(sign != TString::npos, "wrong predicate format in adhoc trace: %s", p.data());
- op->AddArgument()->SetParam(p.substr(0, sign));
- size_t value = sign + 1;
- switch (p[sign]) {
- case '=':
- op->SetType(NLWTrace::OT_EQ);
- break;
- case '!': {
+ op->AddArgument()->SetParam(p.substr(0, sign));
+ size_t value = sign + 1;
+ switch (p[sign]) {
+ case '=':
+ op->SetType(NLWTrace::OT_EQ);
+ break;
+ case '!': {
WWW_CHECK(p.size() > sign + 1, "wrong predicate operator format in adhoc trace: %s", p.data());
WWW_CHECK(p[sign + 1] == '=', "wrong predicate operator format in adhoc trace: %s", p.data());
- value++;
- op->SetType(NLWTrace::OT_NE);
- break;
- }
- case '<': {
+ value++;
+ op->SetType(NLWTrace::OT_NE);
+ break;
+ }
+ case '<': {
WWW_CHECK(p.size() > sign + 1, "wrong predicate operator format in adhoc trace: %s", p.data());
- if (p[sign + 1] == '=') {
- value++;
- op->SetType(NLWTrace::OT_LE);
- } else {
- op->SetType(NLWTrace::OT_LT);
- }
- break;
- }
- case '>': {
+ if (p[sign + 1] == '=') {
+ value++;
+ op->SetType(NLWTrace::OT_LE);
+ } else {
+ op->SetType(NLWTrace::OT_LT);
+ }
+ break;
+ }
+ case '>': {
WWW_CHECK(p.size() > sign + 1, "wrong predicate operator format in adhoc trace: %s", p.data());
- if (p[sign + 1] == '=') {
- value++;
- op->SetType(NLWTrace::OT_GE);
- } else {
- op->SetType(NLWTrace::OT_GT);
- }
- break;
- }
+ if (p[sign + 1] == '=') {
+ value++;
+ op->SetType(NLWTrace::OT_GE);
+ } else {
+ op->SetType(NLWTrace::OT_GT);
+ }
+ break;
+ }
default: WWW_CHECK(false, "wrong predicate operator format in adhoc trace: %s", p.data());
- }
- op->AddArgument()->SetValue(p.substr(value));
- }
-
+ }
+ op->AddArgument()->SetValue(p.substr(value));
+ }
+
void ParseAction(NLWTrace::TAction* action, const TString& a)
- {
- // NOTE: checks for longer action names should go first, your captain.
- if (a.substr(0, 3) == "lsr") {
- auto pb = action->MutableRunLogShuttleAction();
+ {
+ // NOTE: checks for longer action names should go first, your captain.
+ if (a.substr(0, 3) == "lsr") {
+ auto pb = action->MutableRunLogShuttleAction();
for (const TString& opt : SplitString(a.substr(3), "-")) {
- if (!opt.empty()) {
- switch (opt[0]) {
- case 'i': pb->SetIgnore(true); break;
- case 's': pb->SetShuttlesCount(FromString<ui64>(opt.substr(1))); break;
- case 't': pb->SetMaxTrackLength(FromString<ui64>(opt.substr(1))); break;
+ if (!opt.empty()) {
+ switch (opt[0]) {
+ case 'i': pb->SetIgnore(true); break;
+ case 's': pb->SetShuttlesCount(FromString<ui64>(opt.substr(1))); break;
+ case 't': pb->SetMaxTrackLength(FromString<ui64>(opt.substr(1))); break;
default: WWW_CHECK(false, "unknown adhoc trace log shuttle opt '%s' in '%s'", opt.data(), a.data());
- }
- }
- }
- } else if (a.substr(0, 3) == "lse") {
- auto pb = action->MutableEditLogShuttleAction();
+ }
+ }
+ }
+ } else if (a.substr(0, 3) == "lse") {
+ auto pb = action->MutableEditLogShuttleAction();
for (const TString& opt : SplitString(a.substr(3), "-")) {
- if (!opt.empty()) {
- switch (opt[0]) {
- case 'i': pb->SetIgnore(true); break;
+ if (!opt.empty()) {
+ switch (opt[0]) {
+ case 'i': pb->SetIgnore(true); break;
default: WWW_CHECK(false, "unknown adhoc trace log shuttle opt '%s' in '%s'", opt.data(), a.data());
- }
- }
- }
- } else if (a.substr(0, 3) == "lsd") {
- action->MutableDropLogShuttleAction();
- } else if (a.substr(0, 1) == "l") {
- auto pb = action->MutableLogAction();
+ }
+ }
+ }
+ } else if (a.substr(0, 3) == "lsd") {
+ action->MutableDropLogShuttleAction();
+ } else if (a.substr(0, 1) == "l") {
+ auto pb = action->MutableLogAction();
for (const TString& opt : SplitString(a.substr(1), "-")) {
- if (!opt.empty()) {
- switch (opt[0]) {
- case 't': pb->SetLogTimestamp(true); break;
- case 'r': pb->SetMaxRecords(FromString<ui32>(opt.substr(1))); break;
+ if (!opt.empty()) {
+ switch (opt[0]) {
+ case 't': pb->SetLogTimestamp(true); break;
+ case 'r': pb->SetMaxRecords(FromString<ui32>(opt.substr(1))); break;
default: WWW_CHECK(false, "unknown adhoc trace log opt '%s' in '%s'", opt.data(), a.data());
- }
- }
- }
- } else {
+ }
+ }
+ }
+ } else {
WWW_CHECK(false, "wrong action format in adhoc trace: %s", a.data());
- }
- }
-
+ }
+ }
+
static ui64 ParseDuration(const TString& s)
- {
- if (s.substr(s.length() - 2) == "us")
- return FromString<ui64>(s.substr(0, s.length() - 2));
- if (s.substr(s.length() - 2) == "ms")
- return FromString<ui64>(s.substr(0, s.length() - 2)) * 1000;
- if (s.substr(s.length() - 1) == "s")
- return FromString<ui64>(s.substr(0, s.length() - 1)) * 1000 * 1000;
- if (s.substr(s.length() - 1) == "m")
- return FromString<ui64>(s.substr(0, s.length() - 1)) * 60 * 1000 * 1000;
- else
- return FromString<ui64>(s);
- }
-};
-
-// Class that maintains one thread iff there are adhoc traces and cleans'em by deadlines
-class TTraceCleaner {
-private:
- NLWTrace::TManager* TraceMngr;
- TAtomic Quit = 0;
-
- TMutex Mtx;
- TCondVar WakeCondVar;
+ {
+ if (s.substr(s.length() - 2) == "us")
+ return FromString<ui64>(s.substr(0, s.length() - 2));
+ if (s.substr(s.length() - 2) == "ms")
+ return FromString<ui64>(s.substr(0, s.length() - 2)) * 1000;
+ if (s.substr(s.length() - 1) == "s")
+ return FromString<ui64>(s.substr(0, s.length() - 1)) * 1000 * 1000;
+ if (s.substr(s.length() - 1) == "m")
+ return FromString<ui64>(s.substr(0, s.length() - 1)) * 60 * 1000 * 1000;
+ else
+ return FromString<ui64>(s);
+ }
+};
+
+// Class that maintains one thread iff there are adhoc traces and cleans'em by deadlines
+class TTraceCleaner {
+private:
+ NLWTrace::TManager* TraceMngr;
+ TAtomic Quit = 0;
+
+ TMutex Mtx;
+ TCondVar WakeCondVar;
THashMap<TString, TInstant> Deadlines;
- volatile bool ThreadIsRunning = false;
- THolder<TThread> Thread;
-public:
- TTraceCleaner(NLWTrace::TManager* traceMngr)
- : TraceMngr(traceMngr)
- {}
-
- ~TTraceCleaner()
- {
- AtomicSet(Quit, 1);
- WakeCondVar.Signal();
- // TThread dtor joins thread
- }
-
- // Returns deadline for specified trace id or zero
+ volatile bool ThreadIsRunning = false;
+ THolder<TThread> Thread;
+public:
+ TTraceCleaner(NLWTrace::TManager* traceMngr)
+ : TraceMngr(traceMngr)
+ {}
+
+ ~TTraceCleaner()
+ {
+ AtomicSet(Quit, 1);
+ WakeCondVar.Signal();
+ // TThread dtor joins thread
+ }
+
+ // Returns deadline for specified trace id or zero
TInstant GetDeadline(const TString& id) const
- {
- TGuard<TMutex> g(Mtx);
- auto iter = Deadlines.find(id);
- return iter != Deadlines.end()? iter->second: TInstant::Zero();
- }
-
- // Postpone deletion of specified trace for specified timeout
+ {
+ TGuard<TMutex> g(Mtx);
+ auto iter = Deadlines.find(id);
+ return iter != Deadlines.end()? iter->second: TInstant::Zero();
+ }
+
+ // Postpone deletion of specified trace for specified timeout
void Postpone(const TString& id, TDuration timeout, bool allowLowering)
- {
- TGuard<TMutex> g(Mtx);
- TInstant newDeadline = TInstant::Now() + timeout;
- if (Deadlines[id] < newDeadline) {
- Deadlines[id] = newDeadline;
- } else if (allowLowering) { // Deadline lowering requires wake
- Deadlines[id] = newDeadline;
- WakeCondVar.Signal();
- }
- if (newDeadline != TInstant::Max() && !ThreadIsRunning) {
- // Note that dtor joins previous thread if any
- Thread.Reset(new TThread(ThreadProc, this));
- Thread->Start();
- ThreadIsRunning = true;
- }
- }
-
- // Forget about specified trace deletion
+ {
+ TGuard<TMutex> g(Mtx);
+ TInstant newDeadline = TInstant::Now() + timeout;
+ if (Deadlines[id] < newDeadline) {
+ Deadlines[id] = newDeadline;
+ } else if (allowLowering) { // Deadline lowering requires wake
+ Deadlines[id] = newDeadline;
+ WakeCondVar.Signal();
+ }
+ if (newDeadline != TInstant::Max() && !ThreadIsRunning) {
+ // Note that dtor joins previous thread if any
+ Thread.Reset(new TThread(ThreadProc, this));
+ Thread->Start();
+ ThreadIsRunning = true;
+ }
+ }
+
+ // Forget about specified trace deletion
void Forget(const TString& id)
- {
- TGuard<TMutex> g(Mtx);
- Deadlines.erase(id);
- WakeCondVar.Signal(); // in case thread is not required any more
- }
-private:
- void Exec()
- {
- while (!AtomicGet(Quit)) {
- TGuard<TMutex> g(Mtx);
-
- // Delete all timed out traces
- TInstant now = TInstant::Now();
- TInstant nextDeadline = TInstant::Max();
- for (auto i = Deadlines.begin(), e = Deadlines.end(); i != e;) {
+ {
+ TGuard<TMutex> g(Mtx);
+ Deadlines.erase(id);
+ WakeCondVar.Signal(); // in case thread is not required any more
+ }
+private:
+ void Exec()
+ {
+ while (!AtomicGet(Quit)) {
+ TGuard<TMutex> g(Mtx);
+
+ // Delete all timed out traces
+ TInstant now = TInstant::Now();
+ TInstant nextDeadline = TInstant::Max();
+ for (auto i = Deadlines.begin(), e = Deadlines.end(); i != e;) {
const TString& id = i->first;
- TInstant deadline = i->second;
- if (deadline < now) {
- try {
- TraceMngr->Delete(id);
- } catch (...) {
- // already deleted
- }
- Deadlines.erase(i++);
- } else {
- nextDeadline = Min(nextDeadline, deadline);
- ++i;
- }
- }
-
- // Stop thread if there is no more work
- if (Deadlines.empty() || nextDeadline == TInstant::Max()) {
- ThreadIsRunning = false;
- break;
- }
-
- // Wait until next deadline or quit
- WakeCondVar.WaitD(Mtx, nextDeadline);
- }
- }
-
- static void* ThreadProc(void* _this)
- {
+ TInstant deadline = i->second;
+ if (deadline < now) {
+ try {
+ TraceMngr->Delete(id);
+ } catch (...) {
+ // already deleted
+ }
+ Deadlines.erase(i++);
+ } else {
+ nextDeadline = Min(nextDeadline, deadline);
+ ++i;
+ }
+ }
+
+ // Stop thread if there is no more work
+ if (Deadlines.empty() || nextDeadline == TInstant::Max()) {
+ ThreadIsRunning = false;
+ break;
+ }
+
+ // Wait until next deadline or quit
+ WakeCondVar.WaitD(Mtx, nextDeadline);
+ }
+ }
+
+ static void* ThreadProc(void* _this)
+ {
TString name = "LWTraceCleaner";
- // Copy-pasted from kikimr/core/util/thread.h
-#if defined(_linux_)
- TStringStream linuxName;
- linuxName << TStringBuf(GetExecPath()).RNextTok('/') << "." << name;
+ // Copy-pasted from kikimr/core/util/thread.h
+#if defined(_linux_)
+ TStringStream linuxName;
+ linuxName << TStringBuf(GetExecPath()).RNextTok('/') << "." << name;
TThread::SetCurrentThreadName(linuxName.Str().data());
-#else
+#else
TThread::SetCurrentThreadName(name.data());
-#endif
- static_cast<TTraceCleaner*>(_this)->Exec();
- return nullptr;
- }
-};
-
-class TChromeTrace {
-private:
+#endif
+ static_cast<TTraceCleaner*>(_this)->Exec();
+ return nullptr;
+ }
+};
+
+class TChromeTrace {
+private:
TMultiMap<double, TString> TraceEvents;
THashMap<TThread::TId, TString> Tids;
-public:
+public:
void Add(TThread::TId tid, ui64 tsCycles, const TString& ph, const TString& cat,
- const NLWTrace::TLogItem* argsItem = nullptr,
+ const NLWTrace::TLogItem* argsItem = nullptr,
const TString& name = TString(), const TString& id = TString())
- {
- auto tidIter = Tids.find(tid);
- if (tidIter == Tids.end()) {
- tidIter = Tids.emplace(tid, ToString(Tids.size() + 1)).first;
- }
+ {
+ auto tidIter = Tids.find(tid);
+ if (tidIter == Tids.end()) {
+ tidIter = Tids.emplace(tid, ToString(Tids.size() + 1)).first;
+ }
const TString& shortId = tidIter->second;
- double ts = Timestamp(tsCycles);
- TraceEvents.emplace(ts, Event(shortId, ts, ph, cat, argsItem, name, id));
- }
-
+ double ts = Timestamp(tsCycles);
+ TraceEvents.emplace(ts, Event(shortId, ts, ph, cat, argsItem, name, id));
+ }
+
void Output(IOutputStream& os)
- {
- os << "{\"traceEvents\":[";
- bool first = true;
- for (auto kv : TraceEvents) {
- if (!first) {
- os << ",\n";
- }
- os << kv.second;
- first = false;
- }
- os << "]}";
- }
-
-private:
+ {
+ os << "{\"traceEvents\":[";
+ bool first = true;
+ for (auto kv : TraceEvents) {
+ if (!first) {
+ os << ",\n";
+ }
+ os << kv.second;
+ first = false;
+ }
+ os << "]}";
+ }
+
+private:
static TString Event(const TString& tid, double ts, const TString& ph, const TString& cat,
- const NLWTrace::TLogItem* argsItem,
+ const NLWTrace::TLogItem* argsItem,
const TString& name, const TString& id)
- {
- TStringStream ss;
- pid_t pid = 1;
- ss << "{\"pid\":" << pid
- << ",\"tid\":" << tid
- << ",\"ts\":" << Sprintf("%lf", ts)
- << ",\"ph\":\"" << ph << "\""
- << ",\"cat\":\"" << cat << "\"";
- if (name) {
- ss << ",\"name\":\"" << name << "\"";
- }
- if (id) {
- ss << ",\"id\":\"" << id << "\"";
- }
- if (argsItem && argsItem->SavedParamsCount > 0) {
- ss << ",\"args\":{";
+ {
+ TStringStream ss;
+ pid_t pid = 1;
+ ss << "{\"pid\":" << pid
+ << ",\"tid\":" << tid
+ << ",\"ts\":" << Sprintf("%lf", ts)
+ << ",\"ph\":\"" << ph << "\""
+ << ",\"cat\":\"" << cat << "\"";
+ if (name) {
+ ss << ",\"name\":\"" << name << "\"";
+ }
+ if (id) {
+ ss << ",\"id\":\"" << id << "\"";
+ }
+ if (argsItem && argsItem->SavedParamsCount > 0) {
+ ss << ",\"args\":{";
TString paramValues[LWTRACE_MAX_PARAMS];
- argsItem->Probe->Event.Signature.SerializeParams(argsItem->Params, paramValues);
- bool first = true;
- for (size_t pi = 0; pi < argsItem->SavedParamsCount; pi++, first = false) {
- if (!first) {
- ss << ",";
- }
+ argsItem->Probe->Event.Signature.SerializeParams(argsItem->Params, paramValues);
+ bool first = true;
+ for (size_t pi = 0; pi < argsItem->SavedParamsCount; pi++, first = false) {
+ if (!first) {
+ ss << ",";
+ }
ss << "\"" << TString(argsItem->Probe->Event.Signature.ParamNames[pi]) << "\":"
- "\"" << paramValues[pi] << "\"";
- }
- ss << "}";
- }
- ss << "}";
- return ss.Str();
- }
-
- static double Timestamp(ui64 cycles)
- {
- return double(cycles) * 1000000.0 / NHPTimer::GetClockRate();
- }
-};
-
-TString MakeUrl(const TCgiParameters& e, const THashMap<TString, TString>& values)
-{
- TStringStream ss;
- bool first = true;
- for (const auto& [k, v] : e) {
- if (values.find(k) == values.end()) {
- ss << (first? "?": "&") << k << "=" << v;
- first = false;
- }
- }
- for (const auto& [k, v] : values) {
- ss << (first? "?": "&") << k << "=" << v;
- first = false;
- }
- return ss.Str();
-}
-
+ "\"" << paramValues[pi] << "\"";
+ }
+ ss << "}";
+ }
+ ss << "}";
+ return ss.Str();
+ }
+
+ static double Timestamp(ui64 cycles)
+ {
+ return double(cycles) * 1000000.0 / NHPTimer::GetClockRate();
+ }
+};
+
+TString MakeUrl(const TCgiParameters& e, const THashMap<TString, TString>& values)
+{
+ TStringStream ss;
+ bool first = true;
+ for (const auto& [k, v] : e) {
+ if (values.find(k) == values.end()) {
+ ss << (first? "?": "&") << k << "=" << v;
+ first = false;
+ }
+ }
+ for (const auto& [k, v] : values) {
+ ss << (first? "?": "&") << k << "=" << v;
+ first = false;
+ }
+ return ss.Str();
+}
+
TString MakeUrl(const TCgiParameters& e, const TString& key, const TString& value, bool keep = false)
-{
- TStringStream ss;
- bool first = true;
- for (const auto& kv : e) {
- if (keep || kv.first != key) {
- ss << (first? "?": "&") << kv.first << "=" << kv.second;
- first = false;
- }
- }
- ss << (first? "?": "&") << key << "=" << value;
- return ss.Str();
-}
-
+{
+ TStringStream ss;
+ bool first = true;
+ for (const auto& kv : e) {
+ if (keep || kv.first != key) {
+ ss << (first? "?": "&") << kv.first << "=" << kv.second;
+ first = false;
+ }
+ }
+ ss << (first? "?": "&") << key << "=" << value;
+ return ss.Str();
+}
+
TString MakeUrlAdd(const TCgiParameters& e, const TString& key, const TString& value)
-{
- TStringStream ss;
- bool first = true;
- for (const auto& kv : e) {
- ss << (first? "?": "&") << kv.first << "=" << kv.second;
- first = false;
- }
- ss << (first? "?": "&") << key << "=" << value;
- return ss.Str();
-}
-
+{
+ TStringStream ss;
+ bool first = true;
+ for (const auto& kv : e) {
+ ss << (first? "?": "&") << kv.first << "=" << kv.second;
+ first = false;
+ }
+ ss << (first? "?": "&") << key << "=" << value;
+ return ss.Str();
+}
+
TString MakeUrlReplace(const TCgiParameters& e, const TString& key, const TString& oldValue, const TString& newValue)
-{
- TStringStream ss;
- bool first = true;
- bool inserted = false;
- for (const auto& kv : e) {
- if (kv.first == key && (kv.second == oldValue || kv.second == newValue)) {
- if (!inserted) {
- inserted = true;
- ss << (first? "?": "&") << key << "=" << newValue;
- first = false;
- }
- } else {
- ss << (first? "?": "&") << kv.first << "=" << kv.second;
- first = false;
- }
- }
- if (!inserted) {
- ss << (first? "?": "&") << key << "=" << newValue;
- }
- return ss.Str();
-}
-
+{
+ TStringStream ss;
+ bool first = true;
+ bool inserted = false;
+ for (const auto& kv : e) {
+ if (kv.first == key && (kv.second == oldValue || kv.second == newValue)) {
+ if (!inserted) {
+ inserted = true;
+ ss << (first? "?": "&") << key << "=" << newValue;
+ first = false;
+ }
+ } else {
+ ss << (first? "?": "&") << kv.first << "=" << kv.second;
+ first = false;
+ }
+ }
+ if (!inserted) {
+ ss << (first? "?": "&") << key << "=" << newValue;
+ }
+ return ss.Str();
+}
+
TString MakeUrlErase(const TCgiParameters& e, const TString& key, const TString& value)
-{
- TStringStream ss;
- bool first = true;
- for (const auto& kv : e) {
- if (kv.first != key || kv.second != value) {
- ss << (first? "?": "&") << kv.first << "=" << kv.second;
- first = false;
- }
- }
- return ss.Str();
-}
-
+{
+ TStringStream ss;
+ bool first = true;
+ for (const auto& kv : e) {
+ if (kv.first != key || kv.second != value) {
+ ss << (first? "?": "&") << kv.first << "=" << kv.second;
+ first = false;
+ }
+ }
+ return ss.Str();
+}
+
TString EscapeSubvalue(const TString& s)
-{
+{
TString ret;
ret.reserve(s.size());
for (size_t i = 0; i < s.size(); i++) {
- char c = s[i];
- if (c == ':') {
- ret.append("^c");
- } else if (c == '^') {
- ret.append("^^");
- } else {
- ret.append(c);
- }
- }
- return ret;
-}
-
+ char c = s[i];
+ if (c == ':') {
+ ret.append("^c");
+ } else if (c == '^') {
+ ret.append("^^");
+ } else {
+ ret.append(c);
+ }
+ }
+ return ret;
+}
+
TString UnescapeSubvalue(const TString& s)
-{
+{
TString ret;
ret.reserve(s.size());
for (size_t i = 0; i < s.size(); i++) {
- char c = s[i];
+ char c = s[i];
if (c == '^' && i + 1 < s.size()) {
- char c2 = s[++i];
- if (c2 == 'c') {
- ret.append(':');
- } else if (c2 == '^') {
- ret.append('^');
- } else {
- ret.append(c);
- ret.append(c2);
- }
- } else {
- ret.append(c);
- }
- }
- return ret;
-}
-
+ char c2 = s[++i];
+ if (c2 == 'c') {
+ ret.append(':');
+ } else if (c2 == '^') {
+ ret.append('^');
+ } else {
+ ret.append(c);
+ ret.append(c2);
+ }
+ } else {
+ ret.append(c);
+ }
+ }
+ return ret;
+}
+
TVector<TString> Subvalues(const TCgiParameters& e, const TString& key)
-{
- if (!e.Has(key)) {
+{
+ if (!e.Has(key)) {
return TVector<TString>();
- } else {
+ } else {
TVector<TString> ret;
for (const TString& s : SplitString(e.Get(key), ":", 0, KEEP_EMPTY_TOKENS)) {
- ret.push_back(UnescapeSubvalue(s));
- }
- if (ret.empty()) {
- ret.push_back("");
- }
- return ret;
- }
-}
-
+ ret.push_back(UnescapeSubvalue(s));
+ }
+ if (ret.empty()) {
+ ret.push_back("");
+ }
+ return ret;
+ }
+}
+
TString ParseTagsOut(const TString& taggedStr, TTags& tags)
-{
+{
auto vec = SplitString(taggedStr, "-");
- if (vec.empty()) {
- return "";
- }
- auto iter = vec.begin();
+ if (vec.empty()) {
+ return "";
+ }
+ auto iter = vec.begin();
TString value = *iter++;
- for (;iter != vec.end(); ++iter) {
- tags.insert(*iter);
- }
- return value;
-}
-
+ for (;iter != vec.end(); ++iter) {
+ tags.insert(*iter);
+ }
+ return value;
+}
+
TString JoinTags(TTags tags) {
return JoinStrings(TVector<TString>(tags.begin(), tags.end()), "-");
-}
-
+}
+
TString MakeValue(const TVector<TString>& subvalues)
-{
+{
TVector<TString> subvaluesEsc;
for (const TString& s : subvalues) {
- subvaluesEsc.push_back(EscapeSubvalue(s));
- }
+ subvaluesEsc.push_back(EscapeSubvalue(s));
+ }
return JoinStrings(subvaluesEsc, ":");
-}
-
+}
+
TString MakeUrlAddSub(const TCgiParameters& e, const TString& key, const TString& subvalue)
-{
+{
const TString& value = e.Get(key);
- auto subvalues = Subvalues(e, key);
- subvalues.push_back(subvalue);
- return MakeUrlReplace(e, key, value, MakeValue(subvalues));
-}
-
+ auto subvalues = Subvalues(e, key);
+ subvalues.push_back(subvalue);
+ return MakeUrlReplace(e, key, value, MakeValue(subvalues));
+}
+
TString MakeUrlReplaceSub(const TCgiParameters& e, const TString& key, const TString& oldSubvalue, const TString& newSubvalue)
-{
+{
const TString& value = e.Get(key);
- auto subvalues = Subvalues(e, key);
- auto iter = std::find(subvalues.begin(), subvalues.end(), oldSubvalue);
- if (iter != subvalues.end()) {
- *iter = newSubvalue;
- } else {
- subvalues.push_back(newSubvalue);
- }
- return MakeUrlReplace(e, key, value, MakeValue(subvalues));
-}
-
+ auto subvalues = Subvalues(e, key);
+ auto iter = std::find(subvalues.begin(), subvalues.end(), oldSubvalue);
+ if (iter != subvalues.end()) {
+ *iter = newSubvalue;
+ } else {
+ subvalues.push_back(newSubvalue);
+ }
+ return MakeUrlReplace(e, key, value, MakeValue(subvalues));
+}
+
TString MakeUrlEraseSub(const TCgiParameters& e, const TString& key, const TString& subvalue)
-{
+{
const TString& value = e.Get(key);
- auto subvalues = Subvalues(e, key);
- auto iter = std::find(subvalues.begin(), subvalues.end(), subvalue);
- if (iter != subvalues.end()) {
- subvalues.erase(iter);
- }
- if (subvalues.empty()) {
- return MakeUrlErase(e, key, value);
- } else {
- return MakeUrlReplace(e, key, value, MakeValue(subvalues));
- }
-}
-
+ auto subvalues = Subvalues(e, key);
+ auto iter = std::find(subvalues.begin(), subvalues.end(), subvalue);
+ if (iter != subvalues.end()) {
+ subvalues.erase(iter);
+ }
+ if (subvalues.empty()) {
+ return MakeUrlErase(e, key, value);
+ } else {
+ return MakeUrlReplace(e, key, value, MakeValue(subvalues));
+ }
+}
+
template <bool sub> TString UrlAdd(const TCgiParameters& e, const TString& key, const TString& value);
template <> TString UrlAdd<false>(const TCgiParameters& e, const TString& key, const TString& value) {
- return MakeUrlAdd(e, key, value);
-}
+ return MakeUrlAdd(e, key, value);
+}
template <> TString UrlAdd<true>(const TCgiParameters& e, const TString& key, const TString& value) {
- return MakeUrlAddSub(e, key, value);
-}
-
+ return MakeUrlAddSub(e, key, value);
+}
+
template <bool sub> TString UrlReplace(const TCgiParameters& e, const TString& key, const TString& oldValue, const TString& newValue);
template <> TString UrlReplace<false>(const TCgiParameters& e, const TString& key, const TString& oldValue, const TString& newValue) {
- return MakeUrlReplace(e, key, oldValue, newValue);
-}
+ return MakeUrlReplace(e, key, oldValue, newValue);
+}
template <> TString UrlReplace<true>(const TCgiParameters& e, const TString& key, const TString& oldValue, const TString& newValue) {
- return MakeUrlReplaceSub(e, key, oldValue, newValue);
-}
-
+ return MakeUrlReplaceSub(e, key, oldValue, newValue);
+}
+
template <bool sub> TString UrlErase(const TCgiParameters& e, const TString& key, const TString& value);
template <> TString UrlErase<false>(const TCgiParameters& e, const TString& key, const TString& value) {
- return MakeUrlErase(e, key, value);
-}
+ return MakeUrlErase(e, key, value);
+}
template <> TString UrlErase<true>(const TCgiParameters& e, const TString& key, const TString& value) {
- return MakeUrlEraseSub(e, key, value);
-}
-
+ return MakeUrlEraseSub(e, key, value);
+}
+
void OutputCommonHeader(IOutputStream& out)
-{
- out << NResource::Find("lwtrace/mon/static/header.html") << Endl;
-}
-
+{
+ out << NResource::Find("lwtrace/mon/static/header.html") << Endl;
+}
+
void OutputCommonFooter(IOutputStream& out)
-{
- out << NResource::Find("lwtrace/mon/static/footer.html") << Endl;
-}
-
-struct TScopedHtmlInner {
+{
+ out << NResource::Find("lwtrace/mon/static/footer.html") << Endl;
+}
+
+struct TScopedHtmlInner {
explicit TScopedHtmlInner(IOutputStream& str)
- : Str(str)
- {
- Str << "<!DOCTYPE html>\n"
- "<html>";
- HTML(str) {
- HEAD() { OutputCommonHeader(Str); }
- }
- Str << "<body>";
- }
-
- ~TScopedHtmlInner()
- {
- OutputCommonFooter(Str);
- Str << "</body></html>";
- }
-
- inline operator bool () const noexcept { return true; }
-
+ : Str(str)
+ {
+ Str << "<!DOCTYPE html>\n"
+ "<html>";
+ HTML(str) {
+ HEAD() { OutputCommonHeader(Str); }
+ }
+ Str << "<body>";
+ }
+
+ ~TScopedHtmlInner()
+ {
+ OutputCommonFooter(Str);
+ Str << "</body></html>";
+ }
+
+ inline operator bool () const noexcept { return true; }
+
IOutputStream &Str;
-};
-
+};
+
TString NavbarHeader()
-{
- return "<div class=\"navbar-header\">"
- "<a class=\"navbar-brand\" href=\"?mode=\">LWTrace</a>"
- "</div>";
-}
-
-struct TSelectorsContainer {
+{
+ return "<div class=\"navbar-header\">"
+ "<a class=\"navbar-brand\" href=\"?mode=\">LWTrace</a>"
+ "</div>";
+}
+
+struct TSelectorsContainer {
TSelectorsContainer(IOutputStream& str)
- : Str(str)
- {
- Str << "<nav id=\"selectors-container\" class=\"navbar navbar-default\">"
- "<div class=\"container-fluid\">"
- << NavbarHeader() <<
- "<div class=\"navbar-text\" style=\"margin-top:12px;margin-bottom:10px\">";
- }
-
- ~TSelectorsContainer() {
- try {
- Str <<
- "</div>"
- "<div class=\"container-fluid\">"
- "<div class=\"pull-right\">"
- "<button id=\"download-btn\""
- " type=\"button\" style=\"display: inline-block;margin:7px\""
- " title=\"Chromium trace (load it in chrome://tracing/)\""
- " class=\"btn btn-default hidden\">"
- "<span class=\"glyphicon glyphicon-download-alt\"></span>"
- "</button>"
- "</div>"
- "</div>"
- "</div></nav>";
- } catch(...) {}
- }
-
+ : Str(str)
+ {
+ Str << "<nav id=\"selectors-container\" class=\"navbar navbar-default\">"
+ "<div class=\"container-fluid\">"
+ << NavbarHeader() <<
+ "<div class=\"navbar-text\" style=\"margin-top:12px;margin-bottom:10px\">";
+ }
+
+ ~TSelectorsContainer() {
+ try {
+ Str <<
+ "</div>"
+ "<div class=\"container-fluid\">"
+ "<div class=\"pull-right\">"
+ "<button id=\"download-btn\""
+ " type=\"button\" style=\"display: inline-block;margin:7px\""
+ " title=\"Chromium trace (load it in chrome://tracing/)\""
+ " class=\"btn btn-default hidden\">"
+ "<span class=\"glyphicon glyphicon-download-alt\"></span>"
+ "</button>"
+ "</div>"
+ "</div>"
+ "</div></nav>";
+ } catch(...) {}
+ }
+
IOutputStream& Str;
-};
-
-struct TNullContainer {
+};
+
+struct TNullContainer {
TNullContainer(IOutputStream&) {}
-};
-
-class TPageGenBase: public std::exception {};
-template <class TContainer = TNullContainer>
-class TPageGen: public TPageGenBase {
-private:
+};
+
+class TPageGenBase: public std::exception {};
+template <class TContainer = TNullContainer>
+class TPageGen: public TPageGenBase {
+private:
TString Content;
TString HttpResponse;
-public:
- void BuildResponse()
- {
- TStringStream ss;
- WWW_HTML(ss) {
- TContainer container(ss);
- ss << Content;
- }
- HttpResponse = ss.Str();
- }
-
+public:
+ void BuildResponse()
+ {
+ TStringStream ss;
+ WWW_HTML(ss) {
+ TContainer container(ss);
+ ss << Content;
+ }
+ HttpResponse = ss.Str();
+ }
+
explicit TPageGen(const TString& content = TString())
- : Content(content)
- {
- BuildResponse();
- }
-
+ : Content(content)
+ {
+ BuildResponse();
+ }
+
void Append(const TString& moreContent)
- {
- Content.append(moreContent);
- BuildResponse();
- }
-
+ {
+ Content.append(moreContent);
+ BuildResponse();
+ }
+
void Prepend(const TString& moreContent)
- {
- Content.prepend(moreContent);
- BuildResponse();
- }
-
+ {
+ Content.prepend(moreContent);
+ BuildResponse();
+ }
+
virtual const char* what() const noexcept { return HttpResponse.data(); }
operator bool() const { return !Content.empty(); }
-};
-
-enum EStyleFlags {
- // bit 1
- Link = 0x0,
- Button = 0x1,
-
- // bit 2
- NonErasable = 0x0,
- Erasable = 0x2,
-
- // bit 3-4
- Medium = 0x0,
- Large = 0x4,
- Small = 0x8,
- ExtraSmall = 0xC,
- SizeMask = 0xC,
-
- // bit 5
- NoCaret = 0x0,
- Caret = 0x10,
-
- // bit 6
- SimpleValue = 0x0,
- CompositeValue = 0x20
-};
-
-template <ui64 flags>
+};
+
+enum EStyleFlags {
+ // bit 1
+ Link = 0x0,
+ Button = 0x1,
+
+ // bit 2
+ NonErasable = 0x0,
+ Erasable = 0x2,
+
+ // bit 3-4
+ Medium = 0x0,
+ Large = 0x4,
+ Small = 0x8,
+ ExtraSmall = 0xC,
+ SizeMask = 0xC,
+
+ // bit 5
+ NoCaret = 0x0,
+ Caret = 0x10,
+
+ // bit 6
+ SimpleValue = 0x0,
+ CompositeValue = 0x20
+};
+
+template <ui64 flags>
TString BtnClass() {
- if ((flags & SizeMask) == Large) {
- return "btn btn-lg";
- } else if ((flags & SizeMask) == Small) {
- return "btn btn-sm";
- } else if ((flags & SizeMask) == ExtraSmall) {
- return "btn btn-xs";
- }
- return "btn";
-}
-
+ if ((flags & SizeMask) == Large) {
+ return "btn btn-lg";
+ } else if ((flags & SizeMask) == Small) {
+ return "btn btn-sm";
+ } else if ((flags & SizeMask) == ExtraSmall) {
+ return "btn btn-xs";
+ }
+ return "btn";
+}
+
void SelectorTitle(IOutputStream& os, const TString& text)
-{
- if (!text.empty()) {
- os << text;
- }
-}
-
-template <ui64 flags>
+{
+ if (!text.empty()) {
+ os << text;
+ }
+}
+
+template <ui64 flags>
void BtnHref(IOutputStream& os, const TString& text, const TString& href, bool push = false)
-{
- if (flags & Button) {
- os << "<button type=\"button\" style=\"display: inline-block;margin:3px\" class=\""
- << BtnClass<flags>() << " "
- << (push? "btn-primary": "btn-default")
- << "\" onClick=\"window.location.href='" << href << "';\">"
- << text
- << "</button>";
- } else {
- os << "<a href=\"" << href << "\">"
- << text
- << "</a>";
- }
-}
-
+{
+ if (flags & Button) {
+ os << "<button type=\"button\" style=\"display: inline-block;margin:3px\" class=\""
+ << BtnClass<flags>() << " "
+ << (push? "btn-primary": "btn-default")
+ << "\" onClick=\"window.location.href='" << href << "';\">"
+ << text
+ << "</button>";
+ } else {
+ os << "<a href=\"" << href << "\">"
+ << text
+ << "</a>";
+ }
+}
+
void DropdownBeginSublist(IOutputStream& os, const TString& text)
-{
- os << "<li>" << text << "<ul class=\"dropdown-menu\">";
-}
-
+{
+ os << "<li>" << text << "<ul class=\"dropdown-menu\">";
+}
+
void DropdownEndSublist(IOutputStream& os)
-{
- os << "</ul></li>";
-}
-
+{
+ os << "</ul></li>";
+}
+
void DropdownItem(IOutputStream& os, const TString& text, const TString& href, bool separated = false)
-{
- if (separated) {
- os << "<li role=\"separator\" class=\"divider\"></li>";
- }
- os << "<li><a href=\"" << href << "\">" << text << "</a></li>";
-}
-
+{
+ if (separated) {
+ os << "<li role=\"separator\" class=\"divider\"></li>";
+ }
+ os << "<li><a href=\"" << href << "\">" << text << "</a></li>";
+}
+
TString SuggestSelection()
-{
- return "--- ";
-}
-
+{
+ return "--- ";
+}
+
TString RemoveSelection()
-{
- return "Remove";
-}
-
+{
+ return "Remove";
+}
+
TString GetDescription(const TString& value, const TVariants& variants)
-{
- for (const auto& var : variants) {
- if (value == var.first) {
- return var.second;
- }
- }
- if (!value) {
- return SuggestSelection();
- }
- return value;
-}
-
-template <ui64 flags, bool sub = false>
+{
+ for (const auto& var : variants) {
+ if (value == var.first) {
+ return var.second;
+ }
+ }
+ if (!value) {
+ return SuggestSelection();
+ }
+ return value;
+}
+
+template <ui64 flags, bool sub = false>
void DropdownSelector(IOutputStream& os, const TCgiParameters& e, const TString& param, const TString& value,
const TString& text, const TVariants& variants, const TString& realValue = TString())
-{
- HTML(os) {
- SelectorTitle(os, text);
- os << "<div class=\"dropdown\" style=\"display:inline-block;margin:3px\">";
- if (flags & Button) {
- os << "<button class=\"" << BtnClass<flags>() << " btn-primary dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">";
- } else {
- os << "<a href=\"#\" data-toggle=\"dropdown\">";
- }
- os << GetDescription(flags & CompositeValue? realValue: value, variants);
- if (flags & Caret) {
- os << "<span class=\"caret\"></span>";
- }
- if (flags & Button) {
- os <<"</button>";
- } else {
- os <<"</a>";
- }
- UL_CLASS ("dropdown-menu") {
- for (const auto& var : variants) {
- DropdownItem(os, var.second, UrlReplace<sub>(e, param, value, var.first));
- }
- if (flags & Erasable) {
- DropdownItem(os, RemoveSelection(), UrlErase<sub>(e, param, value), true);
- }
- }
- os << "</div>";
- }
-}
-
+{
+ HTML(os) {
+ SelectorTitle(os, text);
+ os << "<div class=\"dropdown\" style=\"display:inline-block;margin:3px\">";
+ if (flags & Button) {
+ os << "<button class=\"" << BtnClass<flags>() << " btn-primary dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">";
+ } else {
+ os << "<a href=\"#\" data-toggle=\"dropdown\">";
+ }
+ os << GetDescription(flags & CompositeValue? realValue: value, variants);
+ if (flags & Caret) {
+ os << "<span class=\"caret\"></span>";
+ }
+ if (flags & Button) {
+ os <<"</button>";
+ } else {
+ os <<"</a>";
+ }
+ UL_CLASS ("dropdown-menu") {
+ for (const auto& var : variants) {
+ DropdownItem(os, var.second, UrlReplace<sub>(e, param, value, var.first));
+ }
+ if (flags & Erasable) {
+ DropdownItem(os, RemoveSelection(), UrlErase<sub>(e, param, value), true);
+ }
+ }
+ os << "</div>";
+ }
+}
+
void RequireSelection(TStringStream& ss, const TCgiParameters& e, const TString& param,
const TString& text, const TVariants& variants)
-{
+{
const TString& value = e.Get(param);
- DropdownSelector<Link>(ss, e, param, value, text, variants);
- if (!value) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- }
-}
-
+ DropdownSelector<Link>(ss, e, param, value, text, variants);
+ if (!value) {
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ }
+}
+
void RequireMultipleSelection(TStringStream& ss, const TCgiParameters& e, const TString& param,
const TString& text, const TVariants& variants)
-{
- SelectorTitle(ss, text);
+{
+ SelectorTitle(ss, text);
TSet<TString> selectedValues;
for (const TString& subvalue : Subvalues(e, param)) {
- selectedValues.insert(subvalue);
- }
+ selectedValues.insert(subvalue);
+ }
for (const TString& subvalue : Subvalues(e, param)) {
- DropdownSelector<Erasable, true>(ss, e, param, subvalue, "", variants);
- }
+ DropdownSelector<Erasable, true>(ss, e, param, subvalue, "", variants);
+ }
if (selectedValues.contains("")) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- } else {
- BtnHref<Button|ExtraSmall>(ss, "+", MakeUrlAddSub(e, param, ""));
- if (selectedValues.empty()) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- }
- }
-}
-
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ } else {
+ BtnHref<Button|ExtraSmall>(ss, "+", MakeUrlAddSub(e, param, ""));
+ if (selectedValues.empty()) {
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ }
+ }
+}
+
void OptionalSelection(TStringStream& ss, const TCgiParameters& e, const TString& param,
const TString& text, const TVariants& variants)
{
@@ -1424,251 +1424,251 @@ void OptionalSelection(TStringStream& ss, const TCgiParameters& e, const TString
void OptionalMultipleSelection(TStringStream& ss, const TCgiParameters& e, const TString& param,
const TString& text, const TVariants& variants)
-{
+{
TSet<TString> selectedValues;
for (const TString& subvalue : Subvalues(e, param)) {
- selectedValues.insert(subvalue);
- }
- if (!selectedValues.empty()) {
- SelectorTitle(ss, text);
- }
+ selectedValues.insert(subvalue);
+ }
+ if (!selectedValues.empty()) {
+ SelectorTitle(ss, text);
+ }
for (const TString& subvalue : Subvalues(e, param)) {
- DropdownSelector<Erasable, true>(ss, e, param, subvalue, "", variants);
- }
+ DropdownSelector<Erasable, true>(ss, e, param, subvalue, "", variants);
+ }
if (selectedValues.contains("")) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- } else {
- BtnHref<Button|ExtraSmall>(ss, selectedValues.empty()? text: "+", MakeUrlAddSub(e, param, ""));
- }
-}
-
-TVariants ListColumns(const NAnalytics::TTable& table)
-{
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ } else {
+ BtnHref<Button|ExtraSmall>(ss, selectedValues.empty()? text: "+", MakeUrlAddSub(e, param, ""));
+ }
+}
+
+TVariants ListColumns(const NAnalytics::TTable& table)
+{
TSet<TString> cols;
-// bool addSpecialCols = false;
-// if (addSpecialCols) {
-// cols.insert("_count");
-// }
- for (auto& row : table) {
- for (auto& kv : row) {
- cols.insert(kv.first);
- }
- }
- TVariants result;
- for (const auto& s : cols) {
- result.emplace_back(s, s);
- }
- return result;
-}
-
+// bool addSpecialCols = false;
+// if (addSpecialCols) {
+// cols.insert("_count");
+// }
+ for (auto& row : table) {
+ for (auto& kv : row) {
+ cols.insert(kv.first);
+ }
+ }
+ TVariants result;
+ for (const auto& s : cols) {
+ result.emplace_back(s, s);
+ }
+ return result;
+}
+
TString TaggedValue(const TString& value, const TString& tag)
-{
- if (!tag) {
- return value;
- }
- return value + "-" + tag;
-}
-
+{
+ if (!tag) {
+ return value;
+ }
+ return value + "-" + tag;
+}
+
TVariants ValueVars(const TVariants& values, const TString& tag)
-{
- TVariants ret;
- for (auto& p : values) {
- ret.emplace_back(TaggedValue(p.first, tag), p.second);
- }
- return ret;
-}
-
+{
+ TVariants ret;
+ for (auto& p : values) {
+ ret.emplace_back(TaggedValue(p.first, tag), p.second);
+ }
+ return ret;
+}
+
TVariants TagVars(const TString& value, const TVariants& tags)
-{
- TVariants ret;
- for (auto& p : tags) {
- ret.emplace_back(TaggedValue(value, p.first), p.second);
- }
- return ret;
-}
-
-TVariants SeriesTags()
-{
- TVariants ret; // MSVS2013 doesn't understand complex initializer lists
- ret.emplace_back("", "as is");
- ret.emplace_back("stack", "cumulative");
- return ret;
-}
-
-void SeriesSelectors(TStringStream& ss, const TCgiParameters& e,
+{
+ TVariants ret;
+ for (auto& p : tags) {
+ ret.emplace_back(TaggedValue(value, p.first), p.second);
+ }
+ return ret;
+}
+
+TVariants SeriesTags()
+{
+ TVariants ret; // MSVS2013 doesn't understand complex initializer lists
+ ret.emplace_back("", "as is");
+ ret.emplace_back("stack", "cumulative");
+ return ret;
+}
+
+void SeriesSelectors(TStringStream& ss, const TCgiParameters& e,
const TString& xparam, const TString& yparam, const NAnalytics::TTable& data)
-{
- TTags xtags;
+{
+ TTags xtags;
TString xn = ParseTagsOut(e.Get(xparam), xtags);
- DropdownSelector<Erasable, true>(ss, e, xparam, e.Get(xparam), "with Ox:",
- ValueVars(ListColumns(data), JoinTags(xtags)));
- if (xn) {
- DropdownSelector<Link, true>(ss, e, xparam, e.Get(xparam), "",
- TagVars(xn, SeriesTags()));
- }
-
+ DropdownSelector<Erasable, true>(ss, e, xparam, e.Get(xparam), "with Ox:",
+ ValueVars(ListColumns(data), JoinTags(xtags)));
+ if (xn) {
+ DropdownSelector<Link, true>(ss, e, xparam, e.Get(xparam), "",
+ TagVars(xn, SeriesTags()));
+ }
+
TString yns = e.Get(yparam);
- SelectorTitle(ss, "and Oy:");
- bool first = true;
- bool hasEmpty = false;
- for (auto& subvalue : Subvalues(e, yparam)) {
- TTags ytags;
+ SelectorTitle(ss, "and Oy:");
+ bool first = true;
+ bool hasEmpty = false;
+ for (auto& subvalue : Subvalues(e, yparam)) {
+ TTags ytags;
TString yn = ParseTagsOut(subvalue, ytags);
- DropdownSelector<Erasable, true>(ss, e, yparam, subvalue, first? "": ", ",
- ValueVars(ListColumns(data), JoinTags(ytags)));
- if (yn) {
- DropdownSelector<Link, true>(ss, e, yparam, subvalue, "",
- TagVars(yn, SeriesTags()));
- }
- first = false;
- if (yn.empty()) {
- hasEmpty = true;
- }
- }
-
- if (hasEmpty) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- } else {
- BtnHref<Button|ExtraSmall>(ss, "+", MakeUrlAddSub(e, yparam, ""));
- }
-
- if (!xn || !yns) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- }
-}
-
+ DropdownSelector<Erasable, true>(ss, e, yparam, subvalue, first? "": ", ",
+ ValueVars(ListColumns(data), JoinTags(ytags)));
+ if (yn) {
+ DropdownSelector<Link, true>(ss, e, yparam, subvalue, "",
+ TagVars(yn, SeriesTags()));
+ }
+ first = false;
+ if (yn.empty()) {
+ hasEmpty = true;
+ }
+ }
+
+ if (hasEmpty) {
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ } else {
+ BtnHref<Button|ExtraSmall>(ss, "+", MakeUrlAddSub(e, yparam, ""));
+ }
+
+ if (!xn || !yns) {
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ }
+}
+
class TProbesHtmlPrinter {
private:
TVector<TVector<TString>> TableData;
- static constexpr int TimeoutSec = 15 * 60; // default timeout
+ static constexpr int TimeoutSec = 15 * 60; // default timeout
public:
void Push(const NLWTrace::TProbe* probe)
{
TableData.emplace_back();
- auto& row = TableData.back();
-
+ auto& row = TableData.back();
+
row.emplace_back();
TString& groups = row.back();
bool first = true;
for (const char* const* i = probe->Event.Groups; *i != nullptr; ++i, first = false) {
groups.append(TString(first? "": ", ") + GroupHtml(*i));
}
-
- row.push_back(ProbeHtml(probe->Event.GetProvider(), probe->Event.Name));
-
+
+ row.push_back(ProbeHtml(probe->Event.GetProvider(), probe->Event.Name));
+
row.emplace_back();
TString& params = row.back();
first = true;
for (size_t i = 0; i < probe->Event.Signature.ParamCount; i++, first = false) {
params.append(TString(first? "": ", ") + probe->Event.Signature.ParamTypes[i]
- + " " + probe->Event.Signature.ParamNames[i]);
+ + " " + probe->Event.Signature.ParamNames[i]);
}
-
- row.emplace_back(ToString(probe->GetExecutorsCount()));
+
+ row.emplace_back(ToString(probe->GetExecutorsCount()));
}
-
+
void Output(IOutputStream& os)
- {
- HTML(os) {
- TABLE() {
- TABLEHEAD() {
- TABLEH() { os << "Groups"; }
- TABLEH() { os << "Name"; }
- TABLEH() { os << "Params"; }
- TABLEH() { os << "ExecCount"; }
- }
- TABLEBODY() {
- for (auto& row : TableData) {
- TABLER() {
+ {
+ HTML(os) {
+ TABLE() {
+ TABLEHEAD() {
+ TABLEH() { os << "Groups"; }
+ TABLEH() { os << "Name"; }
+ TABLEH() { os << "Params"; }
+ TABLEH() { os << "ExecCount"; }
+ }
+ TABLEBODY() {
+ for (auto& row : TableData) {
+ TABLER() {
for (TString& cell : row) {
- TABLED() { os << cell; }
- }
- }
- }
- }
- }
- }
- }
-private:
+ TABLED() { os << cell; }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+private:
TString GroupHtml(const TString& group)
- {
- TStringStream ss;
- ss << "<div class=\"dropdown\" style=\"display:inline-block\">"
- "<a href=\"#\" data-toggle=\"dropdown\">" << group << "</a>"
- "<ul class=\"dropdown-menu\">"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(group).Id() << "'});\">"
- "Trace 1000 items</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(group, 10000).Id() << "'});\">"
- "Trace 10000 items</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(group, 0, 1000000).Id() << "'});\">"
- "Trace 1 second</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(group, 0, 10000000).Id() << "'});\">"
- "Trace 10 seconds</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(group, 0, 0, true).Id() << "'});\">"
- "Trace 1000 tracks</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(group, 10000, 0, true).Id() << "'});\">"
- "Trace 10000 tracks</a></li>"
- "</ul>"
- "</div>";
- return ss.Str();
- }
-
+ {
+ TStringStream ss;
+ ss << "<div class=\"dropdown\" style=\"display:inline-block\">"
+ "<a href=\"#\" data-toggle=\"dropdown\">" << group << "</a>"
+ "<ul class=\"dropdown-menu\">"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(group).Id() << "'});\">"
+ "Trace 1000 items</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(group, 10000).Id() << "'});\">"
+ "Trace 10000 items</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(group, 0, 1000000).Id() << "'});\">"
+ "Trace 1 second</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(group, 0, 10000000).Id() << "'});\">"
+ "Trace 10 seconds</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(group, 0, 0, true).Id() << "'});\">"
+ "Trace 1000 tracks</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(group, 10000, 0, true).Id() << "'});\">"
+ "Trace 10000 tracks</a></li>"
+ "</ul>"
+ "</div>";
+ return ss.Str();
+ }
+
TString ProbeHtml(const TString& provider, const TString& probe)
- {
- TStringStream ss;
- ss << "<div class=\"dropdown\">"
- "<a href=\"#\" data-toggle=\"dropdown\">" << probe << "</a>"
- "<ul class=\"dropdown-menu\">"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(provider, probe).Id() << "'});\">"
- "Trace 1000 items</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(provider, probe, 10000).Id() << "'});\">"
- "Trace 10000 items</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(provider, probe, 0, 1000000).Id() << "'});\">"
- "Trace 1 second</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(provider, probe, 0, 10000000).Id() << "'});\">"
- "Trace 10 seconds</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(provider, probe, 0, 0, true).Id() << "'});\">"
- "Trace 1000 tracks</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
- "{id:'" << TAdHocTraceConfig(provider, probe, 10000, 0, true).Id() << "'});\">"
- "Trace 10000 tracks</a></li>"
- "</ul>"
- "</div>";
- return ss.Str();
- }
+ {
+ TStringStream ss;
+ ss << "<div class=\"dropdown\">"
+ "<a href=\"#\" data-toggle=\"dropdown\">" << probe << "</a>"
+ "<ul class=\"dropdown-menu\">"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(provider, probe).Id() << "'});\">"
+ "Trace 1000 items</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(provider, probe, 10000).Id() << "'});\">"
+ "Trace 10000 items</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(provider, probe, 0, 1000000).Id() << "'});\">"
+ "Trace 1 second</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(provider, probe, 0, 10000000).Id() << "'});\">"
+ "Trace 10 seconds</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(provider, probe, 0, 0, true).Id() << "'});\">"
+ "Trace 1000 tracks</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=new&ui=y&timeout=" << TimeoutSec << "',"
+ "{id:'" << TAdHocTraceConfig(provider, probe, 10000, 0, true).Id() << "'});\">"
+ "Trace 10000 tracks</a></li>"
+ "</ul>"
+ "</div>";
+ return ss.Str();
+ }
};
-void TDashboardRegistry::Register(const NLWTrace::TDashboard& dashboard) {
+void TDashboardRegistry::Register(const NLWTrace::TDashboard& dashboard) {
TGuard<TMutex> g(Mutex);
Dashboards[dashboard.GetName()] = dashboard;
}
-void TDashboardRegistry::Register(const TVector<NLWTrace::TDashboard>& dashboards) {
- for (const auto& dashboard : dashboards) {
- Register(dashboard);
- }
-}
-
+void TDashboardRegistry::Register(const TVector<NLWTrace::TDashboard>& dashboards) {
+ for (const auto& dashboard : dashboards) {
+ Register(dashboard);
+ }
+}
+
void TDashboardRegistry::Register(const TString& dashText) {
- NLWTrace::TDashboard dash;
+ NLWTrace::TDashboard dash;
if (!google::protobuf::TextFormat::ParseFromString(dashText, &dash)) {
ythrow yexception() << "Couldn't parse into dashboard";
}
Register(dash);
}
-bool TDashboardRegistry::Get(const TString& name, NLWTrace::TDashboard& dash) {
+bool TDashboardRegistry::Get(const TString& name, NLWTrace::TDashboard& dash) {
TGuard<TMutex> g(Mutex);
if (!Dashboards.contains(name)) {
return false;
@@ -1698,488 +1698,488 @@ void TDashboardRegistry::Output(TStringStream& ss) {
}
}
-class ILogSource {
-public:
- virtual ~ILogSource() {}
+class ILogSource {
+public:
+ virtual ~ILogSource() {}
virtual TString GetId() = 0;
- virtual TInstant GetStartTime() = 0;
- virtual TDuration GetTimeout(TInstant now) = 0;
- virtual ui64 GetEventsCount() = 0;
- virtual ui64 GetThreadsCount() = 0;
-};
-
-class TTraceLogSource : public ILogSource {
-private:
+ virtual TInstant GetStartTime() = 0;
+ virtual TDuration GetTimeout(TInstant now) = 0;
+ virtual ui64 GetEventsCount() = 0;
+ virtual ui64 GetThreadsCount() = 0;
+};
+
+class TTraceLogSource : public ILogSource {
+private:
TString Id;
- const TTraceCleaner& Cleaner;
- const NLWTrace::TSession* Trace;
-public:
- TTraceLogSource(const TString& id, const NLWTrace::TSession* trace, const TTraceCleaner& cleaner)
- : Id(id)
- , Cleaner(cleaner)
- , Trace(trace)
- {}
-
+ const TTraceCleaner& Cleaner;
+ const NLWTrace::TSession* Trace;
+public:
+ TTraceLogSource(const TString& id, const NLWTrace::TSession* trace, const TTraceCleaner& cleaner)
+ : Id(id)
+ , Cleaner(cleaner)
+ , Trace(trace)
+ {}
+
TString GetId() override
- {
- return Id;
- }
-
- TInstant GetStartTime() override
- {
- return Trace->GetStartTime();
- }
-
- TDuration GetTimeout(TInstant now) override
- {
- TInstant deadline = Cleaner.GetDeadline(Id);
- if (deadline < now) {
- return TDuration::Zero();
- } else if (deadline == TInstant::Max()) {
- return TDuration::Max();
- } else {
- return deadline - now;
- }
- }
-
- ui64 GetEventsCount() override
- {
- return Trace->GetEventsCount();
- }
-
- ui64 GetThreadsCount() override
- {
- return Trace->GetThreadsCount();
- }
-};
-
-class TSnapshotLogSource : public ILogSource {
-private:
+ {
+ return Id;
+ }
+
+ TInstant GetStartTime() override
+ {
+ return Trace->GetStartTime();
+ }
+
+ TDuration GetTimeout(TInstant now) override
+ {
+ TInstant deadline = Cleaner.GetDeadline(Id);
+ if (deadline < now) {
+ return TDuration::Zero();
+ } else if (deadline == TInstant::Max()) {
+ return TDuration::Max();
+ } else {
+ return deadline - now;
+ }
+ }
+
+ ui64 GetEventsCount() override
+ {
+ return Trace->GetEventsCount();
+ }
+
+ ui64 GetThreadsCount() override
+ {
+ return Trace->GetThreadsCount();
+ }
+};
+
+class TSnapshotLogSource : public ILogSource {
+private:
TString Sid;
- // Log should be used for read-only purpose, because it can be accessed from multiple threads
- // Atomic pointer is used to avoid thread-safety issues with snapshot deletion
- // (I hope protobuf const-implementation doesn't use any mutable non-thread-safe stuff inside)
- TAtomicSharedPtr<NLWTrace::TLogPb> Log;
-public:
- // Constructor should be called under SnapshotsMtx lock
+ // Log should be used for read-only purpose, because it can be accessed from multiple threads
+ // Atomic pointer is used to avoid thread-safety issues with snapshot deletion
+ // (I hope protobuf const-implementation doesn't use any mutable non-thread-safe stuff inside)
+ TAtomicSharedPtr<NLWTrace::TLogPb> Log;
+public:
+ // Constructor should be called under SnapshotsMtx lock
TSnapshotLogSource(const TString& sid, const TAtomicSharedPtr<NLWTrace::TLogPb>& log)
- : Sid(sid)
- , Log(log)
- {}
-
+ : Sid(sid)
+ , Log(log)
+ {}
+
TString GetId() override
- {
- return Sid + "~";
- }
-
- TInstant GetStartTime() override
- {
- return TInstant::MicroSeconds(Log->GetCrtTime());
- }
-
- TDuration GetTimeout(TInstant now) override
- {
- Y_UNUSED(now);
- return TDuration::Max();
- }
-
- ui64 GetEventsCount() override
- {
- return Log->GetEventsCount();
- }
-
- ui64 GetThreadsCount() override
- {
- return Log->ThreadLogsSize();
- }
-};
-
-class TLogSources {
-private:
- TTraceCleaner& Cleaner;
- TInstant Now;
+ {
+ return Sid + "~";
+ }
+
+ TInstant GetStartTime() override
+ {
+ return TInstant::MicroSeconds(Log->GetCrtTime());
+ }
+
+ TDuration GetTimeout(TInstant now) override
+ {
+ Y_UNUSED(now);
+ return TDuration::Max();
+ }
+
+ ui64 GetEventsCount() override
+ {
+ return Log->GetEventsCount();
+ }
+
+ ui64 GetThreadsCount() override
+ {
+ return Log->ThreadLogsSize();
+ }
+};
+
+class TLogSources {
+private:
+ TTraceCleaner& Cleaner;
+ TInstant Now;
using TLogSourcePtr = std::unique_ptr<ILogSource>;
TMap<TString, TLogSourcePtr> LogSources;
-public:
- explicit TLogSources(TTraceCleaner& cleaner, TInstant now = TInstant::Now())
- : Cleaner(cleaner)
- , Now(now)
- {}
-
+public:
+ explicit TLogSources(TTraceCleaner& cleaner, TInstant now = TInstant::Now())
+ : Cleaner(cleaner)
+ , Now(now)
+ {}
+
void Push(const TString& sid, const TAtomicSharedPtr<NLWTrace::TLogPb>& log)
- {
- TLogSourcePtr ls(new TSnapshotLogSource(sid, log));
+ {
+ TLogSourcePtr ls(new TSnapshotLogSource(sid, log));
LogSources.emplace(ls->GetId(), std::move(ls));
- }
-
- void Push(const TString& id, const NLWTrace::TSession* trace)
- {
- TLogSourcePtr ls(new TTraceLogSource(id, trace, Cleaner));
+ }
+
+ void Push(const TString& id, const NLWTrace::TSession* trace)
+ {
+ TLogSourcePtr ls(new TTraceLogSource(id, trace, Cleaner));
LogSources.emplace(ls->GetId(), std::move(ls));
- }
-
- template <class TFunc>
- void ForEach(TFunc& func)
- {
- for (auto& kv : LogSources) {
+ }
+
+ template <class TFunc>
+ void ForEach(TFunc& func)
+ {
+ for (auto& kv : LogSources) {
func.Push(kv.second.get());
- }
- }
-
- template <class TFunc>
- void ForEach(TFunc& func) const
- {
- for (const auto& kv : LogSources) {
+ }
+ }
+
+ template <class TFunc>
+ void ForEach(TFunc& func) const
+ {
+ for (const auto& kv : LogSources) {
func.Push(kv.second.get());
- }
- }
-};
-
+ }
+ }
+};
+
class TTracesHtmlPrinter {
private:
IOutputStream& Os;
- TInstant Now;
+ TInstant Now;
public:
explicit TTracesHtmlPrinter(IOutputStream& os)
: Os(os)
- , Now(TInstant::Now())
+ , Now(TInstant::Now())
{}
- void Push(ILogSource* src)
+ void Push(ILogSource* src)
{
TString id = src->GetId();
Os << "<tr>";
Os << "<td>";
try {
- Os << src->GetStartTime().ToStringUpToSeconds();
+ Os << src->GetStartTime().ToStringUpToSeconds();
} catch (...) {
Os << "error: " << CurrentExceptionMessage();
}
Os << "</td>"
- << "<td><div class=\"dropdown\">"
- "<a href=\"#\" data-toggle=\"dropdown\">" << TimeoutToString(src->GetTimeout(Now)) << "</a>"
- "<ul class=\"dropdown-menu\">"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=60', {id:'" << id << "'});\">1 min</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=600', {id:'" << id << "'});\">10 min</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=3600', {id:'" << id << "'});\">1 hour</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=86400', {id:'" << id << "'});\">1 day</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=604800', {id:'" << id << "'});\">1 week</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y', {id:'" << id << "'});\">no timeout</a></li>"
- "</ul>"
- "</div></td>"
+ << "<td><div class=\"dropdown\">"
+ "<a href=\"#\" data-toggle=\"dropdown\">" << TimeoutToString(src->GetTimeout(Now)) << "</a>"
+ "<ul class=\"dropdown-menu\">"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=60', {id:'" << id << "'});\">1 min</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=600', {id:'" << id << "'});\">10 min</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=3600', {id:'" << id << "'});\">1 hour</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=86400', {id:'" << id << "'});\">1 day</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y&timeout=604800', {id:'" << id << "'});\">1 week</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=settimeout&ui=y', {id:'" << id << "'});\">no timeout</a></li>"
+ "</ul>"
+ "</div></td>"
<< "<td>" << EncodeHtmlPcdata(id) << "</td>"
- << "<td>" << src->GetEventsCount() << "</td>"
- << "<td>" << src->GetThreadsCount() << "</td>"
+ << "<td>" << src->GetEventsCount() << "</td>"
+ << "<td>" << src->GetThreadsCount() << "</td>"
<< "<td><a href=\"?mode=log&id=" << id << "\">Text</a></td>"
<< "<td><a href=\"?mode=log&format=json&id=" << id << "\">Json</a></td>"
<< "<td><a href=\"?mode=query&id=" << id << "\">Query</a></td>"
- << "<td><a href=\"?mode=analytics&id=" << id << "\">Analytics</a></td>"
- << "<td><div class=\"dropdown navbar-right\">" // navbar-right is hack to drop left
- "<a href=\"#\" data-toggle=\"dropdown\">Modify</a>"
- "<ul class=\"dropdown-menu\">"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=make_snapshot&ui=y', {id:'" << id << "'});\">Snapshot</a></li>"
- "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=delete&ui=y', {id:'" << id << "'});\">Delete</a></li>"
- "</ul>"
- "</div></td>"
+ << "<td><a href=\"?mode=analytics&id=" << id << "\">Analytics</a></td>"
+ << "<td><div class=\"dropdown navbar-right\">" // navbar-right is hack to drop left
+ "<a href=\"#\" data-toggle=\"dropdown\">Modify</a>"
+ "<ul class=\"dropdown-menu\">"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=make_snapshot&ui=y', {id:'" << id << "'});\">Snapshot</a></li>"
+ "<li><a href=\"#\" onClick=\"$.redirectPost('?mode=delete&ui=y', {id:'" << id << "'});\">Delete</a></li>"
+ "</ul>"
+ "</div></td>"
<< "</tr>\n";
}
-private:
+private:
static TString TimeoutToString(TDuration d)
- {
- TStringStream ss;
- if (d == TDuration::Zero()) {
- ss << "0";
- } else if (d == TDuration::Max()) {
- ss << "-";
- } else {
- ui64 us = d.GetValue();
- ui64 ms = us / 1000;
- ui64 sec = ms / 1000;
- ui64 min = sec / 60;
- ui64 hours = min / 60;
- ui64 days = hours / 24;
- ui64 weeks = days / 7;
- us -= ms * 1000;
- ms -= sec * 1000;
- sec -= min * 60;
- min -= hours * 60;
- hours -= days * 24;
- days -= weeks * 7;
- int terms = 0;
- if ((terms > 0 && terms < 2) || ( terms == 0 && weeks)) { ss << (ss.Str()? " ": "") << weeks << "w"; terms++; }
- if ((terms > 0 && terms < 2) || ( terms == 0 && days)) { ss << (ss.Str()? " ": "") << days << "d"; terms++; }
- if ((terms > 0 && terms < 2) || ( terms == 0 && hours)) { ss << (ss.Str()? " ": "") << hours << "h"; terms++; }
- if ((terms > 0 && terms < 2) || ( terms == 0 && min)) { ss << (ss.Str()? " ": "") << min << "m"; terms++; }
- if ((terms > 0 && terms < 2) || ( terms == 0 && sec)) { ss << (ss.Str()? " ": "") << sec << "s"; terms++; }
- if ((terms > 0 && terms < 2) || ( terms == 0 && ms)) { ss << (ss.Str()? " ": "") << ms << "ms"; terms++; }
- if ((terms > 0 && terms < 2) || ( terms == 0 && us)) { ss << (ss.Str()? " ": "") << us << "us"; terms++; }
- }
- return ss.Str();
- }
+ {
+ TStringStream ss;
+ if (d == TDuration::Zero()) {
+ ss << "0";
+ } else if (d == TDuration::Max()) {
+ ss << "-";
+ } else {
+ ui64 us = d.GetValue();
+ ui64 ms = us / 1000;
+ ui64 sec = ms / 1000;
+ ui64 min = sec / 60;
+ ui64 hours = min / 60;
+ ui64 days = hours / 24;
+ ui64 weeks = days / 7;
+ us -= ms * 1000;
+ ms -= sec * 1000;
+ sec -= min * 60;
+ min -= hours * 60;
+ hours -= days * 24;
+ days -= weeks * 7;
+ int terms = 0;
+ if ((terms > 0 && terms < 2) || ( terms == 0 && weeks)) { ss << (ss.Str()? " ": "") << weeks << "w"; terms++; }
+ if ((terms > 0 && terms < 2) || ( terms == 0 && days)) { ss << (ss.Str()? " ": "") << days << "d"; terms++; }
+ if ((terms > 0 && terms < 2) || ( terms == 0 && hours)) { ss << (ss.Str()? " ": "") << hours << "h"; terms++; }
+ if ((terms > 0 && terms < 2) || ( terms == 0 && min)) { ss << (ss.Str()? " ": "") << min << "m"; terms++; }
+ if ((terms > 0 && terms < 2) || ( terms == 0 && sec)) { ss << (ss.Str()? " ": "") << sec << "s"; terms++; }
+ if ((terms > 0 && terms < 2) || ( terms == 0 && ms)) { ss << (ss.Str()? " ": "") << ms << "ms"; terms++; }
+ if ((terms > 0 && terms < 2) || ( terms == 0 && us)) { ss << (ss.Str()? " ": "") << us << "us"; terms++; }
+ }
+ return ss.Str();
+ }
};
-class TTracesLister {
-private:
- TVariants& Variants;
-public:
- TTracesLister(TVariants& variants)
- : Variants(variants)
- {}
- void Push(ILogSource* src)
- {
- Variants.emplace_back(src->GetId(), src->GetId());
- }
-};
-
-TVariants ListTraces(const TLogSources& srcs)
-{
- TVariants variants;
- TTracesLister lister(variants);
- srcs.ForEach(lister);
- return variants;
-}
-
-class TTimestampCutter {
-private:
+class TTracesLister {
+private:
+ TVariants& Variants;
+public:
+ TTracesLister(TVariants& variants)
+ : Variants(variants)
+ {}
+ void Push(ILogSource* src)
+ {
+ Variants.emplace_back(src->GetId(), src->GetId());
+ }
+};
+
+TVariants ListTraces(const TLogSources& srcs)
+{
+ TVariants variants;
+ TTracesLister lister(variants);
+ srcs.ForEach(lister);
+ return variants;
+}
+
+class TTimestampCutter {
+private:
THashMap<TThread::TId, std::pair<ui64, TInstant>> CutTsForThread; // tid -> time of first item
- mutable ui64 CutTsMax = 0;
- mutable TInstant CutInstantMax;
- bool Enabled;
- ui64 NowTs;
-public:
- explicit TTimestampCutter(bool enabled)
- : Enabled(enabled)
- , NowTs(GetCycleCount())
- {}
-
- void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- auto it = CutTsForThread.find(tid);
- if (it != CutTsForThread.end()) {
- ui64& ts = it->second.first;
- TInstant& inst = it->second.second;
- ts = Min(ts, item.TimestampCycles);
- inst = Min(inst, item.Timestamp);
- } else {
- CutTsForThread[tid] = std::make_pair(item.TimestampCycles, item.Timestamp);
- }
- }
-
- // Timestamp from which we are ensured that cyclic log for every thread is not truncated
- // NOTE: should NOT be called from Push(tid, item) functions
- ui64 StartTimestamp() const
- {
- if (CutTsMax == 0) {
- FindStartTime();
- }
- return CutTsMax;
- }
-
- ui64 NowTimestamp() const
- {
- return NowTs;
- }
-
- TInstant StartInstant() const
- {
- if (CutInstantMax == TInstant::Zero()) {
- FindStartTime();
- }
- return CutInstantMax;
- }
-
- // Returns true iff item should be skipped to avoid surprizes
- bool Skip(const NLWTrace::TLogItem& item) const
- {
- return Enabled && item.TimestampCycles < StartTimestamp();
- }
-
-private:
- void FindStartTime() const
- {
- for (auto& kv : CutTsForThread) {
- CutTsMax = Max(CutTsMax, kv.second.first);
- CutInstantMax = Max(CutInstantMax, kv.second.second);
- }
- }
-};
-
+ mutable ui64 CutTsMax = 0;
+ mutable TInstant CutInstantMax;
+ bool Enabled;
+ ui64 NowTs;
+public:
+ explicit TTimestampCutter(bool enabled)
+ : Enabled(enabled)
+ , NowTs(GetCycleCount())
+ {}
+
+ void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ auto it = CutTsForThread.find(tid);
+ if (it != CutTsForThread.end()) {
+ ui64& ts = it->second.first;
+ TInstant& inst = it->second.second;
+ ts = Min(ts, item.TimestampCycles);
+ inst = Min(inst, item.Timestamp);
+ } else {
+ CutTsForThread[tid] = std::make_pair(item.TimestampCycles, item.Timestamp);
+ }
+ }
+
+ // Timestamp from which we are ensured that cyclic log for every thread is not truncated
+ // NOTE: should NOT be called from Push(tid, item) functions
+ ui64 StartTimestamp() const
+ {
+ if (CutTsMax == 0) {
+ FindStartTime();
+ }
+ return CutTsMax;
+ }
+
+ ui64 NowTimestamp() const
+ {
+ return NowTs;
+ }
+
+ TInstant StartInstant() const
+ {
+ if (CutInstantMax == TInstant::Zero()) {
+ FindStartTime();
+ }
+ return CutInstantMax;
+ }
+
+ // Returns true iff item should be skipped to avoid surprizes
+ bool Skip(const NLWTrace::TLogItem& item) const
+ {
+ return Enabled && item.TimestampCycles < StartTimestamp();
+ }
+
+private:
+ void FindStartTime() const
+ {
+ for (auto& kv : CutTsForThread) {
+ CutTsMax = Max(CutTsMax, kv.second.first);
+ CutInstantMax = Max(CutInstantMax, kv.second.second);
+ }
+ }
+};
+
class TLogFilter {
private:
- struct TFilter {
+ struct TFilter {
TString ParamName;
TString ParamValue;
- bool Parsed;
-
- TLogQuery Query;
- NLWTrace::TLiteral Value;
-
+ bool Parsed;
+
+ TLogQuery Query;
+ NLWTrace::TLiteral Value;
+
explicit TFilter(const TString& text)
- {
- if (!text) { // Neither ParamName nor ParamValue is selected
- ParamName.clear();
- ParamValue.clear();
- Parsed = false;
- return;
- }
- size_t pos = text.find('=');
+ {
+ if (!text) { // Neither ParamName nor ParamValue is selected
+ ParamName.clear();
+ ParamValue.clear();
+ Parsed = false;
+ return;
+ }
+ size_t pos = text.find('=');
if (pos == TString::npos) { // Only ParamName has been selected
- ParamName = text;
- ParamValue.clear();
- Parsed = false;
- return;
- }
- // Both ParamName and ParamValue have been selected
- ParamValue = text.substr(pos + 1);
- ParamName = text.substr(0, pos);
- Parsed = true;
-
- Query = TLogQuery(ParamName);
- Value = NLWTrace::TLiteral(ParamValue);
- }
- };
+ ParamName = text;
+ ParamValue.clear();
+ Parsed = false;
+ return;
+ }
+ // Both ParamName and ParamValue have been selected
+ ParamValue = text.substr(pos + 1);
+ ParamName = text.substr(0, pos);
+ Parsed = true;
+
+ Query = TLogQuery(ParamName);
+ Value = NLWTrace::TLiteral(ParamValue);
+ }
+ };
TVector<TFilter> Filters;
THashSet<const NLWTrace::TSignature*> Signatures; // Just to list param names
- TVariants ParamNames;
+ TVariants ParamNames;
THashMap<TString, THashSet<TString>> FilteredParamValues; // paramName -> { paramValue }
public:
explicit TLogFilter(const TVector<TString>& filters)
{
for (const TString& subvalue : filters) {
- TFilter filter(subvalue);
- FilteredParamValues[filter.ParamName]; // just create empty set to gather values later
- if (filter.Parsed) {
- Filters.push_back(filter);
- }
+ TFilter filter(subvalue);
+ FilteredParamValues[filter.ParamName]; // just create empty set to gather values later
+ if (filter.Parsed) {
+ Filters.push_back(filter);
+ }
}
}
- virtual ~TLogFilter() {}
-
- template <class TLog>
- bool Filter(const TLog& log)
+ virtual ~TLogFilter() {}
+
+ template <class TLog>
+ bool Filter(const TLog& log)
{
- Gather(log);
- for (const TFilter& filter : Filters) {
- if (filter.Query.ExecuteQuery(log) != filter.Value) {
- return false;
+ Gather(log);
+ for (const TFilter& filter : Filters) {
+ if (filter.Query.ExecuteQuery(log) != filter.Value) {
+ return false;
}
}
- return true;
+ return true;
}
-
+
void FilterSelectors(TStringStream& ss, const TCgiParameters& e, const TString& fparam)
- {
- bool first = true;
- bool allParsed = true;
+ {
+ bool first = true;
+ bool allParsed = true;
for (const TString& subvalue : Subvalues(e, fparam)) {
- TFilter filter(subvalue);
- allParsed = allParsed && filter.Parsed;
- if (first) {
- SelectorTitle(ss, "where");
- }
- DropdownSelector<Erasable | CompositeValue, true>(
- ss, e, fparam, subvalue, first? "": ", ", ListParamNames(),
- filter.ParamName
- );
- if (filter.ParamName) {
- DropdownSelector<Link | CompositeValue, true>(
- ss, e, fparam, subvalue, "=", ListParamValues(filter.ParamName),
- filter.ParamValue? (filter.ParamName + "=" + filter.ParamValue): ""
- );
- }
- first = false;
- }
-
- if (!allParsed) {
- throw TPageGen<TSelectorsContainer>(ss.Str());
- } else {
- BtnHref<Button|ExtraSmall>(ss, first? "where": "+", MakeUrlAddSub(e, fparam, ""));
- }
- }
-
- const TVariants& ListParamNames()
- {
- if (ParamNames.empty()) {
+ TFilter filter(subvalue);
+ allParsed = allParsed && filter.Parsed;
+ if (first) {
+ SelectorTitle(ss, "where");
+ }
+ DropdownSelector<Erasable | CompositeValue, true>(
+ ss, e, fparam, subvalue, first? "": ", ", ListParamNames(),
+ filter.ParamName
+ );
+ if (filter.ParamName) {
+ DropdownSelector<Link | CompositeValue, true>(
+ ss, e, fparam, subvalue, "=", ListParamValues(filter.ParamName),
+ filter.ParamValue? (filter.ParamName + "=" + filter.ParamValue): ""
+ );
+ }
+ first = false;
+ }
+
+ if (!allParsed) {
+ throw TPageGen<TSelectorsContainer>(ss.Str());
+ } else {
+ BtnHref<Button|ExtraSmall>(ss, first? "where": "+", MakeUrlAddSub(e, fparam, ""));
+ }
+ }
+
+ const TVariants& ListParamNames()
+ {
+ if (ParamNames.empty()) {
THashSet<TString> paramNames;
- for (const NLWTrace::TSignature* sgn: Signatures) {
- for (size_t pi = 0; pi < sgn->ParamCount; pi++) {
- paramNames.insert(sgn->ParamNames[pi]);
- }
- }
- for (auto& pn : paramNames) {
- ParamNames.emplace_back(pn, pn);
- }
- }
- return ParamNames;
- }
-
+ for (const NLWTrace::TSignature* sgn: Signatures) {
+ for (size_t pi = 0; pi < sgn->ParamCount; pi++) {
+ paramNames.insert(sgn->ParamNames[pi]);
+ }
+ }
+ for (auto& pn : paramNames) {
+ ParamNames.emplace_back(pn, pn);
+ }
+ }
+ return ParamNames;
+ }
+
bool IsFiltered(const TString& paramName) const
- {
+ {
return FilteredParamValues.contains(paramName);
- }
-
-private:
- // Gather param names and values for selectors
- void Gather(const NLWTrace::TLogItem& item)
- {
- Signatures.insert(&item.Probe->Event.Signature);
- if (!FilteredParamValues.empty() && item.SavedParamsCount > 0) {
+ }
+
+private:
+ // Gather param names and values for selectors
+ void Gather(const NLWTrace::TLogItem& item)
+ {
+ Signatures.insert(&item.Probe->Event.Signature);
+ if (!FilteredParamValues.empty() && item.SavedParamsCount > 0) {
TString paramValues[LWTRACE_MAX_PARAMS];
- item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
- for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
- auto iter = FilteredParamValues.find(item.Probe->Event.Signature.ParamNames[pi]);
- if (iter != FilteredParamValues.end()) {
- iter->second.insert(paramValues[pi]);
- }
- }
- }
- }
-
- void Gather(const NLWTrace::TTrackLog& tl)
- {
- for (const NLWTrace::TLogItem& item : tl.Items) {
- Gather(item);
- }
- }
-
+ item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
+ for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
+ auto iter = FilteredParamValues.find(item.Probe->Event.Signature.ParamNames[pi]);
+ if (iter != FilteredParamValues.end()) {
+ iter->second.insert(paramValues[pi]);
+ }
+ }
+ }
+ }
+
+ void Gather(const NLWTrace::TTrackLog& tl)
+ {
+ for (const NLWTrace::TLogItem& item : tl.Items) {
+ Gather(item);
+ }
+ }
+
TVariants ListParamValues(const TString& paramName) const
- {
- TVariants result;
- auto iter = FilteredParamValues.find(paramName);
- if (iter != FilteredParamValues.end()) {
+ {
+ TVariants result;
+ auto iter = FilteredParamValues.find(paramName);
+ if (iter != FilteredParamValues.end()) {
for (const TString& paramValue : iter->second) {
- result.emplace_back(paramName + "=" + paramValue, paramValue);
- }
- }
- Sort(result.begin(), result.end());
- return result;
- }
+ result.emplace_back(paramName + "=" + paramValue, paramValue);
+ }
+ }
+ Sort(result.begin(), result.end());
+ return result;
+ }
};
-static void EscapeJSONString(IOutputStream& os, const TString& s)
-{
- for (TString::const_iterator i = s.begin(), e = s.end(); i != e; ++i) {
- char c = *i;
- if (c < ' ') {
- os << Sprintf("\\u%04x", int(c));
- } else if (c == '"') {
- os << "\\\"";
- } else if (c == '\\') {
- os << "\\\\";
- } else {
- os << c;
- }
- }
-}
-
-static TString EscapeJSONString(const TString& s)
-{
- TStringStream ss;
- EscapeJSONString(ss, s);
- return ss.Str();
-}
-
+static void EscapeJSONString(IOutputStream& os, const TString& s)
+{
+ for (TString::const_iterator i = s.begin(), e = s.end(); i != e; ++i) {
+ char c = *i;
+ if (c < ' ') {
+ os << Sprintf("\\u%04x", int(c));
+ } else if (c == '"') {
+ os << "\\\"";
+ } else if (c == '\\') {
+ os << "\\\\";
+ } else {
+ os << c;
+ }
+ }
+}
+
+static TString EscapeJSONString(const TString& s)
+{
+ TStringStream ss;
+ EscapeJSONString(ss, s);
+ return ss.Str();
+}
+
class TLogJsonPrinter {
private:
IOutputStream& Os;
@@ -2199,15 +2199,15 @@ public:
;
}
- void OutputFooter(const NLWTrace::TSession* trace)
+ void OutputFooter(const NLWTrace::TSession* trace)
{
Os << "\n\t\t]"
"\n\t, \"threads\": ["
;
- trace->ReadThreads(*this);
+ trace->ReadThreads(*this);
Os << "]"
- "\n\t, \"events_count\": " << trace->GetEventsCount() <<
- "\n\t, \"threads_count\": " << trace->GetThreadsCount() <<
+ "\n\t, \"events_count\": " << trace->GetEventsCount() <<
+ "\n\t, \"threads_count\": " << trace->GetThreadsCount() <<
"\n\t, \"timestamp\": " << Now().GetValue() <<
"\n}"
;
@@ -2219,7 +2219,7 @@ public:
FirstThread = false;
}
- void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
+ void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
{
Os << "\n\t\t" << (FirstItem? "": ", ");
FirstItem = false;
@@ -2246,31 +2246,31 @@ public:
class TLogTextPrinter : public TLogFilter {
private:
- TMultiMap<NLWTrace::TTypedParam, std::pair<TThread::TId, NLWTrace::TLogItem> > Items;
- TMultiMap<NLWTrace::TTypedParam, NLWTrace::TTrackLog> Depot;
- THashMap<NLWTrace::TProbe*, size_t> ProbeId;
- TVector<NLWTrace::TProbe*> Probes;
- TTimestampCutter CutTs;
- TLogQuery Order;
- bool ReverseOrder = false;
- ui64 Head = 0;
- ui64 Tail = 0;
- bool ShowTs = false;
+ TMultiMap<NLWTrace::TTypedParam, std::pair<TThread::TId, NLWTrace::TLogItem> > Items;
+ TMultiMap<NLWTrace::TTypedParam, NLWTrace::TTrackLog> Depot;
+ THashMap<NLWTrace::TProbe*, size_t> ProbeId;
+ TVector<NLWTrace::TProbe*> Probes;
+ TTimestampCutter CutTs;
+ TLogQuery Order;
+ bool ReverseOrder = false;
+ ui64 Head = 0;
+ ui64 Tail = 0;
+ bool ShowTs = false;
public:
- TLogTextPrinter(const TVector<TString>& filters, ui64 head, ui64 tail, const TString& order, bool reverseOrder, bool cutTs, bool showTs)
- : TLogFilter(filters)
- , CutTs(cutTs)
- , Order(order)
- , ReverseOrder(reverseOrder)
- , Head(head)
- , Tail(tail)
- , ShowTs(showTs)
- {}
-
+ TLogTextPrinter(const TVector<TString>& filters, ui64 head, ui64 tail, const TString& order, bool reverseOrder, bool cutTs, bool showTs)
+ : TLogFilter(filters)
+ , CutTs(cutTs)
+ , Order(order)
+ , ReverseOrder(reverseOrder)
+ , Head(head)
+ , Tail(tail)
+ , ShowTs(showTs)
+ {}
+
TLogTextPrinter(const TCgiParameters& e)
: TLogTextPrinter(
- Subvalues(e, "f"),
- e.Has("head")? FromString<ui64>(e.Get("head")): 0,
+ Subvalues(e, "f"),
+ e.Has("head")? FromString<ui64>(e.Get("head")): 0,
e.Has("tail")? FromString<ui64>(e.Get("tail")): 0,
e.Get("s"),
e.Get("reverse") == "y",
@@ -2278,1630 +2278,1630 @@ public:
e.Get("showts") == "y")
{}
- enum EFormat {
- Text,
- Json
- };
-
+ enum EFormat {
+ Text,
+ Json
+ };
+
void Output(IOutputStream& os) const
{
- OutputItems<Text>(os);
- OutputDepot<Text>(os);
- }
-
- void OutputJson(IOutputStream& os) const
- {
- os << "{\"depot\":[\n";
- OutputItems<Json>(os);
- OutputDepot<Json>(os);
- os << "],\"probes\":[";
- bool first = true;
- for (const NLWTrace::TProbe* probe : Probes) {
- os << (first? "": ",") << "{\"provider\":\"" << probe->Event.GetProvider()
- << "\",\"name\":\"" << probe->Event.Name << "\"}";
- first = false;
- }
- os << "]}";
- }
-
- NLWTrace::TTypedParam GetKey(const NLWTrace::TLogItem& item)
- {
- return Order? Order.ExecuteQuery(item): NLWTrace::TTypedParam(item.GetTimestampCycles());
- }
-
- NLWTrace::TTypedParam GetKey(const NLWTrace::TTrackLog& tl)
- {
- return Order? Order.ExecuteQuery(tl): NLWTrace::TTypedParam(tl.GetTimestampCycles());
- }
-
- void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- CutTs.Push(tid, item);
+ OutputItems<Text>(os);
+ OutputDepot<Text>(os);
+ }
+
+ void OutputJson(IOutputStream& os) const
+ {
+ os << "{\"depot\":[\n";
+ OutputItems<Json>(os);
+ OutputDepot<Json>(os);
+ os << "],\"probes\":[";
+ bool first = true;
+ for (const NLWTrace::TProbe* probe : Probes) {
+ os << (first? "": ",") << "{\"provider\":\"" << probe->Event.GetProvider()
+ << "\",\"name\":\"" << probe->Event.Name << "\"}";
+ first = false;
+ }
+ os << "]}";
+ }
+
+ NLWTrace::TTypedParam GetKey(const NLWTrace::TLogItem& item)
+ {
+ return Order? Order.ExecuteQuery(item): NLWTrace::TTypedParam(item.GetTimestampCycles());
+ }
+
+ NLWTrace::TTypedParam GetKey(const NLWTrace::TTrackLog& tl)
+ {
+ return Order? Order.ExecuteQuery(tl): NLWTrace::TTypedParam(tl.GetTimestampCycles());
+ }
+
+ void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ CutTs.Push(tid, item);
if (Filter(item)) {
- AddId(item);
- Items.emplace(GetKey(item), std::make_pair(tid, item));
- }
- }
-
- void Push(TThread::TId tid, const NLWTrace::TTrackLog& tl)
- {
- Y_UNUSED(tid);
- if (Filter(tl)) {
- AddId(tl);
- Depot.emplace(GetKey(tl), tl);
- }
- }
-
+ AddId(item);
+ Items.emplace(GetKey(item), std::make_pair(tid, item));
+ }
+ }
+
+ void Push(TThread::TId tid, const NLWTrace::TTrackLog& tl)
+ {
+ Y_UNUSED(tid);
+ if (Filter(tl)) {
+ AddId(tl);
+ Depot.emplace(GetKey(tl), tl);
+ }
+ }
+
private:
- void AddId(const NLWTrace::TLogItem& item)
- {
- if (ProbeId.find(item.Probe) == ProbeId.end()) {
- size_t id = Probes.size();
- ProbeId[item.Probe] = id;
- Probes.emplace_back(item.Probe);
- }
- }
-
- void AddId(const NLWTrace::TTrackLog& tl)
- {
- for (const auto& item : tl.Items) {
- AddId(item);
- }
- }
-
- bool HeadTailFilter(ui64 idx, ui64 size) const
- {
- bool headOk = idx < Head;
- bool tailOk = size < Tail + idx + 1ull;
- if (Head && Tail) {
- return headOk || tailOk;
- } else if (Head) {
- return headOk;
- } else if (Tail) {
- return tailOk;
- } else {
- return true;
- }
- }
-
- template <EFormat Format>
+ void AddId(const NLWTrace::TLogItem& item)
+ {
+ if (ProbeId.find(item.Probe) == ProbeId.end()) {
+ size_t id = Probes.size();
+ ProbeId[item.Probe] = id;
+ Probes.emplace_back(item.Probe);
+ }
+ }
+
+ void AddId(const NLWTrace::TTrackLog& tl)
+ {
+ for (const auto& item : tl.Items) {
+ AddId(item);
+ }
+ }
+
+ bool HeadTailFilter(ui64 idx, ui64 size) const
+ {
+ bool headOk = idx < Head;
+ bool tailOk = size < Tail + idx + 1ull;
+ if (Head && Tail) {
+ return headOk || tailOk;
+ } else if (Head) {
+ return headOk;
+ } else if (Tail) {
+ return tailOk;
+ } else {
+ return true;
+ }
+ }
+
+ template <EFormat Format>
void OutputItems(IOutputStream& os) const
- {
- ui64 idx = 0;
- ui64 size = Items.size();
- ui64 startTs = ShowTs? CutTs.StartTimestamp(): 0;
- ui64 prevTs = 0;
- bool first = true;
- if (!ReverseOrder) {
- for (auto i = Items.begin(), e = Items.end(); i != e; ++i, idx++) {
- if (HeadTailFilter(idx, size)) {
- OutputItem<Format, true>(os, i->second.first, i->second.second, startTs, prevTs, first);
- prevTs = startTs? i->second.second.GetTimestampCycles(): 0;
- }
- }
- } else {
- for (auto i = Items.rbegin(), e = Items.rend(); i != e; ++i, idx++) {
- if (HeadTailFilter(idx, size)) {
- OutputItem<Format, true>(os, i->second.first, i->second.second, startTs, prevTs, first);
- prevTs = startTs? i->second.second.GetTimestampCycles(): 0;
- }
- }
- }
- }
-
- template <EFormat Format>
+ {
+ ui64 idx = 0;
+ ui64 size = Items.size();
+ ui64 startTs = ShowTs? CutTs.StartTimestamp(): 0;
+ ui64 prevTs = 0;
+ bool first = true;
+ if (!ReverseOrder) {
+ for (auto i = Items.begin(), e = Items.end(); i != e; ++i, idx++) {
+ if (HeadTailFilter(idx, size)) {
+ OutputItem<Format, true>(os, i->second.first, i->second.second, startTs, prevTs, first);
+ prevTs = startTs? i->second.second.GetTimestampCycles(): 0;
+ }
+ }
+ } else {
+ for (auto i = Items.rbegin(), e = Items.rend(); i != e; ++i, idx++) {
+ if (HeadTailFilter(idx, size)) {
+ OutputItem<Format, true>(os, i->second.first, i->second.second, startTs, prevTs, first);
+ prevTs = startTs? i->second.second.GetTimestampCycles(): 0;
+ }
+ }
+ }
+ }
+
+ template <EFormat Format>
void OutputDepot(IOutputStream& os) const
- {
- ui64 idx = 0;
- ui64 size = Depot.size();
- bool first = true;
- if (!ReverseOrder) {
- for (auto i = Depot.begin(), e = Depot.end(); i != e; ++i, idx++) {
- if (HeadTailFilter(idx, size)) {
- OutputTrackLog<Format>(os, i->second, first);
- }
- }
- } else {
- for (auto i = Depot.rbegin(), e = Depot.rend(); i != e; ++i, idx++) {
- if (HeadTailFilter(idx, size)) {
- OutputTrackLog<Format>(os, i->second, first);
- }
- }
- }
- }
-
- template <EFormat Format, bool AsTrack = false>
- void OutputItem(IOutputStream& os, TThread::TId tid, const NLWTrace::TLogItem& item, ui64 startTs, ui64 prevTs, bool& first) const
- {
- if (CutTs.Skip(item)) {
- return;
- }
- if constexpr (Format == Text) {
- if (startTs) {
- if (!prevTs) {
- prevTs = item.GetTimestampCycles();
- }
- os << Sprintf("%10.3lf %+10.3lf ms ",
- NHPTimer::GetSeconds(item.GetTimestampCycles() - startTs) * 1000.0,
- NHPTimer::GetSeconds(item.GetTimestampCycles() - prevTs) * 1000.0);
- }
- if (tid) {
- os << "<" << tid << "> ";
- }
- if (item.Timestamp != TInstant::Zero()) {
- os << "[" << item.Timestamp << "] ";
- } else {
- os << "[" << item.TimestampCycles << "] ";
- }
- os << GetProbeName(item.Probe) << "(";
- if (item.SavedParamsCount > 0) {
- TString ParamValues[LWTRACE_MAX_PARAMS];
- item.Probe->Event.Signature.SerializeParams(item.Params, ParamValues);
- bool first = true;
- for (size_t i = 0; i < item.SavedParamsCount; i++, first = false) {
- os << (first? "": ", ") << item.Probe->Event.Signature.ParamNames[i] << "='" << EscapeC(ParamValues[i]) << "'";
- }
- }
- os << ")\n";
- } else if constexpr (Format == Json) {
- if (auto probeId = ProbeId.find(item.Probe); probeId != ProbeId.end()) {
- os << (first? "": ",") << (AsTrack? "[":"") << "[\"" << tid << "\",\"";
- if (item.Timestamp != TInstant::Zero()) {
- os << item.Timestamp.MicroSeconds();
- } else {
- os << Sprintf("%.3lf", NHPTimer::GetSeconds(item.TimestampCycles) * 1e9);
- }
- os << "\"," << probeId->second << ",{";
- if (item.SavedParamsCount > 0) {
- TString ParamValues[LWTRACE_MAX_PARAMS];
- item.Probe->Event.Signature.SerializeParams(item.Params, ParamValues);
- bool first = true;
- for (size_t i = 0; i < item.SavedParamsCount; i++, first = false) {
- os << (first? "": ",") << "\"" << item.Probe->Event.Signature.ParamNames[i] << "\":\"";
- EscapeJSONString(os, ParamValues[i]);
- os << "\"";
- }
- }
- os << "}]" << (AsTrack? "]":"");
- }
- }
- first = false;
- }
-
- template <EFormat Format>
- void OutputTrackLog(IOutputStream& os, const NLWTrace::TTrackLog& tl, bool& first) const
- {
- if constexpr (Format == Json) {
- os << (first? "": ",") << "[";
- }
- first = false;
- ui64 prevTs = tl.GetTimestampCycles();
- bool firstItem = true;
- for (const NLWTrace::TTrackLog::TItem& item: tl.Items) {
- OutputItem<Format>(os, item.ThreadId, item, tl.GetTimestampCycles(), prevTs, firstItem);
- prevTs = item.GetTimestampCycles();
- }
- if constexpr (Format == Json) {
- os << "]";
- }
- os << "\n";
- }
+ {
+ ui64 idx = 0;
+ ui64 size = Depot.size();
+ bool first = true;
+ if (!ReverseOrder) {
+ for (auto i = Depot.begin(), e = Depot.end(); i != e; ++i, idx++) {
+ if (HeadTailFilter(idx, size)) {
+ OutputTrackLog<Format>(os, i->second, first);
+ }
+ }
+ } else {
+ for (auto i = Depot.rbegin(), e = Depot.rend(); i != e; ++i, idx++) {
+ if (HeadTailFilter(idx, size)) {
+ OutputTrackLog<Format>(os, i->second, first);
+ }
+ }
+ }
+ }
+
+ template <EFormat Format, bool AsTrack = false>
+ void OutputItem(IOutputStream& os, TThread::TId tid, const NLWTrace::TLogItem& item, ui64 startTs, ui64 prevTs, bool& first) const
+ {
+ if (CutTs.Skip(item)) {
+ return;
+ }
+ if constexpr (Format == Text) {
+ if (startTs) {
+ if (!prevTs) {
+ prevTs = item.GetTimestampCycles();
+ }
+ os << Sprintf("%10.3lf %+10.3lf ms ",
+ NHPTimer::GetSeconds(item.GetTimestampCycles() - startTs) * 1000.0,
+ NHPTimer::GetSeconds(item.GetTimestampCycles() - prevTs) * 1000.0);
+ }
+ if (tid) {
+ os << "<" << tid << "> ";
+ }
+ if (item.Timestamp != TInstant::Zero()) {
+ os << "[" << item.Timestamp << "] ";
+ } else {
+ os << "[" << item.TimestampCycles << "] ";
+ }
+ os << GetProbeName(item.Probe) << "(";
+ if (item.SavedParamsCount > 0) {
+ TString ParamValues[LWTRACE_MAX_PARAMS];
+ item.Probe->Event.Signature.SerializeParams(item.Params, ParamValues);
+ bool first = true;
+ for (size_t i = 0; i < item.SavedParamsCount; i++, first = false) {
+ os << (first? "": ", ") << item.Probe->Event.Signature.ParamNames[i] << "='" << EscapeC(ParamValues[i]) << "'";
+ }
+ }
+ os << ")\n";
+ } else if constexpr (Format == Json) {
+ if (auto probeId = ProbeId.find(item.Probe); probeId != ProbeId.end()) {
+ os << (first? "": ",") << (AsTrack? "[":"") << "[\"" << tid << "\",\"";
+ if (item.Timestamp != TInstant::Zero()) {
+ os << item.Timestamp.MicroSeconds();
+ } else {
+ os << Sprintf("%.3lf", NHPTimer::GetSeconds(item.TimestampCycles) * 1e9);
+ }
+ os << "\"," << probeId->second << ",{";
+ if (item.SavedParamsCount > 0) {
+ TString ParamValues[LWTRACE_MAX_PARAMS];
+ item.Probe->Event.Signature.SerializeParams(item.Params, ParamValues);
+ bool first = true;
+ for (size_t i = 0; i < item.SavedParamsCount; i++, first = false) {
+ os << (first? "": ",") << "\"" << item.Probe->Event.Signature.ParamNames[i] << "\":\"";
+ EscapeJSONString(os, ParamValues[i]);
+ os << "\"";
+ }
+ }
+ os << "}]" << (AsTrack? "]":"");
+ }
+ }
+ first = false;
+ }
+
+ template <EFormat Format>
+ void OutputTrackLog(IOutputStream& os, const NLWTrace::TTrackLog& tl, bool& first) const
+ {
+ if constexpr (Format == Json) {
+ os << (first? "": ",") << "[";
+ }
+ first = false;
+ ui64 prevTs = tl.GetTimestampCycles();
+ bool firstItem = true;
+ for (const NLWTrace::TTrackLog::TItem& item: tl.Items) {
+ OutputItem<Format>(os, item.ThreadId, item, tl.GetTimestampCycles(), prevTs, firstItem);
+ prevTs = item.GetTimestampCycles();
+ }
+ if constexpr (Format == Json) {
+ os << "]";
+ }
+ os << "\n";
+ }
};
-class TLogAnalyzer: public TLogFilter {
-private:
+class TLogAnalyzer: public TLogFilter {
+private:
TMultiMap<ui64, std::pair<TThread::TId, NLWTrace::TLogItem>> Items;
TVector<NLWTrace::TTrackLog> Depot;
THashMap<TString, TTrackLogRefs> Groups;
- NAnalytics::TTable Table;
- bool TableCreated = false;
+ NAnalytics::TTable Table;
+ bool TableCreated = false;
TVector<TString> GroupBy;
- TTimestampCutter CutTs;
-public:
+ TTimestampCutter CutTs;
+public:
TLogAnalyzer(const TVector<TString>& filters, const TVector<TString>& groupBy, bool cutTs)
- : TLogFilter(filters)
- , CutTs(cutTs)
- {
+ : TLogFilter(filters)
+ , CutTs(cutTs)
+ {
for (const TString& groupParam : groupBy) {
- GroupBy.push_back(groupParam);
- }
- }
-
- const NAnalytics::TTable& GetTable()
- {
- if (!TableCreated) {
- TableCreated = true;
- if (GroupBy.empty()) {
- for (auto i = Items.begin(), e = Items.end(); i != e; ++i) {
- ParseItems(i->second.first, i->second.second);
- }
- ParseDepot();
- } else {
- for (auto i = Items.begin(), e = Items.end(); i != e; ++i) {
- Map(i->second.first, i->second.second);
- }
- Reduce();
- }
- }
- return Table;
- }
-
- void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- CutTs.Push(tid, item);
- if (Filter(item)) {
- Items.emplace(item.TimestampCycles, std::make_pair(tid, item));
- }
- }
-
- void Push(TThread::TId, const NLWTrace::TTrackLog& tl)
- {
- if (Filter(tl)) {
- Depot.emplace_back(tl);
- }
- }
-private:
- void FillRow(NAnalytics::TRow& row, const NLWTrace::TLogItem& item)
- {
- if (item.SavedParamsCount > 0) {
+ GroupBy.push_back(groupParam);
+ }
+ }
+
+ const NAnalytics::TTable& GetTable()
+ {
+ if (!TableCreated) {
+ TableCreated = true;
+ if (GroupBy.empty()) {
+ for (auto i = Items.begin(), e = Items.end(); i != e; ++i) {
+ ParseItems(i->second.first, i->second.second);
+ }
+ ParseDepot();
+ } else {
+ for (auto i = Items.begin(), e = Items.end(); i != e; ++i) {
+ Map(i->second.first, i->second.second);
+ }
+ Reduce();
+ }
+ }
+ return Table;
+ }
+
+ void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ CutTs.Push(tid, item);
+ if (Filter(item)) {
+ Items.emplace(item.TimestampCycles, std::make_pair(tid, item));
+ }
+ }
+
+ void Push(TThread::TId, const NLWTrace::TTrackLog& tl)
+ {
+ if (Filter(tl)) {
+ Depot.emplace_back(tl);
+ }
+ }
+private:
+ void FillRow(NAnalytics::TRow& row, const NLWTrace::TLogItem& item)
+ {
+ if (item.SavedParamsCount > 0) {
TString paramValues[LWTRACE_MAX_PARAMS];
- item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
- for (size_t i = 0; i < item.SavedParamsCount; i++) {
+ item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
+ for (size_t i = 0; i < item.SavedParamsCount; i++) {
double value = FromString<double>(paramValues[i].data(), paramValues[i].size(), NAN);
// If value cannot be cast to double or is inf/nan -- assume it's a string
- if (isfinite(value)) {
- row[item.Probe->Event.Signature.ParamNames[i]] = value;
+ if (isfinite(value)) {
+ row[item.Probe->Event.Signature.ParamNames[i]] = value;
} else {
row[item.Probe->Event.Signature.ParamNames[i]] = paramValues[i];
- }
- }
- }
- }
-
+ }
+ }
+ }
+ }
+
TString GetParam(const NLWTrace::TLogItem& item, TString* paramValues, const TString& paramName)
- {
- for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
- if (paramName == item.Probe->Event.Signature.ParamNames[pi]) {
- return paramValues[pi];
- }
- }
+ {
+ for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
+ if (paramName == item.Probe->Event.Signature.ParamNames[pi]) {
+ return paramValues[pi];
+ }
+ }
return TString();
- }
-
+ }
+
TString GetGroup(const NLWTrace::TLogItem& item, TString* paramValues)
- {
- TStringStream ss;
- bool first = true;
+ {
+ TStringStream ss;
+ bool first = true;
for (const TString& groupParam : GroupBy) {
- ss << (first? "": "|") << GetParam(item, paramValues, groupParam);
- first = false;
- }
- return ss.Str();
- }
-
- void ParseItems(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- if (CutTs.Skip(item)) {
- return;
- }
+ ss << (first? "": "|") << GetParam(item, paramValues, groupParam);
+ first = false;
+ }
+ return ss.Str();
+ }
+
+ void ParseItems(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ if (CutTs.Skip(item)) {
+ return;
+ }
Table.emplace_back();
- NAnalytics::TRow& row = Table.back();
- row["_thread"] = tid;
- if (item.Timestamp != TInstant::Zero()) {
- row["_wallTime"] = item.Timestamp.SecondsFloat();
- row["_wallRTime"] = item.Timestamp.SecondsFloat() - CutTs.StartInstant().SecondsFloat();
- }
- row["_cycles"] = item.TimestampCycles;
- row["_thrTime"] = CyclesToDuration((ui64)item.TimestampCycles).SecondsFloat();
- row["_thrRTime"] = double(i64(item.TimestampCycles) - i64(CutTs.StartTimestamp())) / NHPTimer::GetCyclesPerSecond();
- row["_thrNTime"] = double(i64(item.TimestampCycles) - i64(CutTs.NowTimestamp())) / NHPTimer::GetCyclesPerSecond();
- row.Name = GetProbeName(item.Probe);
- FillRow(row, item);
- }
-
- void Map(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- if (item.SavedParamsCount > 0 && !CutTs.Skip(item)) {
+ NAnalytics::TRow& row = Table.back();
+ row["_thread"] = tid;
+ if (item.Timestamp != TInstant::Zero()) {
+ row["_wallTime"] = item.Timestamp.SecondsFloat();
+ row["_wallRTime"] = item.Timestamp.SecondsFloat() - CutTs.StartInstant().SecondsFloat();
+ }
+ row["_cycles"] = item.TimestampCycles;
+ row["_thrTime"] = CyclesToDuration((ui64)item.TimestampCycles).SecondsFloat();
+ row["_thrRTime"] = double(i64(item.TimestampCycles) - i64(CutTs.StartTimestamp())) / NHPTimer::GetCyclesPerSecond();
+ row["_thrNTime"] = double(i64(item.TimestampCycles) - i64(CutTs.NowTimestamp())) / NHPTimer::GetCyclesPerSecond();
+ row.Name = GetProbeName(item.Probe);
+ FillRow(row, item);
+ }
+
+ void Map(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ if (item.SavedParamsCount > 0 && !CutTs.Skip(item)) {
TString paramValues[LWTRACE_MAX_PARAMS];
- item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
- TTrackLogRefs& tl = Groups[GetGroup(item, paramValues)];
- tl.Items.emplace_back(tid, item);
- }
- }
-
- void Reduce()
- {
- for (auto& v : Groups) {
+ item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
+ TTrackLogRefs& tl = Groups[GetGroup(item, paramValues)];
+ tl.Items.emplace_back(tid, item);
+ }
+ }
+
+ void Reduce()
+ {
+ for (auto& v : Groups) {
const TString& group = v.first;
- const TTrackLogRefs& tl = v.second;
+ const TTrackLogRefs& tl = v.second;
Table.emplace_back();
- NAnalytics::TRow& row = Table.back();
- row.Name = group;
- for (const NLWTrace::TLogItem& item : tl.Items) {
- FillRow(row, item);
- }
- }
- }
-
- void ParseDepot()
- {
- for (NLWTrace::TTrackLog& tl : Depot) {
- Table.emplace_back();
- NAnalytics::TRow& row = Table.back();
- for (const NLWTrace::TLogItem& item : tl.Items) {
- FillRow(row, item);
- }
- }
- }
-};
-
-struct TSampleOpts {
- bool ShowProvider = false;
- size_t SizeLimit = 50;
-};
-
-enum ENodeType {
- NT_ROOT,
- NT_PROBE,
- NT_PARAM
-};
-
-class TPatternTree;
-struct TPatternNode;
-
-struct TTrack : public TTrackLogRefs {
+ NAnalytics::TRow& row = Table.back();
+ row.Name = group;
+ for (const NLWTrace::TLogItem& item : tl.Items) {
+ FillRow(row, item);
+ }
+ }
+ }
+
+ void ParseDepot()
+ {
+ for (NLWTrace::TTrackLog& tl : Depot) {
+ Table.emplace_back();
+ NAnalytics::TRow& row = Table.back();
+ for (const NLWTrace::TLogItem& item : tl.Items) {
+ FillRow(row, item);
+ }
+ }
+ }
+};
+
+struct TSampleOpts {
+ bool ShowProvider = false;
+ size_t SizeLimit = 50;
+};
+
+enum ENodeType {
+ NT_ROOT,
+ NT_PROBE,
+ NT_PARAM
+};
+
+class TPatternTree;
+struct TPatternNode;
+
+struct TTrack : public TTrackLogRefs {
TString TrackId;
- TPatternNode* LastNode = nullptr;
-};
-
-using TTrackTr = TLogTraits<TTrackLogRefs>;
-using TTrackIter = TTrackTr::const_iterator;
-
-// Visitor for tree traversing
-class IVisitor {
-public:
- virtual ~IVisitor() {}
- virtual void Visit(TPatternNode* node) = 0;
-};
-
-// Per-node classifier
-class TClassifier {
-public:
- explicit TClassifier(TPatternNode* node, ENodeType childType, bool keepHead = false)
- : Node(node)
- , KeepHead(keepHead)
- , ChildType(childType)
- {}
- virtual ~TClassifier() {}
- virtual TPatternNode* Classify(TTrackIter cur, const TTrack& track) = 0;
- virtual void Accept(IVisitor* visitor) = 0;
- virtual bool IsLeaf() = 0;
- ENodeType GetChildType() const { return ChildType; }
-public:
- TPatternNode* Node;
- const bool KeepHead;
- ENodeType ChildType;
-};
-
-// Track classification tree node
-struct TPatternNode {
+ TPatternNode* LastNode = nullptr;
+};
+
+using TTrackTr = TLogTraits<TTrackLogRefs>;
+using TTrackIter = TTrackTr::const_iterator;
+
+// Visitor for tree traversing
+class IVisitor {
+public:
+ virtual ~IVisitor() {}
+ virtual void Visit(TPatternNode* node) = 0;
+};
+
+// Per-node classifier
+class TClassifier {
+public:
+ explicit TClassifier(TPatternNode* node, ENodeType childType, bool keepHead = false)
+ : Node(node)
+ , KeepHead(keepHead)
+ , ChildType(childType)
+ {}
+ virtual ~TClassifier() {}
+ virtual TPatternNode* Classify(TTrackIter cur, const TTrack& track) = 0;
+ virtual void Accept(IVisitor* visitor) = 0;
+ virtual bool IsLeaf() = 0;
+ ENodeType GetChildType() const { return ChildType; }
+public:
+ TPatternNode* Node;
+ const bool KeepHead;
+ ENodeType ChildType;
+};
+
+// Track classification tree node
+struct TPatternNode {
TString Name;
- TPatternNode* Parent = nullptr;
- THolder<TClassifier> Classifier;
- struct TDesc {
- ENodeType Type = NT_ROOT;
- // NT_PROBE
- const NLWTrace::TProbe* Probe = nullptr;
- // NT_PARAM
- size_t Rollbacks = 0;
+ TPatternNode* Parent = nullptr;
+ THolder<TClassifier> Classifier;
+ struct TDesc {
+ ENodeType Type = NT_ROOT;
+ // NT_PROBE
+ const NLWTrace::TProbe* Probe = nullptr;
+ // NT_PARAM
+ size_t Rollbacks = 0;
TString ParamName;
TString ParamValue;
- } Desc;
-
- ui64 TrackCount = 0;
- struct TTrackEntry {
- TTrack* Track;
- ui64 ResTotal;
- ui64 ResLast;
-
- TTrackEntry(TTrack* track, ui64 resTotal, ui64 resLast)
- : Track(track)
- , ResTotal(resTotal)
- , ResLast(resLast)
- {}
- };
-
+ } Desc;
+
+ ui64 TrackCount = 0;
+ struct TTrackEntry {
+ TTrack* Track;
+ ui64 ResTotal;
+ ui64 ResLast;
+
+ TTrackEntry(TTrack* track, ui64 resTotal, ui64 resLast)
+ : Track(track)
+ , ResTotal(resTotal)
+ , ResLast(resLast)
+ {}
+ };
+
TVector<TTrackEntry> Tracks;
-
- ui64 ResTotalSum = 0;
- ui64 ResTotalMax = 0;
+
+ ui64 ResTotalSum = 0;
+ ui64 ResTotalMax = 0;
TVector<ui64> ResTotalAll;
-
- ui64 ResLastSum = 0;
- ui64 ResLastMax = 0;
+
+ ui64 ResLastSum = 0;
+ ui64 ResLastMax = 0;
TVector<ui64> ResLastAll;
-
+
TVector<ui64> TimelineSum;
- NAnalytics::TTable Slices;
-
+ NAnalytics::TTable Slices;
+
TString GetPath() const
- {
- if (Parent) {
- return Parent->GetPath() + Name;
- }
- return "/";
- }
-
- NAnalytics::TTable GetTable() const
- {
- using namespace NAnalytics;
- NAnalytics::TTable ret;
- for (ui64 x : ResTotalAll) {
+ {
+ if (Parent) {
+ return Parent->GetPath() + Name;
+ }
+ return "/";
+ }
+
+ NAnalytics::TTable GetTable() const
+ {
+ using namespace NAnalytics;
+ NAnalytics::TTable ret;
+ for (ui64 x : ResTotalAll) {
ret.emplace_back();
- TRow& row = ret.back();
- row["resTotal"] = double(x) * 1000.0 / NHPTimer::GetClockRate();
- }
- for (ui64 x : ResLastAll) {
+ TRow& row = ret.back();
+ row["resTotal"] = double(x) * 1000.0 / NHPTimer::GetClockRate();
+ }
+ for (ui64 x : ResLastAll) {
ret.emplace_back();
- TRow& row = ret.back();
- row["resLast"] = double(x) * 1000.0 / NHPTimer::GetClockRate();
- }
- return ret;
- }
-
+ TRow& row = ret.back();
+ row["resLast"] = double(x) * 1000.0 / NHPTimer::GetClockRate();
+ }
+ return ret;
+ }
+
template <typename TReader>
void OutputSample(const TString& bn, double b1, double b2, const TSampleOpts& opts, TReader& reader) const
- {
- bool filterTotal = false;
- if (bn == "resTotal") {
- filterTotal = true;
- } else {
+ {
+ bool filterTotal = false;
+ if (bn == "resTotal") {
+ filterTotal = true;
+ } else {
WWW_CHECK(bn == "resLast", "wrong sample filter param: %s", bn.data());
- }
-
- size_t spaceLeft = opts.SizeLimit;
- for (const TTrackEntry& entry : Tracks) {
- const TTrack* track = entry.Track;
- // Filter out tracks that are not in sample
- if (filterTotal) {
- double resTotalMs = double(entry.ResTotal) * 1000.0 / NHPTimer::GetClockRate();
- if (resTotalMs < b1 || resTotalMs > b2) {
- continue;
- }
- } else {
- double resLastMs = double(entry.ResLast) * 1000.0 / NHPTimer::GetClockRate();
- if (resLastMs < b1 || resLastMs > b2) {
- continue;
- }
- }
-
+ }
+
+ size_t spaceLeft = opts.SizeLimit;
+ for (const TTrackEntry& entry : Tracks) {
+ const TTrack* track = entry.Track;
+ // Filter out tracks that are not in sample
+ if (filterTotal) {
+ double resTotalMs = double(entry.ResTotal) * 1000.0 / NHPTimer::GetClockRate();
+ if (resTotalMs < b1 || resTotalMs > b2) {
+ continue;
+ }
+ } else {
+ double resLastMs = double(entry.ResLast) * 1000.0 / NHPTimer::GetClockRate();
+ if (resLastMs < b1 || resLastMs > b2) {
+ continue;
+ }
+ }
+
NLWTrace::TTrackLog tl;
for (TTrackIter i = TTrackTr::begin(*track), e = TTrackTr::end(*track); i != e; ++i) {
- const NLWTrace::TLogItem& item = *i;
+ const NLWTrace::TLogItem& item = *i;
const auto threadId = i->ThreadId;
tl.Items.push_back(NLWTrace::TTrackLog::TItem(threadId, item));
- }
+ }
reader.Push(0, tl);
- if (spaceLeft) {
- spaceLeft--;
- if (!spaceLeft) {
- break;
- }
- }
- }
- }
-};
-
-// Track classification tree
-class TPatternTree {
-public:
- // Per-node classifier by probe name
- class TClassifyByProbe : public TClassifier {
- private:
+ if (spaceLeft) {
+ spaceLeft--;
+ if (!spaceLeft) {
+ break;
+ }
+ }
+ }
+ }
+};
+
+// Track classification tree
+class TPatternTree {
+public:
+ // Per-node classifier by probe name
+ class TClassifyByProbe : public TClassifier {
+ private:
using TChildren = THashMap<NLWTrace::TProbe*, TPatternNode>;
- TChildren Children;
+ TChildren Children;
TVector<TChildren::value_type*> SortedChildren;
- public:
- explicit TClassifyByProbe(TPatternNode* node)
- : TClassifier(node, NT_PROBE)
- {}
-
- TPatternNode* Classify(TTrackIter cur, const TTrack& track) override
- {
- Y_UNUSED(track);
- const NLWTrace::TLogItem& item = *cur;
- TPatternNode* node = &Children[item.Probe];
- node->Name = "/" + GetProbeName(item.Probe);
- node->Desc.Type = NT_PROBE;
- node->Desc.Probe = item.Probe;
- return node;
- }
-
- void Accept(IVisitor* visitor) override
- {
- if (SortedChildren.size() != Children.size()) {
- SortedChildren.clear();
- SortedChildren.reserve(Children.size());
- for (auto i = Children.begin(), e = Children.end(); i != e; ++i) {
- SortedChildren.push_back(&*i);
- }
- Sort(SortedChildren, [] (TChildren::value_type* lhs, TChildren::value_type* rhs) {
- NLWTrace::TProbe* lp = lhs->first;
- NLWTrace::TProbe* rp = rhs->first;
- if (int cmp = strcmp(lp->Event.GetProvider(), rp->Event.GetProvider())) {
- return cmp < 0;
- }
- return strcmp(lp->Event.Name, rp->Event.Name) < 0;
- });
- }
- for (auto* kv : SortedChildren) {
- visitor->Visit(&kv->second);
- }
- }
-
- bool IsLeaf() override { return Children.empty(); }
- };
-
- // Per-node classifier by probe param value
- class TClassifyByParam : public TClassifier {
- private:
- size_t Rollbacks; // How many items should we look back in track to locate probe
+ public:
+ explicit TClassifyByProbe(TPatternNode* node)
+ : TClassifier(node, NT_PROBE)
+ {}
+
+ TPatternNode* Classify(TTrackIter cur, const TTrack& track) override
+ {
+ Y_UNUSED(track);
+ const NLWTrace::TLogItem& item = *cur;
+ TPatternNode* node = &Children[item.Probe];
+ node->Name = "/" + GetProbeName(item.Probe);
+ node->Desc.Type = NT_PROBE;
+ node->Desc.Probe = item.Probe;
+ return node;
+ }
+
+ void Accept(IVisitor* visitor) override
+ {
+ if (SortedChildren.size() != Children.size()) {
+ SortedChildren.clear();
+ SortedChildren.reserve(Children.size());
+ for (auto i = Children.begin(), e = Children.end(); i != e; ++i) {
+ SortedChildren.push_back(&*i);
+ }
+ Sort(SortedChildren, [] (TChildren::value_type* lhs, TChildren::value_type* rhs) {
+ NLWTrace::TProbe* lp = lhs->first;
+ NLWTrace::TProbe* rp = rhs->first;
+ if (int cmp = strcmp(lp->Event.GetProvider(), rp->Event.GetProvider())) {
+ return cmp < 0;
+ }
+ return strcmp(lp->Event.Name, rp->Event.Name) < 0;
+ });
+ }
+ for (auto* kv : SortedChildren) {
+ visitor->Visit(&kv->second);
+ }
+ }
+
+ bool IsLeaf() override { return Children.empty(); }
+ };
+
+ // Per-node classifier by probe param value
+ class TClassifyByParam : public TClassifier {
+ private:
+ size_t Rollbacks; // How many items should we look back in track to locate probe
TString ParamName;
using TChildren = THashMap<TString, TPatternNode>;
- TChildren Children;
+ TChildren Children;
TVector<TChildren::value_type*> SortedChildren;
- public:
+ public:
TClassifyByParam(TPatternNode* node, size_t rollbacks, const TString& paramName)
- : TClassifier(node, NT_PARAM, true)
- , Rollbacks(rollbacks)
- , ParamName(paramName)
- {}
-
- TPatternNode* Classify(TTrackIter cur, const TTrack& track) override
- {
- WWW_CHECK((i64)Rollbacks >= 0 && std::distance(TTrackTr::begin(track), cur) >= (i64)Rollbacks, "wrong rollbacks in node '%s'",
+ : TClassifier(node, NT_PARAM, true)
+ , Rollbacks(rollbacks)
+ , ParamName(paramName)
+ {}
+
+ TPatternNode* Classify(TTrackIter cur, const TTrack& track) override
+ {
+ WWW_CHECK((i64)Rollbacks >= 0 && std::distance(TTrackTr::begin(track), cur) >= (i64)Rollbacks, "wrong rollbacks in node '%s'",
Node->GetPath().data());
- const NLWTrace::TLogItem& item = *(cur - Rollbacks);
- WWW_CHECK(item.SavedParamsCount > 0, "classify by params on probe w/o param loggging in node '%s'",
+ const NLWTrace::TLogItem& item = *(cur - Rollbacks);
+ WWW_CHECK(item.SavedParamsCount > 0, "classify by params on probe w/o param loggging in node '%s'",
Node->GetPath().data());
TString paramValues[LWTRACE_MAX_PARAMS];
TString* paramValue = nullptr;
- item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
- for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
- if (item.Probe->Event.Signature.ParamNames[pi] == ParamName) {
- paramValue = &paramValues[pi];
- }
- }
- WWW_CHECK(paramValue, "param '%s' not found in probe '%s' at path '%s'",
+ item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
+ for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
+ if (item.Probe->Event.Signature.ParamNames[pi] == ParamName) {
+ paramValue = &paramValues[pi];
+ }
+ }
+ WWW_CHECK(paramValue, "param '%s' not found in probe '%s' at path '%s'",
ParamName.data(), GetProbeName(item.Probe).data(), Node->GetPath().data());
-
- TPatternNode* node = &Children[*paramValue];
- // Path example: "//Provider1.Probe1/Provider2.Probe2@1.xxx=123@2.type=harakiri"
- node->Name = "@" + ToString(Rollbacks) + "." + ParamName + "=" + *paramValue;
- node->Desc.Type = NT_PARAM;
- node->Desc.Rollbacks = Rollbacks;
- node->Desc.ParamName = ParamName;
- node->Desc.ParamValue = *paramValue;
- return node;
- }
-
- void Accept(IVisitor* visitor) override
- {
- if (SortedChildren.size() != Children.size()) {
- SortedChildren.clear();
- SortedChildren.reserve(Children.size());
- for (auto i = Children.begin(), e = Children.end(); i != e; ++i) {
- SortedChildren.push_back(&*i);
- }
- Sort(SortedChildren, [] (TChildren::value_type* lhs, TChildren::value_type* rhs) {
- return lhs->first < rhs->first;
- });
- }
- for (auto* kv : SortedChildren) {
- visitor->Visit(&kv->second);
- }
- }
-
- bool IsLeaf() override { return Children.empty(); }
- };
-private:
- TPatternNode Root;
+
+ TPatternNode* node = &Children[*paramValue];
+ // Path example: "//Provider1.Probe1/Provider2.Probe2@1.xxx=123@2.type=harakiri"
+ node->Name = "@" + ToString(Rollbacks) + "." + ParamName + "=" + *paramValue;
+ node->Desc.Type = NT_PARAM;
+ node->Desc.Rollbacks = Rollbacks;
+ node->Desc.ParamName = ParamName;
+ node->Desc.ParamValue = *paramValue;
+ return node;
+ }
+
+ void Accept(IVisitor* visitor) override
+ {
+ if (SortedChildren.size() != Children.size()) {
+ SortedChildren.clear();
+ SortedChildren.reserve(Children.size());
+ for (auto i = Children.begin(), e = Children.end(); i != e; ++i) {
+ SortedChildren.push_back(&*i);
+ }
+ Sort(SortedChildren, [] (TChildren::value_type* lhs, TChildren::value_type* rhs) {
+ return lhs->first < rhs->first;
+ });
+ }
+ for (auto* kv : SortedChildren) {
+ visitor->Visit(&kv->second);
+ }
+ }
+
+ bool IsLeaf() override { return Children.empty(); }
+ };
+private:
+ TPatternNode Root;
THashMap<TString, std::pair<size_t, TString>> ParamClassifiers; // path -> (rollbacks, param)
TString SelectedPattern;
- TPatternNode* SelectedNode = nullptr;
+ TPatternNode* SelectedNode = nullptr;
TVector<ui64> Timeline; // Just to avoid reallocations
-public:
- TPatternTree(const TCgiParameters& e)
- {
+public:
+ TPatternTree(const TCgiParameters& e)
+ {
for (const TString& cl : Subvalues(e, "classify")) {
- size_t at = cl.find_last_of('@');
+ size_t at = cl.find_last_of('@');
if (at != TString::npos) {
- size_t dot = cl.find('.', at + 1);
+ size_t dot = cl.find('.', at + 1);
if (dot != TString::npos) {
- size_t rollbacks = FromString<size_t>(cl.substr(at + 1, dot - at - 1));
- ParamClassifiers[cl.substr(0, at)] = std::make_pair(rollbacks, cl.substr(dot + 1));
- }
- }
- }
- SelectedPattern = e.Get("pattern");
- InitNode(&Root, nullptr);
- }
-
- TPatternNode* GetSelectedNode()
- {
- return SelectedNode;
- }
-
- NAnalytics::TTable GetSelectedTable()
- {
- if (SelectedNode) {
- return SelectedNode->GetTable();
- } else {
- return NAnalytics::TTable();
- }
- }
-
+ size_t rollbacks = FromString<size_t>(cl.substr(at + 1, dot - at - 1));
+ ParamClassifiers[cl.substr(0, at)] = std::make_pair(rollbacks, cl.substr(dot + 1));
+ }
+ }
+ }
+ SelectedPattern = e.Get("pattern");
+ InitNode(&Root, nullptr);
+ }
+
+ TPatternNode* GetSelectedNode()
+ {
+ return SelectedNode;
+ }
+
+ NAnalytics::TTable GetSelectedTable()
+ {
+ if (SelectedNode) {
+ return SelectedNode->GetTable();
+ } else {
+ return NAnalytics::TTable();
+ }
+ }
+
template <typename TReader>
void OutputSelectedSample(const TString& bn, double b1, double b2, const TSampleOpts& opts, TReader& reader)
- {
- if (SelectedNode) {
+ {
+ if (SelectedNode) {
SelectedNode->OutputSample(bn, b1, b2, opts, reader);
- }
- }
-
- // Register track in given node
+ }
+ }
+
+ // Register track in given node
void AddTrackToNode(TPatternNode* node, TTrack& track, ui64 resTotal, TVector<ui64>& timeline)
- {
- if (!SelectedNode) {
- if (node->GetPath() == SelectedPattern) {
- SelectedNode = node;
- }
- }
-
- // Counting
- node->TrackCount++;
-
- // Resource total
- node->ResTotalSum += resTotal;
- node->ResTotalMax = Max(node->ResTotalMax, resTotal);
- node->ResTotalAll.push_back(resTotal);
-
- // Resource last
- ui64 resLast = 0;
- resLast = resTotal - (timeline.size() < 2? 0: timeline[timeline.size() - 2]);
- node->ResLastSum += resLast;
- node->ResLastMax = Max(node->ResLastMax, resLast);
- node->ResLastAll.push_back(resLast);
-
- // Timeline
- if (node->TimelineSum.size() < timeline.size()) {
- node->TimelineSum.resize(timeline.size());
- }
- for (size_t i = 0; i < timeline.size(); i++) {
- node->TimelineSum[i] += timeline[i];
- }
-
- if (node == SelectedNode && !timeline.empty()) {
- node->Slices.emplace_back();
- NAnalytics::TRow& row = node->Slices.back();
- ui64 prev = 0;
- for (size_t i = 0; i < timeline.size(); i++) {
- // Note that col names should go in lexicographical order
- // in the same way as slices go in pattern timeline
- double sliceMs = double(timeline[i] - prev) * 1000.0 / NHPTimer::GetClockRate();
- row[Sprintf("%09lu", i)] = sliceMs;
- prev = timeline[i];
- }
- }
-
- // Interlink node and track
- node->Tracks.emplace_back(&track, resTotal, resLast);
- track.LastNode = node;
- }
-
- bool CheckPattern(const char*& pi, const char* pe, TStringBuf str)
- {
- auto si = str.begin(), se = str.end();
- for (;pi != pe && si != se; ++pi, ++si) {
- if (*pi != *si) {
- return false;
- }
- }
- return si == se;
- }
-
-#define WWW_CHECK_PATTERN(str) if (!CheckPattern(pi, pe, (str))) { return false; }
-
+ {
+ if (!SelectedNode) {
+ if (node->GetPath() == SelectedPattern) {
+ SelectedNode = node;
+ }
+ }
+
+ // Counting
+ node->TrackCount++;
+
+ // Resource total
+ node->ResTotalSum += resTotal;
+ node->ResTotalMax = Max(node->ResTotalMax, resTotal);
+ node->ResTotalAll.push_back(resTotal);
+
+ // Resource last
+ ui64 resLast = 0;
+ resLast = resTotal - (timeline.size() < 2? 0: timeline[timeline.size() - 2]);
+ node->ResLastSum += resLast;
+ node->ResLastMax = Max(node->ResLastMax, resLast);
+ node->ResLastAll.push_back(resLast);
+
+ // Timeline
+ if (node->TimelineSum.size() < timeline.size()) {
+ node->TimelineSum.resize(timeline.size());
+ }
+ for (size_t i = 0; i < timeline.size(); i++) {
+ node->TimelineSum[i] += timeline[i];
+ }
+
+ if (node == SelectedNode && !timeline.empty()) {
+ node->Slices.emplace_back();
+ NAnalytics::TRow& row = node->Slices.back();
+ ui64 prev = 0;
+ for (size_t i = 0; i < timeline.size(); i++) {
+ // Note that col names should go in lexicographical order
+ // in the same way as slices go in pattern timeline
+ double sliceMs = double(timeline[i] - prev) * 1000.0 / NHPTimer::GetClockRate();
+ row[Sprintf("%09lu", i)] = sliceMs;
+ prev = timeline[i];
+ }
+ }
+
+ // Interlink node and track
+ node->Tracks.emplace_back(&track, resTotal, resLast);
+ track.LastNode = node;
+ }
+
+ bool CheckPattern(const char*& pi, const char* pe, TStringBuf str)
+ {
+ auto si = str.begin(), se = str.end();
+ for (;pi != pe && si != se; ++pi, ++si) {
+ if (*pi != *si) {
+ return false;
+ }
+ }
+ return si == se;
+ }
+
+#define WWW_CHECK_PATTERN(str) if (!CheckPattern(pi, pe, (str))) { return false; }
+
bool MatchTrack(const TTrack& track, const TString& patternStr)
- {
+ {
const char* pi = patternStr.data();
const char* pe = pi + patternStr.size();
- WWW_CHECK_PATTERN("/");
- for (TTrackIter i = TTrackTr::begin(track), e = TTrackTr::end(track); i != e; ++i) {
- if (pi == pe) {
- return true;
- }
- const NLWTrace::TLogItem& item = *i;
- WWW_CHECK_PATTERN("/");
- WWW_CHECK_PATTERN(item.Probe->Event.GetProvider());
- WWW_CHECK_PATTERN(".");
- WWW_CHECK_PATTERN(item.Probe->Event.Name);
- while (true) {
- if (pi == pe) {
- return true;
- }
- char c = *pi;
- if (c == '/') {
- break;
- } else if (c == '@') {
- pi++;
- // Parse rollbacks
- TStringBuf p(pi, pe);
- size_t dot = p.find('.');
- if (dot == TStringBuf::npos) {
- return false;
- }
- size_t rollbacks = 0;
- try {
- rollbacks = FromString<size_t>(p.substr(0, dot));
- } catch (...) {
- return false;
- }
-
- // Parse param name
- size_t equals = p.find('=', dot + 1);
- if (equals == TStringBuf::npos) {
- return false;
- }
- TStringBuf paramName = p.substr(dot + 1, equals - dot - 1);
-
- pi += equals + 1; // Advance to value
-
- // Check param value
- if ((i64)rollbacks < 0 || std::distance(TTrackTr::begin(track), i) < (i64)rollbacks) {
- return false;
- }
- const NLWTrace::TLogItem& mitem = *(i - rollbacks);
- if (mitem.SavedParamsCount == 0) {
- return false;
- }
+ WWW_CHECK_PATTERN("/");
+ for (TTrackIter i = TTrackTr::begin(track), e = TTrackTr::end(track); i != e; ++i) {
+ if (pi == pe) {
+ return true;
+ }
+ const NLWTrace::TLogItem& item = *i;
+ WWW_CHECK_PATTERN("/");
+ WWW_CHECK_PATTERN(item.Probe->Event.GetProvider());
+ WWW_CHECK_PATTERN(".");
+ WWW_CHECK_PATTERN(item.Probe->Event.Name);
+ while (true) {
+ if (pi == pe) {
+ return true;
+ }
+ char c = *pi;
+ if (c == '/') {
+ break;
+ } else if (c == '@') {
+ pi++;
+ // Parse rollbacks
+ TStringBuf p(pi, pe);
+ size_t dot = p.find('.');
+ if (dot == TStringBuf::npos) {
+ return false;
+ }
+ size_t rollbacks = 0;
+ try {
+ rollbacks = FromString<size_t>(p.substr(0, dot));
+ } catch (...) {
+ return false;
+ }
+
+ // Parse param name
+ size_t equals = p.find('=', dot + 1);
+ if (equals == TStringBuf::npos) {
+ return false;
+ }
+ TStringBuf paramName = p.substr(dot + 1, equals - dot - 1);
+
+ pi += equals + 1; // Advance to value
+
+ // Check param value
+ if ((i64)rollbacks < 0 || std::distance(TTrackTr::begin(track), i) < (i64)rollbacks) {
+ return false;
+ }
+ const NLWTrace::TLogItem& mitem = *(i - rollbacks);
+ if (mitem.SavedParamsCount == 0) {
+ return false;
+ }
TString paramValues[LWTRACE_MAX_PARAMS];
TString* paramValue = nullptr;
- mitem.Probe->Event.Signature.SerializeParams(mitem.Params, paramValues);
- for (size_t pi = 0; pi < mitem.SavedParamsCount; pi++) {
- if (mitem.Probe->Event.Signature.ParamNames[pi] == paramName) {
- paramValue = &paramValues[pi];
- }
- }
- if (!paramValue) {
- return false;
- }
- WWW_CHECK_PATTERN(*paramValue);
- } else {
- return false;
- }
- }
- }
- return true;
- }
-
-#undef WWW_CHECK_PATTERN
-
- // Push new track through pattern tree
- void AddTrack(TTrack& track)
- {
- // Truncate long tracks
- if (track.Items.size() > 50) {
- track.Items.resize(50);
- }
-
- if (SelectedPattern) {
- if (!MatchTrack(track, SelectedPattern)) {
- return;
- }
- }
-
- Timeline.clear();
- TPatternNode* node = &Root;
- AddTrackToNode(node, track, 0, Timeline);
- ui64 trackStart = TTrackTr::front(track).TimestampCycles;
- for (TTrackIter i = TTrackTr::begin(track), e = TTrackTr::end(track); i != e;) {
- // Get or create child by classification
- TPatternNode* parent = node;
- node = node->Classifier->Classify(i, track);
- if (!node->Classifier) {
- InitNode(node, parent);
- }
-
- const NLWTrace::TLogItem& item = *i;
- ui64 resTotal = item.TimestampCycles - trackStart;
- if (i != TTrackTr::begin(track)) {
- Timeline.push_back(resTotal);
- }
- AddTrackToNode(node, track, resTotal, Timeline);
-
- // Move through track
- if (!node->Classifier->KeepHead) {
- ++i;
- }
- }
- }
-
- // Traverse pattern tree (the only way to extract data from it)
- template <class TOnNode, class TOnDescend, class TOnAscend>
- void Traverse(TOnNode&& onNode, TOnDescend&& onDescend, TOnAscend&& onAscend)
- {
- struct TVisitor : public IVisitor {
- TOnNode OnNode;
- TOnDescend OnDescend;
- TOnAscend OnAscend;
- TVisitor(TOnNode&& onNode, TOnDescend&& onDescend, TOnAscend&& onAscend)
- : OnNode(onNode)
- , OnDescend(onDescend)
- , OnAscend(onAscend)
- {}
- virtual void Visit(TPatternNode* node) override
- {
- OnNode(node);
- if (!node->Classifier->IsLeaf()) {
- OnDescend();
- node->Classifier->Accept(this);
- OnAscend();
- }
- }
- };
- TVisitor visitor(std::move(onNode), std::move(onDescend), std::move(onAscend));
- visitor.Visit(&Root);
- }
-
- TPatternNode* GetRoot()
- {
- return &Root;
- }
-
-private:
- void InitNode(TPatternNode* node, TPatternNode* parent)
- {
- node->Parent = parent;
- auto iter = ParamClassifiers.find(node->GetPath());
- if (iter != ParamClassifiers.end()) {
- node->Classifier.Reset(new TClassifyByParam(node, iter->second.first, iter->second.second));
- } else {
- node->Classifier.Reset(new TClassifyByProbe(node));
- }
- }
-};
-
-class TLogTrackExtractor: public TLogFilter {
-private:
- // Data storage
+ mitem.Probe->Event.Signature.SerializeParams(mitem.Params, paramValues);
+ for (size_t pi = 0; pi < mitem.SavedParamsCount; pi++) {
+ if (mitem.Probe->Event.Signature.ParamNames[pi] == paramName) {
+ paramValue = &paramValues[pi];
+ }
+ }
+ if (!paramValue) {
+ return false;
+ }
+ WWW_CHECK_PATTERN(*paramValue);
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+#undef WWW_CHECK_PATTERN
+
+ // Push new track through pattern tree
+ void AddTrack(TTrack& track)
+ {
+ // Truncate long tracks
+ if (track.Items.size() > 50) {
+ track.Items.resize(50);
+ }
+
+ if (SelectedPattern) {
+ if (!MatchTrack(track, SelectedPattern)) {
+ return;
+ }
+ }
+
+ Timeline.clear();
+ TPatternNode* node = &Root;
+ AddTrackToNode(node, track, 0, Timeline);
+ ui64 trackStart = TTrackTr::front(track).TimestampCycles;
+ for (TTrackIter i = TTrackTr::begin(track), e = TTrackTr::end(track); i != e;) {
+ // Get or create child by classification
+ TPatternNode* parent = node;
+ node = node->Classifier->Classify(i, track);
+ if (!node->Classifier) {
+ InitNode(node, parent);
+ }
+
+ const NLWTrace::TLogItem& item = *i;
+ ui64 resTotal = item.TimestampCycles - trackStart;
+ if (i != TTrackTr::begin(track)) {
+ Timeline.push_back(resTotal);
+ }
+ AddTrackToNode(node, track, resTotal, Timeline);
+
+ // Move through track
+ if (!node->Classifier->KeepHead) {
+ ++i;
+ }
+ }
+ }
+
+ // Traverse pattern tree (the only way to extract data from it)
+ template <class TOnNode, class TOnDescend, class TOnAscend>
+ void Traverse(TOnNode&& onNode, TOnDescend&& onDescend, TOnAscend&& onAscend)
+ {
+ struct TVisitor : public IVisitor {
+ TOnNode OnNode;
+ TOnDescend OnDescend;
+ TOnAscend OnAscend;
+ TVisitor(TOnNode&& onNode, TOnDescend&& onDescend, TOnAscend&& onAscend)
+ : OnNode(onNode)
+ , OnDescend(onDescend)
+ , OnAscend(onAscend)
+ {}
+ virtual void Visit(TPatternNode* node) override
+ {
+ OnNode(node);
+ if (!node->Classifier->IsLeaf()) {
+ OnDescend();
+ node->Classifier->Accept(this);
+ OnAscend();
+ }
+ }
+ };
+ TVisitor visitor(std::move(onNode), std::move(onDescend), std::move(onAscend));
+ visitor.Visit(&Root);
+ }
+
+ TPatternNode* GetRoot()
+ {
+ return &Root;
+ }
+
+private:
+ void InitNode(TPatternNode* node, TPatternNode* parent)
+ {
+ node->Parent = parent;
+ auto iter = ParamClassifiers.find(node->GetPath());
+ if (iter != ParamClassifiers.end()) {
+ node->Classifier.Reset(new TClassifyByParam(node, iter->second.first, iter->second.second));
+ } else {
+ node->Classifier.Reset(new TClassifyByProbe(node));
+ }
+ }
+};
+
+class TLogTrackExtractor: public TLogFilter {
+private:
+ // Data storage
TMultiMap<ui64, std::pair<TThread::TId, NLWTrace::TLogItem>> Items;
TVector<NLWTrace::TTrackLog> Depot;
-
- // Data refs organized in tracks
+
+ // Data refs organized in tracks
THashMap<TString, TTrack> Tracks;
TVector<TTrack> TracksFromDepot;
-
- // Analysis
+
+ // Analysis
TVector<TString> GroupBy;
THashSet<TString> TrackIds; // The same content as in GroupBy
- TTimestampCutter CutTs;
- TPatternTree Tree;
-public:
+ TTimestampCutter CutTs;
+ TPatternTree Tree;
+public:
TLogTrackExtractor(const TCgiParameters& e, const TVector<TString>& filters, const TVector<TString>& groupBy)
- : TLogFilter(filters)
- , CutTs(true) // Always cut input data for tracks
- , Tree(e)
- {
+ : TLogFilter(filters)
+ , CutTs(true) // Always cut input data for tracks
+ , Tree(e)
+ {
for (const TString& groupParam : groupBy) {
- GroupBy.push_back(groupParam);
- TrackIds.insert(groupParam);
- }
- }
-
- // For reading lwtrace log (input point for all data)
- void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- CutTs.Push(tid, item);
- if (Filter(item)) {
- Items.emplace(item.TimestampCycles, std::make_pair(tid, item));
- }
- }
-
- // For reading lwtrace depot (input point for all data)
- void Push(TThread::TId, const NLWTrace::TTrackLog& tl)
- {
- if (Filter(tl)) {
- Depot.emplace_back(tl);
- }
- }
-
- // Analyze logs that have been read
- void Run()
- {
- RunImplLog();
- RunImplDepot();
- }
-
- void RunImplLog()
- {
- // Create tracks by filling them with lwtrace items in order of occurance time
- for (auto& kv : Items) {
- AddItemToTrack(kv.second.first, kv.second.second);
- }
- // Push tracks throught pattern tree
- for (auto& kv : Tracks) {
- TTrack& track = kv.second;
- track.TrackId = kv.first;
- Tree.AddTrack(track);
- }
- }
-
- void RunImplDepot()
- {
- // Create tracks from depot
- // OPTIMIZE[serxa]: this convertion is not necessary, done just to keep things simple
- for (NLWTrace::TTrackLog& tl : Depot) {
- TTrack& track = TracksFromDepot.emplace_back();
- track.TrackId = ToString(tl.Id);
- for (const NLWTrace::TTrackLog::TItem& i : tl.Items) {
- track.Items.emplace_back(i.ThreadId, i);
- }
- }
- for (TTrack& t : TracksFromDepot) {
- Tree.AddTrack(t);
- }
- }
-
- // Selected node distribution
- NAnalytics::TTable Distribution(const TString& bn, const TString& b1Str, const TString& b2Str, const TString& widthStr)
- {
- using namespace NAnalytics;
-
- const NAnalytics::TTable& inputTable = Tree.GetSelectedTable();
- double b1 = b1Str? FromString<double>(b1Str): MinValue(bn, inputTable);
- double b2 = b2Str? FromString<double>(b2Str): MaxValue(bn, inputTable);
- if (isfinite(b1) && isfinite(b2)) {
- WWW_CHECK(b1 <= b2, "invalid xrange [%le; %le]", b1, b2);
- double width = widthStr? FromString<double>(widthStr): 99;
- double dx = (b2 - b1) / width;
- if (!(dx > 0)) {
- dx = 1.0;
- }
- return HistogramAll(inputTable, bn, b1, b2, dx);
- } else {
- // Empty table -- it's ok -- leave data table empty
- return NAnalytics::TTable();
- }
- }
-
- // Selected sample
+ GroupBy.push_back(groupParam);
+ TrackIds.insert(groupParam);
+ }
+ }
+
+ // For reading lwtrace log (input point for all data)
+ void Push(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ CutTs.Push(tid, item);
+ if (Filter(item)) {
+ Items.emplace(item.TimestampCycles, std::make_pair(tid, item));
+ }
+ }
+
+ // For reading lwtrace depot (input point for all data)
+ void Push(TThread::TId, const NLWTrace::TTrackLog& tl)
+ {
+ if (Filter(tl)) {
+ Depot.emplace_back(tl);
+ }
+ }
+
+ // Analyze logs that have been read
+ void Run()
+ {
+ RunImplLog();
+ RunImplDepot();
+ }
+
+ void RunImplLog()
+ {
+ // Create tracks by filling them with lwtrace items in order of occurance time
+ for (auto& kv : Items) {
+ AddItemToTrack(kv.second.first, kv.second.second);
+ }
+ // Push tracks throught pattern tree
+ for (auto& kv : Tracks) {
+ TTrack& track = kv.second;
+ track.TrackId = kv.first;
+ Tree.AddTrack(track);
+ }
+ }
+
+ void RunImplDepot()
+ {
+ // Create tracks from depot
+ // OPTIMIZE[serxa]: this convertion is not necessary, done just to keep things simple
+ for (NLWTrace::TTrackLog& tl : Depot) {
+ TTrack& track = TracksFromDepot.emplace_back();
+ track.TrackId = ToString(tl.Id);
+ for (const NLWTrace::TTrackLog::TItem& i : tl.Items) {
+ track.Items.emplace_back(i.ThreadId, i);
+ }
+ }
+ for (TTrack& t : TracksFromDepot) {
+ Tree.AddTrack(t);
+ }
+ }
+
+ // Selected node distribution
+ NAnalytics::TTable Distribution(const TString& bn, const TString& b1Str, const TString& b2Str, const TString& widthStr)
+ {
+ using namespace NAnalytics;
+
+ const NAnalytics::TTable& inputTable = Tree.GetSelectedTable();
+ double b1 = b1Str? FromString<double>(b1Str): MinValue(bn, inputTable);
+ double b2 = b2Str? FromString<double>(b2Str): MaxValue(bn, inputTable);
+ if (isfinite(b1) && isfinite(b2)) {
+ WWW_CHECK(b1 <= b2, "invalid xrange [%le; %le]", b1, b2);
+ double width = widthStr? FromString<double>(widthStr): 99;
+ double dx = (b2 - b1) / width;
+ if (!(dx > 0)) {
+ dx = 1.0;
+ }
+ return HistogramAll(inputTable, bn, b1, b2, dx);
+ } else {
+ // Empty table -- it's ok -- leave data table empty
+ return NAnalytics::TTable();
+ }
+ }
+
+ // Selected sample
template <typename TReader>
void OutputSample(const TString& bn, double b1, double b2, const TSampleOpts& opts, TReader& reader)
- {
+ {
Tree.OutputSelectedSample(bn, b1, b2, opts, reader);
- }
-
- // Tabular representation of tracks data
+ }
+
+ // Tabular representation of tracks data
void OutputTable(IOutputStream& os, const TCgiParameters& e)
- {
- ui64 tracksTotal = Tree.GetRoot()->TrackCount;
-
- double maxAvgResTotal = 0;
- double maxMaxResTotal = 0;
- Tree.Traverse([&] (TPatternNode* node) {
- if (node->TrackCount > 0) {
- maxAvgResTotal = Max(maxAvgResTotal, double(node->ResTotalSum) / node->TrackCount);
- maxMaxResTotal = Max(maxMaxResTotal, double(node->ResTotalMax));
- Sort(node->ResTotalAll);
- Sort(node->ResLastAll);
- }
- }, [&] () { // On descend
- }, [&] () { // On ascend
- });
- double maxTime = Min(maxMaxResTotal, 1.25 * maxAvgResTotal);
-
- double percentile = e.Get("ile")? FromString<double>(e.Get("ile")): 90;
- WWW_CHECK(percentile >= 0.0 && percentile <= 100.0, "wrong percentile: %lf", percentile);
-
- ui64 row = 0;
+ {
+ ui64 tracksTotal = Tree.GetRoot()->TrackCount;
+
+ double maxAvgResTotal = 0;
+ double maxMaxResTotal = 0;
+ Tree.Traverse([&] (TPatternNode* node) {
+ if (node->TrackCount > 0) {
+ maxAvgResTotal = Max(maxAvgResTotal, double(node->ResTotalSum) / node->TrackCount);
+ maxMaxResTotal = Max(maxMaxResTotal, double(node->ResTotalMax));
+ Sort(node->ResTotalAll);
+ Sort(node->ResLastAll);
+ }
+ }, [&] () { // On descend
+ }, [&] () { // On ascend
+ });
+ double maxTime = Min(maxMaxResTotal, 1.25 * maxAvgResTotal);
+
+ double percentile = e.Get("ile")? FromString<double>(e.Get("ile")): 90;
+ WWW_CHECK(percentile >= 0.0 && percentile <= 100.0, "wrong percentile: %lf", percentile);
+
+ ui64 row = 0;
TVector<ui64> chain;
- HTML(os) {
- TABLE_CLASS("tracks-tree") {
- TABLEHEAD() {
- os << "<tr>";
- os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">#</td>";
- os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Pattern</td>";
- os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">";
- DIV_CLASS("rotate") { os << "Track Count"; }
- os << "</td>";
- os << "<td colspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Share</td>";
- os << "<td colspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Total, ms</td>";
- os << "<td colspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Last, ms</td>";
- os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" class=\"timelinehead\" align=\"center\">Global Timeline</td>";
- os << "</tr><tr>";
- TABLEH() DIV_CLASS("rotate") { os << "Absolute"; }
- TABLEH() DIV_CLASS("rotate") { os << "Relative"; }
- TABLEH() DIV_CLASS("rotate") { os << "Average"; }
- TABLEH() DIV_CLASS("rotate") { os << percentile << "%-ile"; }
- TABLEH() DIV_CLASS("rotate") { os << "Average"; }
- TABLEH() DIV_CLASS("rotate") { os << percentile << "%-ile"; }
- os << "</tr>";
- }
- TABLEBODY() {
- if (tracksTotal == 0) {
- return;
- }
- Tree.Traverse([&] (TPatternNode* node) {
+ HTML(os) {
+ TABLE_CLASS("tracks-tree") {
+ TABLEHEAD() {
+ os << "<tr>";
+ os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">#</td>";
+ os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Pattern</td>";
+ os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">";
+ DIV_CLASS("rotate") { os << "Track Count"; }
+ os << "</td>";
+ os << "<td colspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Share</td>";
+ os << "<td colspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Total, ms</td>";
+ os << "<td colspan=\"2\" style=\"vertical-align:bottom\" align=\"center\">Last, ms</td>";
+ os << "<td rowspan=\"2\" style=\"vertical-align:bottom\" class=\"timelinehead\" align=\"center\">Global Timeline</td>";
+ os << "</tr><tr>";
+ TABLEH() DIV_CLASS("rotate") { os << "Absolute"; }
+ TABLEH() DIV_CLASS("rotate") { os << "Relative"; }
+ TABLEH() DIV_CLASS("rotate") { os << "Average"; }
+ TABLEH() DIV_CLASS("rotate") { os << percentile << "%-ile"; }
+ TABLEH() DIV_CLASS("rotate") { os << "Average"; }
+ TABLEH() DIV_CLASS("rotate") { os << percentile << "%-ile"; }
+ os << "</tr>";
+ }
+ TABLEBODY() {
+ if (tracksTotal == 0) {
+ return;
+ }
+ Tree.Traverse([&] (TPatternNode* node) {
TString parentClass;
- if (!chain.empty()) {
- parentClass = " treegrid-parent-" + ToString(chain.back());
- }
+ if (!chain.empty()) {
+ parentClass = " treegrid-parent-" + ToString(chain.back());
+ }
TString selectedClass;
- if (e.Get("pattern") == node->GetPath()) {
- selectedClass = " danger";
- }
- TABLER_CLASS("treegrid-" + ToString(++row) + parentClass + selectedClass) {
- // Counting
- ui64 tracksParent = node->Parent? node->Parent->TrackCount: tracksTotal;
- double absShare = double(node->TrackCount) * 100 / tracksTotal;
- double relShare = double(node->TrackCount) * 100 / tracksParent;
-
- // Resource total
- double avgResTotal = double(node->ResTotalSum) / node->TrackCount;
- size_t ileResTotalIdx = node->ResTotalAll.size() * percentile / 100;
- if (ileResTotalIdx > 0) {
- ileResTotalIdx--;
- }
- double ileResTotal = double(ileResTotalIdx >= node->ResTotalAll.size()? 0: node->ResTotalAll[ileResTotalIdx]);
- double avgResTotalMs = avgResTotal * 1000.0 / NHPTimer::GetClockRate();
- double ileResTotalMs = ileResTotal * 1000.0 / NHPTimer::GetClockRate();
-
- // Resource last
- double avgResLast = double(node->ResLastSum) / node->TrackCount;
- size_t ileResLastIdx = node->ResLastAll.size() * percentile / 100;
- if (ileResLastIdx > 0) {
- ileResLastIdx--;
- }
- double ileResLast = double(ileResLastIdx >= node->ResLastAll.size()? 0: node->ResLastAll[ileResLastIdx]);
- double avgResLastMs = avgResLast * 1000.0 / NHPTimer::GetClockRate();
- double ileResLastMs = ileResLast * 1000.0 / NHPTimer::GetClockRate();
-
- // Output
- TABLED() { os << row; }
- TABLED_CLASS("treegrid-element") { OutputPattern(os, e, node); }
- TABLED() { os << node->TrackCount; }
- TABLED() { OutputShare(os, absShare); }
- TABLED() { OutputShare(os, relShare); }
- TABLED() { os << FormatFloat(avgResTotalMs); }
- TABLED() { os << FormatFloat(ileResTotalMs); }
- TABLED() { os << FormatFloat(avgResLastMs); }
- TABLED() { os << FormatFloat(ileResLastMs); }
- TABLED() { OutputTimeline(os, MakeTimeline(node), maxTime); }
- }
- }, [&] () { // On descend
- chain.push_back(row);
- }, [&] () { // On ascend
- chain.pop_back();
- });
- }
- }
- }
- }
-
- // Chromium-compatible trace representation of tracks data
+ if (e.Get("pattern") == node->GetPath()) {
+ selectedClass = " danger";
+ }
+ TABLER_CLASS("treegrid-" + ToString(++row) + parentClass + selectedClass) {
+ // Counting
+ ui64 tracksParent = node->Parent? node->Parent->TrackCount: tracksTotal;
+ double absShare = double(node->TrackCount) * 100 / tracksTotal;
+ double relShare = double(node->TrackCount) * 100 / tracksParent;
+
+ // Resource total
+ double avgResTotal = double(node->ResTotalSum) / node->TrackCount;
+ size_t ileResTotalIdx = node->ResTotalAll.size() * percentile / 100;
+ if (ileResTotalIdx > 0) {
+ ileResTotalIdx--;
+ }
+ double ileResTotal = double(ileResTotalIdx >= node->ResTotalAll.size()? 0: node->ResTotalAll[ileResTotalIdx]);
+ double avgResTotalMs = avgResTotal * 1000.0 / NHPTimer::GetClockRate();
+ double ileResTotalMs = ileResTotal * 1000.0 / NHPTimer::GetClockRate();
+
+ // Resource last
+ double avgResLast = double(node->ResLastSum) / node->TrackCount;
+ size_t ileResLastIdx = node->ResLastAll.size() * percentile / 100;
+ if (ileResLastIdx > 0) {
+ ileResLastIdx--;
+ }
+ double ileResLast = double(ileResLastIdx >= node->ResLastAll.size()? 0: node->ResLastAll[ileResLastIdx]);
+ double avgResLastMs = avgResLast * 1000.0 / NHPTimer::GetClockRate();
+ double ileResLastMs = ileResLast * 1000.0 / NHPTimer::GetClockRate();
+
+ // Output
+ TABLED() { os << row; }
+ TABLED_CLASS("treegrid-element") { OutputPattern(os, e, node); }
+ TABLED() { os << node->TrackCount; }
+ TABLED() { OutputShare(os, absShare); }
+ TABLED() { OutputShare(os, relShare); }
+ TABLED() { os << FormatFloat(avgResTotalMs); }
+ TABLED() { os << FormatFloat(ileResTotalMs); }
+ TABLED() { os << FormatFloat(avgResLastMs); }
+ TABLED() { os << FormatFloat(ileResLastMs); }
+ TABLED() { OutputTimeline(os, MakeTimeline(node), maxTime); }
+ }
+ }, [&] () { // On descend
+ chain.push_back(row);
+ }, [&] () { // On ascend
+ chain.pop_back();
+ });
+ }
+ }
+ }
+ }
+
+ // Chromium-compatible trace representation of tracks data
void OutputChromeTrace(IOutputStream& os, const TCgiParameters& e)
- {
- Y_UNUSED(e);
- TChromeTrace tr;
- for (TPatternNode::TTrackEntry& entry: Tree.GetRoot()->Tracks) {
- TTrack* track = entry.Track;
- auto first = TTrackTr::begin(*track);
- auto last = TTrackTr::rbegin(*track);
-
+ {
+ Y_UNUSED(e);
+ TChromeTrace tr;
+ for (TPatternNode::TTrackEntry& entry: Tree.GetRoot()->Tracks) {
+ TTrack* track = entry.Track;
+ auto first = TTrackTr::begin(*track);
+ auto last = TTrackTr::rbegin(*track);
+
TString name = track->LastNode->GetPath();
-
- const NLWTrace::TLogItem& firstItem = *first;
- TThread::TId firstTid = first->ThreadId;
- tr.Add(firstTid, firstItem.TimestampCycles, "b", "track", nullptr, name, track->TrackId);
-
- for (auto cur = TTrackTr::begin(*track), end = TTrackTr::end(*track); cur != end; ++cur) {
- const NLWTrace::TLogItem& item = *cur;
-
- tr.Add(cur->ThreadId, item.TimestampCycles, "i", "event", &item, GetProbeName(item.Probe));
-
+
+ const NLWTrace::TLogItem& firstItem = *first;
+ TThread::TId firstTid = first->ThreadId;
+ tr.Add(firstTid, firstItem.TimestampCycles, "b", "track", nullptr, name, track->TrackId);
+
+ for (auto cur = TTrackTr::begin(*track), end = TTrackTr::end(*track); cur != end; ++cur) {
+ const NLWTrace::TLogItem& item = *cur;
+
+ tr.Add(cur->ThreadId, item.TimestampCycles, "i", "event", &item, GetProbeName(item.Probe));
+
TString sliceName = GetProbeName(item.Probe);
-
- auto next = cur + 1;
- if (next != end) {
- const NLWTrace::TLogItem& nextItem = *next;
- tr.Add(cur->ThreadId, item.TimestampCycles, "b", "track", &item, sliceName, track->TrackId);
- tr.Add(next->ThreadId, nextItem.TimestampCycles, "e", "track", &nextItem, sliceName, track->TrackId);
- } else {
- tr.Add(cur->ThreadId, item.TimestampCycles, "n", "track", &item, sliceName, track->TrackId);
- }
- }
-
- const NLWTrace::TLogItem& lastItem = *last;
- tr.Add(last->ThreadId, lastItem.TimestampCycles, "e", "track", nullptr, name, track->TrackId);
- }
- tr.Output(os);
- }
-
+
+ auto next = cur + 1;
+ if (next != end) {
+ const NLWTrace::TLogItem& nextItem = *next;
+ tr.Add(cur->ThreadId, item.TimestampCycles, "b", "track", &item, sliceName, track->TrackId);
+ tr.Add(next->ThreadId, nextItem.TimestampCycles, "e", "track", &nextItem, sliceName, track->TrackId);
+ } else {
+ tr.Add(cur->ThreadId, item.TimestampCycles, "n", "track", &item, sliceName, track->TrackId);
+ }
+ }
+
+ const NLWTrace::TLogItem& lastItem = *last;
+ tr.Add(last->ThreadId, lastItem.TimestampCycles, "e", "track", nullptr, name, track->TrackId);
+ }
+ tr.Output(os);
+ }
+
void OutputSliceCovarianceMatrix(IOutputStream& os, const TCgiParameters& e)
- {
- Y_UNUSED(e);
- TPatternNode* node = Tree.GetSelectedNode();
- if (!node) {
- return;
- }
-
- NAnalytics::TMatrix covMatrix = NAnalytics::CovarianceMatrix(node->Slices);
- double var = covMatrix.CellSum();
-
- double covMax = 0.0;
- for (double x : covMatrix) {
- if (covMax < x) {
- covMax = x;
- }
- }
- double dangerCov = covMax * 0.9 * 0.9;
- double warnCov = covMax * 0.5 * 0.5;
-
- HTML(os) {
- TABLE() {
- TTimeline timeline = MakeTimeline(node);
- TABLEHEAD() TABLER() {
- TABLED();
- for (auto& e : timeline) TABLED() {
- TPatternNode* subnode = e.first;
- os << subnode->Name;
- }
- }
-
- auto tl = timeline.begin();
- TABLEBODY() for (size_t row = 0; row < covMatrix.Rows; row++) TABLER() {
- TABLEH() {
- if (tl != timeline.end()) {
- TPatternNode* subnode = tl->first;
- os << subnode->Name;
- ++tl;
- }
- }
-
- for (size_t col = 0; col < covMatrix.Cols; col++) {
- double cov = covMatrix.Cell(row, col);
- TString tdClass = (cov >= dangerCov? "danger": (cov >= warnCov? "warning": ""));
- TABLED_CLASS(tdClass) {
- double sigmaX = (covMatrix.Cell(row, row) > 0? sqrt(covMatrix.Cell(row, row)): 0);
- double sigmaY = (covMatrix.Cell(col, col) > 0? sqrt(covMatrix.Cell(col, col)): 0);
- os << Sprintf("cov=%.3lf&nbsp;ms<sup>2</sup>&nbsp;(%.3lf&nbsp;ms) corr=%.1lf%% var_share=%.1lf%%",
- cov, sqrt(abs(cov)), cov * 100.0 / sigmaX / sigmaY, cov * 100.0 / var);
- }
- }
- }
- }
- }
- }
-
-private:
- TPatternNode* RollbackFind(TPatternNode* node)
- {
- for (;node != nullptr; node = node->Parent) {
- if (node->Desc.Type == NT_PROBE) {
- return node;
- }
- }
- return nullptr;
- }
-
+ {
+ Y_UNUSED(e);
+ TPatternNode* node = Tree.GetSelectedNode();
+ if (!node) {
+ return;
+ }
+
+ NAnalytics::TMatrix covMatrix = NAnalytics::CovarianceMatrix(node->Slices);
+ double var = covMatrix.CellSum();
+
+ double covMax = 0.0;
+ for (double x : covMatrix) {
+ if (covMax < x) {
+ covMax = x;
+ }
+ }
+ double dangerCov = covMax * 0.9 * 0.9;
+ double warnCov = covMax * 0.5 * 0.5;
+
+ HTML(os) {
+ TABLE() {
+ TTimeline timeline = MakeTimeline(node);
+ TABLEHEAD() TABLER() {
+ TABLED();
+ for (auto& e : timeline) TABLED() {
+ TPatternNode* subnode = e.first;
+ os << subnode->Name;
+ }
+ }
+
+ auto tl = timeline.begin();
+ TABLEBODY() for (size_t row = 0; row < covMatrix.Rows; row++) TABLER() {
+ TABLEH() {
+ if (tl != timeline.end()) {
+ TPatternNode* subnode = tl->first;
+ os << subnode->Name;
+ ++tl;
+ }
+ }
+
+ for (size_t col = 0; col < covMatrix.Cols; col++) {
+ double cov = covMatrix.Cell(row, col);
+ TString tdClass = (cov >= dangerCov? "danger": (cov >= warnCov? "warning": ""));
+ TABLED_CLASS(tdClass) {
+ double sigmaX = (covMatrix.Cell(row, row) > 0? sqrt(covMatrix.Cell(row, row)): 0);
+ double sigmaY = (covMatrix.Cell(col, col) > 0? sqrt(covMatrix.Cell(col, col)): 0);
+ os << Sprintf("cov=%.3lf&nbsp;ms<sup>2</sup>&nbsp;(%.3lf&nbsp;ms) corr=%.1lf%% var_share=%.1lf%%",
+ cov, sqrt(abs(cov)), cov * 100.0 / sigmaX / sigmaY, cov * 100.0 / var);
+ }
+ }
+ }
+ }
+ }
+ }
+
+private:
+ TPatternNode* RollbackFind(TPatternNode* node)
+ {
+ for (;node != nullptr; node = node->Parent) {
+ if (node->Desc.Type == NT_PROBE) {
+ return node;
+ }
+ }
+ return nullptr;
+ }
+
void OutputPattern(IOutputStream& os, const TCgiParameters& e, TPatternNode* node)
- {
- // Fill pattern name
+ {
+ // Fill pattern name
TString patternName;
TString patternTitle;
- switch (node->Desc.Type) {
- case NT_ROOT:
- patternName = "All Tracks";
- break;
- case NT_PROBE:
- patternTitle = GetProbeName(node->Desc.Probe);
- patternName = node->Desc.Probe->Event.Name;
- break;
- case NT_PARAM:
- patternName.append(node->Desc.ParamName + " = " + node->Desc.ParamValue);
- break;
- }
-
- os << "<a href=\"" << MakeUrl(e, {
- {"pattern", node->GetPath()},
- {"ptrn_anlz", e.Get("ptrn_anlz") ? e.Get("ptrn_anlz") : "resTotal"},
- {"linesfill", "y"},
- {"linessteps", "y"},
- {"pointsshow", "n"},
- {"sel_x1", e.Get("sel_x1") ? e.Get("sel_x1") : "0"},
- {"sel_x2", e.Get("sel_x2") ? e.Get("sel_x2") : "inf"}}) << "\""
- " title=\"" + patternTitle + "\">" << patternName << "</a>";
-
- // Add/remove node menu
- if (node->Desc.Type != NT_ROOT) {
- os << "<div class=\"dropdown pull-right\" style=\"display:inline-block\">";
- if (node->Desc.Type == NT_PARAM) {
- os<< "<button class=\"btn btn-xs btn-default\" type=\"button\""
- << "\" onClick=\"window.location.href='"
- << MakeUrlEraseSub(e, "classify", node->Parent->GetPath() + "@"
- + ToString(node->Desc.Rollbacks) + "." + node->Desc.ParamName)
- << "';\">"
- "<span class=\"glyphicon glyphicon-minus\"></span>"
- "</button>";
- }
- if (node->Classifier->GetChildType() != NT_PARAM) {
- os << "<button class=\"btn btn-xs btn-default dropdown-toggle\" type=\"button\""
- " data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">"
- "<span class=\"glyphicon glyphicon-plus\"></span>"
- "</button>"
- "<ul class=\"dropdown-menu\">"
- "<li class=\"dropdown-header\">Classify by param:</li>";
- int rollbacks = 0;
- TPatternNode* probeNode = node;
- while (probeNode = RollbackFind(probeNode)) {
- const NLWTrace::TProbe* probe = probeNode->Desc.Probe;
- os << "<li class=\"dropdown-header\">" << GetProbeName(probe) << "</li>";
- const NLWTrace::TSignature* sgn = &probe->Event.Signature;
- for (size_t pi = 0; pi < sgn->ParamCount; pi++) {
+ switch (node->Desc.Type) {
+ case NT_ROOT:
+ patternName = "All Tracks";
+ break;
+ case NT_PROBE:
+ patternTitle = GetProbeName(node->Desc.Probe);
+ patternName = node->Desc.Probe->Event.Name;
+ break;
+ case NT_PARAM:
+ patternName.append(node->Desc.ParamName + " = " + node->Desc.ParamValue);
+ break;
+ }
+
+ os << "<a href=\"" << MakeUrl(e, {
+ {"pattern", node->GetPath()},
+ {"ptrn_anlz", e.Get("ptrn_anlz") ? e.Get("ptrn_anlz") : "resTotal"},
+ {"linesfill", "y"},
+ {"linessteps", "y"},
+ {"pointsshow", "n"},
+ {"sel_x1", e.Get("sel_x1") ? e.Get("sel_x1") : "0"},
+ {"sel_x2", e.Get("sel_x2") ? e.Get("sel_x2") : "inf"}}) << "\""
+ " title=\"" + patternTitle + "\">" << patternName << "</a>";
+
+ // Add/remove node menu
+ if (node->Desc.Type != NT_ROOT) {
+ os << "<div class=\"dropdown pull-right\" style=\"display:inline-block\">";
+ if (node->Desc.Type == NT_PARAM) {
+ os<< "<button class=\"btn btn-xs btn-default\" type=\"button\""
+ << "\" onClick=\"window.location.href='"
+ << MakeUrlEraseSub(e, "classify", node->Parent->GetPath() + "@"
+ + ToString(node->Desc.Rollbacks) + "." + node->Desc.ParamName)
+ << "';\">"
+ "<span class=\"glyphicon glyphicon-minus\"></span>"
+ "</button>";
+ }
+ if (node->Classifier->GetChildType() != NT_PARAM) {
+ os << "<button class=\"btn btn-xs btn-default dropdown-toggle\" type=\"button\""
+ " data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">"
+ "<span class=\"glyphicon glyphicon-plus\"></span>"
+ "</button>"
+ "<ul class=\"dropdown-menu\">"
+ "<li class=\"dropdown-header\">Classify by param:</li>";
+ int rollbacks = 0;
+ TPatternNode* probeNode = node;
+ while (probeNode = RollbackFind(probeNode)) {
+ const NLWTrace::TProbe* probe = probeNode->Desc.Probe;
+ os << "<li class=\"dropdown-header\">" << GetProbeName(probe) << "</li>";
+ const NLWTrace::TSignature* sgn = &probe->Event.Signature;
+ for (size_t pi = 0; pi < sgn->ParamCount; pi++) {
TString param = sgn->ParamNames[pi];
if (TrackIds.contains(param) || IsFiltered(param)) {
- continue;
- }
- os << "<li><a href=\""
- << MakeUrlAddSub(e, "classify", node->GetPath() + "@" + ToString(rollbacks) + "." + param)
- << "\">" << param << "</a></li>";
- }
- rollbacks++;
- probeNode = probeNode->Parent;
- }
- os << "</ul>";
- }
- os << "</div>";
- }
- }
-
+ continue;
+ }
+ os << "<li><a href=\""
+ << MakeUrlAddSub(e, "classify", node->GetPath() + "@" + ToString(rollbacks) + "." + param)
+ << "\">" << param << "</a></li>";
+ }
+ rollbacks++;
+ probeNode = probeNode->Parent;
+ }
+ os << "</ul>";
+ }
+ os << "</div>";
+ }
+ }
+
void OutputShare(IOutputStream& os, double share)
- {
- double lshare = share;
- double rshare = 100 - lshare;
- os << "<div class=\"progress\" style=\"margin-bottom:0px;position:relative\">"
- "<div class=\"progress-bar progress-bar-success\" role=\"progressbar\""
- " aria-valuenow=\"" << lshare << "\""
- " aria-valuemin=\"0\""
- " aria-valuemax=\"100\""
- " style=\"width: " << lshare << "%;\">"
- "</div>"
- "<div class=\"progress-bar progress-bar-danger\" role=\"progressbar\""
- " aria-valuenow=\"" << rshare << "\""
- " aria-valuemin=\"0\""
- " aria-valuemax=\"100\""
- " style=\"width: " << rshare << "%;\">"
- "</div>"
- "<span style=\"position:absolute;left:0;width:100%;text-align:center;z-index:2;color:white\">"
- << (share == 100? "100%": Sprintf("%2.1lf%%", share)) <<
- "</span>"
- "</div>";
- }
-
+ {
+ double lshare = share;
+ double rshare = 100 - lshare;
+ os << "<div class=\"progress\" style=\"margin-bottom:0px;position:relative\">"
+ "<div class=\"progress-bar progress-bar-success\" role=\"progressbar\""
+ " aria-valuenow=\"" << lshare << "\""
+ " aria-valuemin=\"0\""
+ " aria-valuemax=\"100\""
+ " style=\"width: " << lshare << "%;\">"
+ "</div>"
+ "<div class=\"progress-bar progress-bar-danger\" role=\"progressbar\""
+ " aria-valuenow=\"" << rshare << "\""
+ " aria-valuemin=\"0\""
+ " aria-valuemax=\"100\""
+ " style=\"width: " << rshare << "%;\">"
+ "</div>"
+ "<span style=\"position:absolute;left:0;width:100%;text-align:center;z-index:2;color:white\">"
+ << (share == 100? "100%": Sprintf("%2.1lf%%", share)) <<
+ "</span>"
+ "</div>";
+ }
+
using TTimeline = TVector<std::pair<TPatternNode*, double>>;
-
- TTimeline MakeTimeline(TPatternNode* node)
- {
- TTimeline ret;
- if (node->TrackCount == 0) {
- return ret;
- }
- ret.reserve(node->TimelineSum.size());
- for (double time : node->TimelineSum) {
- ret.emplace_back(nullptr, double(time) / node->TrackCount);
- }
- TPatternNode* n = node;
- for (auto i = ret.rbegin(), e = ret.rend(); i != e; ++i) {
+
+ TTimeline MakeTimeline(TPatternNode* node)
+ {
+ TTimeline ret;
+ if (node->TrackCount == 0) {
+ return ret;
+ }
+ ret.reserve(node->TimelineSum.size());
+ for (double time : node->TimelineSum) {
+ ret.emplace_back(nullptr, double(time) / node->TrackCount);
+ }
+ TPatternNode* n = node;
+ for (auto i = ret.rbegin(), e = ret.rend(); i != e; ++i) {
WWW_CHECK(n, "internal bug: wrong timeline length at pattern node '%s'", node->GetPath().data());
- i->first = n;
- n = n->Parent;
- }
- return ret;
- }
-
+ i->first = n;
+ n = n->Parent;
+ }
+ return ret;
+ }
+
void OutputTimeline(IOutputStream& os, const TTimeline& timeline, double maxTime)
- {
- static const char *barClass[] = {
- "progress-bar-info",
- "progress-bar-warning"
- };
- if (timeline.empty()) {
- return;
- }
- os << "<div class=\"progress\" style=\"margin-bottom:0px;color:black\">";
- double prevPos = 0.0;
- double prevTime = 0.0;
- size_t i = 0;
- for (auto& e : timeline) {
- TPatternNode* node = e.first;
- double time = e.second;
- double pos = time * 100 / maxTime;
- if (pos > 100) {
- pos = 100;
- }
- double width = pos - prevPos;
- os << "<div class=\"progress-bar " << barClass[i % 2] << "\" role=\"progressbar\""
- " aria-valuenow=\"" << width << "\""
- " aria-valuemin=\"0\""
- " aria-valuemax=\"100\""
- " style=\"width:" << width << "%;color:black\""
- " title=\"" << FormatTimelineTooltip(time, prevTime, node) << "\">";
- if (width > 20) { // To ensure text will fit the bar
- os << FormatCycles(time - prevTime);
- }
- os << "</div>";
- prevPos = pos;
- prevTime = time;
- i++;
- }
- os << "</div>";
- }
-
+ {
+ static const char *barClass[] = {
+ "progress-bar-info",
+ "progress-bar-warning"
+ };
+ if (timeline.empty()) {
+ return;
+ }
+ os << "<div class=\"progress\" style=\"margin-bottom:0px;color:black\">";
+ double prevPos = 0.0;
+ double prevTime = 0.0;
+ size_t i = 0;
+ for (auto& e : timeline) {
+ TPatternNode* node = e.first;
+ double time = e.second;
+ double pos = time * 100 / maxTime;
+ if (pos > 100) {
+ pos = 100;
+ }
+ double width = pos - prevPos;
+ os << "<div class=\"progress-bar " << barClass[i % 2] << "\" role=\"progressbar\""
+ " aria-valuenow=\"" << width << "\""
+ " aria-valuemin=\"0\""
+ " aria-valuemax=\"100\""
+ " style=\"width:" << width << "%;color:black\""
+ " title=\"" << FormatTimelineTooltip(time, prevTime, node) << "\">";
+ if (width > 20) { // To ensure text will fit the bar
+ os << FormatCycles(time - prevTime);
+ }
+ os << "</div>";
+ prevPos = pos;
+ prevTime = time;
+ i++;
+ }
+ os << "</div>";
+ }
+
TString FormatTimelineTooltip(double time, double prevTime, TPatternNode* node)
- {
- return FormatCycles(time - prevTime) + ": "
- + FormatCycles(prevTime) + " -> " + FormatCycles(time)
- + "(" + node->Name + ")";
- }
-
+ {
+ return FormatCycles(time - prevTime) + ": "
+ + FormatCycles(prevTime) + " -> " + FormatCycles(time)
+ + "(" + node->Name + ")";
+ }
+
TString FormatFloat(double value)
- {
- if (value == 0.0) {
- return "0";
- }
- if (value > 1.0) {
- if (value > 100.0) {
- return Sprintf("%.0lf", value);
- }
- if (value > 10.0) {
- return Sprintf("%.1lf", value);
- }
- return Sprintf("%.2lf", value);
- } else if (value > 1e-3) {
- if (value > 1e-1) {
- return Sprintf("%.3lf", value);
- }
- if (value > 1e-2) {
- return Sprintf("%.4lf", value);
- }
- return Sprintf("%.5lf", value);
- } else if (value > 1e-6) {
- if (value > 1e-4) {
- return Sprintf("%.6lf", value);
- }
- if (value > 1e-5) {
- return Sprintf("%.7lf", value);
- }
- return Sprintf("%.8lfus", value);
- } else {
- if (value > 1e-7) {
- return Sprintf("%.9lfns", value);
- }
- if (value > 1e-8) {
- return Sprintf("%.10lfns", value);
- }
- return Sprintf("%.2le", value);
- }
- }
-
+ {
+ if (value == 0.0) {
+ return "0";
+ }
+ if (value > 1.0) {
+ if (value > 100.0) {
+ return Sprintf("%.0lf", value);
+ }
+ if (value > 10.0) {
+ return Sprintf("%.1lf", value);
+ }
+ return Sprintf("%.2lf", value);
+ } else if (value > 1e-3) {
+ if (value > 1e-1) {
+ return Sprintf("%.3lf", value);
+ }
+ if (value > 1e-2) {
+ return Sprintf("%.4lf", value);
+ }
+ return Sprintf("%.5lf", value);
+ } else if (value > 1e-6) {
+ if (value > 1e-4) {
+ return Sprintf("%.6lf", value);
+ }
+ if (value > 1e-5) {
+ return Sprintf("%.7lf", value);
+ }
+ return Sprintf("%.8lfus", value);
+ } else {
+ if (value > 1e-7) {
+ return Sprintf("%.9lfns", value);
+ }
+ if (value > 1e-8) {
+ return Sprintf("%.10lfns", value);
+ }
+ return Sprintf("%.2le", value);
+ }
+ }
+
TString FormatCycles(double timeCycles)
- {
- double timeSec = timeCycles / NHPTimer::GetClockRate();
- if (timeSec > 1.0) {
- if (timeSec > 100.0) {
- return Sprintf("%.0lfs", timeSec);
- }
- if (timeSec > 10.0) {
- return Sprintf("%.1lfs", timeSec);
- }
- return Sprintf("%.2lfs", timeSec);
- } else if (timeSec > 1e-3) {
- if (timeSec > 1e-1) {
- return Sprintf("%.0lfms", timeSec * 1e3);
- }
- if (timeSec > 1e-2) {
- return Sprintf("%.1lfms", timeSec * 1e3);
- }
- return Sprintf("%.2lfms", timeSec * 1e3);
- } else if (timeSec > 1e-6) {
- if (timeSec > 1e-4) {
- return Sprintf("%.0lfus", timeSec * 1e6);
- }
- if (timeSec > 1e-5) {
- return Sprintf("%.1lfus", timeSec * 1e6);
- }
- return Sprintf("%.2lfus", timeSec * 1e6);
- } else {
- if (timeSec > 1e-7) {
- return Sprintf("%.0lfns", timeSec * 1e9);
- }
- if (timeSec > 1e-8) {
- return Sprintf("%.1lfns", timeSec * 1e9);
- }
- return Sprintf("%.2lfns", timeSec * 1e9);
- }
- }
-
+ {
+ double timeSec = timeCycles / NHPTimer::GetClockRate();
+ if (timeSec > 1.0) {
+ if (timeSec > 100.0) {
+ return Sprintf("%.0lfs", timeSec);
+ }
+ if (timeSec > 10.0) {
+ return Sprintf("%.1lfs", timeSec);
+ }
+ return Sprintf("%.2lfs", timeSec);
+ } else if (timeSec > 1e-3) {
+ if (timeSec > 1e-1) {
+ return Sprintf("%.0lfms", timeSec * 1e3);
+ }
+ if (timeSec > 1e-2) {
+ return Sprintf("%.1lfms", timeSec * 1e3);
+ }
+ return Sprintf("%.2lfms", timeSec * 1e3);
+ } else if (timeSec > 1e-6) {
+ if (timeSec > 1e-4) {
+ return Sprintf("%.0lfus", timeSec * 1e6);
+ }
+ if (timeSec > 1e-5) {
+ return Sprintf("%.1lfus", timeSec * 1e6);
+ }
+ return Sprintf("%.2lfus", timeSec * 1e6);
+ } else {
+ if (timeSec > 1e-7) {
+ return Sprintf("%.0lfns", timeSec * 1e9);
+ }
+ if (timeSec > 1e-8) {
+ return Sprintf("%.1lfns", timeSec * 1e9);
+ }
+ return Sprintf("%.2lfns", timeSec * 1e9);
+ }
+ }
+
TString GetParam(const NLWTrace::TLogItem& item, TString* paramValues, const TString& paramName)
- {
- for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
- if (paramName == item.Probe->Event.Signature.ParamNames[pi]) {
- return paramValues[pi];
- }
- }
+ {
+ for (size_t pi = 0; pi < item.SavedParamsCount; pi++) {
+ if (paramName == item.Probe->Event.Signature.ParamNames[pi]) {
+ return paramValues[pi];
+ }
+ }
return TString();
- }
-
+ }
+
TString GetGroup(const NLWTrace::TLogItem& item, TString* paramValues)
- {
- TStringStream ss;
- bool first = true;
+ {
+ TStringStream ss;
+ bool first = true;
for (const TString& groupParam : GroupBy) {
- ss << (first? "": "|") << GetParam(item, paramValues, groupParam);
- first = false;
- }
- return ss.Str();
- }
-
- void AddItemToTrack(TThread::TId tid, const NLWTrace::TLogItem& item)
- {
- // Ensure cyclic per thread lwtrace logs wont drop *inner* items of a track
- // (note that some *starting* items can be dropped)
- if (item.SavedParamsCount > 0 && !CutTs.Skip(item)) {
+ ss << (first? "": "|") << GetParam(item, paramValues, groupParam);
+ first = false;
+ }
+ return ss.Str();
+ }
+
+ void AddItemToTrack(TThread::TId tid, const NLWTrace::TLogItem& item)
+ {
+ // Ensure cyclic per thread lwtrace logs wont drop *inner* items of a track
+ // (note that some *starting* items can be dropped)
+ if (item.SavedParamsCount > 0 && !CutTs.Skip(item)) {
TString paramValues[LWTRACE_MAX_PARAMS];
- item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
- Tracks[GetGroup(item, paramValues)].Items.emplace_back(tid, item);
- }
- }
-};
-
-NLWTrace::TProbeRegistry g_Probes;
+ item.Probe->Event.Signature.SerializeParams(item.Params, paramValues);
+ Tracks[GetGroup(item, paramValues)].Items.emplace_back(tid, item);
+ }
+ }
+};
+
+NLWTrace::TProbeRegistry g_Probes;
TString g_sanitizerTest("TString g_sanitizerTest");
-NLWTrace::TManager g_SafeManager(g_Probes, false);
-NLWTrace::TManager g_UnsafeManager(g_Probes, true);
+NLWTrace::TManager g_SafeManager(g_Probes, false);
+NLWTrace::TManager g_UnsafeManager(g_Probes, true);
TDashboardRegistry g_DashboardRegistry;
-
-class TLWTraceMonPage : public NMonitoring::IMonPage {
+
+class TLWTraceMonPage : public NMonitoring::IMonPage {
private:
- NLWTrace::TManager* TraceMngr;
+ NLWTrace::TManager* TraceMngr;
TString StartTime;
- TTraceCleaner Cleaner;
- TMutex SnapshotsMtx;
+ TTraceCleaner Cleaner;
+ TMutex SnapshotsMtx;
THashMap<TString, TAtomicSharedPtr<NLWTrace::TLogPb>> Snapshots;
public:
- explicit TLWTraceMonPage(bool allowUnsafe = false)
+ explicit TLWTraceMonPage(bool allowUnsafe = false)
: NMonitoring::IMonPage("trace", "Tracing")
- , TraceMngr(&TraceManager(allowUnsafe))
- , Cleaner(TraceMngr)
- {
- time_t stime = TInstant::Now().TimeT();
- StartTime = CTimeR(&stime);
- }
+ , TraceMngr(&TraceManager(allowUnsafe))
+ , Cleaner(TraceMngr)
+ {
+ time_t stime = TInstant::Now().TimeT();
+ StartTime = CTimeR(&stime);
+ }
virtual void Output(NMonitoring::IMonHttpRequest& request) {
- TStringStream out;
+ TStringStream out;
try {
- if (request.GetParams().Get("mode") == "") {
- OutputTracesAndSnapshots(request, out);
+ if (request.GetParams().Get("mode") == "") {
+ OutputTracesAndSnapshots(request, out);
} else if (request.GetParams().Get("mode") == "probes") {
- OutputProbes(request, out);
+ OutputProbes(request, out);
} else if (request.GetParams().Get("mode") == "dashboards") {
OutputDashboards(request, out);
} else if (request.GetParams().Get("mode") == "dashboard") {
OutputDashboard(request, out);
} else if (request.GetParams().Get("mode") == "log") {
- OutputLog(request, out);
+ OutputLog(request, out);
} else if (request.GetParams().Get("mode") == "query") {
- OutputQuery(request, out);
- } else if (request.GetParams().Get("mode") == "builder") {
- OutputBuilder(request, out);
- } else if (request.GetParams().Get("mode") == "analytics") {
- OutputAnalytics(request, out);
+ OutputQuery(request, out);
+ } else if (request.GetParams().Get("mode") == "builder") {
+ OutputBuilder(request, out);
+ } else if (request.GetParams().Get("mode") == "analytics") {
+ OutputAnalytics(request, out);
} else if (request.GetParams().Get("mode") == "new") {
- PostNew(request, out);
+ PostNew(request, out);
} else if (request.GetParams().Get("mode") == "delete") {
- PostDelete(request, out);
- } else if (request.GetParams().Get("mode") == "make_snapshot") {
- PostSnapshot(request, out);
- } else if (request.GetParams().Get("mode") == "settimeout") {
- PostSetTimeout(request, out);
+ PostDelete(request, out);
+ } else if (request.GetParams().Get("mode") == "make_snapshot") {
+ PostSnapshot(request, out);
+ } else if (request.GetParams().Get("mode") == "settimeout") {
+ PostSetTimeout(request, out);
} else {
ythrow yexception() << "Bad request";
}
- } catch (TPageGenBase& gen) {
- out.Clear();
- out << gen.what();
- } catch (...) {
- out.Clear();
- if (request.GetParams().Get("error") == "text") {
- // Text error reply is helpful for ajax requests
- out << NMonitoring::HTTPOKTEXT;
- out << CurrentExceptionMessage();
- } else {
- WWW_HTML(out) {
- out << "<h2>Error</h2><pre>"
- << CurrentExceptionMessage()
- << Endl;
- }
- }
- }
+ } catch (TPageGenBase& gen) {
+ out.Clear();
+ out << gen.what();
+ } catch (...) {
+ out.Clear();
+ if (request.GetParams().Get("error") == "text") {
+ // Text error reply is helpful for ajax requests
+ out << NMonitoring::HTTPOKTEXT;
+ out << CurrentExceptionMessage();
+ } else {
+ WWW_HTML(out) {
+ out << "<h2>Error</h2><pre>"
+ << CurrentExceptionMessage()
+ << Endl;
+ }
+ }
+ }
request.Output() << out.Str();
- }
-
-private:
+ }
+
+private:
void OutputNavbar(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
+ {
TString active = " class=\"active\"";
- out <<
- "<nav class=\"navbar navbar-default\"><div class=\"container-fluid\">"
- << NavbarHeader() <<
- "<ul class=\"nav navbar-nav\">"
- "<li" << (request.GetParams().Get("mode") == ""? active: "") << "><a href=\"?mode=\">Traces</a></li>"
- "<li" << (request.GetParams().Get("mode") == "probes"? active: "") << "><a href=\"?mode=probes\">Probes</a></li>"
+ out <<
+ "<nav class=\"navbar navbar-default\"><div class=\"container-fluid\">"
+ << NavbarHeader() <<
+ "<ul class=\"nav navbar-nav\">"
+ "<li" << (request.GetParams().Get("mode") == ""? active: "") << "><a href=\"?mode=\">Traces</a></li>"
+ "<li" << (request.GetParams().Get("mode") == "probes"? active: "") << "><a href=\"?mode=probes\">Probes</a></li>"
"<li" << (request.GetParams().Get("mode") == "dashboards"? active: "") << "><a href=\"?mode=dashboards\">Dashboard</a></li>"
- "<li" << (request.GetParams().Get("mode") == "builder"? active: "") << "><a href=\"?mode=builder\">Builder</a></li>"
- "<li" << (request.GetParams().Get("mode") == "analytics"? active: "") << "><a href=\"?mode=analytics&id=\">Analytics</a></li>"
+ "<li" << (request.GetParams().Get("mode") == "builder"? active: "") << "><a href=\"?mode=builder\">Builder</a></li>"
+ "<li" << (request.GetParams().Get("mode") == "analytics"? active: "") << "><a href=\"?mode=analytics&id=\">Analytics</a></li>"
"<li><a href=\"https://wiki.yandex-team.ru/development/poisk/arcadia/library/cpp/lwtrace/\" target=\"_blank\">Documentation</a></li>"
- "</ul>"
- "</div></nav>"
- ;
- }
-
- template <class TReader>
- void ReadSnapshots(TReader& reader) const
- {
- TGuard<TMutex> g(SnapshotsMtx);
- for (const auto& kv : Snapshots) {
- reader.Push(kv.first, kv.second);
- }
- }
-
+ "</ul>"
+ "</div></nav>"
+ ;
+ }
+
+ template <class TReader>
+ void ReadSnapshots(TReader& reader) const
+ {
+ TGuard<TMutex> g(SnapshotsMtx);
+ for (const auto& kv : Snapshots) {
+ reader.Push(kv.first, kv.second);
+ }
+ }
+
void OutputTracesAndSnapshots(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- TLogSources logSources(Cleaner);
- TraceMngr->ReadTraces(logSources);
- ReadSnapshots(logSources);
-
- TStringStream ss;
- TTracesHtmlPrinter printer(ss);
- logSources.ForEach(printer);
- WWW_HTML(out) {
- OutputNavbar(request, out);
- out <<
- "<table class=\"table table-striped\">"
- "<tr><th>Start Time</th><th>Timeout</th><th>Name</th><th>Events</th><th>Threads</th><th></th><th></th><th></th><th></th><th></th></tr>"
- << ss.Str() <<
- "</table>"
- ;
- out << "<hr/><p><strong>Start time:</strong> " << StartTime;
- out << "<br/><strong>Build date:</strong> ";
- out << __DATE__ << " " << __TIME__ << "</p>" << Endl;
- }
- }
-
+ {
+ TLogSources logSources(Cleaner);
+ TraceMngr->ReadTraces(logSources);
+ ReadSnapshots(logSources);
+
+ TStringStream ss;
+ TTracesHtmlPrinter printer(ss);
+ logSources.ForEach(printer);
+ WWW_HTML(out) {
+ OutputNavbar(request, out);
+ out <<
+ "<table class=\"table table-striped\">"
+ "<tr><th>Start Time</th><th>Timeout</th><th>Name</th><th>Events</th><th>Threads</th><th></th><th></th><th></th><th></th><th></th></tr>"
+ << ss.Str() <<
+ "</table>"
+ ;
+ out << "<hr/><p><strong>Start time:</strong> " << StartTime;
+ out << "<br/><strong>Build date:</strong> ";
+ out << __DATE__ << " " << __TIME__ << "</p>" << Endl;
+ }
+ }
+
void OutputProbes(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- TStringStream ss;
- TProbesHtmlPrinter printer;
- TraceMngr->ReadProbes(printer);
- printer.Output(ss);
- WWW_HTML(out) {
- OutputNavbar(request, out);
- out << ss.Str();
- }
- }
-
+ {
+ TStringStream ss;
+ TProbesHtmlPrinter printer;
+ TraceMngr->ReadProbes(printer);
+ printer.Output(ss);
+ WWW_HTML(out) {
+ OutputNavbar(request, out);
+ out << ss.Str();
+ }
+ }
+
void OutputDashboards(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
{
TStringStream ss;
@@ -3910,7 +3910,7 @@ private:
WWW_HTML(out) {
OutputNavbar(request, out);
out << ss.Str();
- }
+ }
}
void OutputDashboard(const NMonitoring::IMonHttpRequest& request, IOutputStream& out) {
@@ -3918,97 +3918,97 @@ private:
ythrow yexception() << "Cgi-parameter 'name' is not specified";
} else {
auto name = request.GetParams().Get("name");
- NLWTrace::TDashboard dash;
+ NLWTrace::TDashboard dash;
if (!g_DashboardRegistry.Get(name, dash)) {
ythrow yexception() << "Dashboard doesn't exist";
}
WWW_HTML(out) {
OutputNavbar(request, out);
- out << "<style type='text/css'>html, body { height: 100%; }</style>";
- out << "<h2>" << dash.GetName() << "</h2>";
- if (dash.GetDescription()) {
- out << "<h3>" << dash.GetDescription() << "</h3>";
- }
- int height = 85; // %
- int minHeight = 100; // px
- out << "<table height='" << height << "%' width='100%' cellpadding='4'><tbody height='100%' width='100%'>";
- ui32 rows = 0;
- auto maxRowSpan = [](const auto& row) {
- ui32 rowSpan = 1;
- for (const auto& cell : row.GetCells()) {
- rowSpan = Max(rowSpan, cell.GetRowSpan());
- }
- return rowSpan;
- };
- for (const auto& row : dash.GetRows()) {
- rows += maxRowSpan(row);
- }
- for (const auto& row : dash.GetRows()) {
- int rowSpan = maxRowSpan(row);
- out << "<tr align='left' valign='top' style='height:" << (height * rowSpan / rows) << "%; min-height:" << (minHeight * rowSpan)<< "px'>";
- for (const auto& cell : row.GetCells()) {
- TString url = cell.GetUrl();
- TString title = cell.GetTitle();
- TString text = cell.GetText();
- auto rowSpan = Max<ui64>(1, cell.GetRowSpan());
- auto colSpan = Max<ui64>(1, cell.GetColSpan());
- if (url) {
- if (title) {
- out << "<td rowspan='" << rowSpan << "' colSpan='1'><a href=" << url << ">" << title << "</a><br>";
- }
- out << "<iframe scrolling='no' width='" << 100 * colSpan << "%' height='" << height << "%' style='border: 0' src=" << url << "></iframe></td>";
- // Add fake cells to fix html table
- for (ui32 left = 1; left < colSpan; ++left) {
- out << "<td height='100%' rowspan='" << rowSpan << "' colSpan='1'>"
- << "<iframe scrolling='no' width='100%' height='100%' style='border: 0' src=" << "" << "></iframe></td>";
+ out << "<style type='text/css'>html, body { height: 100%; }</style>";
+ out << "<h2>" << dash.GetName() << "</h2>";
+ if (dash.GetDescription()) {
+ out << "<h3>" << dash.GetDescription() << "</h3>";
+ }
+ int height = 85; // %
+ int minHeight = 100; // px
+ out << "<table height='" << height << "%' width='100%' cellpadding='4'><tbody height='100%' width='100%'>";
+ ui32 rows = 0;
+ auto maxRowSpan = [](const auto& row) {
+ ui32 rowSpan = 1;
+ for (const auto& cell : row.GetCells()) {
+ rowSpan = Max(rowSpan, cell.GetRowSpan());
+ }
+ return rowSpan;
+ };
+ for (const auto& row : dash.GetRows()) {
+ rows += maxRowSpan(row);
+ }
+ for (const auto& row : dash.GetRows()) {
+ int rowSpan = maxRowSpan(row);
+ out << "<tr align='left' valign='top' style='height:" << (height * rowSpan / rows) << "%; min-height:" << (minHeight * rowSpan)<< "px'>";
+ for (const auto& cell : row.GetCells()) {
+ TString url = cell.GetUrl();
+ TString title = cell.GetTitle();
+ TString text = cell.GetText();
+ auto rowSpan = Max<ui64>(1, cell.GetRowSpan());
+ auto colSpan = Max<ui64>(1, cell.GetColSpan());
+ if (url) {
+ if (title) {
+ out << "<td rowspan='" << rowSpan << "' colSpan='1'><a href=" << url << ">" << title << "</a><br>";
}
- } else {
- out << "<td style='font-size: 25px' align='left' rowspan='" << rowSpan << "' colSpan='" << colSpan << "'>" << text << "</td>";
+ out << "<iframe scrolling='no' width='" << 100 * colSpan << "%' height='" << height << "%' style='border: 0' src=" << url << "></iframe></td>";
+ // Add fake cells to fix html table
+ for (ui32 left = 1; left < colSpan; ++left) {
+ out << "<td height='100%' rowspan='" << rowSpan << "' colSpan='1'>"
+ << "<iframe scrolling='no' width='100%' height='100%' style='border: 0' src=" << "" << "></iframe></td>";
+ }
+ } else {
+ out << "<td style='font-size: 25px' align='left' rowspan='" << rowSpan << "' colSpan='" << colSpan << "'>" << text << "</td>";
}
}
- }
+ }
out << "</tbody></table>";
}
}
}
- static double ParseDouble(const TString& s)
- {
- if (s == "inf") {
- return std::numeric_limits<double>::infinity();
- } else if (s == "-inf") {
- return -std::numeric_limits<double>::infinity();
- } else {
- return FromString<double>(s);
- }
- }
-
+ static double ParseDouble(const TString& s)
+ {
+ if (s == "inf") {
+ return std::numeric_limits<double>::infinity();
+ } else if (s == "-inf") {
+ return -std::numeric_limits<double>::infinity();
+ } else {
+ return FromString<double>(s);
+ }
+ }
+
void OutputLog(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- if (request.GetParams().NumOfValues("id") == 0) {
- ythrow yexception() << "Cgi-parameter 'id' is not specified";
- } else {
+ {
+ if (request.GetParams().NumOfValues("id") == 0) {
+ ythrow yexception() << "Cgi-parameter 'id' is not specified";
+ } else {
const TCgiParameters& e = request.GetParams();
- TStringStream ss;
- if (e.Get("format") == "json") {
- TLogJsonPrinter printer(ss);
- printer.OutputHeader();
- TString id = e.Get("id");
- CheckAdHocTrace(id, TDuration::Minutes(1));
- TraceMngr->ReadLog(id, printer);
- printer.OutputFooter(TraceMngr->GetTrace(id));
- out << HTTPOKJSON;
- out << ss.Str();
- } if (e.Get("format") == "json2") {
- TLogTextPrinter printer(e);
- for (const TString& id : Subvalues(e, "id")) {
- CheckAdHocTrace(id, TDuration::Minutes(1));
- TraceMngr->ReadLog(id, printer);
- TraceMngr->ReadDepot(id, printer);
- }
- printer.OutputJson(ss);
- out << HTTPOKJSON;
- out << ss.Str();
+ TStringStream ss;
+ if (e.Get("format") == "json") {
+ TLogJsonPrinter printer(ss);
+ printer.OutputHeader();
+ TString id = e.Get("id");
+ CheckAdHocTrace(id, TDuration::Minutes(1));
+ TraceMngr->ReadLog(id, printer);
+ printer.OutputFooter(TraceMngr->GetTrace(id));
+ out << HTTPOKJSON;
+ out << ss.Str();
+ } if (e.Get("format") == "json2") {
+ TLogTextPrinter printer(e);
+ for (const TString& id : Subvalues(e, "id")) {
+ CheckAdHocTrace(id, TDuration::Minutes(1));
+ TraceMngr->ReadLog(id, printer);
+ TraceMngr->ReadDepot(id, printer);
+ }
+ printer.OutputJson(ss);
+ out << HTTPOKJSON;
+ out << ss.Str();
} else if (e.Get("format") == "analytics" && e.Get("aggr") == "tracks") {
TLogTrackExtractor logTrackExtractor(e,
Subvalues(e, "f"),
@@ -4027,8 +4027,8 @@ private:
TLogTextPrinter printer(e);
const TString& distBy = patternAnalyzer;
- double sel_x1 = e.Get("sel_x1")? ParseDouble(e.Get("sel_x1")): NAN;
- double sel_x2 = e.Get("sel_x2")? ParseDouble(e.Get("sel_x2")): NAN;
+ double sel_x1 = e.Get("sel_x1")? ParseDouble(e.Get("sel_x1")): NAN;
+ double sel_x2 = e.Get("sel_x2")? ParseDouble(e.Get("sel_x2")): NAN;
TSampleOpts opts;
opts.ShowProvider = (e.Get("show_provider") == "y");
if (e.Get("size_limit")) {
@@ -4038,101 +4038,101 @@ private:
printer.Output(ss);
out << HTTPOKTEXT;
out << ss.Str();
- } else {
+ } else {
TLogTextPrinter printer(e);
for (const TString& id : Subvalues(e, "id")) {
- CheckAdHocTrace(id, TDuration::Minutes(1));
- TraceMngr->ReadLog(id, printer);
- TraceMngr->ReadDepot(id, printer);
- }
- printer.Output(ss);
- out << HTTPOKTEXT;
- out << ss.Str();
- }
- }
- }
-
+ CheckAdHocTrace(id, TDuration::Minutes(1));
+ TraceMngr->ReadLog(id, printer);
+ TraceMngr->ReadDepot(id, printer);
+ }
+ printer.Output(ss);
+ out << HTTPOKTEXT;
+ out << ss.Str();
+ }
+ }
+ }
+
void OutputQuery(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- if (request.GetParams().NumOfValues("id") == 0) {
- ythrow yexception() << "Cgi-parameter 'id' is not specified";
- } else {
+ {
+ if (request.GetParams().NumOfValues("id") == 0) {
+ ythrow yexception() << "Cgi-parameter 'id' is not specified";
+ } else {
TString id = request.GetParams().Get("id");
- const NLWTrace::TQuery& query = TraceMngr->GetTrace(id)->GetQuery();
+ const NLWTrace::TQuery& query = TraceMngr->GetTrace(id)->GetQuery();
TString queryStr = query.DebugString();
- WWW_HTML(out) {
- out << "<h2>Trace Query: " << id << "</h2><pre>" << queryStr;
- }
+ WWW_HTML(out) {
+ out << "<h2>Trace Query: " << id << "</h2><pre>" << queryStr;
+ }
}
}
-
+
void OutputBuilder(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- Y_UNUSED(request);
- WWW_HTML(out) {
- OutputNavbar(request, out);
- out << "<form class=\"form-horizontal\" action=\"?mode=new&ui=y\" method=\"POST\">";
- DIV_CLASS("form-group") {
- LABEL_CLASS_FOR("col-sm-1 control-label", "inputId") { out << "Name"; }
- DIV_CLASS("col-sm-11") {
- out << "<input class=\"form-control\" id=\"inputId\" name=\"id\" placeholder=\"mytrace\">";
- }
- }
- DIV_CLASS("form-group") {
- LABEL_CLASS_FOR("col-sm-1 control-label", "textareaQuery") { out << "Query"; }
- DIV_CLASS("col-sm-11") {
- out << "<textarea class=\"form-control\" id=\"textareaQuery\" name=\"query\" rows=\"10\"></textarea>";
- }
- }
- DIV_CLASS("form-group") {
- DIV_CLASS("col-sm-offset-1 col-sm-11") {
- out << "<button type=\"submit\" class=\"btn btn-default\">Trace</button>";
- }
- }
- out << "</form>";
- }
- }
-
+ {
+ Y_UNUSED(request);
+ WWW_HTML(out) {
+ OutputNavbar(request, out);
+ out << "<form class=\"form-horizontal\" action=\"?mode=new&ui=y\" method=\"POST\">";
+ DIV_CLASS("form-group") {
+ LABEL_CLASS_FOR("col-sm-1 control-label", "inputId") { out << "Name"; }
+ DIV_CLASS("col-sm-11") {
+ out << "<input class=\"form-control\" id=\"inputId\" name=\"id\" placeholder=\"mytrace\">";
+ }
+ }
+ DIV_CLASS("form-group") {
+ LABEL_CLASS_FOR("col-sm-1 control-label", "textareaQuery") { out << "Query"; }
+ DIV_CLASS("col-sm-11") {
+ out << "<textarea class=\"form-control\" id=\"textareaQuery\" name=\"query\" rows=\"10\"></textarea>";
+ }
+ }
+ DIV_CLASS("form-group") {
+ DIV_CLASS("col-sm-offset-1 col-sm-11") {
+ out << "<button type=\"submit\" class=\"btn btn-default\">Trace</button>";
+ }
+ }
+ out << "</form>";
+ }
+ }
+
void OutputAnalytics(const NMonitoring::IMonHttpRequest& request, TStringStream& out)
- {
- using namespace NAnalytics;
- const TCgiParameters& e = request.GetParams();
-
- TLogSources logSources(Cleaner);
- TraceMngr->ReadTraces(logSources);
- ReadSnapshots(logSources);
-
- RequireMultipleSelection(out, e, "id", "Analyze ", ListTraces(logSources));
-
- THolder<TLogFilter> logFilter;
- TLogAnalyzer* logAnalyzer = nullptr;
- TLogTrackExtractor* logTracks = nullptr;
- if (request.GetParams().Get("aggr") == "tracks") {
- logFilter.Reset(logTracks = new TLogTrackExtractor(e,
- Subvalues(request.GetParams(), "f"),
- Subvalues(request.GetParams(), "g")
- ));
+ {
+ using namespace NAnalytics;
+ const TCgiParameters& e = request.GetParams();
+
+ TLogSources logSources(Cleaner);
+ TraceMngr->ReadTraces(logSources);
+ ReadSnapshots(logSources);
+
+ RequireMultipleSelection(out, e, "id", "Analyze ", ListTraces(logSources));
+
+ THolder<TLogFilter> logFilter;
+ TLogAnalyzer* logAnalyzer = nullptr;
+ TLogTrackExtractor* logTracks = nullptr;
+ if (request.GetParams().Get("aggr") == "tracks") {
+ logFilter.Reset(logTracks = new TLogTrackExtractor(e,
+ Subvalues(request.GetParams(), "f"),
+ Subvalues(request.GetParams(), "g")
+ ));
for (const TString& id : Subvalues(request.GetParams(), "id")) {
- CheckAdHocTrace(id, TDuration::Minutes(1));
- TraceMngr->ReadLog(id, *logTracks);
- TraceMngr->ReadDepot(id, *logTracks);
- }
- } else {
- logFilter.Reset(logAnalyzer = new TLogAnalyzer(
- Subvalues(request.GetParams(), "f"),
- Subvalues(request.GetParams(), "g"),
- request.GetParams().Get("cutts") == "y"
- ));
+ CheckAdHocTrace(id, TDuration::Minutes(1));
+ TraceMngr->ReadLog(id, *logTracks);
+ TraceMngr->ReadDepot(id, *logTracks);
+ }
+ } else {
+ logFilter.Reset(logAnalyzer = new TLogAnalyzer(
+ Subvalues(request.GetParams(), "f"),
+ Subvalues(request.GetParams(), "g"),
+ request.GetParams().Get("cutts") == "y"
+ ));
for (const TString& id : Subvalues(request.GetParams(), "id")) {
- CheckAdHocTrace(id, TDuration::Minutes(1));
- TraceMngr->ReadLog(id, *logAnalyzer);
- TraceMngr->ReadDepot(id, *logAnalyzer);
- }
- }
-
- logFilter->FilterSelectors(out, e, "f");
-
- OptionalMultipleSelection(out, e, "g", "group by", logFilter->ListParamNames());
+ CheckAdHocTrace(id, TDuration::Minutes(1));
+ TraceMngr->ReadLog(id, *logAnalyzer);
+ TraceMngr->ReadDepot(id, *logAnalyzer);
+ }
+ }
+
+ logFilter->FilterSelectors(out, e, "f");
+
+ OptionalMultipleSelection(out, e, "g", "group by", logFilter->ListParamNames());
{
auto paramNamesList = logFilter->ListParamNames();
if (e.Get("aggr") == "tracks") {
@@ -4140,7 +4140,7 @@ private:
}
OptionalSelection(out, e, "s", "order by", paramNamesList);
}
-
+
if (e.Get("s")) {
TVariants variants;
variants.emplace_back("", "asc");
@@ -4149,130 +4149,130 @@ private:
}
TString aggr = e.Get("aggr");
- TVariants variants1; // MSVS2013 doesn't understand complex initializer lists
- variants1.emplace_back("", "without aggregation");
- variants1.emplace_back("hist", "as histogram");
- variants1.emplace_back("tracks", "tracks");
- DropdownSelector<Link>(out, e, "aggr", e.Get("aggr"), "", variants1);
-
- unsigned refresh = e.Get("refresh")?
- FromString<unsigned>(e.Get("refresh")):
- 1000;
-
- if (aggr == "tracks") {
- TVariants ileVars;
- ileVars.emplace_back("0", "0");
- ileVars.emplace_back("25", "25");
- ileVars.emplace_back("50", "50");
- ileVars.emplace_back("75", "75");
- ileVars.emplace_back("", "90");
- ileVars.emplace_back("95", "95");
- ileVars.emplace_back("99", "99");
- ileVars.emplace_back("99.9", "99.9");
- ileVars.emplace_back("100", "100");
- DropdownSelector<Link>(out, e, "ile", e.Get("ile"), "and show", ileVars);
- out << "%-ile. ";
- TString patternAnalyzer;
+ TVariants variants1; // MSVS2013 doesn't understand complex initializer lists
+ variants1.emplace_back("", "without aggregation");
+ variants1.emplace_back("hist", "as histogram");
+ variants1.emplace_back("tracks", "tracks");
+ DropdownSelector<Link>(out, e, "aggr", e.Get("aggr"), "", variants1);
+
+ unsigned refresh = e.Get("refresh")?
+ FromString<unsigned>(e.Get("refresh")):
+ 1000;
+
+ if (aggr == "tracks") {
+ TVariants ileVars;
+ ileVars.emplace_back("0", "0");
+ ileVars.emplace_back("25", "25");
+ ileVars.emplace_back("50", "50");
+ ileVars.emplace_back("75", "75");
+ ileVars.emplace_back("", "90");
+ ileVars.emplace_back("95", "95");
+ ileVars.emplace_back("99", "99");
+ ileVars.emplace_back("99.9", "99.9");
+ ileVars.emplace_back("100", "100");
+ DropdownSelector<Link>(out, e, "ile", e.Get("ile"), "and show", ileVars);
+ out << "%-ile. ";
+ TString patternAnalyzer;
TString distBy;
TString distType;
- if (e.Get("pattern")) {
- TVariants analyzePatternVars;
- analyzePatternVars.emplace_back("resTotal", "distribution by total");
- analyzePatternVars.emplace_back("resLast", "distribution by last");
- analyzePatternVars.emplace_back("covMatrix", "covariance matrix");
- DropdownSelector<Link>(
- out, e, "ptrn_anlz", e.Get("ptrn_anlz"),
- "Pattern", analyzePatternVars
- );
- patternAnalyzer = e.Get("ptrn_anlz");
-
- TVariants distTypeVars;
- distTypeVars.emplace_back("", "as is");
- distTypeVars.emplace_back("-stack", "cumulative");
- DropdownSelector<Link>(out, e, "dist_type", e.Get("dist_type"), "", distTypeVars);
- distType = e.Get("dist_type");
- } else {
- out << "<i>Select pattern for more options</i>";
- }
- logTracks->Run();
-
- if (e.Get("download") == "y") {
- out.Clear();
- out <<
- "HTTP/1.1 200 Ok\r\n"
- "Content-Type: application/force-download\r\n"
- "Content-Transfer-Encoding: binary\r\n"
- "Content-Disposition: attachment; filename=\"trace_chrome.json\"\r\n"
- "\r\n"
- ;
- logTracks->OutputChromeTrace(out, e);
- return;
- }
-
- NAnalytics::TTable distData;
- bool showSample = false;
+ if (e.Get("pattern")) {
+ TVariants analyzePatternVars;
+ analyzePatternVars.emplace_back("resTotal", "distribution by total");
+ analyzePatternVars.emplace_back("resLast", "distribution by last");
+ analyzePatternVars.emplace_back("covMatrix", "covariance matrix");
+ DropdownSelector<Link>(
+ out, e, "ptrn_anlz", e.Get("ptrn_anlz"),
+ "Pattern", analyzePatternVars
+ );
+ patternAnalyzer = e.Get("ptrn_anlz");
+
+ TVariants distTypeVars;
+ distTypeVars.emplace_back("", "as is");
+ distTypeVars.emplace_back("-stack", "cumulative");
+ DropdownSelector<Link>(out, e, "dist_type", e.Get("dist_type"), "", distTypeVars);
+ distType = e.Get("dist_type");
+ } else {
+ out << "<i>Select pattern for more options</i>";
+ }
+ logTracks->Run();
+
+ if (e.Get("download") == "y") {
+ out.Clear();
+ out <<
+ "HTTP/1.1 200 Ok\r\n"
+ "Content-Type: application/force-download\r\n"
+ "Content-Transfer-Encoding: binary\r\n"
+ "Content-Disposition: attachment; filename=\"trace_chrome.json\"\r\n"
+ "\r\n"
+ ;
+ logTracks->OutputChromeTrace(out, e);
+ return;
+ }
+
+ NAnalytics::TTable distData;
+ bool showSample = false;
TLogTextPrinter printer(e);
-
- if (patternAnalyzer == "resTotal" || patternAnalyzer == "resLast") {
- distBy = patternAnalyzer;
- distData = logTracks->Distribution(distBy, "", "", e.Get("width"));
- double sel_x1 = e.Get("sel_x1")? ParseDouble(e.Get("sel_x1")): NAN;
- double sel_x2 = e.Get("sel_x2")? ParseDouble(e.Get("sel_x2")): NAN;
- if (!isnan(sel_x1) && !isnan(sel_x2)) {
- showSample = true;
- TSampleOpts opts;
- opts.ShowProvider = (e.Get("show_provider") == "y");
- if (e.Get("size_limit")) {
- opts.SizeLimit = FromString<size_t>(e.Get("size_limit"));
- }
+
+ if (patternAnalyzer == "resTotal" || patternAnalyzer == "resLast") {
+ distBy = patternAnalyzer;
+ distData = logTracks->Distribution(distBy, "", "", e.Get("width"));
+ double sel_x1 = e.Get("sel_x1")? ParseDouble(e.Get("sel_x1")): NAN;
+ double sel_x2 = e.Get("sel_x2")? ParseDouble(e.Get("sel_x2")): NAN;
+ if (!isnan(sel_x1) && !isnan(sel_x2)) {
+ showSample = true;
+ TSampleOpts opts;
+ opts.ShowProvider = (e.Get("show_provider") == "y");
+ if (e.Get("size_limit")) {
+ opts.SizeLimit = FromString<size_t>(e.Get("size_limit"));
+ }
logTracks->OutputSample(distBy, sel_x1, sel_x2, opts, printer);
- }
- }
-
+ }
+ }
+
TString selectors = out.Str();
- out.Clear();
- out << NMonitoring::HTTPOKHTML;
- out << "<!DOCTYPE html>" << Endl;
- HTML(out) {
- HTML_TAG() {
- HEAD() {
- out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
- if (distBy) {
- out <<
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " var dataurl = null;\n"
- " var datajson = " << ToJsonFlot(distData, distBy, {"_count_sum" + distType}) << ";\n"
- " var refreshPeriod = 0;\n"
- " var xn = \"" << distBy << "\";\n"
- " var navigate = false;\n"
- << NResource::Find("lwtrace/mon/static/analytics.js") <<
- " embededMode();"
- " enableSelection();"
- "});\n"
- "</script>\n";
- }
- // Show download button
- out <<
- "<script type=\"text/javascript\">"
- "$(function() {"
- " $(\"#download-btn\").click(function(){window.location.href='"
- << MakeUrlAdd(e, "download", "y") <<
- "';});"
- " $(\"#download-btn\").removeClass(\"hidden\");"
- "});"
- "</script>\n";
- }
- BODY() {
- // Wrap selectors with navbar
- { TSelectorsContainer sc(out);
- out << selectors;
- }
-
- logTracks->OutputTable(out, e);
- if (distBy) {
- out << NResource::Find("lwtrace/mon/static/analytics.flot.html") << Endl;
- if (showSample) {
+ out.Clear();
+ out << NMonitoring::HTTPOKHTML;
+ out << "<!DOCTYPE html>" << Endl;
+ HTML(out) {
+ HTML_TAG() {
+ HEAD() {
+ out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
+ if (distBy) {
+ out <<
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " var dataurl = null;\n"
+ " var datajson = " << ToJsonFlot(distData, distBy, {"_count_sum" + distType}) << ";\n"
+ " var refreshPeriod = 0;\n"
+ " var xn = \"" << distBy << "\";\n"
+ " var navigate = false;\n"
+ << NResource::Find("lwtrace/mon/static/analytics.js") <<
+ " embededMode();"
+ " enableSelection();"
+ "});\n"
+ "</script>\n";
+ }
+ // Show download button
+ out <<
+ "<script type=\"text/javascript\">"
+ "$(function() {"
+ " $(\"#download-btn\").click(function(){window.location.href='"
+ << MakeUrlAdd(e, "download", "y") <<
+ "';});"
+ " $(\"#download-btn\").removeClass(\"hidden\");"
+ "});"
+ "</script>\n";
+ }
+ BODY() {
+ // Wrap selectors with navbar
+ { TSelectorsContainer sc(out);
+ out << selectors;
+ }
+
+ logTracks->OutputTable(out, e);
+ if (distBy) {
+ out << NResource::Find("lwtrace/mon/static/analytics.flot.html") << Endl;
+ if (showSample) {
static const THashSet<TString> keepParams = {
"f",
"g",
@@ -4302,134 +4302,134 @@ private:
out << "<pre>\n";
printer.Output(out);
out << "</pre>\n";
- }
- }
-
- if (patternAnalyzer == "covMatrix") {
- logTracks->OutputSliceCovarianceMatrix(out, e);
- }
- }
- }
- }
- } else {
- double width = e.Get("width")? FromString<double>(e.Get("width")): 99;
-
- NAnalytics::TTable data;
- if (aggr == "") {
- data = logAnalyzer->GetTable();
- } else if (aggr == "hist") {
- RequireSelection(out, e, "bn", "by", logFilter->ListParamNames());
- const NAnalytics::TTable& inputTable = logAnalyzer->GetTable();
+ }
+ }
+
+ if (patternAnalyzer == "covMatrix") {
+ logTracks->OutputSliceCovarianceMatrix(out, e);
+ }
+ }
+ }
+ }
+ } else {
+ double width = e.Get("width")? FromString<double>(e.Get("width")): 99;
+
+ NAnalytics::TTable data;
+ if (aggr == "") {
+ data = logAnalyzer->GetTable();
+ } else if (aggr == "hist") {
+ RequireSelection(out, e, "bn", "by", logFilter->ListParamNames());
+ const NAnalytics::TTable& inputTable = logAnalyzer->GetTable();
TString bn = e.Get("bn");
- double b1 = e.Get("b1")? FromString<double>(e.Get("b1")): MinValue(bn, inputTable);
- double b2 = e.Get("b2")? FromString<double>(e.Get("b2")): MaxValue(bn, inputTable);
- if (isfinite(b1) && isfinite(b2)) {
- WWW_CHECK(b1 <= b2, "invalid xrange [%le; %le]", b1, b2);
- double dx = e.Get("dx")? FromString<double>(e.Get("dx")): (b2-b1)/width;
- data = HistogramAll(inputTable, e.Get("bn"), b1, b2, dx);
- } else {
- // Empty table -- it's ok -- leave data table empty
- }
- }
-
+ double b1 = e.Get("b1")? FromString<double>(e.Get("b1")): MinValue(bn, inputTable);
+ double b2 = e.Get("b2")? FromString<double>(e.Get("b2")): MaxValue(bn, inputTable);
+ if (isfinite(b1) && isfinite(b2)) {
+ WWW_CHECK(b1 <= b2, "invalid xrange [%le; %le]", b1, b2);
+ double dx = e.Get("dx")? FromString<double>(e.Get("dx")): (b2-b1)/width;
+ data = HistogramAll(inputTable, e.Get("bn"), b1, b2, dx);
+ } else {
+ // Empty table -- it's ok -- leave data table empty
+ }
+ }
+
TString xn = e.Get("xn");
-
+
TString outFormat = e.Get("out");
- TVariants variants2;
- variants2.emplace_back("html", "table");
- variants2.emplace_back("flot", "chart");
- variants2.emplace_back("gantt", "gantt");
- variants2.emplace_back("text", "text");
- variants2.emplace_back("csv", "CSV");
- variants2.emplace_back("json_flot", "JSON");
-
- RequireSelection(out, e, "out", "and show", variants2);
- if (outFormat == "csv") {
+ TVariants variants2;
+ variants2.emplace_back("html", "table");
+ variants2.emplace_back("flot", "chart");
+ variants2.emplace_back("gantt", "gantt");
+ variants2.emplace_back("text", "text");
+ variants2.emplace_back("csv", "CSV");
+ variants2.emplace_back("json_flot", "JSON");
+
+ RequireSelection(out, e, "out", "and show", variants2);
+ if (outFormat == "csv") {
TString sep = e.Get("sep")? e.Get("sep"): TString("\t");
- out.Clear();
- out << NMonitoring::HTTPOKTEXT;
- out << ToCsv(data, sep, e.Get("head") != "n");
- } else if (outFormat == "html") {
+ out.Clear();
+ out << NMonitoring::HTTPOKTEXT;
+ out << ToCsv(data, sep, e.Get("head") != "n");
+ } else if (outFormat == "html") {
TString selectors = out.Str();
- out.Clear();
- WWW_HTML(out) {
- // Wrap selectors with navbar
- { TSelectorsContainer sc(out);
- out << selectors;
- }
- out << ToHtml(data);
- }
- } else if (outFormat == "json_flot") {
- SeriesSelectors(out, e, "xn", "yns", data);
- out.Clear();
- out << NMonitoring::HTTPOKJSON;
+ out.Clear();
+ WWW_HTML(out) {
+ // Wrap selectors with navbar
+ { TSelectorsContainer sc(out);
+ out << selectors;
+ }
+ out << ToHtml(data);
+ }
+ } else if (outFormat == "json_flot") {
+ SeriesSelectors(out, e, "xn", "yns", data);
+ out.Clear();
+ out << NMonitoring::HTTPOKJSON;
out << ToJsonFlot(data, xn, SplitString(e.Get("yns"), ":"));
- } else if (outFormat == "flot") {
- SeriesSelectors(out, e, "xn", "yns", data);
+ } else if (outFormat == "flot") {
+ SeriesSelectors(out, e, "xn", "yns", data);
TString selectors = out.Str();
-
+
TVector<TString> ynos = SplitString(e.Get("yns"), ":");
- out.Clear();
- out << NMonitoring::HTTPOKHTML;
- out << "<!DOCTYPE html>" << Endl;
- HTML(out) {
- HTML_TAG() {
- HEAD() {
- out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
- out <<
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " var dataurl = \"" << EscapeJSONString(MakeUrl(e, "out", "json_flot")) << "\";\n"
- " var refreshPeriod = " << refresh << ";\n"
- " var xn = \"" << ParseName(xn) << "\";\n"
- " var navigate = true;\n"
- << NResource::Find("lwtrace/mon/static/analytics.js") <<
- "});\n"
- "</script>\n"
- ;
- }
- BODY() {
- // Wrap selectors with navbar
- { TSelectorsContainer sc(out);
- out << selectors;
- }
- out << NResource::Find("lwtrace/mon/static/analytics.flot.html") << Endl;
- }
- }
- }
- } else if (outFormat == "gantt") {
- TString selectors = out.Str();
- out.Clear();
- out << NMonitoring::HTTPOKHTML;
- out << "<!DOCTYPE html>" << Endl;
- HTML(out) {
- HTML_TAG() {
- HEAD() {
- out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
- out <<
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " var dataurl = \"" << EscapeJSONString(MakeUrl(e, {{"mode", "log"}, {"format", "json2"}, {"gantt",""}})) << "\";\n"
- " var refreshPeriod = " << refresh << ";\n"
- " var xn = \"" << ParseName(xn) << "\";\n"
- " var navigate = true;\n"
- << NResource::Find("lwtrace/mon/static/analytics.js") <<
- "});\n"
- "</script>\n"
- ;
- }
- BODY() {
- // Wrap selectors with navbar
- { TSelectorsContainer sc(out);
- out << selectors;
- }
- out << NResource::Find("lwtrace/mon/static/analytics.gantt.html") << Endl;
- }
- }
- }
+ out.Clear();
+ out << NMonitoring::HTTPOKHTML;
+ out << "<!DOCTYPE html>" << Endl;
+ HTML(out) {
+ HTML_TAG() {
+ HEAD() {
+ out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
+ out <<
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " var dataurl = \"" << EscapeJSONString(MakeUrl(e, "out", "json_flot")) << "\";\n"
+ " var refreshPeriod = " << refresh << ";\n"
+ " var xn = \"" << ParseName(xn) << "\";\n"
+ " var navigate = true;\n"
+ << NResource::Find("lwtrace/mon/static/analytics.js") <<
+ "});\n"
+ "</script>\n"
+ ;
+ }
+ BODY() {
+ // Wrap selectors with navbar
+ { TSelectorsContainer sc(out);
+ out << selectors;
+ }
+ out << NResource::Find("lwtrace/mon/static/analytics.flot.html") << Endl;
+ }
+ }
+ }
+ } else if (outFormat == "gantt") {
+ TString selectors = out.Str();
+ out.Clear();
+ out << NMonitoring::HTTPOKHTML;
+ out << "<!DOCTYPE html>" << Endl;
+ HTML(out) {
+ HTML_TAG() {
+ HEAD() {
+ out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
+ out <<
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " var dataurl = \"" << EscapeJSONString(MakeUrl(e, {{"mode", "log"}, {"format", "json2"}, {"gantt",""}})) << "\";\n"
+ " var refreshPeriod = " << refresh << ";\n"
+ " var xn = \"" << ParseName(xn) << "\";\n"
+ " var navigate = true;\n"
+ << NResource::Find("lwtrace/mon/static/analytics.js") <<
+ "});\n"
+ "</script>\n"
+ ;
+ }
+ BODY() {
+ // Wrap selectors with navbar
+ { TSelectorsContainer sc(out);
+ out << selectors;
+ }
+ out << NResource::Find("lwtrace/mon/static/analytics.gantt.html") << Endl;
+ }
+ }
+ }
} else if (outFormat = "text") {
- out << " <input type='text' id='logsLimit' size='2' placeholder='Limit'>" << Endl;
- out <<
+ out << " <input type='text' id='logsLimit' size='2' placeholder='Limit'>" << Endl;
+ out <<
R"END(<script>
{
var url = new URL(window.location.href);
@@ -4468,7 +4468,7 @@ private:
HTML(out) {
HTML_TAG() {
HEAD() {
- out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
+ out << NResource::Find("lwtrace/mon/static/analytics.header.html") << Endl;
}
BODY() {
// Wrap selectors with navbar
@@ -4511,213 +4511,213 @@ private:
}
}
}
- }
- }
- }
-
+ }
+ }
+ }
+
TDuration GetGetTimeout(const NMonitoring::IMonHttpRequest& request)
- {
- return (request.GetParams().Has("timeout")?
- TDuration::Seconds(FromString<double>(request.GetParams().Get("timeout"))):
- TDuration::Max());
- }
-
+ {
+ return (request.GetParams().Has("timeout")?
+ TDuration::Seconds(FromString<double>(request.GetParams().Get("timeout"))):
+ TDuration::Max());
+ }
+
void PostNew(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
+ {
+ WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
const TString& id = request.GetPostParams().Get("id");
- bool ui = (request.GetParams().Get("ui") == "y");
- TDuration timeout = GetGetTimeout(request);
- if (!CheckAdHocTrace(id, timeout)) {
- NLWTrace::TQuery query;
+ bool ui = (request.GetParams().Get("ui") == "y");
+ TDuration timeout = GetGetTimeout(request);
+ if (!CheckAdHocTrace(id, timeout)) {
+ NLWTrace::TQuery query;
TString queryStr = request.GetPostParams().Get("query");
- if (!ui) {
- queryStr = Base64Decode(queryStr); // Needed for trace.sh (historically)
- }
- WWW_CHECK(queryStr, "Empty trace query");
- bool parsed = NProtoBuf::TextFormat::ParseFromString(queryStr, &query);
- WWW_CHECK(parsed, "Trace query text protobuf parse failed"); // TODO[serxa]: report error line/col and message
- TraceMngr->New(id, query);
- Cleaner.Postpone(id, timeout, false);
- } else {
+ if (!ui) {
+ queryStr = Base64Decode(queryStr); // Needed for trace.sh (historically)
+ }
+ WWW_CHECK(queryStr, "Empty trace query");
+ bool parsed = NProtoBuf::TextFormat::ParseFromString(queryStr, &query);
+ WWW_CHECK(parsed, "Trace query text protobuf parse failed"); // TODO[serxa]: report error line/col and message
+ TraceMngr->New(id, query);
+ Cleaner.Postpone(id, timeout, false);
+ } else {
WWW_CHECK(!request.GetPostParams().Has("query"), "trace id '%s' is reserved for ad-hoc traces", id.data());
- }
- if (ui) {
- WWW_HTML(out) {
- out <<
- "<div class=\"jumbotron alert-success\">"
- "<h2>Trace created successfully</h2>"
- "</div>"
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " setTimeout(function() {"
- " window.location.replace('?');"
- " }, 1000);"
- "});\n"
- "</script>\n";
- }
- } else {
- out << HTTPOKTEXT;
- out << "OK\n";
- }
- }
-
+ }
+ if (ui) {
+ WWW_HTML(out) {
+ out <<
+ "<div class=\"jumbotron alert-success\">"
+ "<h2>Trace created successfully</h2>"
+ "</div>"
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " setTimeout(function() {"
+ " window.location.replace('?');"
+ " }, 1000);"
+ "});\n"
+ "</script>\n";
+ }
+ } else {
+ out << HTTPOKTEXT;
+ out << "OK\n";
+ }
+ }
+
void PostDelete(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
+ {
+ WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
const TString& id = request.GetPostParams().Get("id");
- bool ui = (request.GetParams().Get("ui") == "y");
- TraceMngr->Delete(id);
- Cleaner.Forget(id);
- if (ui) {
- WWW_HTML(out) {
- out <<
- "<div class=\"jumbotron alert-success\">"
- "<h2>Trace deleted successfully</h2>"
- "</div>"
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " setTimeout(function() {"
- " window.location.replace('?');"
- " }, 1000);"
- "});\n"
- "</script>\n";
- }
- } else {
- out << HTTPOKTEXT;
- out << "OK\n";
- }
- }
-
+ bool ui = (request.GetParams().Get("ui") == "y");
+ TraceMngr->Delete(id);
+ Cleaner.Forget(id);
+ if (ui) {
+ WWW_HTML(out) {
+ out <<
+ "<div class=\"jumbotron alert-success\">"
+ "<h2>Trace deleted successfully</h2>"
+ "</div>"
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " setTimeout(function() {"
+ " window.location.replace('?');"
+ " }, 1000);"
+ "});\n"
+ "</script>\n";
+ }
+ } else {
+ out << HTTPOKTEXT;
+ out << "OK\n";
+ }
+ }
+
void PostSnapshot(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
+ {
+ WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
const TString& id = request.GetPostParams().Get("id");
- bool ui = (request.GetParams().Get("ui") == "y");
- TInstant now = TInstant::Now();
-
- TGuard<TMutex> g(SnapshotsMtx);
- const NLWTrace::TSession* trace = TraceMngr->GetTrace(id);
- struct tm tm0;
+ bool ui = (request.GetParams().Get("ui") == "y");
+ TInstant now = TInstant::Now();
+
+ TGuard<TMutex> g(SnapshotsMtx);
+ const NLWTrace::TSession* trace = TraceMngr->GetTrace(id);
+ struct tm tm0;
TString sid = id + Strftime("_%Y%m%d-%H%M%S", now.GmTime(&tm0));
- TAtomicSharedPtr<NLWTrace::TLogPb>& pbPtr = Snapshots[sid];
- pbPtr.Reset(new NLWTrace::TLogPb());
- trace->ToProtobuf(*pbPtr);
- pbPtr->SetName(sid);
- if (ui) {
- WWW_HTML(out) {
- out <<
- "<div class=\"jumbotron alert-success\">"
- "<h2>Snapshot created successfully</h2>"
- "</div>"
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " setTimeout(function() {"
- " window.location.replace('?');"
- " }, 1000);"
- "});\n"
- "</script>\n";
- }
- } else {
- out << HTTPOKTEXT;
- out << "OK\n";
- }
- }
-
+ TAtomicSharedPtr<NLWTrace::TLogPb>& pbPtr = Snapshots[sid];
+ pbPtr.Reset(new NLWTrace::TLogPb());
+ trace->ToProtobuf(*pbPtr);
+ pbPtr->SetName(sid);
+ if (ui) {
+ WWW_HTML(out) {
+ out <<
+ "<div class=\"jumbotron alert-success\">"
+ "<h2>Snapshot created successfully</h2>"
+ "</div>"
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " setTimeout(function() {"
+ " window.location.replace('?');"
+ " }, 1000);"
+ "});\n"
+ "</script>\n";
+ }
+ } else {
+ out << HTTPOKTEXT;
+ out << "OK\n";
+ }
+ }
+
void PostSetTimeout(const NMonitoring::IMonHttpRequest& request, IOutputStream& out)
- {
- WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
+ {
+ WWW_CHECK(request.GetPostParams().Has("id"), "POST parameter 'id' is not specified");
const TString& id = request.GetPostParams().Get("id");
- TDuration timeout = GetGetTimeout(request);
- bool ui = (request.GetParams().Get("ui") == "y");
- Cleaner.Postpone(id, timeout, true);
- if (ui) {
- WWW_HTML(out) {
- out <<
- "<div class=\"jumbotron alert-success\">"
- "<h2>Timeout changed successfully</h2>"
- "</div>"
- "<script type=\"text/javascript\">\n"
- "$(function() {\n"
- " setTimeout(function() {"
- " window.location.replace('?');"
- " }, 1000);"
- "});\n"
- "</script>\n";
- }
- } else {
- out << HTTPOKTEXT;
- out << "OK\n";
- }
- }
+ TDuration timeout = GetGetTimeout(request);
+ bool ui = (request.GetParams().Get("ui") == "y");
+ Cleaner.Postpone(id, timeout, true);
+ if (ui) {
+ WWW_HTML(out) {
+ out <<
+ "<div class=\"jumbotron alert-success\">"
+ "<h2>Timeout changed successfully</h2>"
+ "</div>"
+ "<script type=\"text/javascript\">\n"
+ "$(function() {\n"
+ " setTimeout(function() {"
+ " window.location.replace('?');"
+ " }, 1000);"
+ "});\n"
+ "</script>\n";
+ }
+ } else {
+ out << HTTPOKTEXT;
+ out << "OK\n";
+ }
+ }
void RegisterDashboard(const TString& dashConfig) {
g_DashboardRegistry.Register(dashConfig);
}
-private:
- // Returns true iff trace is ad-hoc and ensures trace is created
+private:
+ // Returns true iff trace is ad-hoc and ensures trace is created
bool CheckAdHocTrace(const TString& id, TDuration timeout)
- {
- TAdHocTraceConfig cfg;
- if (cfg.ParseId(id)) {
- if (!TraceMngr->HasTrace(id)) {
- TraceMngr->New(id, cfg.Query());
- }
- Cleaner.Postpone(id, timeout, false);
- return true;
- }
- return false;
- }
+ {
+ TAdHocTraceConfig cfg;
+ if (cfg.ParseId(id)) {
+ if (!TraceMngr->HasTrace(id)) {
+ TraceMngr->New(id, cfg.Query());
+ }
+ Cleaner.Postpone(id, timeout, false);
+ return true;
+ }
+ return false;
+ }
};
-void RegisterPages(NMonitoring::TMonService2* mon, bool allowUnsafe) {
+void RegisterPages(NMonitoring::TMonService2* mon, bool allowUnsafe) {
THolder<NLwTraceMonPage::TLWTraceMonPage> p = MakeHolder<NLwTraceMonPage::TLWTraceMonPage>(allowUnsafe);
- mon->Register(p.Release());
-
-#define WWW_STATIC_FILE(file, type) \
- mon->Register(new TResourceMonPage(file, file, NMonitoring::TResourceMonPage::type));
- WWW_STATIC_FILE("lwtrace/mon/static/common.css", CSS);
- WWW_STATIC_FILE("lwtrace/mon/static/common.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/css/bootstrap.min.css", CSS);
- WWW_STATIC_FILE("lwtrace/mon/static/css/d3-gantt.css", CSS);
- WWW_STATIC_FILE("lwtrace/mon/static/css/jquery.treegrid.css", CSS);
- WWW_STATIC_FILE("lwtrace/mon/static/analytics.css", CSS);
- WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.eot", FONT_EOT);
- WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg", SVG);
- WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.ttf", FONT_TTF);
- WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff2", FONT_WOFF2);
- WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff", FONT_WOFF);
- WWW_STATIC_FILE("lwtrace/mon/static/img/collapse.png", PNG);
- WWW_STATIC_FILE("lwtrace/mon/static/img/expand.png", PNG);
- WWW_STATIC_FILE("lwtrace/mon/static/img/file.png", PNG);
- WWW_STATIC_FILE("lwtrace/mon/static/img/folder.png", PNG);
- WWW_STATIC_FILE("lwtrace/mon/static/js/bootstrap.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/d3.v4.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/d3-gantt.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/filesaver.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.extents.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.navigate.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.selection.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.treegrid.min.js", JAVASCRIPT);
- WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.url.min.js", JAVASCRIPT);
-#undef WWW_STATIC_FILE
+ mon->Register(p.Release());
+
+#define WWW_STATIC_FILE(file, type) \
+ mon->Register(new TResourceMonPage(file, file, NMonitoring::TResourceMonPage::type));
+ WWW_STATIC_FILE("lwtrace/mon/static/common.css", CSS);
+ WWW_STATIC_FILE("lwtrace/mon/static/common.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/css/bootstrap.min.css", CSS);
+ WWW_STATIC_FILE("lwtrace/mon/static/css/d3-gantt.css", CSS);
+ WWW_STATIC_FILE("lwtrace/mon/static/css/jquery.treegrid.css", CSS);
+ WWW_STATIC_FILE("lwtrace/mon/static/analytics.css", CSS);
+ WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.eot", FONT_EOT);
+ WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg", SVG);
+ WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.ttf", FONT_TTF);
+ WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff2", FONT_WOFF2);
+ WWW_STATIC_FILE("lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff", FONT_WOFF);
+ WWW_STATIC_FILE("lwtrace/mon/static/img/collapse.png", PNG);
+ WWW_STATIC_FILE("lwtrace/mon/static/img/expand.png", PNG);
+ WWW_STATIC_FILE("lwtrace/mon/static/img/file.png", PNG);
+ WWW_STATIC_FILE("lwtrace/mon/static/img/folder.png", PNG);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/bootstrap.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/d3.v4.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/d3-gantt.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/filesaver.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.extents.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.navigate.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.flot.selection.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.treegrid.min.js", JAVASCRIPT);
+ WWW_STATIC_FILE("lwtrace/mon/static/js/jquery.url.min.js", JAVASCRIPT);
+#undef WWW_STATIC_FILE
}
-
-NLWTrace::TProbeRegistry& ProbeRegistry() {
- return g_Probes;
-}
-
-NLWTrace::TManager& TraceManager(bool allowUnsafe) {
- return allowUnsafe? g_UnsafeManager: g_SafeManager;
-}
-
+
+NLWTrace::TProbeRegistry& ProbeRegistry() {
+ return g_Probes;
+}
+
+NLWTrace::TManager& TraceManager(bool allowUnsafe) {
+ return allowUnsafe? g_UnsafeManager: g_SafeManager;
+}
+
TDashboardRegistry& DashboardRegistry() {
return g_DashboardRegistry;
}
-} // namespace NLwTraceMonPage
+} // namespace NLwTraceMonPage
diff --git a/library/cpp/lwtrace/mon/mon_lwtrace.h b/library/cpp/lwtrace/mon/mon_lwtrace.h
index 8030f6ea61..3c239d478c 100644
--- a/library/cpp/lwtrace/mon/mon_lwtrace.h
+++ b/library/cpp/lwtrace/mon/mon_lwtrace.h
@@ -1,27 +1,27 @@
#pragma once
-
-#include <library/cpp/lwtrace/protos/lwtrace.pb.h>
+
+#include <library/cpp/lwtrace/protos/lwtrace.pb.h>
#include <library/cpp/monlib/service/monservice.h>
#include <library/cpp/lwtrace/control.h>
-#include <util/generic/vector.h>
-
-namespace NLwTraceMonPage {
-
+#include <util/generic/vector.h>
+
+namespace NLwTraceMonPage {
+
class TDashboardRegistry {
- THashMap<TString, NLWTrace::TDashboard> Dashboards;
+ THashMap<TString, NLWTrace::TDashboard> Dashboards;
TMutex Mutex;
public:
- void Register(const NLWTrace::TDashboard& dashboard);
- void Register(const TVector<NLWTrace::TDashboard>& dashboards);
+ void Register(const NLWTrace::TDashboard& dashboard);
+ void Register(const TVector<NLWTrace::TDashboard>& dashboards);
void Register(const TString& dashText);
- bool Get(const TString& name, NLWTrace::TDashboard& dash);
+ bool Get(const TString& name, NLWTrace::TDashboard& dash);
void Output(TStringStream& ss);
};
-void RegisterPages(NMonitoring::TMonService2* mon, bool allowUnsafe = false);
-NLWTrace::TProbeRegistry& ProbeRegistry(); // This is not safe to use this function before main()
-NLWTrace::TManager& TraceManager(bool allowUnsafe = false);
+void RegisterPages(NMonitoring::TMonService2* mon, bool allowUnsafe = false);
+NLWTrace::TProbeRegistry& ProbeRegistry(); // This is not safe to use this function before main()
+NLWTrace::TManager& TraceManager(bool allowUnsafe = false);
TDashboardRegistry& DashboardRegistry();
-
-} // namespace NLwTraceMonPage
+
+} // namespace NLwTraceMonPage
diff --git a/library/cpp/lwtrace/mon/static/analytics.css b/library/cpp/lwtrace/mon/static/analytics.css
index 1b0c268e43..916fb9136e 100644
--- a/library/cpp/lwtrace/mon/static/analytics.css
+++ b/library/cpp/lwtrace/mon/static/analytics.css
@@ -1,68 +1,68 @@
-#header {
- position: relative;
- width: 900px;
- margin: auto;
-}
-
-#header h2 {
- margin-left: 10px;
- vertical-align: middle;
- font-size: 42px;
- font-weight: bold;
- text-decoration: none;
- color: #000;
-}
-
-#errmsg {
- width: 95vw;
- margin: 0 auto;
- padding: 10px;
-}
-
-#footer {
- margin-top: 25px;
- margin-bottom: 10px;
- text-align: center;
- font-size: 12px;
- color: #999;
-}
-
-.chart-container {
- box-sizing: border-box;
- width: 90vw;
- height: 70vh;
- padding: 10px 0px 0px 0px;
- margin: 15px auto 30px auto;
-}
-
-#playback div { display: inline-block; }
-#playback input { display: inline-block; }
-
-.chart-placeholder {
- width: 100%;
- height: 100%;
- font-size: 14px;
- line-height: 1.2em;
-}
-
-.legend table {
- border-spacing: 5px;
-}
-
-.body-fullscreen {
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
-}
-
-.container-fullscreen {
- width: 100vw;
- height: 100vh;
- margin: 0;
-}
-
-.toolbar-fullscreen {
- display:none;
- margin: 0;
-}
+#header {
+ position: relative;
+ width: 900px;
+ margin: auto;
+}
+
+#header h2 {
+ margin-left: 10px;
+ vertical-align: middle;
+ font-size: 42px;
+ font-weight: bold;
+ text-decoration: none;
+ color: #000;
+}
+
+#errmsg {
+ width: 95vw;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#footer {
+ margin-top: 25px;
+ margin-bottom: 10px;
+ text-align: center;
+ font-size: 12px;
+ color: #999;
+}
+
+.chart-container {
+ box-sizing: border-box;
+ width: 90vw;
+ height: 70vh;
+ padding: 10px 0px 0px 0px;
+ margin: 15px auto 30px auto;
+}
+
+#playback div { display: inline-block; }
+#playback input { display: inline-block; }
+
+.chart-placeholder {
+ width: 100%;
+ height: 100%;
+ font-size: 14px;
+ line-height: 1.2em;
+}
+
+.legend table {
+ border-spacing: 5px;
+}
+
+.body-fullscreen {
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+}
+
+.container-fullscreen {
+ width: 100vw;
+ height: 100vh;
+ margin: 0;
+}
+
+.toolbar-fullscreen {
+ display:none;
+ margin: 0;
+}
diff --git a/library/cpp/lwtrace/mon/static/analytics.flot.html b/library/cpp/lwtrace/mon/static/analytics.flot.html
index ea0a2880a5..9f2a2264fd 100644
--- a/library/cpp/lwtrace/mon/static/analytics.flot.html
+++ b/library/cpp/lwtrace/mon/static/analytics.flot.html
@@ -1,49 +1,49 @@
-<div class="container-fluid" id="toolbar" style="margin:10px;width:92vw">
- <div class="pull-right" id="playback">
- <div class="btn-group" style="margin-right:40px">
- <button type="button" class="btn btn-default" id="pb-linesfill">linesfill</button>
- <button type="button" class="btn btn-default" id="pb-linessteps">linessteps</button>
- <button type="button" class="btn btn-default" id="pb-linesshow">linesshow</button>
- <button type="button" class="btn btn-default" id="pb-pointsshow">pointsshow</button>
- </div>
- <div class="btn-group" style="margin-right:40px">
- <button type="button" class="btn btn-default" id="pb-export">Export</button>
- <button type="button" class="btn btn-default" id="pb-import" data-toggle="modal" data-target="#importModal">Import</button>
- </div>
- <button type="button" class="btn btn-default hidden" id="pb-unselect">unselect</button>
- <button type="button" class="btn" id="pb-fullscreen">Fullscreen</button>
- <button type="button" class="btn" id="pb-autoscale" title="Enforce axis min/max value to be equal to min/max value of data points">Autoscale</button>
- <button type="button" class="btn" id="pb-legendshow">Legend</button>
- <button type="button" class="btn" id="pb-cutts" title="Cuts old items in every trace log to make them start from the same instant">Cut Tails</button>
- <button type="button" class="btn btn-default" id="pb-pause"><strong>||</strong></button>
- </div>
-
- <div style="display:inline-block">
- <div style="display: inline-block">
- <span id="errmsg2" style="display:none"></span>
- </div>
- </div>
-</div>
-
-<div class="chart-container" id="container">
- <div id="placeholder" class="chart-placeholder"></div>
-</div>
-
-<div class="modal fade" id="importModal" tabindex="-1" role="dialog" aria-labelledby="importModalLabel">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
- aria-hidden="true">&times;</span></button>
- <h4 class="modal-title" id="importModalLabel">Import chart Data</h4>
- </div>
- <div class="modal-body">
- <input type="file" id="importFiles" value="Import" /><br />
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary" id="btnDoImport">Import</button>
- </div>
- </div>
- </div>
-</div>
+<div class="container-fluid" id="toolbar" style="margin:10px;width:92vw">
+ <div class="pull-right" id="playback">
+ <div class="btn-group" style="margin-right:40px">
+ <button type="button" class="btn btn-default" id="pb-linesfill">linesfill</button>
+ <button type="button" class="btn btn-default" id="pb-linessteps">linessteps</button>
+ <button type="button" class="btn btn-default" id="pb-linesshow">linesshow</button>
+ <button type="button" class="btn btn-default" id="pb-pointsshow">pointsshow</button>
+ </div>
+ <div class="btn-group" style="margin-right:40px">
+ <button type="button" class="btn btn-default" id="pb-export">Export</button>
+ <button type="button" class="btn btn-default" id="pb-import" data-toggle="modal" data-target="#importModal">Import</button>
+ </div>
+ <button type="button" class="btn btn-default hidden" id="pb-unselect">unselect</button>
+ <button type="button" class="btn" id="pb-fullscreen">Fullscreen</button>
+ <button type="button" class="btn" id="pb-autoscale" title="Enforce axis min/max value to be equal to min/max value of data points">Autoscale</button>
+ <button type="button" class="btn" id="pb-legendshow">Legend</button>
+ <button type="button" class="btn" id="pb-cutts" title="Cuts old items in every trace log to make them start from the same instant">Cut Tails</button>
+ <button type="button" class="btn btn-default" id="pb-pause"><strong>||</strong></button>
+ </div>
+
+ <div style="display:inline-block">
+ <div style="display: inline-block">
+ <span id="errmsg2" style="display:none"></span>
+ </div>
+ </div>
+</div>
+
+<div class="chart-container" id="container">
+ <div id="placeholder" class="chart-placeholder"></div>
+</div>
+
+<div class="modal fade" id="importModal" tabindex="-1" role="dialog" aria-labelledby="importModalLabel">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
+ aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="importModalLabel">Import chart Data</h4>
+ </div>
+ <div class="modal-body">
+ <input type="file" id="importFiles" value="Import" /><br />
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-primary" id="btnDoImport">Import</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/library/cpp/lwtrace/mon/static/analytics.gantt.html b/library/cpp/lwtrace/mon/static/analytics.gantt.html
index cf41008900..9b846510c9 100644
--- a/library/cpp/lwtrace/mon/static/analytics.gantt.html
+++ b/library/cpp/lwtrace/mon/static/analytics.gantt.html
@@ -1,26 +1,26 @@
-<div id="placeholder" class="chart-placeholder"></div>
-
-<div class="form-group"><label class="col-sm-1 control-label" for="textareaGantt">Config</label>
- <div class="col-sm-11">
- <textarea class="form-control" id="textareaGantt" name="gantt" rows="5">
-{
- "bands": [
- {
- "t1": "_thrRTime[0]",
- "t2": "_thrRTime[-1]",
- "band": "_thread",
- "color": "1",
- "colorScale": "colors1"
- }
- ],
- "scales": {
- "colors1": "linear().domain([-1,0,1]).range(['red','black','green'])",
- "colors2": "ordinal().domain(['VALUE1','VALUE2']).range(['blue','yellow'])"
- }
-}
- </textarea>
- </div>
-</div>
-<div class="form-group">
- <div class="col-sm-offset-1 col-sm-11"><button class="btn btn-default" id="gantt-apply">Apply</button></div>
-</div>
+<div id="placeholder" class="chart-placeholder"></div>
+
+<div class="form-group"><label class="col-sm-1 control-label" for="textareaGantt">Config</label>
+ <div class="col-sm-11">
+ <textarea class="form-control" id="textareaGantt" name="gantt" rows="5">
+{
+ "bands": [
+ {
+ "t1": "_thrRTime[0]",
+ "t2": "_thrRTime[-1]",
+ "band": "_thread",
+ "color": "1",
+ "colorScale": "colors1"
+ }
+ ],
+ "scales": {
+ "colors1": "linear().domain([-1,0,1]).range(['red','black','green'])",
+ "colors2": "ordinal().domain(['VALUE1','VALUE2']).range(['blue','yellow'])"
+ }
+}
+ </textarea>
+ </div>
+</div>
+<div class="form-group">
+ <div class="col-sm-offset-1 col-sm-11"><button class="btn btn-default" id="gantt-apply">Apply</button></div>
+</div>
diff --git a/library/cpp/lwtrace/mon/static/analytics.header.html b/library/cpp/lwtrace/mon/static/analytics.header.html
index 0a6790e232..53d080f41f 100644
--- a/library/cpp/lwtrace/mon/static/analytics.header.html
+++ b/library/cpp/lwtrace/mon/static/analytics.header.html
@@ -1,21 +1,21 @@
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link rel="stylesheet" href="lwtrace/mon/static/analytics.css" type="text/css">
-<link rel="stylesheet" href="lwtrace/mon/static/css/d3-gantt.css" type="text/css">
-<link rel="stylesheet" href="lwtrace/mon/static/css/bootstrap.min.css">
-<link rel="stylesheet" href="lwtrace/mon/static/css/jquery.treegrid.css">
-<link rel="stylesheet" href="lwtrace/mon/static/common.css">
-
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.url.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.navigate.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.extents.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.selection.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/bootstrap.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/filesaver.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/d3.v4.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/d3-gantt.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/common.js"></script>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel="stylesheet" href="lwtrace/mon/static/analytics.css" type="text/css">
+<link rel="stylesheet" href="lwtrace/mon/static/css/d3-gantt.css" type="text/css">
+<link rel="stylesheet" href="lwtrace/mon/static/css/bootstrap.min.css">
+<link rel="stylesheet" href="lwtrace/mon/static/css/jquery.treegrid.css">
+<link rel="stylesheet" href="lwtrace/mon/static/common.css">
+
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.url.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.navigate.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.extents.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.flot.selection.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/bootstrap.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/filesaver.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/d3.v4.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/d3-gantt.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/common.js"></script>
diff --git a/library/cpp/lwtrace/mon/static/analytics.js b/library/cpp/lwtrace/mon/static/analytics.js
index 7b66cca4c0..85b869869b 100644
--- a/library/cpp/lwtrace/mon/static/analytics.js
+++ b/library/cpp/lwtrace/mon/static/analytics.js
@@ -1,561 +1,561 @@
-/*
- * This code is executed from document ready function
- * Also note that some variable are set from C++ code
- */
-
-var x1 = $.url("?x1");
-var x2 = $.url("?x2");
-var y1 = $.url("?y1");
-var y2 = $.url("?y2");
-
-var gantt = $.url("?gantt");
-var out = $.url("?out");
-
-var linesfill = $.url("?linesfill") == "y";
-var linessteps = $.url("?linessteps") == "y";
-var linesshow = $.url("?linesshow") != "n";
-var pointsshow = $.url("?pointsshow") != "n";
-var autoscale = $.url("?autoscale") == "y";
-var legendshow = $.url("?legendshow") != "n";
-var cutts = $.url("?cutts") == "y";
-var fullscreen = $.url("?fullscreen") == "y";
-var realnames = $.url("?realnames") == "y";
-var xzoomoff = $.url("?xzoomoff") == "y";
-var yzoomoff = $.url("?yzoomoff") == "y";
-
-function inIframe() { try { return window.self !== window.top; } catch (e) { return true; } }
-function inDashboard() { return fullscreen && inIframe(); }
-
-// URL management
-function makeUrl(url, queryFunc, hashFunc) {
- var query = $.url("?", url);
- var hash = $.url("#", url);
- if (paused) {
- query.paused = "y";
- }
-
- if (queryFunc) { queryFunc(query); }
- if (hashFunc) { hashFunc(hash); }
- var queryStr = "";
- var first = true;
- for (var k in query) {
- queryStr += (first? "?": "&") + k + "=" + encodeURIComponent(query[k]);
- first = false;
- }
- var hashStr = "";
- first = true;
- for (k in hash) {
- hashStr += (first? "#": "&") + k + "=" + encodeURIComponent(hash[k]);
- first = false;
- }
- return queryStr + hashStr;
-}
-
-function dataUrl() {
- return makeUrl(dataurl, function(query) {
- query.error = "text";
- });
-}
-
-// Error message popup
-$("<div id='errmsg'></div>").css({
- position: "absolute",
- display: "none",
- border: "1px solid #faa",
- padding: "2px",
- "background-color": "#fcc",
- opacity: 0.80
-}).appendTo("body");
-
-if (out == "gantt") {
- $("#gantt-apply").click(function() {
- try {
- let val = $("#textareaGantt").val().replace(/\s/g, "");
- JSON.parse(val);
- window.location.replace(makeUrl($.url(), function(query) {
- query.gantt = val;
- }));
- } catch(e) {
- $("#errmsg").text("Not valid JSON: " + e)
- .css({bottom: "5px", left: "25%", width: "50%"})
- .fadeIn(200);
- }
- });
-
- if (gantt) {
- // Data fetching and auto-refreshing
- var fetchCounter = 0;
- function fetchData() {
- function onDataReceived(json, textStatus, xhr) {
- $("#errmsg").hide();
- logs = json;
- chart(config, logs, true);
- }
-
- function onDataError(xhr, error) {
- console.log(arguments);
- $("#errmsg").text("Fetch data error: " + error + (xhr.status == 200? xhr.responseText: ""))
- .css({bottom: "5px", left: "25%", width: "50%"})
- .fadeIn(200);
- }
-
- if (dataurl) {
- $.ajax({
- url: dataUrl(),
- type: "GET",
- dataType: "json",
- success: function (json, textStatus, xhr) { onDataReceived(json, textStatus, xhr); },
- error: onDataError
- });
- } else {
- onDataReceived(datajson, "textStatus", "xhr");
- }
-
- // if (fetchPeriod > 0) {
- // if (fetchCounter == 0) {
- // fetchCounter++;
- // setTimeout(function() {
- // fetchCounter--;
- // if (!paused) {
- // fetchData();
- // }
- // }, $("#errmsg").is(":visible")? errorPeriod: fetchPeriod);
- // }
- // }
- }
-
- try {
- var config = JSON.parse(gantt);
- $("#textareaGantt").val(JSON.stringify(config, "\n", " "));
- let formHeight = 220;
- var chart = d3.gantt()
- .height(window.innerHeight - $("#placeholder")[0].getBoundingClientRect().y - window.scrollY - formHeight)
- .selector("#placeholder");
- var logs = null;
- fetchData();
- } catch(e) {
- $("#textareaGantt").val(gantt);
- alert("Not valid JSON: " + e);
- }
- }
-} else { // flot
- // Special options adjustment for fullscreen charts in iframe (solomon dashboards)
- if (fullscreen) {
- navigate = false; // Disable navigation to avoid scrolling problems
- legendshow = false; // Show legend only on hover
- }
-
- // Adjust zooming options
- var xZoomRange = null;
- var yZoomRange = null;
- if (xzoomoff) {
- xZoomRange = false;
- }
- if (yzoomoff) {
- yZoomRange = false;
- }
-
- var placeholder = $("#placeholder");
- var playback = $("#playback");
-
- var data = null;
- var loaded_data = [];
- var imported_data = [];
- var fetchPeriod = refreshPeriod;
- var errorPeriod = 5000;
- var playbackPeriod = 500;
- var abstimestep = 1.0;
-
- var paused = $.url("?paused") == "y";
- var timestep = abstimestep;
-
- var seriesDescription = {
- _time: "time",
- _thread: "thread"
- }
-
- function seriesDesc(name) {
- if (seriesDescription.hasOwnProperty(name)) {
- return (realnames? "[" + name + "] ": "") + seriesDescription[name];
- } else {
- return name;
- }
- }
-
- playback.show();
-
- var options = {
- series: {
- lines: { show: linesshow, fill: linesfill, steps: linessteps},
- points: { show: pointsshow },
- shadowSize: 0
- },
- xaxis: { zoomRange: xZoomRange },
- yaxis: { zoomRange: yZoomRange },
- grid: { clickable: true, hoverable: true },
- zoom: { interactive: navigate },
- pan: { interactive: navigate },
- legend: {
- show: legendshow,
- labelFormatter: function(label, series) { return seriesDesc(label) + '(' + seriesDesc(xn) + ')'; }
- }
- };
-
- if (fullscreen) {
- $("body").attr("class","body-fullscreen");
- $("#container").attr("class","container-fullscreen");
- $("#toolbar").attr("class","toolbar-fullscreen");
- $("#selectors-container").attr("class","toolbar-fullscreen");
- options.grid.margin = 0;
- }
-
- if (x1) { options.xaxis.min = x1; }
- if (x2) { options.xaxis.max = x2; }
- if (y1) { options.yaxis.min = y1; }
- if (y2) { options.yaxis.max = y2; }
-
- $("<div id='tooltip'></div>").css({
- position: "absolute",
- display: "none",
- border: "1px solid #fdd",
- padding: "2px",
- "background-color": "#fee",
- opacity: 0.80
- }).appendTo("body");
-
- // Helper to hide tooltip
- var lastShow = new Date();
- var hideCounter = 0;
- function hideTooltip() {
- if (hideCounter == 0) {
- hideCounter++;
- setTimeout(function() {
- hideCounter--;
- if (new Date().getTime() - lastShow.getTime() > 1000) {
- $("#tooltip").fadeOut(200);
- } else if ($("#tooltip").is(":visible")) {
- hideTooltip();
- }
- }, 200);
- }
- }
-
- // Helper to hide legend
- var legendLastShow = new Date();
- var legendHideCounter = 0;
- function hideLegend() {
- if (legendHideCounter == 0) {
- legendHideCounter++;
- setTimeout(function() {
- legendHideCounter--;
- if (new Date().getTime() - legendLastShow.getTime() > 1000) {
- options.legend.show = false;
- $.plot(placeholder, data, options);
- } else {
- hideLegend();
- }
- }, 200);
- }
- }
-
- function onPlotClick(event, pos, item) {
- // Leave fullscreen on click
- var nonFullscreenUrl = makeUrl($.url(), function(query) {
- delete query.fullscreen;
- });
- if (inDashboard()) {
- window.open(nonFullscreenUrl, "_blank");
- } else if (fullscreen) {
- window.location.href = nonFullscreenUrl;
- }
- }
-
- function onPlotHover(event, pos, item) {
- var redraw = false;
- // Show legend on hover
- if (fullscreen) {
- legendLastShow = new Date();
- if (!options.legend.show) {
- redraw = true;
- }
- options.legend.show = true;
- hideLegend();
- }
-
- // Show names on hover
- var left = placeholder.position().left;
- var top = placeholder.position().top;
- var ttmargin = 10;
- var ttwidth = $("#tooltip").width();
- var ttheight = $("#tooltip").height();
- if (linessteps) {
- var pts = data[0].data;
- var idx = 0;
- for (var i = 0; i < pts.length - 1; i++) {
- var x1 = pts[i][0];
- var x2 = pts[i+1][0];
- if (pos.x >= x1 && (x2 == null || pos.x < x2)) {
- idx = i;
- }
- }
- var n = pts[idx][2];
- var html = (n? "<u><b><center>" + n + "</center></b></u>": "") + "<table><tr><td align=\"right\">" + seriesDesc(xn) + "</td><td>: </td><td>" + pts[idx][3] + "</td></tr>";
- for (var sid = 0; sid < data.length; sid++) {
- var series = data[sid];
- var y = series.data[idx][4];
- html += "<tr><td align=\"right\">" + seriesDesc(series.label) + "</td><td>: </td><td>" + y + "</td></tr>";
- }
- html += "</table>";
-
- lastShow = new Date();
- if (pos.pageX < left + placeholder.width() && pos.pageX > left &&
- pos.pageY < top + placeholder.height() && pos.pageY > top) {
- $("#tooltip").html(html)
- .css({top: Math.max(top + ttmargin + 10, pos.pageY - ttheight - 20),
- left: Math.max(left + ttmargin + 10, pos.pageX - ttwidth - 20)})
- .fadeIn(200, "swing", hideTooltip());
- }
- } else {
- if (item) {
- var idx = item.dataIndex;
- var n = item.series.data[idx][2];
- var x = item.series.data[idx][3]; //item.datapoint[0];
- var y = item.series.data[idx][4]; //item.datapoint[1];
- $("#tooltip").html((n? n + ": ": "") + seriesDesc(item.series.label) + " = " + y + ", " + seriesDesc(xn) + " = " + x)
- .css({top: Math.max(top + ttmargin + 10, item.pageY - ttheight - 20),
- left: Math.max(left + ttmargin + 10, item.pageX - ttwidth - 20)})
- .fadeIn(200);
- } else {
- $("#tooltip").hide();
- }
- }
-
- // Redraw if required
- if (redraw) {
- $.plot(placeholder, data, options);
- }
- }
-
- // Add some more interactivity
- function onZoomOrPan(event, plot) {
- var axes = plot.getAxes();
- options.xaxis.min = axes.xaxis.min;
- options.xaxis.max = axes.xaxis.max;
- options.yaxis.min = axes.yaxis.min;
- options.yaxis.max = axes.yaxis.max;
- }
-
- // Bind to events
- placeholder.bind("plotclick", onPlotClick);
- placeholder.bind("plothover", onPlotHover);
- placeholder.bind("plotpan", onZoomOrPan);
- placeholder.bind("plotzoom", onZoomOrPan);
-
- // Data fetching and auto-refreshing
- var fetchCounter = 0;
- function fetchData() {
- function onDataReceived(json, textStatus, xhr) {
- $("#errmsg").hide();
- if (paused && logs) {
- return;
- }
-
- // Plot fetched data
- loaded_data = json;
- data = loaded_data.concat(imported_data);
-
- if (autoscale) {
- var xmin = null;
- var xmax = null;
- var ymin = null;
- var ymax = null;
- for (var sid = 0; sid < data.length; sid++) {
- var pts = data[sid].data;
- for (var i = 0; i < pts.length; i++) {
- var x = pts[i][0];
- var y = pts[i][1];
- if (x != null && y != null) {
- if (xmin == null || x < xmin) { xmin = x; }
- if (xmax == null || x > xmax) { xmax = x; }
- if (ymin == null || y < ymin) { ymin = y; }
- if (ymax == null || y > ymax) { ymax = y; }
- }
- }
- }
- if (xmin != null) { options.xaxis.min = xmin; }
- if (xmax != null) { options.xaxis.max = xmax; }
- if (ymin != null) { options.yaxis.min = ymin; }
- if (ymax != null) { options.yaxis.max = ymax; }
- }
- $.plot(placeholder, data, options);
- }
-
- function onDataError(xhr, error) {
- console.log(arguments);
- $("#errmsg").text("Fetch data error: " + error + (xhr.status == 200? xhr.responseText: ""))
- .css({bottom: "5px", left: "25%", width: "50%"})
- .fadeIn(200);
- }
-
- if (dataurl) {
- $.ajax({
- url: dataUrl(),
- type: "GET",
- dataType: "json",
- success: function (json, textStatus, xhr) { onDataReceived(json, textStatus, xhr); },
- error: onDataError
- });
- } else {
- onDataReceived(datajson, "textStatus", "xhr");
- }
-
- if (fetchPeriod > 0) {
- if (fetchCounter == 0) {
- fetchCounter++;
- setTimeout(function() {
- fetchCounter--;
- if (!paused) {
- fetchData();
- }
- }, $("#errmsg").is(":visible")? errorPeriod: fetchPeriod);
- }
- }
- }
-
- // Playback control
- var pb_pause = $("#pb-pause");
-
- function setActive(btn, active) {
- if (active) {
- btn.addClass("btn-primary");
- btn.removeClass("btn-default");
- } else {
- btn.addClass("btn-default");
- btn.removeClass("btn-primary");
- }
- }
-
- function onPlaybackControl() {
- setActive(pb_pause, paused);
- fetchPeriod = refreshPeriod;
- fetchData();
- }
-
- function clickPause(val) {
- paused = val;
- onPlaybackControl();
- }
-
- pb_pause.click(function() { clickPause(!paused); });
-
- function addOptionButton(opt, btn, defOn) {
- setActive(btn, defOn ? $.url("?" + opt) != "n" : $.url("?" + opt) == "y");
- btn.click(function() {
- window.location.replace(makeUrl($.url(), function(query) {
- if (defOn) {
- if ($.url("?" + opt) != "n") {
- query[opt] = "n";
- } else {
- delete query[opt];
- }
- } else {
- if ($.url("?" + opt) == "y") {
- delete query[opt];
- } else {
- query[opt] = "y";
- }
- }
- }));
- });
- }
-
- // Options
- addOptionButton("linesfill", $("#pb-linesfill"), false);
- addOptionButton("linessteps", $("#pb-linessteps"), false);
- addOptionButton("linesshow", $("#pb-linesshow"), true);
- addOptionButton("pointsshow", $("#pb-pointsshow"), true);
- addOptionButton("legendshow", $("#pb-legendshow"), true);
- addOptionButton("cutts", $("#pb-cutts"), false);
- addOptionButton("autoscale", $("#pb-autoscale"), false);
-
- var pb_fullscreen = $("#pb-fullscreen");
- setActive(pb_fullscreen, fullscreen);
- pb_fullscreen.click(function(){
- window.location.href = makeUrl($.url(), function(query) {
- if (fullscreen) {
- delete query.fullscreen;
- } else {
- query.fullscreen = "y";
- }
- });
- });
-
- // Embeded mode (in case there is other stuff on page)
- function embededMode() {
- $("#pb-fullscreen").hide();
- $("#pb-autoscale").hide();
- $("#pb-legendshow").hide();
- $("#pb-pause").hide();
- }
-
- function enableSelection() {
- // Redraw chart with selection enabled
- options.selection = {mode: "x"};
- var plot = $.plot(placeholder, data, options);
- if ($.url("?sel_x1") && $.url("?sel_x2")) {
- plot.setSelection({
- xaxis: {
- from: $.url("?sel_x1") ,
- to: $.url("?sel_x2")
- }
- });
- }
-
- // Create selection hooks
- placeholder.bind("plotselected", function (event, ranges) {
- window.location.replace(makeUrl($.url(), function(query) {
- query.sel_x1 = ranges.xaxis.from;
- query.sel_x2 = ranges.xaxis.to;
- }));
- });
- placeholder.bind("plotunselected", function (event) {
- window.location.replace(makeUrl($.url(), function(query) {
- delete query.sel_x1;
- delete query.sel_x2;
- }));
- });
-
- // Init and show unselect button
- $("#pb-unselect").click(function () {
- plot.clearSelection();
- });
- $("#pb-unselect").removeClass("hidden");
- }
-
- // Export data
- var pb_export = $("#pb-export");
- pb_export.click(function(){
- var blob = new Blob([JSON.stringify(data)], {type: "application/json;charset=utf-8"});
- saveAs(blob, "exported.json");
- });
-
- // Import data
- $("#btnDoImport").click(function(){
- var files = document.getElementById('importFiles').files;
- if (files.length <= 0) {
- return false;
- }
-
- var fr = new FileReader();
- fr.onload = function(e) {
- imported_data = imported_data.concat(JSON.parse(e.target.result));
- data = loaded_data.concat(imported_data);
- $.plot(placeholder, data, options);
- $('#importModal').modal('hide');
- }
- fr.readAsText(files.item(0));
- });
-
- // Initialize stuff and fetch data
- onPlaybackControl();
-}
+/*
+ * This code is executed from document ready function
+ * Also note that some variable are set from C++ code
+ */
+
+var x1 = $.url("?x1");
+var x2 = $.url("?x2");
+var y1 = $.url("?y1");
+var y2 = $.url("?y2");
+
+var gantt = $.url("?gantt");
+var out = $.url("?out");
+
+var linesfill = $.url("?linesfill") == "y";
+var linessteps = $.url("?linessteps") == "y";
+var linesshow = $.url("?linesshow") != "n";
+var pointsshow = $.url("?pointsshow") != "n";
+var autoscale = $.url("?autoscale") == "y";
+var legendshow = $.url("?legendshow") != "n";
+var cutts = $.url("?cutts") == "y";
+var fullscreen = $.url("?fullscreen") == "y";
+var realnames = $.url("?realnames") == "y";
+var xzoomoff = $.url("?xzoomoff") == "y";
+var yzoomoff = $.url("?yzoomoff") == "y";
+
+function inIframe() { try { return window.self !== window.top; } catch (e) { return true; } }
+function inDashboard() { return fullscreen && inIframe(); }
+
+// URL management
+function makeUrl(url, queryFunc, hashFunc) {
+ var query = $.url("?", url);
+ var hash = $.url("#", url);
+ if (paused) {
+ query.paused = "y";
+ }
+
+ if (queryFunc) { queryFunc(query); }
+ if (hashFunc) { hashFunc(hash); }
+ var queryStr = "";
+ var first = true;
+ for (var k in query) {
+ queryStr += (first? "?": "&") + k + "=" + encodeURIComponent(query[k]);
+ first = false;
+ }
+ var hashStr = "";
+ first = true;
+ for (k in hash) {
+ hashStr += (first? "#": "&") + k + "=" + encodeURIComponent(hash[k]);
+ first = false;
+ }
+ return queryStr + hashStr;
+}
+
+function dataUrl() {
+ return makeUrl(dataurl, function(query) {
+ query.error = "text";
+ });
+}
+
+// Error message popup
+$("<div id='errmsg'></div>").css({
+ position: "absolute",
+ display: "none",
+ border: "1px solid #faa",
+ padding: "2px",
+ "background-color": "#fcc",
+ opacity: 0.80
+}).appendTo("body");
+
+if (out == "gantt") {
+ $("#gantt-apply").click(function() {
+ try {
+ let val = $("#textareaGantt").val().replace(/\s/g, "");
+ JSON.parse(val);
+ window.location.replace(makeUrl($.url(), function(query) {
+ query.gantt = val;
+ }));
+ } catch(e) {
+ $("#errmsg").text("Not valid JSON: " + e)
+ .css({bottom: "5px", left: "25%", width: "50%"})
+ .fadeIn(200);
+ }
+ });
+
+ if (gantt) {
+ // Data fetching and auto-refreshing
+ var fetchCounter = 0;
+ function fetchData() {
+ function onDataReceived(json, textStatus, xhr) {
+ $("#errmsg").hide();
+ logs = json;
+ chart(config, logs, true);
+ }
+
+ function onDataError(xhr, error) {
+ console.log(arguments);
+ $("#errmsg").text("Fetch data error: " + error + (xhr.status == 200? xhr.responseText: ""))
+ .css({bottom: "5px", left: "25%", width: "50%"})
+ .fadeIn(200);
+ }
+
+ if (dataurl) {
+ $.ajax({
+ url: dataUrl(),
+ type: "GET",
+ dataType: "json",
+ success: function (json, textStatus, xhr) { onDataReceived(json, textStatus, xhr); },
+ error: onDataError
+ });
+ } else {
+ onDataReceived(datajson, "textStatus", "xhr");
+ }
+
+ // if (fetchPeriod > 0) {
+ // if (fetchCounter == 0) {
+ // fetchCounter++;
+ // setTimeout(function() {
+ // fetchCounter--;
+ // if (!paused) {
+ // fetchData();
+ // }
+ // }, $("#errmsg").is(":visible")? errorPeriod: fetchPeriod);
+ // }
+ // }
+ }
+
+ try {
+ var config = JSON.parse(gantt);
+ $("#textareaGantt").val(JSON.stringify(config, "\n", " "));
+ let formHeight = 220;
+ var chart = d3.gantt()
+ .height(window.innerHeight - $("#placeholder")[0].getBoundingClientRect().y - window.scrollY - formHeight)
+ .selector("#placeholder");
+ var logs = null;
+ fetchData();
+ } catch(e) {
+ $("#textareaGantt").val(gantt);
+ alert("Not valid JSON: " + e);
+ }
+ }
+} else { // flot
+ // Special options adjustment for fullscreen charts in iframe (solomon dashboards)
+ if (fullscreen) {
+ navigate = false; // Disable navigation to avoid scrolling problems
+ legendshow = false; // Show legend only on hover
+ }
+
+ // Adjust zooming options
+ var xZoomRange = null;
+ var yZoomRange = null;
+ if (xzoomoff) {
+ xZoomRange = false;
+ }
+ if (yzoomoff) {
+ yZoomRange = false;
+ }
+
+ var placeholder = $("#placeholder");
+ var playback = $("#playback");
+
+ var data = null;
+ var loaded_data = [];
+ var imported_data = [];
+ var fetchPeriod = refreshPeriod;
+ var errorPeriod = 5000;
+ var playbackPeriod = 500;
+ var abstimestep = 1.0;
+
+ var paused = $.url("?paused") == "y";
+ var timestep = abstimestep;
+
+ var seriesDescription = {
+ _time: "time",
+ _thread: "thread"
+ }
+
+ function seriesDesc(name) {
+ if (seriesDescription.hasOwnProperty(name)) {
+ return (realnames? "[" + name + "] ": "") + seriesDescription[name];
+ } else {
+ return name;
+ }
+ }
+
+ playback.show();
+
+ var options = {
+ series: {
+ lines: { show: linesshow, fill: linesfill, steps: linessteps},
+ points: { show: pointsshow },
+ shadowSize: 0
+ },
+ xaxis: { zoomRange: xZoomRange },
+ yaxis: { zoomRange: yZoomRange },
+ grid: { clickable: true, hoverable: true },
+ zoom: { interactive: navigate },
+ pan: { interactive: navigate },
+ legend: {
+ show: legendshow,
+ labelFormatter: function(label, series) { return seriesDesc(label) + '(' + seriesDesc(xn) + ')'; }
+ }
+ };
+
+ if (fullscreen) {
+ $("body").attr("class","body-fullscreen");
+ $("#container").attr("class","container-fullscreen");
+ $("#toolbar").attr("class","toolbar-fullscreen");
+ $("#selectors-container").attr("class","toolbar-fullscreen");
+ options.grid.margin = 0;
+ }
+
+ if (x1) { options.xaxis.min = x1; }
+ if (x2) { options.xaxis.max = x2; }
+ if (y1) { options.yaxis.min = y1; }
+ if (y2) { options.yaxis.max = y2; }
+
+ $("<div id='tooltip'></div>").css({
+ position: "absolute",
+ display: "none",
+ border: "1px solid #fdd",
+ padding: "2px",
+ "background-color": "#fee",
+ opacity: 0.80
+ }).appendTo("body");
+
+ // Helper to hide tooltip
+ var lastShow = new Date();
+ var hideCounter = 0;
+ function hideTooltip() {
+ if (hideCounter == 0) {
+ hideCounter++;
+ setTimeout(function() {
+ hideCounter--;
+ if (new Date().getTime() - lastShow.getTime() > 1000) {
+ $("#tooltip").fadeOut(200);
+ } else if ($("#tooltip").is(":visible")) {
+ hideTooltip();
+ }
+ }, 200);
+ }
+ }
+
+ // Helper to hide legend
+ var legendLastShow = new Date();
+ var legendHideCounter = 0;
+ function hideLegend() {
+ if (legendHideCounter == 0) {
+ legendHideCounter++;
+ setTimeout(function() {
+ legendHideCounter--;
+ if (new Date().getTime() - legendLastShow.getTime() > 1000) {
+ options.legend.show = false;
+ $.plot(placeholder, data, options);
+ } else {
+ hideLegend();
+ }
+ }, 200);
+ }
+ }
+
+ function onPlotClick(event, pos, item) {
+ // Leave fullscreen on click
+ var nonFullscreenUrl = makeUrl($.url(), function(query) {
+ delete query.fullscreen;
+ });
+ if (inDashboard()) {
+ window.open(nonFullscreenUrl, "_blank");
+ } else if (fullscreen) {
+ window.location.href = nonFullscreenUrl;
+ }
+ }
+
+ function onPlotHover(event, pos, item) {
+ var redraw = false;
+ // Show legend on hover
+ if (fullscreen) {
+ legendLastShow = new Date();
+ if (!options.legend.show) {
+ redraw = true;
+ }
+ options.legend.show = true;
+ hideLegend();
+ }
+
+ // Show names on hover
+ var left = placeholder.position().left;
+ var top = placeholder.position().top;
+ var ttmargin = 10;
+ var ttwidth = $("#tooltip").width();
+ var ttheight = $("#tooltip").height();
+ if (linessteps) {
+ var pts = data[0].data;
+ var idx = 0;
+ for (var i = 0; i < pts.length - 1; i++) {
+ var x1 = pts[i][0];
+ var x2 = pts[i+1][0];
+ if (pos.x >= x1 && (x2 == null || pos.x < x2)) {
+ idx = i;
+ }
+ }
+ var n = pts[idx][2];
+ var html = (n? "<u><b><center>" + n + "</center></b></u>": "") + "<table><tr><td align=\"right\">" + seriesDesc(xn) + "</td><td>: </td><td>" + pts[idx][3] + "</td></tr>";
+ for (var sid = 0; sid < data.length; sid++) {
+ var series = data[sid];
+ var y = series.data[idx][4];
+ html += "<tr><td align=\"right\">" + seriesDesc(series.label) + "</td><td>: </td><td>" + y + "</td></tr>";
+ }
+ html += "</table>";
+
+ lastShow = new Date();
+ if (pos.pageX < left + placeholder.width() && pos.pageX > left &&
+ pos.pageY < top + placeholder.height() && pos.pageY > top) {
+ $("#tooltip").html(html)
+ .css({top: Math.max(top + ttmargin + 10, pos.pageY - ttheight - 20),
+ left: Math.max(left + ttmargin + 10, pos.pageX - ttwidth - 20)})
+ .fadeIn(200, "swing", hideTooltip());
+ }
+ } else {
+ if (item) {
+ var idx = item.dataIndex;
+ var n = item.series.data[idx][2];
+ var x = item.series.data[idx][3]; //item.datapoint[0];
+ var y = item.series.data[idx][4]; //item.datapoint[1];
+ $("#tooltip").html((n? n + ": ": "") + seriesDesc(item.series.label) + " = " + y + ", " + seriesDesc(xn) + " = " + x)
+ .css({top: Math.max(top + ttmargin + 10, item.pageY - ttheight - 20),
+ left: Math.max(left + ttmargin + 10, item.pageX - ttwidth - 20)})
+ .fadeIn(200);
+ } else {
+ $("#tooltip").hide();
+ }
+ }
+
+ // Redraw if required
+ if (redraw) {
+ $.plot(placeholder, data, options);
+ }
+ }
+
+ // Add some more interactivity
+ function onZoomOrPan(event, plot) {
+ var axes = plot.getAxes();
+ options.xaxis.min = axes.xaxis.min;
+ options.xaxis.max = axes.xaxis.max;
+ options.yaxis.min = axes.yaxis.min;
+ options.yaxis.max = axes.yaxis.max;
+ }
+
+ // Bind to events
+ placeholder.bind("plotclick", onPlotClick);
+ placeholder.bind("plothover", onPlotHover);
+ placeholder.bind("plotpan", onZoomOrPan);
+ placeholder.bind("plotzoom", onZoomOrPan);
+
+ // Data fetching and auto-refreshing
+ var fetchCounter = 0;
+ function fetchData() {
+ function onDataReceived(json, textStatus, xhr) {
+ $("#errmsg").hide();
+ if (paused && logs) {
+ return;
+ }
+
+ // Plot fetched data
+ loaded_data = json;
+ data = loaded_data.concat(imported_data);
+
+ if (autoscale) {
+ var xmin = null;
+ var xmax = null;
+ var ymin = null;
+ var ymax = null;
+ for (var sid = 0; sid < data.length; sid++) {
+ var pts = data[sid].data;
+ for (var i = 0; i < pts.length; i++) {
+ var x = pts[i][0];
+ var y = pts[i][1];
+ if (x != null && y != null) {
+ if (xmin == null || x < xmin) { xmin = x; }
+ if (xmax == null || x > xmax) { xmax = x; }
+ if (ymin == null || y < ymin) { ymin = y; }
+ if (ymax == null || y > ymax) { ymax = y; }
+ }
+ }
+ }
+ if (xmin != null) { options.xaxis.min = xmin; }
+ if (xmax != null) { options.xaxis.max = xmax; }
+ if (ymin != null) { options.yaxis.min = ymin; }
+ if (ymax != null) { options.yaxis.max = ymax; }
+ }
+ $.plot(placeholder, data, options);
+ }
+
+ function onDataError(xhr, error) {
+ console.log(arguments);
+ $("#errmsg").text("Fetch data error: " + error + (xhr.status == 200? xhr.responseText: ""))
+ .css({bottom: "5px", left: "25%", width: "50%"})
+ .fadeIn(200);
+ }
+
+ if (dataurl) {
+ $.ajax({
+ url: dataUrl(),
+ type: "GET",
+ dataType: "json",
+ success: function (json, textStatus, xhr) { onDataReceived(json, textStatus, xhr); },
+ error: onDataError
+ });
+ } else {
+ onDataReceived(datajson, "textStatus", "xhr");
+ }
+
+ if (fetchPeriod > 0) {
+ if (fetchCounter == 0) {
+ fetchCounter++;
+ setTimeout(function() {
+ fetchCounter--;
+ if (!paused) {
+ fetchData();
+ }
+ }, $("#errmsg").is(":visible")? errorPeriod: fetchPeriod);
+ }
+ }
+ }
+
+ // Playback control
+ var pb_pause = $("#pb-pause");
+
+ function setActive(btn, active) {
+ if (active) {
+ btn.addClass("btn-primary");
+ btn.removeClass("btn-default");
+ } else {
+ btn.addClass("btn-default");
+ btn.removeClass("btn-primary");
+ }
+ }
+
+ function onPlaybackControl() {
+ setActive(pb_pause, paused);
+ fetchPeriod = refreshPeriod;
+ fetchData();
+ }
+
+ function clickPause(val) {
+ paused = val;
+ onPlaybackControl();
+ }
+
+ pb_pause.click(function() { clickPause(!paused); });
+
+ function addOptionButton(opt, btn, defOn) {
+ setActive(btn, defOn ? $.url("?" + opt) != "n" : $.url("?" + opt) == "y");
+ btn.click(function() {
+ window.location.replace(makeUrl($.url(), function(query) {
+ if (defOn) {
+ if ($.url("?" + opt) != "n") {
+ query[opt] = "n";
+ } else {
+ delete query[opt];
+ }
+ } else {
+ if ($.url("?" + opt) == "y") {
+ delete query[opt];
+ } else {
+ query[opt] = "y";
+ }
+ }
+ }));
+ });
+ }
+
+ // Options
+ addOptionButton("linesfill", $("#pb-linesfill"), false);
+ addOptionButton("linessteps", $("#pb-linessteps"), false);
+ addOptionButton("linesshow", $("#pb-linesshow"), true);
+ addOptionButton("pointsshow", $("#pb-pointsshow"), true);
+ addOptionButton("legendshow", $("#pb-legendshow"), true);
+ addOptionButton("cutts", $("#pb-cutts"), false);
+ addOptionButton("autoscale", $("#pb-autoscale"), false);
+
+ var pb_fullscreen = $("#pb-fullscreen");
+ setActive(pb_fullscreen, fullscreen);
+ pb_fullscreen.click(function(){
+ window.location.href = makeUrl($.url(), function(query) {
+ if (fullscreen) {
+ delete query.fullscreen;
+ } else {
+ query.fullscreen = "y";
+ }
+ });
+ });
+
+ // Embeded mode (in case there is other stuff on page)
+ function embededMode() {
+ $("#pb-fullscreen").hide();
+ $("#pb-autoscale").hide();
+ $("#pb-legendshow").hide();
+ $("#pb-pause").hide();
+ }
+
+ function enableSelection() {
+ // Redraw chart with selection enabled
+ options.selection = {mode: "x"};
+ var plot = $.plot(placeholder, data, options);
+ if ($.url("?sel_x1") && $.url("?sel_x2")) {
+ plot.setSelection({
+ xaxis: {
+ from: $.url("?sel_x1") ,
+ to: $.url("?sel_x2")
+ }
+ });
+ }
+
+ // Create selection hooks
+ placeholder.bind("plotselected", function (event, ranges) {
+ window.location.replace(makeUrl($.url(), function(query) {
+ query.sel_x1 = ranges.xaxis.from;
+ query.sel_x2 = ranges.xaxis.to;
+ }));
+ });
+ placeholder.bind("plotunselected", function (event) {
+ window.location.replace(makeUrl($.url(), function(query) {
+ delete query.sel_x1;
+ delete query.sel_x2;
+ }));
+ });
+
+ // Init and show unselect button
+ $("#pb-unselect").click(function () {
+ plot.clearSelection();
+ });
+ $("#pb-unselect").removeClass("hidden");
+ }
+
+ // Export data
+ var pb_export = $("#pb-export");
+ pb_export.click(function(){
+ var blob = new Blob([JSON.stringify(data)], {type: "application/json;charset=utf-8"});
+ saveAs(blob, "exported.json");
+ });
+
+ // Import data
+ $("#btnDoImport").click(function(){
+ var files = document.getElementById('importFiles').files;
+ if (files.length <= 0) {
+ return false;
+ }
+
+ var fr = new FileReader();
+ fr.onload = function(e) {
+ imported_data = imported_data.concat(JSON.parse(e.target.result));
+ data = loaded_data.concat(imported_data);
+ $.plot(placeholder, data, options);
+ $('#importModal').modal('hide');
+ }
+ fr.readAsText(files.item(0));
+ });
+
+ // Initialize stuff and fetch data
+ onPlaybackControl();
+}
diff --git a/library/cpp/lwtrace/mon/static/common.js b/library/cpp/lwtrace/mon/static/common.js
index 42b93a6836..38ca5e464c 100644
--- a/library/cpp/lwtrace/mon/static/common.js
+++ b/library/cpp/lwtrace/mon/static/common.js
@@ -1,17 +1,17 @@
/* jquery.tablesorter.min.js 2.18.4 */ !function(h){h.extend({tablesorter:new function(){function d(){var b=arguments[0],a=1<arguments.length?Array.prototype.slice.call(arguments):b;if("undefined"!==typeof console&&"undefined"!==typeof console.log)console[/error/i.test(b)?"error":/warn/i.test(b)?"warn":"log"](a);else alert(a)}function r(b,a){d(b+" ("+((new Date).getTime()-a.getTime())+"ms)")}function k(b){for(var a in b)return!1;return!0}function v(b,a,c){if(!a)return"";var f,e=b.config,m=e.textExtraction||"",d="",d="basic"===m?h(a).attr(e.textAttribute)|| a.textContent||a.innerText||h(a).text()||"":"function"===typeof m?m(a,b,c):"function"===typeof(f=g.getColumnData(b,m,c))?f(a,b,c):a.textContent||a.innerText||h(a).text()||"";return h.trim(d)}function p(b){var a,c,f=b.config,e=f.$tbodies=f.$table.children("tbody:not(."+f.cssInfoBlock+")"),m,x,l,n,w,u,k,q,t,D=0,A="",y=e.length;if(0===y)return f.debug?d("Warning: *Empty table!* Not building a parser cache"):"";f.debug&&(t=new Date,d("Detecting parsers for each column"));a=[];for(c=[];D<y;){m=e[D].rows; if(m[D])for(x=f.columns,l=0;l<x;l++){n=f.$headers.filter('[data-column="'+l+'"]:last');w=g.getColumnData(b,f.headers,l);q=g.getParserById(g.getData(n,w,"extractor"));k=g.getParserById(g.getData(n,w,"sorter"));u="false"===g.getData(n,w,"parser");f.empties[l]=(g.getData(n,w,"empty")||f.emptyTo||(f.emptyToBottom?"bottom":"top")).toLowerCase();f.strings[l]=(g.getData(n,w,"string")||f.stringTo||"max").toLowerCase();u&&(k=g.getParserById("no-parser"));q||(q=!1);if(!k)a:{n=b;w=m;u=-1;k=l;for(var C=void 0, L=void 0,M=g.parsers.length,z=!1,B="",C=!0;""===B&&C;)u++,w[u]?(z=w[u].cells[k],B=v(n,z,k),L=h(z),n.config.debug&&d("Checking if value was empty on row "+u+", column: "+k+': "'+B+'"')):C=!1;for(;0<=--M;)if((C=g.parsers[M])&&"text"!==C.id&&C.is&&C.is(B,n,z,L)){k=C;break a}k=g.getParserById("text")}f.debug&&(A+="column:"+l+"; extractor:"+q.id+"; parser:"+k.id+"; string:"+f.strings[l]+"; empty: "+f.empties[l]+"\n");c[l]=k;a[l]=q}D+=c.length?y:1}f.debug&&(d(A?A:"No parsers detected"),r("Completed detecting parsers", t));f.parsers=c;f.extractors=a}function y(b){var a,c,f,e,m,x,l,n,w,u,k,q=b.config,t=q.$table.children("tbody"),p=q.extractors,A=q.parsers;q.cache={};q.totalRows=0;if(!A)return q.debug?d("Warning: *Empty table!* Not building a cache"):"";q.debug&&(n=new Date);q.showProcessing&&g.isProcessing(b,!0);for(m=0;m<t.length;m++)if(k=[],a=q.cache[m]={normalized:[]},!t.eq(m).hasClass(q.cssInfoBlock)){w=t[m]&&t[m].rows.length||0;for(f=0;f<w;++f)if(u={child:[]},x=h(t[m].rows[f]),l=[],x.hasClass(q.cssChildRow)&& 0!==f)c=a.normalized.length-1,a.normalized[c][q.columns].$row=a.normalized[c][q.columns].$row.add(x),x.prev().hasClass(q.cssChildRow)||x.prev().addClass(g.css.cssHasChild),u.child[c]=h.trim(x[0].textContent||x[0].innerText||x.text()||"");else{u.$row=x;u.order=f;for(e=0;e<q.columns;++e)"undefined"===typeof A[e]?q.debug&&d("No parser found for cell:",x[0].cells[e],"does it have a header?"):(c=v(b,x[0].cells[e],e),c="undefined"===typeof p[e].id?c:p[e].format(c,b,x[0].cells[e],e),c="no-parser"===A[e].id? "":A[e].format(c,b,x[0].cells[e],e),l.push(q.ignoreCase&&"string"===typeof c?c.toLowerCase():c),"numeric"===(A[e].type||"").toLowerCase()&&(k[e]=Math.max(Math.abs(c)||0,k[e]||0)));l[q.columns]=u;a.normalized.push(l)}a.colMax=k;q.totalRows+=a.normalized.length}q.showProcessing&&g.isProcessing(b);q.debug&&r("Building cache for "+w+" rows",n)}function B(b,a){var c=b.config,f=c.widgetOptions,e=b.tBodies,m=[],d=c.cache,l,n,w,u,p,q;if(k(d))return c.appender?c.appender(b,m):b.isUpdating?c.$table.trigger("updateComplete", b):"";c.debug&&(q=new Date);for(p=0;p<e.length;p++)if(l=h(e[p]),l.length&&!l.hasClass(c.cssInfoBlock)){w=g.processTbody(b,l,!0);l=d[p].normalized;n=l.length;for(u=0;u<n;u++)m.push(l[u][c.columns].$row),c.appender&&(!c.pager||c.pager.removeRows&&f.pager_removeRows||c.pager.ajax)||w.append(l[u][c.columns].$row);g.processTbody(b,w,!1)}c.appender&&c.appender(b,m);c.debug&&r("Rebuilt table",q);a||c.appender||g.applyWidget(b);b.isUpdating&&c.$table.trigger("updateComplete",b)}function F(b){return/^d/i.test(b)|| 1===b}function E(b){var a,c,f,e,m,x,l,n=b.config;n.headerList=[];n.headerContent=[];n.debug&&(l=new Date);n.columns=g.computeColumnIndex(n.$table.children("thead, tfoot").children("tr"));e=n.cssIcon?'<i class="'+(n.cssIcon===g.css.icon?g.css.icon:n.cssIcon+" "+g.css.icon)+'"></i>':"";n.$headers=h(h.map(h(b).find(n.selectorHeaders),function(l,d){c=h(l);if(!c.parent().hasClass(n.cssIgnoreRow))return a=g.getColumnData(b,n.headers,d,!0),n.headerContent[d]=c.html(),""!==n.headerTemplate&&(m=n.headerTemplate.replace(/\{content\}/g, c.html()).replace(/\{icon\}/g,e),n.onRenderTemplate&&(f=n.onRenderTemplate.apply(c,[d,m]))&&"string"===typeof f&&(m=f),c.html('<div class="'+g.css.headerIn+'">'+m+"</div>")),n.onRenderHeader&&n.onRenderHeader.apply(c,[d,n,n.$table]),l.column=parseInt(c.attr("data-column"),10),l.order=F(g.getData(c,a,"sortInitialOrder")||n.sortInitialOrder)?[1,0,2]:[0,1,2],l.count=-1,l.lockedOrder=!1,x=g.getData(c,a,"lockedOrder")||!1,"undefined"!==typeof x&&!1!==x&&(l.order=l.lockedOrder=F(x)?[1,1,1]:[0,0,0]),c.addClass(g.css.header+ " "+n.cssHeader),n.headerList[d]=l,c.parent().addClass(g.css.headerRow+" "+n.cssHeaderRow).attr("role","row"),n.tabIndex&&c.attr("tabindex",0),l}));h(b).find(n.selectorHeaders).attr({scope:"col",role:"columnheader"});H(b);n.debug&&(r("Built headers:",l),d(n.$headers))}function I(b,a,c){var f=b.config;f.$table.find(f.selectorRemove).remove();p(b);y(b);J(f.$table,a,c)}function H(b){var a,c,f,e=b.config;e.$headers.each(function(m,d){c=h(d);f=g.getColumnData(b,e.headers,m,!0);a="false"===g.getData(d, f,"sorter")||"false"===g.getData(d,f,"parser");d.sortDisabled=a;c[a?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+a);b.id&&(a?c.removeAttr("aria-controls"):c.attr("aria-controls",b.id))})}function G(b){var a,c,f=b.config,e=f.sortList,m=e.length,d=g.css.sortNone+" "+f.cssNone,l=[g.css.sortAsc+" "+f.cssAsc,g.css.sortDesc+" "+f.cssDesc],n=[f.cssIconAsc,f.cssIconDesc,f.cssIconNone],w=["ascending","descending"],k=h(b).find("tfoot tr").children().add(f.$extraHeaders).removeClass(l.join(" ")); f.$headers.removeClass(l.join(" ")).addClass(d).attr("aria-sort","none").find("."+f.cssIcon).removeClass(n.join(" ")).addClass(n[2]);for(a=0;a<m;a++)if(2!==e[a][1]&&(b=f.$headers.not(".sorter-false").filter('[data-column="'+e[a][0]+'"]'+(1===m?":last":"")),b.length)){for(c=0;c<b.length;c++)b[c].sortDisabled||b.eq(c).removeClass(d).addClass(l[e[a][1]]).attr("aria-sort",w[e[a][1]]).find("."+f.cssIcon).removeClass(n[2]).addClass(n[e[a][1]]);k.length&&k.filter('[data-column="'+e[a][0]+'"]').removeClass(d).addClass(l[e[a][1]])}f.$headers.not(".sorter-false").each(function(){var b= h(this),a=this.order[(this.count+1)%(f.sortReset?3:2)],a=b.text()+": "+g.language[b.hasClass(g.css.sortAsc)?"sortAsc":b.hasClass(g.css.sortDesc)?"sortDesc":"sortNone"]+g.language[0===a?"nextAsc":1===a?"nextDesc":"nextNone"];b.attr("aria-label",a)})}function Q(b){var a,c,f=b.config;f.widthFixed&&0===f.$table.children("colgroup").length&&(a=h("<colgroup>"),c=h(b).width(),h(b.tBodies).not("."+f.cssInfoBlock).find("tr:first").children(":visible").each(function(){a.append(h("<col>").css("width",parseInt(h(this).width()/ c*1E3,10)/10+"%"))}),f.$table.prepend(a))}function R(b,a){var c,f,e,m,g,l=b.config,d=a||l.sortList;l.sortList=[];h.each(d,function(b,a){m=parseInt(a[0],10);if(e=l.$headers.filter('[data-column="'+m+'"]:last')[0]){f=(f=(""+a[1]).match(/^(1|d|s|o|n)/))?f[0]:"";switch(f){case "1":case "d":f=1;break;case "s":f=g||0;break;case "o":c=e.order[(g||0)%(l.sortReset?3:2)];f=0===c?1:1===c?0:2;break;case "n":e.count+=1;f=e.order[e.count%(l.sortReset?3:2)];break;default:f=0}g=0===b?f:g;c=[m,parseInt(f,10)||0]; l.sortList.push(c);f=h.inArray(c[1],e.order);e.count=0<=f?f:c[1]%(l.sortReset?3:2)}})}function S(b,a){return b&&b[a]?b[a].type||"":""}function N(b,a,c){if(b.isUpdating)return setTimeout(function(){N(b,a,c)},50);var f,e,m,d,l=b.config,n=!c[l.sortMultiSortKey],w=l.$table;w.trigger("sortStart",b);a.count=c[l.sortResetKey]?2:(a.count+1)%(l.sortReset?3:2);l.sortRestart&&(e=a,l.$headers.each(function(){this===e||!n&&h(this).is("."+g.css.sortDesc+",."+g.css.sortAsc)||(this.count=-1)}));e=parseInt(h(a).attr("data-column"), 10);if(n){l.sortList=[];if(null!==l.sortForce)for(f=l.sortForce,m=0;m<f.length;m++)f[m][0]!==e&&l.sortList.push(f[m]);f=a.order[a.count];if(2>f&&(l.sortList.push([e,f]),1<a.colSpan))for(m=1;m<a.colSpan;m++)l.sortList.push([e+m,f])}else{if(l.sortAppend&&1<l.sortList.length)for(m=0;m<l.sortAppend.length;m++)d=g.isValueInArray(l.sortAppend[m][0],l.sortList),0<=d&&l.sortList.splice(d,1);if(0<=g.isValueInArray(e,l.sortList))for(m=0;m<l.sortList.length;m++)d=l.sortList[m],f=l.$headers.filter('[data-column="'+ d[0]+'"]:last')[0],d[0]===e&&(d[1]=f.order[a.count],2===d[1]&&(l.sortList.splice(m,1),f.count=-1));else if(f=a.order[a.count],2>f&&(l.sortList.push([e,f]),1<a.colSpan))for(m=1;m<a.colSpan;m++)l.sortList.push([e+m,f])}if(null!==l.sortAppend)for(f=l.sortAppend,m=0;m<f.length;m++)f[m][0]!==e&&l.sortList.push(f[m]);w.trigger("sortBegin",b);setTimeout(function(){G(b);K(b);B(b);w.trigger("sortEnd",b)},1)}function K(b){var a,c,f,e,m,d,l,n,h,u,p,q=0,t=b.config,v=t.textSorter||"",A=t.sortList,z=A.length,y= b.tBodies.length;if(!t.serverSideSorting&&!k(t.cache)){t.debug&&(m=new Date);for(c=0;c<y;c++)d=t.cache[c].colMax,l=t.cache[c].normalized,l.sort(function(c,m){for(a=0;a<z;a++){e=A[a][0];n=A[a][1];q=0===n;if(t.sortStable&&c[e]===m[e]&&1===z)break;(f=/n/i.test(S(t.parsers,e)))&&t.strings[e]?(f="boolean"===typeof t.string[t.strings[e]]?(q?1:-1)*(t.string[t.strings[e]]?-1:1):t.strings[e]?t.string[t.strings[e]]||0:0,h=t.numberSorter?t.numberSorter(c[e],m[e],q,d[e],b):g["sortNumeric"+(q?"Asc":"Desc")](c[e], m[e],f,d[e],e,b)):(u=q?c:m,p=q?m:c,h="function"===typeof v?v(u[e],p[e],q,e,b):"object"===typeof v&&v.hasOwnProperty(e)?v[e](u[e],p[e],q,e,b):g["sortNatural"+(q?"Asc":"Desc")](c[e],m[e],e,b,t));if(h)return h}return c[t.columns].order-m[t.columns].order});t.debug&&r("Sorting on "+A.toString()+" and dir "+n+" time",m)}}function O(b,a){var c=b[0];c.isUpdating&&b.trigger("updateComplete",c);h.isFunction(a)&&a(b[0])}function J(b,a,c){var f=b[0].config.sortList;!1!==a&&!b[0].isProcessing&&f.length?b.trigger("sorton", [f,function(){O(b,c)},!0]):(O(b,c),g.applyWidget(b[0],!1))}function P(b){var a=b.config,c=a.$table;c.unbind("sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(a.namespace+" ")).bind("sortReset"+a.namespace,function(c,e){c.stopPropagation();a.sortList=[];G(b);K(b);B(b);h.isFunction(e)&&e(b)}).bind("updateAll"+a.namespace,function(c,e,m){c.stopPropagation();b.isUpdating= !0;g.refreshWidgets(b,!0,!0);g.restoreHeaders(b);E(b);g.bindEvents(b,a.$headers,!0);P(b);I(b,e,m)}).bind("update"+a.namespace+" updateRows"+a.namespace,function(a,c,m){a.stopPropagation();b.isUpdating=!0;H(b);I(b,c,m)}).bind("updateCell"+a.namespace,function(f,e,m,g){f.stopPropagation();b.isUpdating=!0;c.find(a.selectorRemove).remove();var l,d,k;d=c.find("tbody");k=h(e);f=d.index(h.fn.closest?k.closest("tbody"):k.parents("tbody").filter(":first"));l=h.fn.closest?k.closest("tr"):k.parents("tr").filter(":first"); e=k[0];d.length&&0<=f&&(d=d.eq(f).find("tr").index(l),k=k.index(),a.cache[f].normalized[d][a.columns].$row=l,l="undefined"===typeof a.extractors[k].id?v(b,e,k):a.extractors[k].format(v(b,e,k),b,e,k),e="no-parser"===a.parsers[k].id?"":a.parsers[k].format(l,b,e,k),a.cache[f].normalized[d][k]=a.ignoreCase&&"string"===typeof e?e.toLowerCase():e,"numeric"===(a.parsers[k].type||"").toLowerCase()&&(a.cache[f].colMax[k]=Math.max(Math.abs(e)||0,a.cache[f].colMax[k]||0)),J(c,m,g))}).bind("addRows"+a.namespace, function(f,e,m,g){f.stopPropagation();b.isUpdating=!0;if(k(a.cache))H(b),I(b,m,g);else{e=h(e).attr("role","row");var d,n,r,u,y,q=e.filter("tr").length,t=c.find("tbody").index(e.parents("tbody").filter(":first"));a.parsers&&a.parsers.length||p(b);for(f=0;f<q;f++){n=e[f].cells.length;y=[];u={child:[],$row:e.eq(f),order:a.cache[t].normalized.length};for(d=0;d<n;d++)r="undefined"===typeof a.extractors[d].id?v(b,e[f].cells[d],d):a.extractors[d].format(v(b,e[f].cells[d],d),b,e[f].cells[d],d),r="no-parser"=== a.parsers[d].id?"":a.parsers[d].format(r,b,e[f].cells[d],d),y[d]=a.ignoreCase&&"string"===typeof r?r.toLowerCase():r,"numeric"===(a.parsers[d].type||"").toLowerCase()&&(a.cache[t].colMax[d]=Math.max(Math.abs(y[d])||0,a.cache[t].colMax[d]||0));y.push(u);a.cache[t].normalized.push(y)}J(c,m,g)}}).bind("updateComplete"+a.namespace,function(){b.isUpdating=!1}).bind("sorton"+a.namespace,function(a,e,m,d){var l=b.config;a.stopPropagation();c.trigger("sortStart",this);R(b,e);G(b);l.delayInit&&k(l.cache)&& y(b);c.trigger("sortBegin",this);K(b);B(b,d);c.trigger("sortEnd",this);g.applyWidget(b);h.isFunction(m)&&m(b)}).bind("appendCache"+a.namespace,function(a,c,d){a.stopPropagation();B(b,d);h.isFunction(c)&&c(b)}).bind("updateCache"+a.namespace,function(c,e){a.parsers&&a.parsers.length||p(b);y(b);h.isFunction(e)&&e(b)}).bind("applyWidgetId"+a.namespace,function(c,e){c.stopPropagation();g.getWidgetById(e).format(b,a,a.widgetOptions)}).bind("applyWidgets"+a.namespace,function(a,c){a.stopPropagation();g.applyWidget(b, c)}).bind("refreshWidgets"+a.namespace,function(a,c,d){a.stopPropagation();g.refreshWidgets(b,c,d)}).bind("destroy"+a.namespace,function(a,c,d){a.stopPropagation();g.destroy(b,c,d)}).bind("resetToLoadState"+a.namespace,function(){g.refreshWidgets(b,!0,!0);a=h.extend(!0,g.defaults,a.originalSettings);b.hasInitialized=!1;g.setup(b,a)})}var g=this;g.version="2.18.4";g.parsers=[];g.widgets=[];g.defaults={theme:"default",widthFixed:!1,showProcessing:!1,headerTemplate:"{content}",onRenderTemplate:null, onRenderHeader:null,cancelSelection:!0,tabIndex:!0,dateFormat:"mmddyyyy",sortMultiSortKey:"shiftKey",sortResetKey:"ctrlKey",usNumberFormat:!0,delayInit:!1,serverSideSorting:!1,headers:{},ignoreCase:!0,sortForce:null,sortList:[],sortAppend:null,sortStable:!1,sortInitialOrder:"asc",sortLocaleCompare:!1,sortReset:!1,sortRestart:!1,emptyTo:"bottom",stringTo:"max",textExtraction:"basic",textAttribute:"data-text",textSorter:null,numberSorter:null,widgets:[],widgetOptions:{zebra:["even","odd"]},initWidgets:!0, widgetClass:"widget-{name}",initialized:null,tableClass:"",cssAsc:"",cssDesc:"",cssNone:"",cssHeader:"",cssHeaderRow:"",cssProcessing:"",cssChildRow:"tablesorter-childRow",cssIcon:"tablesorter-icon",cssIconNone:"",cssIconAsc:"",cssIconDesc:"",cssInfoBlock:"tablesorter-infoOnly",cssAllowClicks:"tablesorter-allowClicks",cssIgnoreRow:"tablesorter-ignoreRow",selectorHeaders:"> thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]}; g.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",info:"tablesorter-infoOnly",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"};g.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ", nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"};g.log=d;g.benchmark=r;g.construct=function(b){return this.each(function(){var a=h.extend(!0,{},g.defaults,b);a.originalSettings=b;!this.hasInitialized&&g.buildTable&&"TABLE"!==this.tagName?g.buildTable(this,a):g.setup(this,a)})};g.setup=function(b,a){if(!b||!b.tHead||0===b.tBodies.length||!0===b.hasInitialized)return a.debug?d("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"): "";var c="",f=h(b),e=h.metadata;b.hasInitialized=!1;b.isProcessing=!0;b.config=a;h.data(b,"tablesorter",a);a.debug&&h.data(b,"startoveralltimer",new Date);a.supportsDataObject=function(a){a[0]=parseInt(a[0],10);return 1<a[0]||1===a[0]&&4<=parseInt(a[1],10)}(h.fn.jquery.split("."));a.string={max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,"null":0,top:!0,bottom:!1};a.emptyTo=a.emptyTo.toLowerCase();a.stringTo=a.stringTo.toLowerCase();/tablesorter\-/.test(f.attr("class"))||(c=""!==a.theme?" tablesorter-"+ a.theme:"");a.table=b;a.$table=f.addClass(g.css.table+" "+a.tableClass+c).attr("role","grid");a.$headers=f.find(a.selectorHeaders);a.namespace=a.namespace?"."+a.namespace.replace(/\W/g,""):".tablesorter"+Math.random().toString(16).slice(2);a.$table.children().children("tr").attr("role","row");a.$tbodies=f.children("tbody:not(."+a.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"});a.$table.children("caption").length&&(c=a.$table.children("caption")[0],c.id||(c.id=a.namespace.slice(1)+ "caption"),a.$table.attr("aria-labelledby",c.id));a.widgetInit={};a.textExtraction=a.$table.attr("data-text-extraction")||a.textExtraction||"basic";E(b);Q(b);p(b);a.totalRows=0;a.delayInit||y(b);g.bindEvents(b,a.$headers,!0);P(b);a.supportsDataObject&&"undefined"!==typeof f.data().sortlist?a.sortList=f.data().sortlist:e&&f.metadata()&&f.metadata().sortlist&&(a.sortList=f.metadata().sortlist);g.applyWidget(b,!0);0<a.sortList.length?f.trigger("sorton",[a.sortList,{},!a.initWidgets,!0]):(G(b),a.initWidgets&& g.applyWidget(b,!1));a.showProcessing&&f.unbind("sortBegin"+a.namespace+" sortEnd"+a.namespace).bind("sortBegin"+a.namespace+" sortEnd"+a.namespace,function(c){clearTimeout(a.processTimer);g.isProcessing(b);"sortBegin"===c.type&&(a.processTimer=setTimeout(function(){g.isProcessing(b,!0)},500))});b.hasInitialized=!0;b.isProcessing=!1;a.debug&&g.benchmark("Overall initialization time",h.data(b,"startoveralltimer"));f.trigger("tablesorter-initialized",b);"function"===typeof a.initialized&&a.initialized(b)}; g.getColumnData=function(b,a,c,f,e){if("undefined"!==typeof a&&null!==a){b=h(b)[0];var d;b=b.config;e=e||b.$headers;if(a[c])return f?a[c]:a[e.index(e.filter('[data-column="'+c+'"]:last'))];for(d in a)if("string"===typeof d&&(f=e.filter('[data-column="'+c+'"]:last').filter(d).add(e.filter('[data-column="'+c+'"]:last').find(d)),f.length))return a[d]}};g.computeColumnIndex=function(b){var a=[],c=0,f,e,d,g,l,k,r,u,p,q;for(f=0;f<b.length;f++)for(l=b[f].cells,e=0;e<l.length;e++){d=l[e];g=h(d);k=d.parentNode.rowIndex; g.index();r=d.rowSpan||1;u=d.colSpan||1;"undefined"===typeof a[k]&&(a[k]=[]);for(d=0;d<a[k].length+1;d++)if("undefined"===typeof a[k][d]){p=d;break}c=Math.max(p,c);g.attr({"data-column":p});for(d=k;d<k+r;d++)for("undefined"===typeof a[d]&&(a[d]=[]),q=a[d],g=p;g<p+u;g++)q[g]="x"}return c+1};g.isProcessing=function(b,a,c){b=h(b);var f=b[0].config,e=c||b.find("."+g.css.header);a?("undefined"!==typeof c&&0<f.sortList.length&&(e=e.filter(function(){return this.sortDisabled?!1:0<=g.isValueInArray(parseFloat(h(this).attr("data-column")), f.sortList)})),b.add(e).addClass(g.css.processing+" "+f.cssProcessing)):b.add(e).removeClass(g.css.processing+" "+f.cssProcessing)};g.processTbody=function(b,a,c){b=h(b)[0];if(c)return b.isProcessing=!0,a.before('<span class="tablesorter-savemyplace"/>'),c=h.fn.detach?a.detach():a.remove();c=h(b).find("span.tablesorter-savemyplace");a.insertAfter(c);c.remove();b.isProcessing=!1};g.clearTableBody=function(b){h(b)[0].config.$tbodies.children().detach()};g.bindEvents=function(b,a,c){b=h(b)[0];var f, e=b.config;!0!==c&&(e.$extraHeaders=e.$extraHeaders?e.$extraHeaders.add(a):a);a.find(e.selectorSort).add(a.filter(e.selectorSort)).unbind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" ")).bind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" "),function(c,d){var g;g=c.type;if(!(1!==(c.which||c.button)&&!/sort|keyup/.test(g)||"keyup"===g&&13!==c.which||"mouseup"===g&&!0!==d&&250<(new Date).getTime()-f)){if("mousedown"===g)return f=(new Date).getTime(),/(input|select|button|textarea)/i.test(c.target.tagName)|| h(c.target).closest("td,th").hasClass(e.cssAllowClicks)?"":!e.cancelSelection;e.delayInit&&k(e.cache)&&y(b);g=h.fn.closest?h(this).closest("th, td")[0]:/TH|TD/.test(this.tagName)?this:h(this).parents("th, td")[0];g=e.$headers[a.index(g)];g.sortDisabled||N(b,g,c)}});e.cancelSelection&&a.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})};g.restoreHeaders=function(b){var a=h(b)[0].config;a.$table.find(a.selectorHeaders).each(function(b){h(this).find("."+ g.css.headerIn).length&&h(this).html(a.headerContent[b])})};g.destroy=function(b,a,c){b=h(b)[0];if(b.hasInitialized){g.refreshWidgets(b,!0,!0);var f=h(b),e=b.config,d=f.find("thead:first"),k=d.find("tr."+g.css.headerRow).removeClass(g.css.headerRow+" "+e.cssHeaderRow),l=f.find("tfoot:first > tr").children("th, td");!1===a&&0<=h.inArray("uitheme",e.widgets)&&(f.trigger("applyWidgetId",["uitheme"]),f.trigger("applyWidgetId",["zebra"]));d.find("tr").not(k).remove();f.removeData("tablesorter").unbind("sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState ".split(" ").join(e.namespace+ " "));e.$headers.add(l).removeClass([g.css.header,e.cssHeader,e.cssAsc,e.cssDesc,g.css.sortAsc,g.css.sortDesc,g.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true");k.find(e.selectorSort).unbind(["mousedown","mouseup","keypress",""].join(e.namespace+" "));g.restoreHeaders(b);f.toggleClass(g.css.table+" "+e.tableClass+" tablesorter-"+e.theme,!1===a);b.hasInitialized=!1;delete b.config.cache;"function"===typeof c&&c(b)}};g.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i};g.sortNatural=function(b,a){if(b===a)return 0;var c,f,e,d,k,l;f=g.regex;if(f.hex.test(a)){c=parseInt(b.match(f.hex),16);e=parseInt(a.match(f.hex),16);if(c<e)return-1;if(c>e)return 1}c=b.replace(f.chunk,"\\0$1\\0").replace(f.chunks,"").split("\\0");f=a.replace(f.chunk,"\\0$1\\0").replace(f.chunks,"").split("\\0");l=Math.max(c.length,f.length);for(k=0;k<l;k++){e=isNaN(c[k])?c[k]||0:parseFloat(c[k])||0;d=isNaN(f[k])?f[k]||0:parseFloat(f[k])||0;if(isNaN(e)!== isNaN(d))return isNaN(e)?1:-1;typeof e!==typeof d&&(e+="",d+="");if(e<d)return-1;if(e>d)return 1}return 0};g.sortNaturalAsc=function(b,a,c,f,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:-c||-1:""===a&&0!==c?"boolean"===typeof c?c?1:-1:c||1:g.sortNatural(b,a)};g.sortNaturalDesc=function(b,a,c,f,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:c||1:""===a&&0!==c?"boolean"===typeof c?c? 1:-1:-c||-1:g.sortNatural(a,b)};g.sortText=function(b,a){return b>a?1:b<a?-1:0};g.getTextValue=function(b,a,c){if(c){var f=b?b.length:0,e=c+a;for(c=0;c<f;c++)e+=b.charCodeAt(c);return a*e}return 0};g.sortNumericAsc=function(b,a,c,f,e,d){if(b===a)return 0;d=d.config;e=d.string[d.empties[e]||d.emptyTo];if(""===b&&0!==e)return"boolean"===typeof e?e?-1:1:-e||-1;if(""===a&&0!==e)return"boolean"===typeof e?e?1:-1:e||1;isNaN(b)&&(b=g.getTextValue(b,c,f));isNaN(a)&&(a=g.getTextValue(a,c,f));return b-a};g.sortNumericDesc= function(b,a,c,f,e,d){if(b===a)return 0;d=d.config;e=d.string[d.empties[e]||d.emptyTo];if(""===b&&0!==e)return"boolean"===typeof e?e?-1:1:e||1;if(""===a&&0!==e)return"boolean"===typeof e?e?1:-1:-e||-1;isNaN(b)&&(b=g.getTextValue(b,c,f));isNaN(a)&&(a=g.getTextValue(a,c,f));return a-b};g.sortNumeric=function(b,a){return b-a};g.characterEquivalents={a:"\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5",A:"\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5",c:"\u00e7\u0107\u010d",C:"\u00c7\u0106\u010c",e:"\u00e9\u00e8\u00ea\u00eb\u011b\u0119", E:"\u00c9\u00c8\u00ca\u00cb\u011a\u0118",i:"\u00ed\u00ec\u0130\u00ee\u00ef\u0131",I:"\u00cd\u00cc\u0130\u00ce\u00cf",o:"\u00f3\u00f2\u00f4\u00f5\u00f6",O:"\u00d3\u00d2\u00d4\u00d5\u00d6",ss:"\u00df",SS:"\u1e9e",u:"\u00fa\u00f9\u00fb\u00fc\u016f",U:"\u00da\u00d9\u00db\u00dc\u016e"};g.replaceAccents=function(b){var a,c="[",f=g.characterEquivalents;if(!g.characterRegex){g.characterRegexArray={};for(a in f)"string"===typeof a&&(c+=f[a],g.characterRegexArray[a]=new RegExp("["+f[a]+"]","g"));g.characterRegex= new RegExp(c+"]")}if(g.characterRegex.test(b))for(a in f)"string"===typeof a&&(b=b.replace(g.characterRegexArray[a],a));return b};g.isValueInArray=function(b,a){var c,f=a.length;for(c=0;c<f;c++)if(a[c][0]===b)return c;return-1};g.addParser=function(b){var a,c=g.parsers.length,f=!0;for(a=0;a<c;a++)g.parsers[a].id.toLowerCase()===b.id.toLowerCase()&&(f=!1);f&&g.parsers.push(b)};g.getParserById=function(b){if("false"==b)return!1;var a,c=g.parsers.length;for(a=0;a<c;a++)if(g.parsers[a].id.toLowerCase()=== b.toString().toLowerCase())return g.parsers[a];return!1};g.addWidget=function(b){g.widgets.push(b)};g.hasWidget=function(b,a){b=h(b);return b.length&&b[0].config&&b[0].config.widgetInit[a]||!1};g.getWidgetById=function(b){var a,c,f=g.widgets.length;for(a=0;a<f;a++)if((c=g.widgets[a])&&c.hasOwnProperty("id")&&c.id.toLowerCase()===b.toLowerCase())return c};g.applyWidget=function(b,a){b=h(b)[0];var c=b.config,f=c.widgetOptions,e=" "+c.table.className+" ",d=[],k,l,n;!1!==a&&b.hasInitialized&&(b.isApplyingWidgets|| b.isUpdating)||(c.debug&&(k=new Date),n=new RegExp("\\s"+c.widgetClass.replace(/\{name\}/i,"([\\w-]+)")+"\\s","g"),e.match(n)&&(e=e.match(n))&&h.each(e,function(a,b){c.widgets.push(b.replace(n,"$1"))}),c.widgets.length&&(b.isApplyingWidgets=!0,c.widgets=h.grep(c.widgets,function(a,b){return h.inArray(a,c.widgets)===b}),h.each(c.widgets||[],function(a,b){(n=g.getWidgetById(b))&&n.id&&(n.priority||(n.priority=10),d[a]=n)}),d.sort(function(a,b){return a.priority<b.priority?-1:a.priority===b.priority? 0:1}),h.each(d,function(e,d){if(d){if(a||!c.widgetInit[d.id])c.widgetInit[d.id]=!0,d.hasOwnProperty("options")&&(f=b.config.widgetOptions=h.extend(!0,{},d.options,f)),d.hasOwnProperty("init")&&(c.debug&&(l=new Date),d.init(b,d,c,f),c.debug&&g.benchmark("Initializing "+d.id+" widget",l));!a&&d.hasOwnProperty("format")&&(c.debug&&(l=new Date),d.format(b,c,f,!1),c.debug&&g.benchmark((a?"Initializing ":"Applying ")+d.id+" widget",l))}})),setTimeout(function(){b.isApplyingWidgets=!1;h.data(b,"lastWidgetApplication", new Date)},0),c.debug&&(e=c.widgets.length,r("Completed "+(!0===a?"initializing ":"applying ")+e+" widget"+(1!==e?"s":""),k)))};g.refreshWidgets=function(b,a,c){b=h(b)[0];var f,e=b.config,k=e.widgets,r=g.widgets,l=r.length;for(f=0;f<l;f++)r[f]&&r[f].id&&(a||0>h.inArray(r[f].id,k))&&(e.debug&&d('Refeshing widgets: Removing "'+r[f].id+'"'),r[f].hasOwnProperty("remove")&&e.widgetInit[r[f].id]&&(r[f].remove(b,e,e.widgetOptions),e.widgetInit[r[f].id]=!1));!0!==c&&g.applyWidget(b,a)};g.getData=function(b, a,c){var d="";b=h(b);var e,g;if(!b.length)return"";e=h.metadata?b.metadata():!1;g=" "+(b.attr("class")||"");"undefined"!==typeof b.data(c)||"undefined"!==typeof b.data(c.toLowerCase())?d+=b.data(c)||b.data(c.toLowerCase()):e&&"undefined"!==typeof e[c]?d+=e[c]:a&&"undefined"!==typeof a[c]?d+=a[c]:" "!==g&&g.match(" "+c+"-")&&(d=g.match(new RegExp("\\s"+c+"-([\\w-]+)"))[1]||"");return h.trim(d)};g.formatFloat=function(b,a){if("string"!==typeof b||""===b)return b;var c;b=(a&&a.config?!1!==a.config.usNumberFormat: "undefined"!==typeof a?a:1)?b.replace(/,/g,""):b.replace(/[\s|\.]/g,"").replace(/,/g,".");/^\s*\([.\d]+\)/.test(b)&&(b=b.replace(/^\s*\(([.\d]+)\)/,"-$1"));c=parseFloat(b);return isNaN(c)?h.trim(b):c};g.isDigit=function(b){return isNaN(b)?/^[\-+(]?\d+[)]?$/.test(b.toString().replace(/[,.'"\s]/g,"")):!0}}});var p=h.tablesorter;h.fn.extend({tablesorter:p.construct});p.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"});p.addParser({id:"text",is:function(){return!0}, format:function(d,r){var k=r.config;d&&(d=h.trim(k.ignoreCase?d.toLocaleLowerCase():d),d=k.sortLocaleCompare?p.replaceAccents(d):d);return d},type:"text"});p.addParser({id:"digit",is:function(d){return p.isDigit(d)},format:function(d,r){var k=p.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),r);return d&&"number"===typeof k?k:d?h.trim(d&&r.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});p.addParser({id:"currency",is:function(d){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((d|| "").replace(/[+\-,. ]/g,""))},format:function(d,r){var k=p.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),r);return d&&"number"===typeof k?k:d?h.trim(d&&r.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});p.addParser({id:"url",is:function(d){return/^(https?|ftp|file):\/\//.test(d)},format:function(d){return d?h.trim(d.replace(/(https?|ftp|file):\/\//,"")):d},parsed:!0,type:"text"});p.addParser({id:"isoDate",is:function(d){return/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/.test(d)},format:function(d, h){var k=d?new Date(d.replace(/-/g,"/")):d;return k instanceof Date&&isFinite(k)?k.getTime():d},type:"numeric"});p.addParser({id:"percent",is:function(d){return/(\d\s*?%|%\s*?\d)/.test(d)&&15>d.length},format:function(d,h){return d?p.formatFloat(d.replace(/%/g,""),h):d},type:"numeric"});p.addParser({id:"image",is:function(d,h,k,p){return 0<p.find("img").length},format:function(d,r,k){return h(k).find("img").attr(r.config.imgAttr||"alt")||d},parsed:!0,type:"text"});p.addParser({id:"usLongDate",is:function(d){return/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i.test(d)|| /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(d)},format:function(d,h){var k=d?new Date(d.replace(/(\S)([AP]M)$/i,"$1 $2")):d;return k instanceof Date&&isFinite(k)?k.getTime():d},type:"numeric"});p.addParser({id:"shortDate",is:function(d){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((d||"").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(d,h,k,v){if(d){k=h.config;var z=k.$headers.filter("[data-column="+v+"]:last");v=z.length&&z[0].dateFormat||p.getData(z, p.getColumnData(h,k.headers,v),"dateFormat")||k.dateFormat;h=d.replace(/\s+/g," ").replace(/[\-.,]/g,"/");"mmddyyyy"===v?h=h.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$1/$2"):"ddmmyyyy"===v?h=h.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===v&&(h=h.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,"$1/$2/$3"));h=new Date(h);return h instanceof Date&&isFinite(h)?h.getTime():d}return d},type:"numeric"});p.addParser({id:"time",is:function(d){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(d)}, format:function(d,h){var k=d?new Date("2000/01/01 "+d.replace(/(\S)([AP]M)$/i,"$1 $2")):d;return k instanceof Date&&isFinite(k)?k.getTime():d},type:"numeric"});p.addParser({id:"metadata",is:function(){return!1},format:function(d,p,k){d=p.config;d=d.parserMetadataName?d.parserMetadataName:"sortValue";return h(k).metadata()[d]},type:"numeric"});p.addWidget({id:"zebra",priority:90,format:function(d,p,k){var v,z,y,B,F=new RegExp(p.cssChildRow,"i"),E=p.$tbodies;for(d=0;d<E.length;d++)y=0,v=E.eq(d),v=v.children("tr:visible").not(p.selectorRemove), v.each(function(){z=h(this);F.test(this.className)||y++;B=0===y%2;z.removeClass(k.zebra[B?1:0]).addClass(k.zebra[B?0:1])})},remove:function(d,h,k){var v;h=h.$tbodies;var z=(k.zebra||["even","odd"]).join(" ");for(k=0;k<h.length;k++)v=p.processTbody(d,h.eq(k),!0),v.children().removeClass(z),p.processTbody(d,v,!1)}})}(jQuery);
/* jquery.tablesorter.widgets.min.js 2.18.4 */ ;(function(k,A){ var e=k.tablesorter=k.tablesorter||{}; e.themes={bootstrap:{table:"table table-bordered table-striped",caption:"caption",header:"bootstrap-header",footerRow:"",footerCells:"",icons:"",sortNone:"bootstrap-icon-unsorted",sortAsc:"icon-chevron-up glyphicon glyphicon-chevron-up",sortDesc:"icon-chevron-down glyphicon glyphicon-chevron-down",active:"",hover:"",filterRow:"",even:"",odd:""},jui:{table:"ui-widget ui-widget-content ui-corner-all",caption:"ui-widget-content",header:"ui-widget-header ui-corner-all ui-state-default", footerRow:"",footerCells:"",icons:"ui-icon",sortNone:"ui-icon-carat-2-n-s",sortAsc:"ui-icon-carat-1-n",sortDesc:"ui-icon-carat-1-s",active:"ui-state-active",hover:"ui-state-hover",filterRow:"",even:"ui-widget-content",odd:"ui-state-default"}};k.extend(e.css,{filterRow:"tablesorter-filter-row",filter:"tablesorter-filter",wrapper:"tablesorter-wrapper",resizer:"tablesorter-resizer",sticky:"tablesorter-stickyHeader",stickyVis:"tablesorter-sticky-visible",stickyWrap:"tablesorter-sticky-wrapper"}); e.storage= function(c,a,b,d){c=k(c)[0];var e,h,g=!1;e={};h=c.config;var m=k(c);c=d&&d.id||m.attr(d&&d.group||"data-table-group")||c.id||k(".tablesorter").index(m);d=d&&d.url||m.attr(d&&d.page||"data-table-page")||h&&h.fixedUrl||A.location.pathname;if("localStorage"in A)try{A.localStorage.setItem("_tmptest","temp"),g=!0,A.localStorage.removeItem("_tmptest")}catch(n){}k.parseJSON&&(g?e=k.parseJSON(localStorage[a]||"{}"):(h=document.cookie.split(/[;\s|=]/),e=k.inArray(a,h)+1,e=0!==e?k.parseJSON(h[e]||"{}"):{})); if((b||""===b)&&A.JSON&&JSON.hasOwnProperty("stringify"))e[d]||(e[d]={}),e[d][c]=b,g?localStorage[a]=JSON.stringify(e):(b=new Date,b.setTime(b.getTime()+31536E6),document.cookie=a+"="+JSON.stringify(e).replace(/\"/g,'"')+"; expires="+b.toGMTString()+"; path=/");else return e&&e[d]?e[d][c]:""}; e.addHeaderResizeEvent=function(c,a,b){c=k(c)[0];var d;b=k.extend({},{timer:250},b);var e=c.config,h=e.widgetOptions,g=function(a){h.resize_flag=!0;d=[];e.$headers.each(function(){var a=k(this),b=a.data("savedSizes")|| [0,0],c=this.offsetWidth,e=this.offsetHeight;if(c!==b[0]||e!==b[1])a.data("savedSizes",[c,e]),d.push(this)});d.length&&!1!==a&&e.$table.trigger("resize",[d]);h.resize_flag=!1};g(!1);clearInterval(h.resize_timer);if(a)return h.resize_flag=!1;h.resize_timer=setInterval(function(){h.resize_flag||g()},b.timer)}; e.addWidget({id:"uitheme",priority:10,format:function(c,a,b){var d,f,h,g=e.themes;d=a.$table;var m=a.$headers,n=a.theme||"jui",p=g[n]||g.jui,g=[p.sortNone,p.sortDesc,p.sortAsc,p.active].join(" "); a.debug&&(f=new Date);d.hasClass("tablesorter-"+n)&&a.theme===a.appliedTheme&&c.hasInitialized||(h=(c=p[a.appliedTheme]||{},[c.sortNone,c.sortDesc,c.sortAsc,c.active].join(" ")),c&&(b.zebra[0]=b.zebra[0].replace(" "+c.even,""),b.zebra[1]=b.zebra[1].replace(" "+c.odd,"")),""!==p.even&&(b.zebra[0]+=" "+p.even),""!==p.odd&&(b.zebra[1]+=" "+p.odd),d.children("caption").removeClass(c.caption).addClass(p.caption),b=d.removeClass(a.appliedTheme?"tablesorter-"+(a.appliedTheme||""):"").addClass("tablesorter-"+ n+" "+p.table).children("tfoot"),b.length&&b.children("tr").removeClass(c.footerRow||"").addClass(p.footerRow).children("th, td").removeClass(c.footerCells||"").addClass(p.footerCells),m.add(a.$extraHeaders).removeClass(c.header+" "+c.hover+" "+h).addClass(p.header).not(".sorter-false").bind("mouseenter.tsuitheme mouseleave.tsuitheme",function(a){k(this)["mouseenter"===a.type?"addClass":"removeClass"](p.hover)}),m.find("."+e.css.wrapper).length||m.wrapInner('<div class="'+e.css.wrapper+'" style="position:relative;height:100%;width:100%"></div>'), a.cssIcon&&m.find("."+e.css.icon).removeClass(c.icons+" "+h).addClass(p.icons),d.hasClass("hasFilters")&&d.children("thead").children("."+e.css.filterRow).removeClass(c.filterRow).addClass(p.filterRow),a.appliedTheme=a.theme);for(d=0;d<a.columns;d++)b=a.$headers.add(a.$extraHeaders).not(".sorter-false").filter('[data-column="'+d+'"]'),c=e.css.icon?b.find("."+e.css.icon):b,h=m.not(".sorter-false").filter('[data-column="'+d+'"]:last'),h.length&&(h[0].sortDisabled?(b.removeClass(g),c.removeClass(g+" "+ p.icons)):(h=b.hasClass(e.css.sortAsc)?p.sortAsc:b.hasClass(e.css.sortDesc)?p.sortDesc:b.hasClass(e.css.header)?p.sortNone:"",b[h===p.sortNone?"removeClass":"addClass"](p.active),c.removeClass(g).addClass(h)));a.debug&&e.benchmark("Applying "+n+" theme",f)},remove:function(c,a){var b=a.$table,d=a.theme||"jui",f=e.themes[d]||e.themes.jui,h=b.children("thead").children(),g=f.sortNone+" "+f.sortDesc+" "+f.sortAsc;b.removeClass("tablesorter-"+d+" "+f.table).find(e.css.header).removeClass(f.header);h.unbind("mouseenter.tsuitheme mouseleave.tsuitheme").removeClass(f.hover+ " "+g+" "+f.active).find("."+e.css.filterRow).removeClass(f.filterRow);h.find("."+e.css.icon).removeClass(f.icons)}}); e.addWidget({id:"columns",priority:30,options:{columns:["primary","secondary","tertiary"]},format:function(c,a,b){var d,f,h,g,m,n,p=a.$table,r=a.$tbodies,w=a.sortList,x=w.length,t=b&&b.columns||["primary","secondary","tertiary"],u=t.length-1;m=t.join(" ");for(d=0;d<r.length;d++)a=e.processTbody(c,r.eq(d),!0),f=a.children("tr"),f.each(function(){h=k(this);if("none"!==this.style.display&& (g=h.children().removeClass(m),w&&w[0]&&(g.eq(w[0][0]).addClass(t[0]),1<x)))for(n=1;n<x;n++)g.eq(w[n][0]).addClass(t[n]||t[u])}),e.processTbody(c,a,!1);c=!1!==b.columns_thead?["thead tr"]:[];!1!==b.columns_tfoot&&c.push("tfoot tr");if(c.length&&(f=p.find(c.join(",")).children().removeClass(m),x))for(n=0;n<x;n++)f.filter('[data-column="'+w[n][0]+'"]').addClass(t[n]||t[u])},remove:function(c,a,b){var d=a.$tbodies,f=(b.columns||["primary","secondary","tertiary"]).join(" ");a.$headers.removeClass(f); a.$table.children("tfoot").children("tr").children("th, td").removeClass(f);for(a=0;a<d.length;a++)b=e.processTbody(c,d.eq(a),!0),b.children("tr").each(function(){k(this).children().removeClass(f)}),e.processTbody(c,b,!1)}}); e.addWidget({id:"filter",priority:50,options:{filter_childRows:!1,filter_columnFilters:!0,filter_cellFilter:"",filter_cssFilter:"",filter_defaultFilter:{},filter_excludeFilter:{},filter_external:"",filter_filteredRow:"filtered",filter_formatter:null,filter_functions:null,filter_hideEmpty:!0, filter_hideFilters:!1,filter_ignoreCase:!0,filter_liveSearch:!0,filter_onlyAvail:"filter-onlyAvail",filter_placeholder:{search:"",select:""},filter_reset:null,filter_saveFilters:!1,filter_searchDelay:300,filter_searchFiltered:!0,filter_selectSource:null,filter_startsWith:!1,filter_useParsedData:!1,filter_serversideFiltering:!1,filter_defaultAttrib:"data-value",filter_selectSourceSeparator:"|"},format:function(c,a,b){a.$table.hasClass("hasFilters")||e.filter.init(c,a,b)},remove:function(c,a,b){var d, f=a.$tbodies;a.$table.removeClass("hasFilters").unbind("addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search ".split(" ").join(a.namespace+"filter ")).find("."+e.css.filterRow).remove();for(a=0;a<f.length;a++)d=e.processTbody(c,f.eq(a),!0),d.children().removeClass(b.filter_filteredRow).show(),e.processTbody(c,d,!1);b.filter_reset&&k(document).undelegate(b.filter_reset,"click.tsfilter")}}); e.filter={regex:{regex:/^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/,child:/tablesorter-childRow/, filtered:/filtered/,type:/undefined|number/,exact:/(^[\"\'=]+)|([\"\'=]+$)/g,nondigit:/[^\w,. \-()]/g,operators:/[<>=]/g,query:"(q|query)"},types:{regex:function(c,a){if(e.filter.regex.regex.test(a.iFilter)){var b,d=e.filter.regex.regex.exec(a.iFilter);try{b=(new RegExp(d[1],d[2])).test(a.iExact)}catch(f){b=!1}return b}return null},operators:function(c,a){if(/^[<>]=?/.test(a.iFilter)){var b,d;b=c.table;var f=a.index,h=a.parsed[f],g=e.formatFloat(a.iFilter.replace(e.filter.regex.operators,""),b),m= c.parsers[f],n=g;if(h||"numeric"===m.type)d=e.filter.parseFilter(c,k.trim(""+a.iFilter.replace(e.filter.regex.operators,"")),f,h,!0),g="number"!==typeof d||""===d||isNaN(d)?g:d;b=!h&&"numeric"!==m.type||isNaN(g)||"undefined"===typeof a.cache?isNaN(a.iExact)?e.formatFloat(a.iExact.replace(e.filter.regex.nondigit,""),b):e.formatFloat(a.iExact,b):a.cache;/>/.test(a.iFilter)&&(d=/>=/.test(a.iFilter)?b>=g:b>g);/</.test(a.iFilter)&&(d=/<=/.test(a.iFilter)?b<=g:b<g);d||""!==n||(d=!0);return d}return null}, notMatch:function(c,a){if(/^\!/.test(a.iFilter)){var b,d=e.filter.parseFilter(c,a.iFilter.replace("!",""),a.index,a.parsed[a.index]);if(e.filter.regex.exact.test(d))return d=d.replace(e.filter.regex.exact,""),""===d?!0:k.trim(d)!==a.iExact;b=a.iExact.search(k.trim(d));return""===d?!0:!(c.widgetOptions.filter_startsWith?0===b:0<=b)}return null},exact:function(c,a){if(e.filter.regex.exact.test(a.iFilter)){var b=e.filter.parseFilter(c,a.iFilter.replace(e.filter.regex.exact,""),a.index,a.parsed[a.index]); return a.anyMatch?0<=k.inArray(b,a.rowArray):b==a.iExact}return null},and:function(c,a){if(e.filter.regex.andTest.test(a.filter)){for(var b=a.index,d=a.parsed[b],f=a.iFilter.split(e.filter.regex.andSplit),h=0<=a.iExact.search(k.trim(e.filter.parseFilter(c,f[0],b,d))),g=f.length-1;h&&g;)h=h&&0<=a.iExact.search(k.trim(e.filter.parseFilter(c,f[g],b,d))),g--;return h}return null},range:function(c,a){if(e.filter.regex.toTest.test(a.iFilter)){var b,d;d=c.table;var f=a.index,h=a.parsed[f],g=a.iFilter.split(e.filter.regex.toSplit), k=e.formatFloat(e.filter.parseFilter(c,g[0].replace(e.filter.regex.nondigit,""),f,h),d),n=e.formatFloat(e.filter.parseFilter(c,g[1].replace(e.filter.regex.nondigit,""),f,h),d);if(h||"numeric"===c.parsers[f].type)b=c.parsers[f].format(""+g[0],d,c.$headers.eq(f),f),k=""===b||isNaN(b)?k:b,b=c.parsers[f].format(""+g[1],d,c.$headers.eq(f),f),n=""===b||isNaN(b)?n:b;b=!h&&"numeric"!==c.parsers[f].type||isNaN(k)||isNaN(n)?isNaN(a.iExact)?e.formatFloat(a.iExact.replace(e.filter.regex.nondigit,""),d):e.formatFloat(a.iExact, d):a.cache;k>n&&(d=k,k=n,n=d);return b>=k&&b<=n||""===k||""===n}return null},wild:function(c,a){if(/[\?\*\|]/.test(a.iFilter)||e.filter.regex.orReplace.test(a.filter)){var b=a.index,d=a.parsed[b],d=e.filter.parseFilter(c,a.iFilter.replace(e.filter.regex.orReplace,"|"),b,d);!c.$headers.filter('[data-column="'+b+'"]:last').hasClass("filter-match")&&/\|/.test(d)&&("|"===d[d.length-1]&&(d+="*"),d=a.anyMatch&&k.isArray(a.rowArray)?"("+d+")":"^("+d+")$");return(new RegExp(d.replace(/\?/g,"\\S{1}").replace(/\*/g, "\\S*"))).test(a.iExact)}return null},fuzzy:function(c,a){if(/^~/.test(a.iFilter)){var b,d=0,f=a.iExact.length,h=e.filter.parseFilter(c,a.iFilter.slice(1),a.index,a.parsed[a.index]);for(b=0;b<f;b++)a.iExact[b]===h[d]&&(d+=1);return d===h.length?!0:!1}return null}},init:function(c,a,b){e.language=k.extend(!0,{},{to:"to",or:"or",and:"and"},e.language);var d,f,h,g,m,n,p;d=e.filter.regex;a.$table.addClass("hasFilters");b.searchTimer=null;b.filter_initTimer=null;b.filter_formatterCount=0;b.filter_formatterInit= [];b.filter_anyColumnSelector='[data-column="all"],[data-column="any"]';b.filter_multipleColumnSelector='[data-column*="-"],[data-column*=","]';h="\\{"+e.filter.regex.query+"\\}";k.extend(d,{child:new RegExp(a.cssChildRow),filtered:new RegExp(b.filter_filteredRow),alreadyFiltered:new RegExp("(\\s+("+e.language.or+"|-|"+e.language.to+")\\s+)","i"),toTest:new RegExp("\\s+(-|"+e.language.to+")\\s+","i"),toSplit:new RegExp("(?:\\s+(?:-|"+e.language.to+")\\s+)","gi"),andTest:new RegExp("\\s+("+e.language.and+ "|&&)\\s+","i"),andSplit:new RegExp("(?:\\s+(?:"+e.language.and+"|&&)\\s+)","gi"),orReplace:new RegExp("\\s+("+e.language.or+")\\s+","gi"),iQuery:new RegExp(h,"i"),igQuery:new RegExp(h,"ig")});!1!==b.filter_columnFilters&&a.$headers.filter(".filter-false, .parser-false").length!==a.$headers.length&&e.filter.buildRow(c,a,b);a.$table.bind("addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search ".split(" ").join(a.namespace+"filter "),function(d,f){a.$table.find("."+ e.css.filterRow).toggle(!(b.filter_hideEmpty&&k.isEmptyObject(a.cache)&&(!a.delayInit||"appendCache"!==d.type)));/(search|filter)/.test(d.type)||(d.stopPropagation(),e.filter.buildDefault(c,!0));"filterReset"===d.type?(a.$table.find("."+e.css.filter).add(b.filter_$externalFilters).val(""),e.filter.searching(c,[])):"filterEnd"===d.type?e.filter.buildDefault(c,!0):(f="search"===d.type?f:"updateComplete"===d.type?a.$table.data("lastSearch"):"",/(update|add)/.test(d.type)&&"updateComplete"!==d.type&& (a.lastCombinedFilter=null,a.lastSearch=[]),e.filter.searching(c,f,!0));return!1});b.filter_reset&&(b.filter_reset instanceof k?b.filter_reset.click(function(){a.$table.trigger("filterReset")}):k(b.filter_reset).length&&k(document).undelegate(b.filter_reset,"click.tsfilter").delegate(b.filter_reset,"click.tsfilter",function(){a.$table.trigger("filterReset")}));if(b.filter_functions)for(m=0;m<a.columns;m++)if(h=e.getColumnData(c,b.filter_functions,m))if(g=a.$headers.filter('[data-column="'+m+'"]:last').removeClass("filter-select"), p=!(g.hasClass("filter-false")||g.hasClass("parser-false")),d="",!0===h&&p)e.filter.buildSelect(c,m);else if("object"===typeof h&&p){for(f in h)"string"===typeof f&&(d+=""===d?'<option value="">'+(g.data("placeholder")||g.attr("data-placeholder")||b.filter_placeholder.select||"")+"</option>":"",h=p=f,0<=f.indexOf(b.filter_selectSourceSeparator)&&(p=f.split(b.filter_selectSourceSeparator),h=p[1],p=p[0]),d+="<option "+(h===p?"":'data-function-name="'+f+'" ')+'value="'+p+'">'+h+"</option>");a.$table.find("thead").find("select."+ e.css.filter+'[data-column="'+m+'"]').append(d)}e.filter.buildDefault(c,!0);e.filter.bindSearch(c,a.$table.find("."+e.css.filter),!0);b.filter_external&&e.filter.bindSearch(c,b.filter_external);b.filter_hideFilters&&e.filter.hideFilters(c,a);a.showProcessing&&a.$table.bind("filterStart"+a.namespace+"filter filterEnd"+a.namespace+"filter",function(b,d){g=d?a.$table.find("."+e.css.header).filter("[data-column]").filter(function(){return""!==d[k(this).data("column")]}):"";e.isProcessing(c,"filterStart"=== b.type,d?g:"")});a.filteredRows=a.totalRows;a.$table.bind("tablesorter-initialized pagerBeforeInitialized",function(){var b=this.config.widgetOptions;n=e.filter.setDefaults(c,a,b)||[];n.length&&(a.delayInit&&""===n.join("")||e.setFilters(c,n,!0));a.$table.trigger("filterFomatterUpdate");setTimeout(function(){b.filter_initialized||e.filter.filterInitComplete(a)},100)});a.pager&&a.pager.initialized&&!b.filter_initialized&&(a.$table.trigger("filterFomatterUpdate"),setTimeout(function(){e.filter.filterInitComplete(a)}, 100))},formatterUpdated:function(c,a){var b=c.closest("table")[0].config.widgetOptions;b.filter_initialized||(b.filter_formatterInit[a]=1)},filterInitComplete:function(c){var a=c.widgetOptions,b=0,d=function(){a.filter_initialized=!0;c.$table.trigger("filterInit",c);e.filter.findRows(c.table,c.$table.data("lastSearch")||[])};k.isEmptyObject(a.filter_formatter)?d():(k.each(a.filter_formatterInit,function(a,c){1===c&&b++}),clearTimeout(a.filter_initTimer),a.filter_initialized||b!==a.filter_formatterCount)? a.filter_initialized||(a.filter_initTimer=setTimeout(function(){d()},500)):d()},setDefaults:function(c,a,b){var d,f=e.getFilters(c)||[];b.filter_saveFilters&&e.storage&&(d=e.storage(c,"tablesorter-filters")||[],(c=k.isArray(d))&&""===d.join("")||!c||(f=d));if(""===f.join(""))for(c=0;c<a.columns;c++)f[c]=a.$headers.filter('[data-column="'+c+'"]:last').attr(b.filter_defaultAttrib)||f[c];a.$table.data("lastSearch",f);return f},parseFilter:function(c,a,b,d,e){return e||d?c.parsers[b].format(a,c.table, [],b):a},buildRow:function(c,a,b){var d,f,h,g,m=a.columns;h=k.isArray(b.filter_cellFilter);g='<tr role="row" class="'+e.css.filterRow+'">';for(f=0;f<m;f++)g=h?g+("<td"+(b.filter_cellFilter[f]?' class="'+b.filter_cellFilter[f]+'"':"")+"></td>"):g+("<td"+(""!==b.filter_cellFilter?' class="'+b.filter_cellFilter+'"':"")+"></td>");a.$filters=k(g+"</tr>").appendTo(a.$table.children("thead").eq(0)).find("td");for(f=0;f<m;f++)h=a.$headers.filter('[data-column="'+f+'"]:last'),g=e.getColumnData(c,b.filter_functions, f),g=b.filter_functions&&g&&"function"!==typeof g||h.hasClass("filter-select"),d=e.getColumnData(c,a.headers,f),d="false"===e.getData(h[0],d,"filter")||"false"===e.getData(h[0],d,"parser"),g?g=k("<select>").appendTo(a.$filters.eq(f)):((g=e.getColumnData(c,b.filter_formatter,f))?(b.filter_formatterCount++,(g=g(a.$filters.eq(f),f))&&0===g.length&&(g=a.$filters.eq(f).children("input")),g&&(0===g.parent().length||g.parent().length&&g.parent()[0]!==a.$filters[f])&&a.$filters.eq(f).append(g)):g=k('<input type="search">').appendTo(a.$filters.eq(f)), g&&g.attr("placeholder",h.data("placeholder")||h.attr("data-placeholder")||b.filter_placeholder.search||"")),g&&(h=(k.isArray(b.filter_cssFilter)?"undefined"!==typeof b.filter_cssFilter[f]?b.filter_cssFilter[f]||"":"":b.filter_cssFilter)||"",g.addClass(e.css.filter+" "+h).attr("data-column",f),d&&(g.attr("placeholder","").addClass("disabled")[0].disabled=!0))},bindSearch:function(c,a,b){c=k(c)[0];a=k(a);if(a.length){var d=c.config,f=d.widgetOptions,h=f.filter_$externalFilters;!0!==b&&(f.filter_$anyMatch= a.filter(f.filter_anyColumnSelector+","+f.filter_multipleColumnSelector),f.filter_$externalFilters=h&&h.length?f.filter_$externalFilters.add(a):a,e.setFilters(c,d.$table.data("lastSearch")||[],!1===b));a.attr("data-lastSearchTime",(new Date).getTime()).unbind(["keypress","keyup","search","change",""].join(d.namespace+"filter ")).bind("keyup"+d.namespace+"filter",function(a){k(this).attr("data-lastSearchTime",(new Date).getTime());if(27===a.which)this.value="";else if(!1===f.filter_liveSearch||""!== this.value&&("number"===typeof f.filter_liveSearch&&this.value.length<f.filter_liveSearch||13!==a.which&&8!==a.which&&(32>a.which||37<=a.which&&40>=a.which)))return;e.filter.searching(c,!0,!0)}).bind(["search","change","keypress",""].join(d.namespace+"filter "),function(a){var b=k(this).data("column");if(13===a.which||"search"===a.type||"change"===a.type&&this.value!==d.lastSearch[b])a.preventDefault(),k(this).attr("data-lastSearchTime",(new Date).getTime()),e.filter.searching(c,!1,!0)})}},searching:function(c, a,b){var d=c.config.widgetOptions;clearTimeout(d.searchTimer);"undefined"===typeof a||!0===a?d.searchTimer=setTimeout(function(){e.filter.checkFilters(c,a,b)},d.filter_liveSearch?d.filter_searchDelay:10):e.filter.checkFilters(c,a,b)},checkFilters:function(c,a,b){var d=c.config,f=d.widgetOptions,h=k.isArray(a),g=h?a:e.getFilters(c,!0),m=(g||[]).join("");if(k.isEmptyObject(d.cache))d.delayInit&&d.pager&&d.pager.initialized&&d.$table.trigger("updateCache",[function(){e.filter.checkFilters(c,!1,b)}]); else if(h&&(e.setFilters(c,g,!1,!0!==b),f.filter_initialized||(d.lastCombinedFilter="")),f.filter_hideFilters&&d.$table.find("."+e.css.filterRow).trigger(""===m?"mouseleave":"mouseenter"),d.lastCombinedFilter!==m||!1===a)if(!1===a&&(d.lastCombinedFilter=null,d.lastSearch=[]),f.filter_initialized&&d.$table.trigger("filterStart",[g]),d.showProcessing)setTimeout(function(){e.filter.findRows(c,g,m);return!1},30);else return e.filter.findRows(c,g,m),!1},hideFilters:function(c,a){var b,d,f;k(c).find("."+ e.css.filterRow).addClass("hideme").bind("mouseenter mouseleave",function(c){b=k(this);clearTimeout(f);f=setTimeout(function(){/enter|over/.test(c.type)?b.removeClass("hideme"):k(document.activeElement).closest("tr")[0]!==b[0]&&""===a.lastCombinedFilter&&b.addClass("hideme")},200)}).find("input, select").bind("focus blur",function(b){d=k(this).closest("tr");clearTimeout(f);f=setTimeout(function(){if(""===e.getFilters(a.$table).join(""))d["focus"===b.type?"removeClass":"addClass"]("hideme")},200)})}, defaultFilter:function(c,a){if(""===c)return c;var b=e.filter.regex.iQuery,d=a.match(e.filter.regex.igQuery).length,f=1<d?k.trim(c).split(/\s/):[k.trim(c)],h=f.length-1,g=0,m=a;for(1>h&&1<d&&(f[1]=f[0]);b.test(m);)m=m.replace(b,f[g++]||""),b.test(m)&&g<h&&""!==(f[g]||"")&&(m=a.replace(b,m));return m},getLatestSearch:function(c){return c.sort(function(a,b){return k(b).attr("data-lastSearchTime")-k(a).attr("data-lastSearchTime")})},multipleColumns:function(c,a){var b,d;b=c.widgetOptions;var f=b.filter_initialized|| !a.filter(b.filter_anyColumnSelector).length,h=[],g=k.trim(e.filter.getLatestSearch(a).attr("data-column"));f&&/-/.test(g)&&(b=g.match(/(\d+)\s*-\s*(\d+)/g),k.each(b,function(a,b){var d;d=b.split(/\s*-\s*/);var e=parseInt(d[0],10)||0,f=parseInt(d[1],10)||c.columns-1;e>f&&(d=e,e=f,f=d);for(f>=c.columns&&(f=c.columns-1);e<=f;e++)h.push(e);g=g.replace(b,"")}));f&&/,/.test(g)&&(b=g.split(/\s*,\s*/),k.each(b,function(a,b){""!==b&&(d=parseInt(b,10),d<c.columns&&h.push(d))}));if(!h.length)for(d=0;d<c.columns;d++)h.push(d); return h},findRows:function(c,a,b){if(c.config.lastCombinedFilter!==b&&c.config.widgetOptions.filter_initialized){var d,f,h,g,m,n,p,r,w,x,t,u,y,A,z,B,C,G,D,H,F=e.filter.regex,q=c.config,v=q.widgetOptions,I=q.$table.children("tbody"),l={anyMatch:!1},J=["range","notMatch","operators"];l.parsed=q.$headers.map(function(a){return q.parsers&&q.parsers[a]&&q.parsers[a].parsed||e.getData&&"parsed"===e.getData(q.$headers.filter('[data-column="'+a+'"]:last'),e.getColumnData(c,q.headers,a),"filter")||k(this).hasClass("filter-parsed")}).get(); q.debug&&(e.log("Starting filter widget search",a),A=new Date);q.filteredRows=0;q.totalRows=0;b=(a||[]).join("");for(g=0;g<I.length;g++)if(!I.eq(g).hasClass(q.cssInfoBlock||e.css.info)){m=e.processTbody(c,I.eq(g),!0);r=q.columns;f=k(k.map(q.cache[g].normalized,function(a){return a[r].$row.get()}));if(""===b||v.filter_serversideFiltering)f.removeClass(v.filter_filteredRow).not("."+q.cssChildRow).show();else{f=f.not("."+q.cssChildRow);d=f.length;B=v.filter_searchFiltered;h=q.lastSearch||q.$table.data("lastSearch")|| [];if(B)for(n=0;n<r+1;n++)z=a[n]||"",B||(n=r),B=B&&h.length&&0===z.indexOf(h[n]||"")&&!F.alreadyFiltered.test(z)&&!/[=\"\|!]/.test(z)&&!(/(>=?\s*-\d)/.test(z)||/(<=?\s*\d)/.test(z))&&!(""!==z&&q.$filters&&q.$filters.eq(n).find("select").length&&!q.$headers.filter('[data-column="'+n+'"]:last').hasClass("filter-match"));z=f.not("."+v.filter_filteredRow).length;B&&0===z&&(B=!1);q.debug&&e.log("Searching through "+(B&&z<d?z:"all")+" rows");if(v.filter_$anyMatch&&v.filter_$anyMatch.length||a[q.columns])l.anyMatchFlag= !0,l.anyMatchFilter=v.filter_$anyMatch&&e.filter.getLatestSearch(v.filter_$anyMatch).val()||a[q.columns]||"",q.sortLocaleCompare&&(l.anyMatchFilter=e.replaceAccents(l.anyMatchFilter)),v.filter_defaultFilter&&F.iQuery.test(e.getColumnData(c,v.filter_defaultFilter,q.columns,!0)||"")&&(l.anyMatchFilter=e.filter.defaultFilter(l.anyMatchFilter,e.getColumnData(c,v.filter_defaultFilter,q.columns,!0)),B=!1),l.iAnyMatchFilter=v.filter_ignoreCase&&q.ignoreCase?l.anyMatchFilter.toLocaleLowerCase():l.anyMatchFilter; for(h=0;h<d;h++)if(l.cacheArray=q.cache[g].normalized[h],w=f[h].className,!(F.child.test(w)||B&&F.filtered.test(w))){y=!0;w=f.eq(h).nextUntil("tr:not(."+q.cssChildRow+")");l.childRowText=w.length&&v.filter_childRows?w.text():"";l.childRowText=v.filter_ignoreCase?l.childRowText.toLocaleLowerCase():l.childRowText;n=f.eq(h).children();if(l.anyMatchFlag){r=e.filter.multipleColumns(q,v.filter_$anyMatch);l.anyMatch=!0;l.rowArray=n.map(function(a){if(-1<k.inArray(a,r))return l.parsed[a]?a=l.cacheArray[a]: (a=v.filter_ignoreCase?k(this).text().toLowerCase():k(this).text(),q.sortLocaleCompare&&(a=e.replaceAccents(a))),a}).get();l.filter=l.anyMatchFilter;l.iFilter=l.iAnyMatchFilter;l.exact=l.rowArray.join(" ");l.iExact=v.filter_ignoreCase?l.exact.toLowerCase():l.exact;l.cache=l.cacheArray.slice(0,-1).join(" ");C=null;k.each(e.filter.types,function(a,b){if(0>k.inArray(a,J)&&(t=b(q,l),null!==t))return C=t,!1});if(null!==C)y=C;else if(v.filter_startsWith)for(y=!1,r=q.columns;!y&&0<r;)r--,y=y||0===l.rowArray[r].indexOf(l.iFilter); else y=0<=(l.iExact+l.childRowText).indexOf(l.iFilter);l.anyMatch=!1}for(r=0;r<q.columns;r++)l.filter=a[r],l.index=r,G=(e.getColumnData(c,v.filter_excludeFilter,r,!0)||"").split(/\s+/),l.filter&&(l.cache=l.cacheArray[r],v.filter_useParsedData||l.parsed[r]?l.exact=l.cache:(l.exact=k.trim(n.eq(r).text()),l.exact=q.sortLocaleCompare?e.replaceAccents(l.exact):l.exact),l.iExact=!F.type.test(typeof l.exact)&&v.filter_ignoreCase?l.exact.toLocaleLowerCase():l.exact,u=y,H=v.filter_columnFilters?q.$filters.add(q.$externalFilters).filter('[data-column="'+ r+'"]').find("select option:selected").attr("data-function-name")||"":"",l.filter=q.sortLocaleCompare?e.replaceAccents(l.filter):l.filter,z=!0,v.filter_defaultFilter&&F.iQuery.test(e.getColumnData(c,v.filter_defaultFilter,r)||"")&&(l.filter=e.filter.defaultFilter(l.filter,e.getColumnData(c,v.filter_defaultFilter,r)),z=!1),l.iFilter=v.filter_ignoreCase?(l.filter||"").toLocaleLowerCase():l.filter,D=e.getColumnData(c,v.filter_functions,r),p=q.$headers.filter('[data-column="'+r+'"]:last'),x=p.hasClass("filter-select"), D||x&&z?!0===D||x?u=p.hasClass("filter-match")?0<=l.iExact.search(l.iFilter):l.filter===l.exact:"function"===typeof D?u=D(l.exact,l.cache,l.filter,r,f.eq(h)):"function"===typeof D[H||l.filter]&&(u=D[H||l.filter](l.exact,l.cache,l.filter,r,f.eq(h))):(C=null,k.each(e.filter.types,function(a,b){if(0>k.inArray(a,G)&&(t=b(q,l),null!==t))return C=t,!1}),null!==C?u=C:(l.exact=(l.iExact+l.childRowText).indexOf(e.filter.parseFilter(q,l.iFilter,r,l.parsed[r])),u=!v.filter_startsWith&&0<=l.exact||v.filter_startsWith&& 0===l.exact)),y=u?y:!1);f.eq(h).toggle(y).toggleClass(v.filter_filteredRow,!y);w.length&&w.toggleClass(v.filter_filteredRow,!y)}}q.filteredRows+=f.not("."+v.filter_filteredRow).length;q.totalRows+=f.length;e.processTbody(c,m,!1)}q.lastCombinedFilter=b;q.lastSearch=a;q.$table.data("lastSearch",a);v.filter_saveFilters&&e.storage&&e.storage(c,"tablesorter-filters",a);q.debug&&e.benchmark("Completed filter widget search",A);v.filter_initialized&&q.$table.trigger("filterEnd",q);setTimeout(function(){q.$table.trigger("applyWidgets")}, 0)}},getOptionSource:function(c,a,b){var d,f=c.config,h=[],g=!1,m=f.widgetOptions.filter_selectSource,n=f.$table.data("lastSearch")||[],p=k.isFunction(m)?!0:e.getColumnData(c,m,a);b&&""!==n[a]&&(b=!1);if(!0===p)g=m(c,a,b);else{if(p instanceof k||"string"===k.type(p)&&0<=p.indexOf("</option>"))return p;k.isArray(p)?g=p:"object"===k.type(m)&&p&&(g=p(c,a,b))}!1===g&&(g=e.filter.getOptions(c,a,b));g=k.grep(g,function(a,b){return k.inArray(a,g)===b});f.$headers.filter('[data-column="'+a+'"]:last').hasClass("filter-select-nosort")|| (k.each(g,function(b,d){h.push({t:d,p:f.parsers&&f.parsers[a].format(d,c,[],a)})}),d=f.textSorter||"",h.sort(function(b,f){var g=b.p.toString(),h=f.p.toString();return k.isFunction(d)?d(g,h,!0,a,c):"object"===typeof d&&d.hasOwnProperty(a)?d[a](g,h,!0,a,c):e.sortNatural?e.sortNatural(g,h):!0}),g=[],k.each(h,function(a,b){g.push(b.t)}));return g},getOptions:function(c,a,b){var d,e,h,g,m=c.config,n=m.widgetOptions,p=m.$table.children("tbody"),r=[];for(d=0;d<p.length;d++)if(!p.eq(d).hasClass(m.cssInfoBlock))for(g= m.cache[d],e=m.cache[d].normalized.length,c=0;c<e;c++)h=g.row?g.row[c]:g.normalized[c][m.columns].$row[0],b&&h.className.match(n.filter_filteredRow)||(n.filter_useParsedData||m.parsers[a].parsed||m.$headers.filter('[data-column="'+a+'"]:last').hasClass("filter-parsed")?r.push(""+g.normalized[c][a]):(h=h.cells[a])&&r.push(k.trim(h.textContent||h.innerText||k(h).text())));return r},buildSelect:function(c,a,b,d,f){c=k(c)[0];a=parseInt(a,10);if(c.config.cache&&!k.isEmptyObject(c.config.cache)){var h, g;g=c.config;var m=g.widgetOptions,n=g.$headers.filter('[data-column="'+a+'"]:last'),n='<option value="">'+(n.data("placeholder")||n.attr("data-placeholder")||m.filter_placeholder.select||"")+"</option>",p=g.$table.find("thead").find("select."+e.css.filter+'[data-column="'+a+'"]').val();if("undefined"===typeof b||""===b)b=e.filter.getOptionSource(c,a,f);if(k.isArray(b)){for(c=0;c<b.length;c++)f=h=b[c]=(""+b[c]).replace(/\"/g,"&quot;"),0<=h.indexOf(m.filter_selectSourceSeparator)&&(h=h.split(m.filter_selectSourceSeparator), f=h[0],h=h[1]),n+=""!==b[c]?"<option "+(f===h?"":'data-function-name="'+b[c]+'" ')+'value="'+f+'">'+h+"</option>":"";b=[]}g=(g.$filters?g.$filters:g.$table.children("thead")).find("."+e.css.filter);m.filter_$externalFilters&&(g=g&&g.length?g.add(m.filter_$externalFilters):m.filter_$externalFilters);a=g.filter('select[data-column="'+a+'"]');a.length&&(a[d?"html":"append"](n),k.isArray(b)||a.append(b).val(p),a.val(p))}},buildDefault:function(c,a){var b,d,f,h=c.config,g=h.widgetOptions,k=h.columns;for(b= 0;b<k;b++)d=h.$headers.filter('[data-column="'+b+'"]:last'),f=!(d.hasClass("filter-false")||d.hasClass("parser-false")),(d.hasClass("filter-select")||!0===e.getColumnData(c,g.filter_functions,b))&&f&&e.filter.buildSelect(c,b,"",a,d.hasClass(g.filter_onlyAvail))}}; e.getFilters=function(c,a,b,d){var f,h,g=!1,m=c?k(c)[0].config:"",n=m?m.widgetOptions:"";if(!0!==a&&n&&!n.filter_columnFilters)return k(c).data("lastSearch");if(m&&(m.$filters&&(f=m.$filters.find("."+e.css.filter)),n.filter_$externalFilters&& (f=f&&f.length?f.add(n.filter_$externalFilters):n.filter_$externalFilters),f&&f.length))for(g=b||[],c=0;c<m.columns+1;c++)h=c===m.columns?n.filter_anyColumnSelector+","+n.filter_multipleColumnSelector:'[data-column="'+c+'"]',a=f.filter(h),a.length&&(a=e.filter.getLatestSearch(a),k.isArray(b)?(d&&a.slice(1),c===m.columns&&(h=a.filter(n.filter_anyColumnSelector),a=h.length?h:a),a.val(b[c]).trigger("change.tsfilter")):(g[c]=a.val()||"",c===m.columns?a.slice(1).filter('[data-column*="'+a.attr("data-column")+ '"]').val(g[c]):a.slice(1).val(g[c])),c===m.columns&&a.length&&(n.filter_$anyMatch=a));0===g.length&&(g=!1);return g}; e.setFilters=function(c,a,b,d){var f=c?k(c)[0].config:"";c=e.getFilters(c,!0,a,d);f&&b&&(f.lastCombinedFilter=null,f.lastSearch=[],e.filter.searching(f.$table[0],a,d),f.$table.trigger("filterFomatterUpdate"));return!!c}; e.addWidget({id:"stickyHeaders",priority:60,options:{stickyHeaders:"",stickyHeaders_attachTo:null,stickyHeaders_xScroll:null,stickyHeaders_yScroll:null,stickyHeaders_offset:0, stickyHeaders_filteredToTop:!0,stickyHeaders_cloneId:"-sticky",stickyHeaders_addResizeEvent:!0,stickyHeaders_includeCaption:!0,stickyHeaders_zIndex:2},format:function(c,a,b){if(!(a.$table.hasClass("hasStickyHeaders")||0<=k.inArray("filter",a.widgets)&&!a.$table.hasClass("hasFilters"))){var d=a.$table,f=k(b.stickyHeaders_attachTo),h=a.namespace+"stickyheaders ",g=k(b.stickyHeaders_yScroll||b.stickyHeaders_attachTo||A),m=k(b.stickyHeaders_xScroll||b.stickyHeaders_attachTo||A),n=d.children("thead:first").children("tr").not(".sticky-false").children(), p=d.children("tfoot"),r=isNaN(b.stickyHeaders_offset)?k(b.stickyHeaders_offset):"",w=f.length?0:r.length?r.height()||0:parseInt(b.stickyHeaders_offset,10)||0,x=d.parent().closest("."+e.css.table).hasClass("hasStickyHeaders")?d.parent().closest("table.tablesorter")[0].config.widgetOptions.$sticky.parent():[],t=x.length?x.height():0,u=b.$sticky=d.clone().addClass("containsStickyHeaders "+e.css.sticky+" "+b.stickyHeaders).wrap('<div class="'+e.css.stickyWrap+'">'),y=u.parent().css({position:f.length? "absolute":"fixed",padding:parseInt(u.parent().parent().css("padding-left"),10),top:w+t,left:0,visibility:"hidden",zIndex:b.stickyHeaders_zIndex||2}),E=u.children("thead:first"),z,B="",C=0,G=function(a,b){a.filter(":visible").each(function(a){var d;a=b.filter(":visible").eq(a);var c=k(this);"border-box"===c.css("box-sizing")?d=c.outerWidth():"collapse"===a.css("border-collapse")?A.getComputedStyle?d=parseFloat(A.getComputedStyle(this,null).width):(d=parseFloat(c.css("border-width")),d=c.outerWidth()- parseFloat(c.css("padding-left"))-parseFloat(c.css("padding-right"))-d):d=c.width();a.css({"min-width":d,"max-width":d})})},D=function(){w=r.length?r.height()||0:parseInt(b.stickyHeaders_offset,10)||0;C=0;y.css({left:f.length?parseInt(f.css("padding-left"),10)||0:d.offset().left-parseInt(d.css("margin-left"),10)-m.scrollLeft()-C,width:d.outerWidth()});G(d,u);G(n,z)};u.attr("id")&&(u[0].id+=b.stickyHeaders_cloneId);u.find("thead:gt(0), tr.sticky-false").hide();u.find("tbody, tfoot").remove();u.find("caption").toggle(b.stickyHeaders_includeCaption); z=E.children().children();u.css({height:0,width:0,margin:0});z.find("."+e.css.resizer).remove();d.addClass("hasStickyHeaders").bind("pagerComplete"+h,function(){D()});e.bindEvents(c,E.children().children(".tablesorter-header"));d.after(y);a.onRenderHeader&&E.children("tr").children().each(function(b){a.onRenderHeader.apply(k(this),[b,a,u])});m.add(g).unbind(["scroll","resize",""].join(h)).bind(["scroll","resize",""].join(h),function(a){if(d.is(":visible")){t=x.length?x.offset().top-g.scrollTop()+ x.height():0;var b=d.offset(),c=k.isWindow(g[0]),e=k.isWindow(m[0]),h=(f.length?c?g.scrollTop():g.offset().top:g.scrollTop())+w+t,l=d.height()-(y.height()+(p.height()||0)),b=h>b.top&&h<b.top+l?"visible":"hidden",l={visibility:b};f.length&&(l.top=c?h:f.scrollTop());e&&(l.left=d.offset().left-parseInt(d.css("margin-left"),10)-m.scrollLeft()-C);x.length&&(l.top=(l.top||0)+w+t);y.removeClass("tablesorter-sticky-visible tablesorter-sticky-hidden").addClass("tablesorter-sticky-"+b).css(l);if(b!==B||"resize"=== a.type)D(),B=b}});b.stickyHeaders_addResizeEvent&&e.addHeaderResizeEvent(c);d.hasClass("hasFilters")&&b.filter_columnFilters&&(d.bind("filterEnd"+h,function(){var c=k(document.activeElement).closest("td"),c=c.parent().children().index(c);y.hasClass(e.css.stickyVis)&&b.stickyHeaders_filteredToTop&&(A.scrollTo(0,d.position().top),0<=c&&a.$filters&&a.$filters.eq(c).find("a, select, input").filter(":visible").focus())}),e.filter.bindSearch(d,z.find("."+e.css.filter)),b.filter_hideFilters&&e.filter.hideFilters(u, a));d.trigger("stickyHeadersInit")}},remove:function(c,a,b){var d=a.namespace+"stickyheaders ";a.$table.removeClass("hasStickyHeaders").unbind(["pagerComplete","filterEnd",""].join(d)).next("."+e.css.stickyWrap).remove();b.$sticky&&b.$sticky.length&&b.$sticky.remove();k(".hasStickyHeaders").length||k(A).add(b.stickyHeaders_xScroll).add(b.stickyHeaders_yScroll).add(b.stickyHeaders_attachTo).unbind(["scroll","resize",""].join(d));e.addHeaderResizeEvent(c,!1)}}); e.addWidget({id:"resizable",priority:40, options:{resizable:!0,resizable_addLastColumn:!1,resizable_widths:[],resizable_throttle:!1},format:function(c,a,b){if(!a.$table.hasClass("hasResizable")){a.$table.addClass("hasResizable");e.resizableReset(c,!0);var d,f,h,g,m,n={},p=a.$table,r=p.parent(),w="auto"===p.parent().css("overflow"),x=0,t=null,u=null,y=20>Math.abs(p.parent().width()-p.width()),E=function(a){if(0!==x&&t){var b=a.pageX-x,c=t.width();t.width(c+b);t.width()!==c&&y?u.width(u.width()-b):w&&(p.width(function(a,c){return c+b}),u.length|| (r[0].scrollLeft=p.width()));x=a.pageX}},z=function(){e.storage&&t&&u&&(n={},n[t.index()]=t.width(),n[u.index()]=u.width(),t.width(n[t.index()]),u.width(n[u.index()]),!1!==b.resizable&&e.storage(c,"tablesorter-resizable",a.$headers.map(function(){return k(this).width()}).get()));x=0;t=u=null;k(A).trigger("resize")};if(n=e.storage&&!1!==b.resizable?e.storage(c,"tablesorter-resizable"):{})for(g in n)!isNaN(g)&&g<a.$headers.length&&a.$headers.eq(g).width(n[g]);d=p.children("thead:first").children("tr"); d.children().each(function(){var b;b=k(this);g=b.attr("data-column");b="false"===e.getData(b,e.getColumnData(c,a.headers,g),"resizable");d.children().filter('[data-column="'+g+'"]')[b?"addClass":"removeClass"]("resizable-false")});d.each(function(){h=k(this).children().not(".resizable-false");k(this).find("."+e.css.wrapper).length||h.wrapInner('<div class="'+e.css.wrapper+'" style="position:relative;height:100%;width:100%"></div>');b.resizable_addLastColumn||(h=h.slice(0,-1));f=f?f.add(h):h});f.each(function(){var a= k(this),b=parseInt(a.css("padding-right"),10)+10;a.find("."+e.css.wrapper).append('<div class="'+e.css.resizer+'" style="cursor:w-resize;position:absolute;z-index:1;right:-'+b+'px;top:0;height:100%;width:20px;"></div>')}).find("."+e.css.resizer).bind("mousedown",function(b){t=k(b.target).closest("th");var c=a.$headers.filter('[data-column="'+t.attr("data-column")+'"]');1<c.length&&(t=t.add(c));u=b.shiftKey?t.parent().find("th").not(".resizable-false").filter(":last"):t.nextAll(":not(.resizable-false)").eq(0); x=b.pageX});k(document).bind("mousemove.tsresize",function(a){0!==x&&t&&(b.resizable_throttle?(clearTimeout(m),m=setTimeout(function(){E(a)},isNaN(b.resizable_throttle)?5:b.resizable_throttle)):E(a))}).bind("mouseup.tsresize",function(){z()});p.find("thead:first").bind("contextmenu.tsresize",function(){e.resizableReset(c);var a=k.isEmptyObject?k.isEmptyObject(n):!0;n={};return a})}},remove:function(c,a){a.$table.removeClass("hasResizable").children("thead").unbind("mouseup.tsresize mouseleave.tsresize contextmenu.tsresize").children("tr").children().unbind("mousemove.tsresize mouseup.tsresize").find("."+ e.css.resizer).remove();e.resizableReset(c)}}); e.resizableReset=function(c,a){k(c).each(function(){var b,d=this.config,f=d&&d.widgetOptions;c&&d&&(d.$headers.each(function(a){b=k(this);f.resizable_widths[a]?b.css("width",f.resizable_widths[a]):b.hasClass("resizable-false")||b.css("width","")}),e.storage&&!a&&e.storage(this,"tablesorter-resizable",{}))})}; e.addWidget({id:"saveSort",priority:20,options:{saveSort:!0},init:function(c,a,b,d){a.format(c,b,d,!0)},format:function(c,a,b,d){var f,h=a.$table; b=!1!==b.saveSort;var g={sortList:a.sortList};a.debug&&(f=new Date);h.hasClass("hasSaveSort")?b&&c.hasInitialized&&e.storage&&(e.storage(c,"tablesorter-savesort",g),a.debug&&e.benchmark("saveSort widget: Saving last sort: "+a.sortList,f)):(h.addClass("hasSaveSort"),g="",e.storage&&(g=(b=e.storage(c,"tablesorter-savesort"))&&b.hasOwnProperty("sortList")&&k.isArray(b.sortList)?b.sortList:"",a.debug&&e.benchmark('saveSort: Last sort loaded: "'+g+'"',f),h.bind("saveSortReset",function(a){a.stopPropagation(); e.storage(c,"tablesorter-savesort","")})),d&&g&&0<g.length?a.sortList=g:c.hasInitialized&&g&&0<g.length&&h.trigger("sorton",[g]))},remove:function(c){e.storage&&e.storage(c,"tablesorter-savesort","")}}) })(jQuery,window);
-/* tablesorter */ $(document).ready(function(){$('table').tablesorter({theme:'bootstrap',widgets:['uitheme','zebra','filter'],headerTemplate:'{content} {icon}',widthFixed:true,ignoreCase:true,widgetOptions:{filter_columnFilters:true,zebra:['even','odd'],filter_reset:'.reset'}});});
-/* treegrid */ $(document).ready(function(){$('.tracks-tree').treegrid({'treeColumn':1});});
-
-/* redirectPost */
-$.extend(
-{
- redirectPost: function(location, args)
- {
- var form = '';
- $.each(args, function(key, value) {
- form += '<input type="hidden" name="' + key + '" value="' + value + '">';
- });
- $('<form action="' + location + '" method="POST">' + form + '</form>').appendTo('body').submit();
- }
-});
+/* tablesorter */ $(document).ready(function(){$('table').tablesorter({theme:'bootstrap',widgets:['uitheme','zebra','filter'],headerTemplate:'{content} {icon}',widthFixed:true,ignoreCase:true,widgetOptions:{filter_columnFilters:true,zebra:['even','odd'],filter_reset:'.reset'}});});
+/* treegrid */ $(document).ready(function(){$('.tracks-tree').treegrid({'treeColumn':1});});
+
+/* redirectPost */
+$.extend(
+{
+ redirectPost: function(location, args)
+ {
+ var form = '';
+ $.each(args, function(key, value) {
+ form += '<input type="hidden" name="' + key + '" value="' + value + '">';
+ });
+ $('<form action="' + location + '" method="POST">' + form + '</form>').appendTo('body').submit();
+ }
+});
diff --git a/library/cpp/lwtrace/mon/static/css/bootstrap.min.css b/library/cpp/lwtrace/mon/static/css/bootstrap.min.css
index f602cacbf8..361830c990 100644
--- a/library/cpp/lwtrace/mon/static/css/bootstrap.min.css
+++ b/library/cpp/lwtrace/mon/static/css/bootstrap.min.css
@@ -1,9 +1,9 @@
-/*!
- * Bootstrap v3.0.2 by @fat and @mdo
- * Copyright 2013 Twitter, Inc.
- * Licensed under http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world by @mdo and @fat.
- */
-
-/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}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}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!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:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-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}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#c09853}.text-warning:hover{color:#a47e3c}.text-danger{color:#b94a48}.text-danger:hover{color:#953b39}.text-success{color:#468847}.text-success:hover{color:#356635}.text-info{color:#3a87ad}.text-info:hover{color:#2d6987}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .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}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.list-inline>li:first-child{padding-left:0}dl{margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}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}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:''}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;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}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.container{width:750px}.col-sm-1,.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-sm-10,.col-sm-11{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.container{width:970px}.col-md-1,.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-md-10,.col-md-11{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.container{width:1170px}.col-lg-1,.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-lg-10,.col-lg-11{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;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>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}@media(max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{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;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-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,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.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}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{margin-bottom: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}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{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,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@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.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';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1;-moz-osx-font-smoothing:grayscale}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.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"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent}.dropdown{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;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.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:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{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-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.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{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.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:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-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-bottom-left-radius:0;border-top-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>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.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,0.125);box-shadow:inset 0 3px 5px rgba(0,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{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.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-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;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:45px;line-height:45px}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}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-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control: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:normal;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="radio"],.input-group-addon input[type="checkbox"]{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>.dropdown-toggle,.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:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .open>a .caret,.nav .open>a:hover .caret,.nav .open>a:focus .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.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.428571429;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:hover,.nav-tabs>li.active>a:focus{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:hover,.nav-tabs.nav-justified>.active>a:focus{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:hover,.nav-tabs.nav-justified>.active>a:focus{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:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-pills>li.active>a .caret,.nav-pills>li.active>a:hover .caret,.nav-pills>li.active>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.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:hover,.nav-tabs-justified>.active>a:focus{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:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:auto}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{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-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{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;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .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;border:1px solid transparent;border-radius:4px}.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;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{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}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.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,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.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}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@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-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{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:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{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:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.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:#999}.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.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-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:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-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}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-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:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.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:hover,.pager li>a:focus{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:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.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:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 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,0.1);box-shadow:inset 0 1px 2px rgba(0,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:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-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-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.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-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.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,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>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-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.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>.dropdown .caret{border-color:#333 transparent}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-heading>.dropdown .caret{border-color:#fff transparent}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading>.dropdown .caret{border-color:#468847 transparent}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading>.dropdown .caret{border-color:#c09853 transparent}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading>.dropdown .caret{border-color:#b94a48 transparent}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading>.dropdown .caret{border-color:#3a87ad transparent}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.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,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,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:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.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}@media screen and (min-width:768px){.modal-dialog{width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.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;text-decoration:none;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-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.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;font-weight:normal;line-height:18px;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{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.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;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.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,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.5)),to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.0001)),to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.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,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix: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;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}}
+/*!
+ * Bootstrap v3.0.2 by @fat and @mdo
+ * Copyright 2013 Twitter, Inc.
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world by @mdo and @fat.
+ */
+
+/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}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}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!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:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-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}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#c09853}.text-warning:hover{color:#a47e3c}.text-danger{color:#b94a48}.text-danger:hover{color:#953b39}.text-success{color:#468847}.text-success:hover{color:#356635}.text-info{color:#3a87ad}.text-info:hover{color:#2d6987}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .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}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.list-inline>li:first-child{padding-left:0}dl{margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}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}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:''}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;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}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.container{width:750px}.col-sm-1,.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-sm-10,.col-sm-11{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.container{width:970px}.col-md-1,.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-md-10,.col-md-11{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.container{width:1170px}.col-lg-1,.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-lg-10,.col-lg-11{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;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>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}@media(max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{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;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-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,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.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}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{margin-bottom: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}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{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,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@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.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';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1;-moz-osx-font-smoothing:grayscale}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.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"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent}.dropdown{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;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.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:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{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-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.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{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.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:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-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-bottom-left-radius:0;border-top-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>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.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,0.125);box-shadow:inset 0 3px 5px rgba(0,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{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.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-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;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:45px;line-height:45px}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}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-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control: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:normal;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="radio"],.input-group-addon input[type="checkbox"]{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>.dropdown-toggle,.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:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .open>a .caret,.nav .open>a:hover .caret,.nav .open>a:focus .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.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.428571429;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:hover,.nav-tabs>li.active>a:focus{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:hover,.nav-tabs.nav-justified>.active>a:focus{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:hover,.nav-tabs.nav-justified>.active>a:focus{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:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-pills>li.active>a .caret,.nav-pills>li.active>a:hover .caret,.nav-pills>li.active>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.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:hover,.nav-tabs-justified>.active>a:focus{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:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:auto}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{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-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{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;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .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;border:1px solid transparent;border-radius:4px}.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;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{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}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.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,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.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}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@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-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{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:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{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:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.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:#999}.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.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-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:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-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}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-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:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.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:hover,.pager li>a:focus{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:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.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:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 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,0.1);box-shadow:inset 0 1px 2px rgba(0,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:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-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-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.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-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.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,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>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-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.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>.dropdown .caret{border-color:#333 transparent}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-heading>.dropdown .caret{border-color:#fff transparent}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading>.dropdown .caret{border-color:#468847 transparent}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading>.dropdown .caret{border-color:#c09853 transparent}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading>.dropdown .caret{border-color:#b94a48 transparent}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading>.dropdown .caret{border-color:#3a87ad transparent}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.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,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,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:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.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}@media screen and (min-width:768px){.modal-dialog{width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.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;text-decoration:none;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-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.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;font-weight:normal;line-height:18px;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{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.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;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.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,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.5)),to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.0001)),to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.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,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix: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;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}}
diff --git a/library/cpp/lwtrace/mon/static/css/d3-gantt.css b/library/cpp/lwtrace/mon/static/css/d3-gantt.css
index 25ba8fae6e..d6aeeb1a54 100644
--- a/library/cpp/lwtrace/mon/static/css/d3-gantt.css
+++ b/library/cpp/lwtrace/mon/static/css/d3-gantt.css
@@ -1,68 +1,68 @@
-.chart {
- font-family: Arial, sans-serif;
- font-size: 12px;
-}
-
-rect.zoom-panel {
- /*cursor: ew-resize;*/
- fill: none;
- pointer-events: all;
-}
-
-.axis path,.axis line {
- fill: none;
- stroke: #000;
- shape-rendering: crispEdges;
-}
-
-.axis.y {
- font-size: 16px;
- cursor: ns-resize;
-}
-
-.axis.x {
- font-size: 16px;
-}
-
-#ruler {
- text-anchor: middle;
- alignment-baseline: before-edge;
- font-size: 16px;
- font-family: sans-serif;
- pointer-events: none;
-}
-
-.d3-tip {
- line-height: 1;
- font-weight: bold;
- padding: 12px;
- background: rgba(0, 0, 0, 0.8);
- color: #fff;
- border-radius: 2px;
-}
-
-.d3-tip pre {
- font-weight: bold;
- padding: 12px;
- background: rgba(0, 0, 0, 0);
- color: #fff;
- border: 0px;
-}
-
-/* Style northward tooltips differently */
-.d3-tip.n:after {
- margin: -1px 0 0 0;
- top: 100%;
- left: 0;
-}
-
-/* for arrowhead marker */
-#arrow {
- stroke-width:1;
- stroke-dasharray:0;
-}
-
-.bar:hover {
- stroke-width: 1px;
- stroke: black;
-} \ No newline at end of file
+.chart {
+ font-family: Arial, sans-serif;
+ font-size: 12px;
+}
+
+rect.zoom-panel {
+ /*cursor: ew-resize;*/
+ fill: none;
+ pointer-events: all;
+}
+
+.axis path,.axis line {
+ fill: none;
+ stroke: #000;
+ shape-rendering: crispEdges;
+}
+
+.axis.y {
+ font-size: 16px;
+ cursor: ns-resize;
+}
+
+.axis.x {
+ font-size: 16px;
+}
+
+#ruler {
+ text-anchor: middle;
+ alignment-baseline: before-edge;
+ font-size: 16px;
+ font-family: sans-serif;
+ pointer-events: none;
+}
+
+.d3-tip {
+ line-height: 1;
+ font-weight: bold;
+ padding: 12px;
+ background: rgba(0, 0, 0, 0.8);
+ color: #fff;
+ border-radius: 2px;
+}
+
+.d3-tip pre {
+ font-weight: bold;
+ padding: 12px;
+ background: rgba(0, 0, 0, 0);
+ color: #fff;
+ border: 0px;
+}
+
+/* Style northward tooltips differently */
+.d3-tip.n:after {
+ margin: -1px 0 0 0;
+ top: 100%;
+ left: 0;
+}
+
+/* for arrowhead marker */
+#arrow {
+ stroke-width:1;
+ stroke-dasharray:0;
+}
+
+.bar:hover {
+ stroke-width: 1px;
+ stroke: black;
+} \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/css/jquery.treegrid.css b/library/cpp/lwtrace/mon/static/css/jquery.treegrid.css
index 3980272607..068cfdc134 100644
--- a/library/cpp/lwtrace/mon/static/css/jquery.treegrid.css
+++ b/library/cpp/lwtrace/mon/static/css/jquery.treegrid.css
@@ -1,8 +1,8 @@
-.treegrid-indent {width:16px; height: 16px; display: inline-block; position: relative;}
-.treegrid-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
-.treegrid-expander-expanded{background-image: url(../img/collapse.png); }
-.treegrid-expander-collapsed{background-image: url(../img/expand.png);}
-
-.treegrid-element {white-space: unset;}
-
-.timelinehead {width:30vw;}
+.treegrid-indent {width:16px; height: 16px; display: inline-block; position: relative;}
+.treegrid-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
+.treegrid-expander-expanded{background-image: url(../img/collapse.png); }
+.treegrid-expander-collapsed{background-image: url(../img/expand.png);}
+
+.treegrid-element {white-space: unset;}
+
+.timelinehead {width:30vw;}
diff --git a/library/cpp/lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg b/library/cpp/lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg
index 94fb5490a2..02ec85726c 100644
--- a/library/cpp/lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg
+++ b/library/cpp/lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg
@@ -1,288 +1,288 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata></metadata>
-<defs>
-<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
-<font-face units-per-em="1200" ascent="960" descent="-240" />
-<missing-glyph horiz-adv-x="500" />
-<glyph horiz-adv-x="0" />
-<glyph horiz-adv-x="400" />
-<glyph unicode=" " />
-<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
-<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xa0;" />
-<glyph unicode="&#xa5;" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
-<glyph unicode="&#x2000;" horiz-adv-x="650" />
-<glyph unicode="&#x2001;" horiz-adv-x="1300" />
-<glyph unicode="&#x2002;" horiz-adv-x="650" />
-<glyph unicode="&#x2003;" horiz-adv-x="1300" />
-<glyph unicode="&#x2004;" horiz-adv-x="433" />
-<glyph unicode="&#x2005;" horiz-adv-x="325" />
-<glyph unicode="&#x2006;" horiz-adv-x="216" />
-<glyph unicode="&#x2007;" horiz-adv-x="216" />
-<glyph unicode="&#x2008;" horiz-adv-x="162" />
-<glyph unicode="&#x2009;" horiz-adv-x="260" />
-<glyph unicode="&#x200a;" horiz-adv-x="72" />
-<glyph unicode="&#x202f;" horiz-adv-x="260" />
-<glyph unicode="&#x205f;" horiz-adv-x="325" />
-<glyph unicode="&#x20ac;" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
-<glyph unicode="&#x20bd;" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
-<glyph unicode="&#x2212;" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#x231b;" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
-<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
-<glyph unicode="&#x2601;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
-<glyph unicode="&#x26fa;" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
-<glyph unicode="&#x2709;" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
-<glyph unicode="&#x270f;" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
-<glyph unicode="&#xe001;" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
-<glyph unicode="&#xe002;" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
-<glyph unicode="&#xe003;" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
-<glyph unicode="&#xe005;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
-<glyph unicode="&#xe006;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
-<glyph unicode="&#xe007;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
-<glyph unicode="&#xe008;" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
-<glyph unicode="&#xe009;" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
-<glyph unicode="&#xe010;" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe011;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
-<glyph unicode="&#xe012;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe013;" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
-<glyph unicode="&#xe014;" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
-<glyph unicode="&#xe015;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe016;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe017;" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
-<glyph unicode="&#xe018;" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe019;" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
-<glyph unicode="&#xe020;" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
-<glyph unicode="&#xe021;" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
-<glyph unicode="&#xe022;" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
-<glyph unicode="&#xe023;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe024;" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
-<glyph unicode="&#xe025;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe026;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
-<glyph unicode="&#xe027;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
-<glyph unicode="&#xe028;" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
-<glyph unicode="&#xe029;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
-<glyph unicode="&#xe030;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
-<glyph unicode="&#xe031;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
-<glyph unicode="&#xe032;" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe033;" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
-<glyph unicode="&#xe034;" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
-<glyph unicode="&#xe035;" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
-<glyph unicode="&#xe036;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
-<glyph unicode="&#xe037;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
-<glyph unicode="&#xe038;" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
-<glyph unicode="&#xe039;" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
-<glyph unicode="&#xe040;" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
-<glyph unicode="&#xe041;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
-<glyph unicode="&#xe042;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
-<glyph unicode="&#xe043;" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
-<glyph unicode="&#xe044;" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe045;" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
-<glyph unicode="&#xe046;" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
-<glyph unicode="&#xe047;" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
-<glyph unicode="&#xe048;" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
-<glyph unicode="&#xe049;" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
-<glyph unicode="&#xe050;" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
-<glyph unicode="&#xe051;" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
-<glyph unicode="&#xe052;" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe053;" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
-<glyph unicode="&#xe055;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe056;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe057;" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe058;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe059;" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
-<glyph unicode="&#xe060;" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
-<glyph unicode="&#xe062;" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
-<glyph unicode="&#xe063;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
-<glyph unicode="&#xe064;" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
-<glyph unicode="&#xe065;" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
-<glyph unicode="&#xe066;" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
-<glyph unicode="&#xe067;" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
-<glyph unicode="&#xe068;" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
-<glyph unicode="&#xe069;" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe070;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe071;" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
-<glyph unicode="&#xe072;" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
-<glyph unicode="&#xe073;" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe074;" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
-<glyph unicode="&#xe075;" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
-<glyph unicode="&#xe076;" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe078;" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe079;" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
-<glyph unicode="&#xe080;" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
-<glyph unicode="&#xe081;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
-<glyph unicode="&#xe082;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
-<glyph unicode="&#xe083;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
-<glyph unicode="&#xe084;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
-<glyph unicode="&#xe085;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
-<glyph unicode="&#xe086;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
-<glyph unicode="&#xe087;" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
-<glyph unicode="&#xe088;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
-<glyph unicode="&#xe089;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
-<glyph unicode="&#xe090;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
-<glyph unicode="&#xe091;" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
-<glyph unicode="&#xe092;" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
-<glyph unicode="&#xe093;" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
-<glyph unicode="&#xe094;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe095;" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
-<glyph unicode="&#xe096;" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
-<glyph unicode="&#xe097;" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
-<glyph unicode="&#xe101;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
-<glyph unicode="&#xe102;" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
-<glyph unicode="&#xe103;" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
-<glyph unicode="&#xe104;" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
-<glyph unicode="&#xe105;" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
-<glyph unicode="&#xe106;" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
-<glyph unicode="&#xe107;" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
-<glyph unicode="&#xe108;" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
-<glyph unicode="&#xe109;" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
-<glyph unicode="&#xe110;" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
-<glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
-<glyph unicode="&#xe112;" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
-<glyph unicode="&#xe113;" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
-<glyph unicode="&#xe114;" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
-<glyph unicode="&#xe115;" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
-<glyph unicode="&#xe116;" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
-<glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
-<glyph unicode="&#xe118;" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
-<glyph unicode="&#xe119;" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
-<glyph unicode="&#xe120;" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
-<glyph unicode="&#xe121;" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
-<glyph unicode="&#xe122;" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
-<glyph unicode="&#xe123;" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
-<glyph unicode="&#xe124;" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
-<glyph unicode="&#xe125;" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe126;" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
-<glyph unicode="&#xe127;" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe128;" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe129;" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe130;" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
-<glyph unicode="&#xe131;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
-<glyph unicode="&#xe132;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
-<glyph unicode="&#xe133;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
-<glyph unicode="&#xe134;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
-<glyph unicode="&#xe135;" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
-<glyph unicode="&#xe136;" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
-<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
-<glyph unicode="&#xe138;" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
-<glyph unicode="&#xe139;" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
-<glyph unicode="&#xe140;" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
-<glyph unicode="&#xe141;" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
-<glyph unicode="&#xe142;" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
-<glyph unicode="&#xe143;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
-<glyph unicode="&#xe144;" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
-<glyph unicode="&#xe145;" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
-<glyph unicode="&#xe146;" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
-<glyph unicode="&#xe148;" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
-<glyph unicode="&#xe149;" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
-<glyph unicode="&#xe150;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
-<glyph unicode="&#xe151;" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
-<glyph unicode="&#xe152;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
-<glyph unicode="&#xe153;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
-<glyph unicode="&#xe154;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
-<glyph unicode="&#xe155;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
-<glyph unicode="&#xe156;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
-<glyph unicode="&#xe157;" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
-<glyph unicode="&#xe158;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
-<glyph unicode="&#xe159;" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
-<glyph unicode="&#xe160;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
-<glyph unicode="&#xe161;" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
-<glyph unicode="&#xe162;" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
-<glyph unicode="&#xe163;" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
-<glyph unicode="&#xe164;" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
-<glyph unicode="&#xe165;" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
-<glyph unicode="&#xe166;" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
-<glyph unicode="&#xe167;" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
-<glyph unicode="&#xe168;" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
-<glyph unicode="&#xe169;" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
-<glyph unicode="&#xe170;" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
-<glyph unicode="&#xe171;" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
-<glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
-<glyph unicode="&#xe173;" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
-<glyph unicode="&#xe174;" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
-<glyph unicode="&#xe175;" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe176;" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
-<glyph unicode="&#xe177;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
-<glyph unicode="&#xe178;" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
-<glyph unicode="&#xe179;" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
-<glyph unicode="&#xe180;" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
-<glyph unicode="&#xe181;" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
-<glyph unicode="&#xe182;" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
-<glyph unicode="&#xe183;" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
-<glyph unicode="&#xe184;" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe185;" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
-<glyph unicode="&#xe186;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
-<glyph unicode="&#xe187;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
-<glyph unicode="&#xe188;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
-<glyph unicode="&#xe189;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
-<glyph unicode="&#xe190;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
-<glyph unicode="&#xe191;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
-<glyph unicode="&#xe192;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
-<glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
-<glyph unicode="&#xe194;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
-<glyph unicode="&#xe195;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
-<glyph unicode="&#xe197;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe198;" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
-<glyph unicode="&#xe199;" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
-<glyph unicode="&#xe200;" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
-<glyph unicode="&#xe201;" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
-<glyph unicode="&#xe202;" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
-<glyph unicode="&#xe203;" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
-<glyph unicode="&#xe204;" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
-<glyph unicode="&#xe205;" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
-<glyph unicode="&#xe206;" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
-<glyph unicode="&#xe209;" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
-<glyph unicode="&#xe210;" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe211;" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe212;" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe213;" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe214;" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe215;" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe216;" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
-<glyph unicode="&#xe218;" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
-<glyph unicode="&#xe219;" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
-<glyph unicode="&#xe221;" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe223;" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
-<glyph unicode="&#xe224;" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
-<glyph unicode="&#xe225;" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
-<glyph unicode="&#xe226;" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
-<glyph unicode="&#xe227;" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
-<glyph unicode="&#xe230;" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
-<glyph unicode="&#xe231;" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
-<glyph unicode="&#xe232;" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
-<glyph unicode="&#xe233;" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
-<glyph unicode="&#xe234;" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
-<glyph unicode="&#xe235;" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
-<glyph unicode="&#xe236;" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
-<glyph unicode="&#xe237;" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
-<glyph unicode="&#xe238;" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe239;" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
-<glyph unicode="&#xe240;" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
-<glyph unicode="&#xe241;" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
-<glyph unicode="&#xe242;" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
-<glyph unicode="&#xe243;" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
-<glyph unicode="&#xe244;" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
-<glyph unicode="&#xe245;" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
-<glyph unicode="&#xe246;" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
-<glyph unicode="&#xe247;" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe248;" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
-<glyph unicode="&#xe249;" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
-<glyph unicode="&#xe250;" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
-<glyph unicode="&#xe251;" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
-<glyph unicode="&#xe252;" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
-<glyph unicode="&#xe253;" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
-<glyph unicode="&#xe254;" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
-<glyph unicode="&#xe255;" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
-<glyph unicode="&#xe256;" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
-<glyph unicode="&#xe257;" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
-<glyph unicode="&#xe258;" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
-<glyph unicode="&#xe259;" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
-<glyph unicode="&#xe260;" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
-<glyph unicode="&#xf8ff;" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
-<glyph unicode="&#x1f511;" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
-<glyph unicode="&#x1f6aa;" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
-</font>
-</defs></svg> \ No newline at end of file
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph horiz-adv-x="0" />
+<glyph horiz-adv-x="400" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
+<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#xa5;" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
+<glyph unicode="&#x2000;" horiz-adv-x="650" />
+<glyph unicode="&#x2001;" horiz-adv-x="1300" />
+<glyph unicode="&#x2002;" horiz-adv-x="650" />
+<glyph unicode="&#x2003;" horiz-adv-x="1300" />
+<glyph unicode="&#x2004;" horiz-adv-x="433" />
+<glyph unicode="&#x2005;" horiz-adv-x="325" />
+<glyph unicode="&#x2006;" horiz-adv-x="216" />
+<glyph unicode="&#x2007;" horiz-adv-x="216" />
+<glyph unicode="&#x2008;" horiz-adv-x="162" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="325" />
+<glyph unicode="&#x20ac;" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
+<glyph unicode="&#x20bd;" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
+<glyph unicode="&#x2212;" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#x231b;" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#x2601;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
+<glyph unicode="&#x26fa;" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
+<glyph unicode="&#x2709;" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
+<glyph unicode="&#x270f;" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
+<glyph unicode="&#xe001;" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
+<glyph unicode="&#xe002;" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
+<glyph unicode="&#xe003;" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
+<glyph unicode="&#xe005;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
+<glyph unicode="&#xe006;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
+<glyph unicode="&#xe007;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
+<glyph unicode="&#xe008;" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
+<glyph unicode="&#xe009;" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
+<glyph unicode="&#xe010;" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe011;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
+<glyph unicode="&#xe012;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe013;" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
+<glyph unicode="&#xe014;" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
+<glyph unicode="&#xe015;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe016;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe017;" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
+<glyph unicode="&#xe018;" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe019;" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
+<glyph unicode="&#xe020;" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
+<glyph unicode="&#xe021;" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="&#xe022;" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
+<glyph unicode="&#xe023;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe024;" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
+<glyph unicode="&#xe025;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe026;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
+<glyph unicode="&#xe027;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
+<glyph unicode="&#xe028;" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
+<glyph unicode="&#xe029;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="&#xe030;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
+<glyph unicode="&#xe031;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
+<glyph unicode="&#xe032;" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe033;" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
+<glyph unicode="&#xe034;" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
+<glyph unicode="&#xe035;" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
+<glyph unicode="&#xe036;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
+<glyph unicode="&#xe037;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
+<glyph unicode="&#xe038;" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
+<glyph unicode="&#xe039;" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
+<glyph unicode="&#xe040;" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
+<glyph unicode="&#xe041;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="&#xe042;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="&#xe043;" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
+<glyph unicode="&#xe044;" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe045;" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
+<glyph unicode="&#xe046;" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
+<glyph unicode="&#xe047;" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
+<glyph unicode="&#xe048;" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
+<glyph unicode="&#xe049;" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
+<glyph unicode="&#xe050;" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
+<glyph unicode="&#xe051;" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
+<glyph unicode="&#xe052;" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe053;" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe055;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe056;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe057;" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe058;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe059;" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
+<glyph unicode="&#xe062;" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
+<glyph unicode="&#xe063;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
+<glyph unicode="&#xe064;" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
+<glyph unicode="&#xe065;" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
+<glyph unicode="&#xe066;" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
+<glyph unicode="&#xe067;" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
+<glyph unicode="&#xe068;" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="&#xe069;" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe070;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe071;" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
+<glyph unicode="&#xe072;" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
+<glyph unicode="&#xe073;" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe074;" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe075;" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
+<glyph unicode="&#xe076;" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe078;" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe079;" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
+<glyph unicode="&#xe080;" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
+<glyph unicode="&#xe081;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="&#xe082;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="&#xe083;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
+<glyph unicode="&#xe084;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
+<glyph unicode="&#xe085;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe086;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe087;" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
+<glyph unicode="&#xe088;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe089;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe090;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
+<glyph unicode="&#xe091;" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
+<glyph unicode="&#xe092;" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="&#xe093;" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
+<glyph unicode="&#xe094;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe095;" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="&#xe096;" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
+<glyph unicode="&#xe097;" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
+<glyph unicode="&#xe101;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe102;" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
+<glyph unicode="&#xe103;" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
+<glyph unicode="&#xe104;" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
+<glyph unicode="&#xe105;" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="&#xe106;" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="&#xe107;" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
+<glyph unicode="&#xe108;" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
+<glyph unicode="&#xe109;" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
+<glyph unicode="&#xe110;" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
+<glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
+<glyph unicode="&#xe112;" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
+<glyph unicode="&#xe113;" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
+<glyph unicode="&#xe114;" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
+<glyph unicode="&#xe115;" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe116;" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
+<glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
+<glyph unicode="&#xe118;" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
+<glyph unicode="&#xe119;" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe120;" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
+<glyph unicode="&#xe121;" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
+<glyph unicode="&#xe122;" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
+<glyph unicode="&#xe123;" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
+<glyph unicode="&#xe124;" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
+<glyph unicode="&#xe125;" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe126;" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
+<glyph unicode="&#xe127;" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe128;" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe129;" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe130;" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
+<glyph unicode="&#xe131;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
+<glyph unicode="&#xe132;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
+<glyph unicode="&#xe133;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
+<glyph unicode="&#xe134;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe135;" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
+<glyph unicode="&#xe136;" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
+<glyph unicode="&#xe138;" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
+<glyph unicode="&#xe139;" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
+<glyph unicode="&#xe140;" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
+<glyph unicode="&#xe141;" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
+<glyph unicode="&#xe142;" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
+<glyph unicode="&#xe143;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
+<glyph unicode="&#xe144;" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
+<glyph unicode="&#xe145;" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
+<glyph unicode="&#xe146;" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
+<glyph unicode="&#xe148;" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
+<glyph unicode="&#xe149;" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
+<glyph unicode="&#xe150;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe151;" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
+<glyph unicode="&#xe152;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
+<glyph unicode="&#xe153;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
+<glyph unicode="&#xe154;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
+<glyph unicode="&#xe155;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
+<glyph unicode="&#xe156;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
+<glyph unicode="&#xe157;" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
+<glyph unicode="&#xe158;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="&#xe159;" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
+<glyph unicode="&#xe160;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
+<glyph unicode="&#xe161;" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="&#xe162;" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
+<glyph unicode="&#xe163;" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="&#xe164;" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
+<glyph unicode="&#xe165;" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
+<glyph unicode="&#xe166;" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe167;" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe168;" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
+<glyph unicode="&#xe169;" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe170;" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe171;" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
+<glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
+<glyph unicode="&#xe173;" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe174;" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
+<glyph unicode="&#xe175;" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe176;" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe177;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
+<glyph unicode="&#xe178;" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
+<glyph unicode="&#xe179;" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
+<glyph unicode="&#xe180;" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
+<glyph unicode="&#xe181;" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
+<glyph unicode="&#xe182;" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
+<glyph unicode="&#xe183;" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
+<glyph unicode="&#xe184;" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe185;" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
+<glyph unicode="&#xe186;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="&#xe187;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="&#xe188;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
+<glyph unicode="&#xe189;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
+<glyph unicode="&#xe190;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
+<glyph unicode="&#xe191;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
+<glyph unicode="&#xe192;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
+<glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
+<glyph unicode="&#xe194;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
+<glyph unicode="&#xe195;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
+<glyph unicode="&#xe197;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe198;" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
+<glyph unicode="&#xe199;" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
+<glyph unicode="&#xe200;" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
+<glyph unicode="&#xe201;" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
+<glyph unicode="&#xe202;" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
+<glyph unicode="&#xe203;" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
+<glyph unicode="&#xe204;" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
+<glyph unicode="&#xe205;" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="&#xe206;" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="&#xe209;" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
+<glyph unicode="&#xe210;" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe211;" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe212;" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe213;" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe214;" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe215;" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe216;" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
+<glyph unicode="&#xe218;" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
+<glyph unicode="&#xe219;" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
+<glyph unicode="&#xe221;" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe223;" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
+<glyph unicode="&#xe224;" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
+<glyph unicode="&#xe225;" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe226;" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
+<glyph unicode="&#xe227;" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
+<glyph unicode="&#xe230;" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
+<glyph unicode="&#xe231;" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="&#xe232;" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="&#xe233;" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
+<glyph unicode="&#xe234;" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="&#xe235;" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="&#xe236;" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe237;" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
+<glyph unicode="&#xe238;" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe239;" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
+<glyph unicode="&#xe240;" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
+<glyph unicode="&#xe241;" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
+<glyph unicode="&#xe242;" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe243;" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
+<glyph unicode="&#xe244;" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
+<glyph unicode="&#xe245;" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
+<glyph unicode="&#xe246;" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
+<glyph unicode="&#xe247;" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe248;" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
+<glyph unicode="&#xe249;" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe250;" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
+<glyph unicode="&#xe251;" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
+<glyph unicode="&#xe252;" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
+<glyph unicode="&#xe253;" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
+<glyph unicode="&#xe254;" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
+<glyph unicode="&#xe255;" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
+<glyph unicode="&#xe256;" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
+<glyph unicode="&#xe257;" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
+<glyph unicode="&#xe258;" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
+<glyph unicode="&#xe259;" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
+<glyph unicode="&#xe260;" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
+<glyph unicode="&#xf8ff;" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
+<glyph unicode="&#x1f511;" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
+<glyph unicode="&#x1f6aa;" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/header.html b/library/cpp/lwtrace/mon/static/header.html
index 9a263673d3..52352eced8 100644
--- a/library/cpp/lwtrace/mon/static/header.html
+++ b/library/cpp/lwtrace/mon/static/header.html
@@ -1,11 +1,11 @@
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-
-<link rel="stylesheet" href="lwtrace/mon/static/css/bootstrap.min.css">
-<link rel="stylesheet" href="lwtrace/mon/static/css/jquery.treegrid.css">
-<link rel="stylesheet" href="lwtrace/mon/static/common.css">
-
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/bootstrap.min.js"></script>
-<script language="javascript" type="text/javascript" src="lwtrace/mon/static/common.js"></script>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<link rel="stylesheet" href="lwtrace/mon/static/css/bootstrap.min.css">
+<link rel="stylesheet" href="lwtrace/mon/static/css/jquery.treegrid.css">
+<link rel="stylesheet" href="lwtrace/mon/static/common.css">
+
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/js/bootstrap.min.js"></script>
+<script language="javascript" type="text/javascript" src="lwtrace/mon/static/common.js"></script>
diff --git a/library/cpp/lwtrace/mon/static/js/bootstrap.min.js b/library/cpp/lwtrace/mon/static/js/bootstrap.min.js
index 80e40418f2..175d50353d 100644
--- a/library/cpp/lwtrace/mon/static/js/bootstrap.min.js
+++ b/library/cpp/lwtrace/mon/static/js/bootstrap.min.js
@@ -1,9 +1,9 @@
-/*!
- * Bootstrap v3.0.2 by @fat and @mdo
- * Copyright 2013 Twitter, Inc.
- * Licensed under http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world by @mdo and @fat.
- */
-
-if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("dropdown");d||c.data("dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;if("top"==b&&j!=f&&(c=!0,a.top=a.top+f-j),/bottom|top/.test(b)){var k=0;a.left<0&&(k=-2*a.left,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach()}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.$element.trigger("hidden.bs."+this.type),this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);
+/*!
+ * Bootstrap v3.0.2 by @fat and @mdo
+ * Copyright 2013 Twitter, Inc.
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world by @mdo and @fat.
+ */
+
+if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("dropdown");d||c.data("dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;if("top"==b&&j!=f&&(c=!0,a.top=a.top+f-j),/bottom|top/.test(b)){var k=0;a.left<0&&(k=-2*a.left,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach()}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.$element.trigger("hidden.bs."+this.type),this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);
diff --git a/library/cpp/lwtrace/mon/static/js/d3-gantt.js b/library/cpp/lwtrace/mon/static/js/d3-gantt.js
index 54ec38ae57..4e95ad347a 100644
--- a/library/cpp/lwtrace/mon/static/js/d3-gantt.js
+++ b/library/cpp/lwtrace/mon/static/js/d3-gantt.js
@@ -1,759 +1,759 @@
-d3.gantt = function() {
- function gantt(config, logs, autoscale) {
- parseLogs(config, logs);
-
- if (autoscale) {
- gantt.timeDomain([minT, maxT]);
- }
-
- initAxis();
-
- // create svg element
- svg = d3.select(selector)
- .append("svg")
- .attr("class", "chart")
- .attr("width", width + margin.left + margin.right)
- .attr("height", height + margin.top + margin.bottom)
- ;
-
- // create arrowhead marker
- defs = svg.append("defs");
- defs.append("marker")
- .attr("id", "arrow")
- .attr("viewBox", "0 -5 10 10")
- .attr("refX", 5)
- .attr("refY", 0)
- .attr("markerWidth", 4)
- .attr("markerHeight", 4)
- .attr("orient", "auto")
- .append("path")
- .attr("d", "M0,-5L10,0L0,5")
- .attr("class","arrowHead")
- ;
-
- zoom = d3.zoom()
- .scaleExtent([0.1, 1000])
- //.translateExtent([0, 0], [1000,0])
- .on("zoom", function() {
- if (tipShown != null) {
- tip.hide(tipShown);
- }
- var tr = d3.event.transform;
- xZoomed = tr.rescaleX(x);
- svg.select("g.x.axis").call(xAxis.scale(xZoomed));
-
- var dy = d3.event.sourceEvent.screenY - zoom.startScreenY;
- var newScrollTop = documentBodyScrollTop() - dy;
- window.scrollTo(documentBodyScrollLeft(), newScrollTop);
- documentBodyScrollTop(newScrollTop);
- zoom.startScreenY = d3.event.sourceEvent.screenY;
-
- zoomContainer1.attr("transform", "translate(" + tr.x + ",0) scale(" + tr.k + ",1)");
- zoomContainer2.attr("transform", "translate(" + tr.x + ",0) scale(" + tr.k + ",1)");
-
- render();
- })
- .on("start", function() {
- zoom.startScreenY = d3.event.sourceEvent.screenY;
- })
- .on("end", function() {
- })
- ;
-
- svgChartContainer = svg.append('g')
- .attr("transform", "translate(" + margin.left + ", " + margin.top + ")")
- ;
- svgChart = svgChartContainer.append("svg")
- .attr("top", 0)
- .attr("left", 0)
- .attr("width", width)
- .attr("height", height)
- .attr("viewBox", "0 0 " + width + " " + height)
- ;
-
- zoomContainer1 = svgChart.append("g");
-
- zoomPanel = svgChart.append("rect")
- .attr("class", "zoom-panel")
- .attr("width", width)
- .attr("height", height)
- .call(zoom)
- ;
-
- zoomContainer2 = svgChart.append("g");
- bandsSvg = zoomContainer2.append("g");
-
- // tooltips for bands
- var maxTipHeight = 130;
- const tipDirection = d => y(d.band) - maxTipHeight < documentBodyScrollTop()? 's': 'n';
- tip = d3.tip()
- .attr("class", "d3-tip")
- .offset(function(d) {
- // compute x to return tip in chart region
- var t0 = (d.t1 + d.t2) / 2;
- var t1 = Math.min(Math.max(t0, xZoomed.invert(0)), xZoomed.invert(width));
- var dir = tipDirection(d);
- return [dir === 'n'? -10 : 10, xZoomed(t1) - xZoomed(t0)];
- })
- .direction(tipDirection)
- .html(function(d) {
- let text = '';
- for (let item of d.record) {
- text += probes[item[PROBEID]].provider + "." + probes[item[PROBEID]].name + "(";
- let first = true;
- for (let [param, value] of Object.entries(item[PARAMS])) {
- text += (first? "": ", ") + param + "='" + value + "'";
- first = false;
- }
- text += ")\n";
- }
- return "<pre>" + text + "</pre>";
- })
- ;
-
- bandsSvg.call(tip);
-
- render();
-
- // container for non-zoomable elements
- fixedContainer = svg.append("g")
- .attr("transform", "translate(" + margin.left + ", " + margin.top + ")")
- ;
-
- // create x axis
- fixedContainer.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0, " + (height - margin.top - margin.bottom) + ")")
- .transition()
- .call(xAxis)
- ;
-
- // create y axis
- fixedContainer.append("g")
- .attr("class", "y axis")
- .transition()
- .call(yAxis)
- ;
-
- // make y axis ticks draggable
- var ytickdrag = d3.drag()
- .on("drag", function(d) {
- var ypos = d3.event.y - margin.top;
- var index = Math.floor((ypos / y.step()));
- index = Math.min(Math.max(index, 0), this.initDomain.length - 1);
- if (index != this.curIndex) {
- var newDomain = [];
- for (var i = 0; i < this.initDomain.length; ++i) {
- newDomain.push(this.initDomain[i]);
- }
- newDomain.splice(this.initIndex, 1);
- newDomain.splice(index, 0, this.initDomain[this.initIndex]);
-
- this.curIndex = index;
- this.curDomain = newDomain;
- y.domain(newDomain);
-
- // rearange y scale and axis
- svg.select("g.y.axis").transition().call(yAxis);
-
- // rearange other stuff
- render(-1, true);
- }
- })
- .on("start", function(d) {
- var ypos = d3.event.y - margin.top;
- this.initIndex = Math.floor((ypos / y.step()));
- this.initDomain = y.domain();
- })
- .on("end", function(d) {
- svg.select("g.y.axis").call(yAxis);
- })
- ;
- svg.selectAll("g.y.axis .tick")
- .call(ytickdrag)
- ;
-
- // right margin
- var rmargin = fixedContainer.append("g")
- .attr("id", "right-margin")
- .attr("transform", "translate(" + width + ", 0)")
- ;
- rmargin.append("rect")
- .attr("x", 0)
- .attr("y", 0)
- .attr("width", 1)
- .attr("height", height - margin.top - margin.bottom)
- ;
-
- // top margin
- var tmargin = fixedContainer.append("g")
- .attr("id", "top-margin")
- .attr("transform", "translate(0, 0)")
- ;
- tmargin.append("rect")
- .attr("x", 0)
- .attr("y", 0)
- .attr("width", width)
- .attr("height", 1)
- ;
-
- // ruler
- ruler = fixedContainer.append("g")
- .attr("id", "ruler")
- .attr("transform", "translate(0, 0)")
- ;
- ruler.append("rect")
- .attr("id", "ruler-line")
- .attr("x", 0)
- .attr("y", 0)
- .attr("width", "1")
- .attr("height", height - margin.top - margin.bottom + 8)
- ;
- ruler.append("rect")
- .attr("id", "bgrect")
- .attr("x", 0)
- .attr("y", 0)
- .attr("width", 0)
- .attr("height", 0)
- .style("fill", "white")
- ;
- ruler.append("text")
- .attr("x", 0)
- .attr("y", height - margin.top - margin.bottom + 16)
- .attr("dy", "0.71em")
- .text("0")
- ;
-
- svg.on('mousemove', function() {
- positionRuler(d3.event.pageX);
- });
-
- // scroll handling
- window.onscroll = function myFunction() {
- documentBodyScrollLeft(document.body.scrollLeft);
- documentBodyScrollTop(document.body.scrollTop);
- var scroll = scrollParams();
-
- svgChartContainer
- .attr("transform", "translate(" + margin.left
- + ", " + (margin.top + scroll.y1) + ")");
- svgChart
- .attr("viewBox", "0 " + scroll.y1 + " " + width + " " + scroll.h)
- .attr("height", scroll.h);
- tmargin
- .attr("transform", "translate(0," + scroll.y1 + ")");
- fixedContainer.select(".x.axis")
- .attr("transform", "translate(0," + scroll.y2 + ")");
- rmargin.select("rect")
- .attr("y", scroll.y1)
- .attr("height", scroll.h);
- ruler.select("#ruler-line")
- .attr("y", scroll.y1)
- .attr("height", scroll.h);
-
- positionRuler();
- }
-
- // render axis
- svg.select("g.x.axis").call(xAxis);
- svg.select("g.y.axis").call(yAxis);
-
- // update to initiale state
- window.onscroll(0);
-
- return gantt;
- }
-
-// private:
-
- var keyFunction = function(d) {
- return d.t1.toString() + d.t2.toString() + d.band.toString();
- }
-
- var bandTransform = function(d) {
- return "translate(" + x(d.t1) + "," + y(d.band) + ")";
- }
-
- var xPixel = function(d) {
- return xZoomed.invert(1) - xZoomed.invert(0);
- }
-
- var render = function(t0, smooth) {
- // Save/restore last t0 value
- if (!arguments.length || t0 == -1) {
- t0 = render.t0;
- }
- render.t0 = t0;
- smooth = smooth || false;
-
- // Create rectangles for bands
- bands = bandsSvg.selectAll("rect.bar")
- .data(data, keyFunction);
- bands.exit().remove();
- bands.enter().append("rect")
- .attr("class", "bar")
- .attr("vector-effect", "non-scaling-stroke")
- .style("fill", d => d.color)
- .on('click', function(d) {
- if (tipShown != d) {
- tipShown = d;
- tip.show(d);
- } else {
- tipShown = null;
- tip.hide(d);
- }
- })
- .merge(bands)
- .transition().duration(smooth? 250: 0)
- .attr("y", 0)
- .attr("transform", bandTransform)
- .attr("height", y.bandwidth())
- .attr("width", d => Math.max(1*xPixel(), x(d.t2) - x(d.t1)))
- ;
-
- var emptyMarker = bandsSvg.selectAll("text")
- .data(data.length == 0? ["no data to show"]: []);
- emptyMarker.exit().remove();
- emptyMarker.enter().append("text")
- .text(d => d)
- ;
- }
-
- function initAxis() {
- x = d3.scaleLinear()
- .domain([timeDomainStart, timeDomainEnd])
- .range([0, width])
- //.clamp(true); // dosn't work with zoom/pan
- xZoomed = x;
- y = d3.scaleBand()
- .domain(Object.values(data).map(d => d.band).sort())
- .rangeRound([0, height - margin.top - margin.bottom])
- .padding(0.5);
- xAxis = d3.axisBottom()
- .scale(x)
- //.tickSubdivide(true)
- .tickSize(8)
- .tickPadding(8);
- yAxis = d3.axisLeft()
- .scale(y)
- .tickSize(0);
- }
-
- // slow function wrapper
- var documentBodyScrollLeft = function(value) {
- if (!arguments.length) {
- if (documentBodyScrollLeft.value === undefined) {
- documentBodyScrollLeft.value = document.body.scrollLeft;
- }
- return documentBodyScrollLeft.value;
- } else {
- documentBodyScrollLeft.value = value;
- }
- }
-
- // slow function wrapper
- var documentBodyScrollTop = function(value) {
- if (!arguments.length) {
- if (!documentBodyScrollTop.value === undefined) {
- documentBodyScrollTop.value = document.body.scrollTop;
- }
- return documentBodyScrollTop.value;
- } else {
- documentBodyScrollTop.value = value;
- }
- }
-
- var scrollParams = function() {
- var y1 = documentBodyScrollTop();
- var y2 = y1 + window.innerHeight - margin.footer;
- y2 = Math.min(y2, height - margin.top - margin.bottom);
- var h = y2 - y1;
- return {
- y1: y1,
- y2: y2,
- h: h
- };
- }
-
- var posTextFormat = d3.format(".1f");
-
- var positionRuler = function(pageX) {
- if (!arguments.length) {
- pageX = positionRuler.pageX || 0;
- } else {
- positionRuler.pageX = pageX;
- }
-
- // x-coordinate
- if (!positionRuler.svgLeft) {
- positionRuler.svgLeft = svg.node().getBoundingClientRect().x;
- }
-
- var xpos = pageX - margin.left + 1 - positionRuler.svgLeft;
- var tpos = xZoomed.invert(xpos);
- tpos = Math.min(Math.max(tpos, xZoomed.invert(0)), xZoomed.invert(width));
- ruler.attr("transform", "translate(" + xZoomed(tpos) + ", 0)");
- var posText = posTextFormat(tpos);
-
- // scroll-related
- var scroll = scrollParams();
-
- var text = ruler.select("text")
- .attr("y", scroll.y2 + 16)
- ;
-
- // getBBox() is very slow, so compute symbol width once
- var xpadding = 5;
- var ypadding = 5;
- if (!positionRuler.bbox) {
- positionRuler.bbox = text.node().getBBox();
- }
-
- text.text(posText);
- var textWidth = 10 * posText.length;
- ruler.select("#bgrect")
- .attr("x", -textWidth/2 - xpadding)
- .attr("y", positionRuler.bbox.y - ypadding)
- .attr("width", textWidth + (xpadding*2))
- .attr("height", positionRuler.bbox.height + (ypadding*2))
- ;
-
- render(tpos);
- }
-
- /*
- * Log Query Language:
- * Data expressions:
- * 1) myparam[0], myparam[-1] // the first and the last myparam in any probe/provider
- * 2) myparam // the first (the same as [0])
- * 3) PROVIDER..myparam // any probe with myparam in PROVIDER
- * 4) MyProbe._elapsedMs // Ms since track begin for the first MyProbe event
- * 5) PROVIDER.MyProbe._sliceUs // Us since previous event in track for the first PROVIDER.MyProbe event
- */
- function compile(query) {
- query = query.replace(/\s/g, "");
- let [compiled, rest] = sum(query);
- if (rest.length != 0) {
- throw "parse error: unexpected expression starting at: '" + query + "'";
- }
- return record => {
- try {
- return compiled(record);
- } catch (e) {
- return null;
- }
- };
-
- function sum(query) {
- let term0;
- if (query[0] == '-') {
- let [term, rest] = product(query.substr(1));
- query = rest;
- term0 = x => -term(x);
- } else {
- let [term, rest] = product(query);
- query = rest;
- term0 = term;
- }
- let terms = [];
- while (query.length > 0) {
- let negate;
- if (query[0] == '+') {
- negate = false;
- } else if (query[0] == '-') {
- negate = true;
- } else {
- break;
- }
- let [term, rest] = product(query.substr(1));
- query = rest;
- terms.push(negate? x => -term(x): term);
- }
- const cast = x => (isNaN(+x)? x: +x);
- return [terms.reduce((a, f) => x => cast(a(x)) + cast(f(x)), term0), query];
- }
-
- function product(query) {
- let [factor0, rest] = parentheses(query);
- query = rest;
- let factors = [];
- while (query.length > 0) {
- let invert;
- if (query[0] == '*') {
- invert = false;
- } else if (query[0] == '/') {
- invert = true;
- } else {
- break;
- }
- let [factor, rest] = parentheses(query.substr(1));
- query = rest;
- factors.push(invert? x => 1 / factor(x): factor);
- }
- return [factors.reduce((a, f) => x => a(x) * f(x), factor0), query];
- }
-
- function parentheses(query) {
- if (query[0] == "(") {
- let [expr, rest] = sum(query.substr(1));
- if (rest[0] != ")") {
- throw "parse error: missing ')' before '" + rest + "'";
- }
- return [expr, rest.substr(1)];
- } else {
- return atom(query);
- }
- }
-
- function atom(query) {
- specialParam = {
- _thrNTime: item => (item[US] - thrNTimeZero) * 1e-6,
- _thrRTime: item => (item[US] - thrRTimeZero) * 1e-6,
- _thrTime: item => item[US] * 1e-6,
- _thrNTimeMs: item => (item[US] - thrNTimeZero) * 1e-3,
- _thrRTimeMs: item => (item[US] - thrRTimeZero) * 1e-3,
- _thrTimeMs: item => item[US] * 1e-3,
- _thrNTimeUs: item => item[US] - thrNTimeZero,
- _thrRTimeUs: item => item[US] - thrRTimeZero,
- _thrTimeUs: item => item[US],
- _thrNTimeNs: item => (item[US] - thrNTimeZero) * 1e+3,
- _thrRTimeNs: item => (item[US] - thrRTimeZero) * 1e+3,
- _thrTimeNs: item => item[US] * 1e+3,
- _thread: item => item[THREAD],
- };
- var match;
- if (match = query.match(/^\d+(\.\d+)?/)) { // number literals
- let literal = match[0];
- return [record => literal, query.substr(match[0].length)];
- } else if (match = query.match(/^#[0-9a-fA-F]+/)) { // color literals
- let literal = match[0];
- return [record => literal, query.substr(match[0].length)];
- } else if (match = query.match(/^'(.*)'/)) { // string literal
- let literal = match[1].replace(/\\'/, "'").replace(/\\\\/, "\\");
- return [record => literal, query.substr(match[0].length)];
- } else if (match = query.match(/^(?:(?:(\w+)\.)?(\w*)\.)?(\w+)(?:\[(-?\d+)\])?/)) {
- let provider = match[1] || "";
- let probe = match[2] || "";
- let param = match[3];
- let index = +(match[4] || 0);
- let probeId = new Set();
- for (let id = 0; id < probes.length; id++) {
- if ((!probe || probes[id].name == probe) &&
- (!provider || probes[id].provider == provider))
- {
- probeId.add(id);
- }
- }
- let isSpecial = specialParam.hasOwnProperty(param);
- return [record => {
- let end = index >= 0? record.length: -1;
- let step = index >= 0? 1: -1;
- let skip = index >= 0? index: -index - 1;
- for (let i = index >= 0? 0: record.length - 1; i != end; i += step) {
- let item = record[i];
- if (probeId.has(item[PROBEID]) && (isSpecial || item[PARAMS].hasOwnProperty(param))) {
- if (skip == 0) {
- return isSpecial? specialParam[param](item): item[PARAMS][param];
- } else {
- skip--;
- }
- }
- }
- throw "no data";
- }, query.substr(match[0].length)];
- } else {
- throw "parse error: invalid expression starting at '" + query + "'";
- }
- }
- }
-
- // ex1: "linear().domain([-1, 0, 1]).range(['red', 'white', 'green'])",
- // ex2: "ordinal().domain(['a1', 'a2']).range(['blue', 'yellow'])"
- function parseScale(query) {
- query = query.replaceAll("'","\"");
- var match, scale;
- if (match = query.match(/^linear\(\)/)) {
- scale = d3.scaleLinear();
- } else if (match = query.match(/^pow\(\)/)) {
- scale = d3.scalePow();
- } else if (match = query.match(/^log\(\)/)) {
- scale = d3.scaleLog();
- } else if (match = query.match(/^identity\(\)/)) {
- scale = d3.scaleIdentity();
- } else if (match = query.match(/^time\(\)/)) {
- scale = d3.scaleTime();
- } else if (match = query.match(/^threshold\(\)/)) {
- scale = d3.scaleThreshold();
- } else if (match = query.match(/^ordinal\(\)/)) {
- scale = d3.scaleOrdinal();
- } else {
- throw "Unable to parse scale: " + query;
- }
- if (match = query.match(/\.domain\(([^\)]+)\)/)) {
- scale.domain(JSON.parse(match[1]));
- }
- if (match = query.match(/\.range\(([^\)]+)\)/)) {
- scale.range(JSON.parse(match[1]));
- }
- if (match = query.match(/\.unknown\(([^\)]+)\)/)) {
- scale.unknown(JSON.parse(match[1]));
- }
- return scale;
- }
-
- function parseLogs(config, logs) {
- data = [];
- probes = logs.probes;
- if (config.hasOwnProperty('scales'))
- for (let [name, text] of Object.entries(config.scales)) {
- scales[name] = parseScale(text);
- }
- // Compute aggregates
- let minUs = new Map();
- for (record of logs.depot) {
- if (record.length > 0) {
- let item = record[0];
- let us = item[US];
- let thread = item[US];
- if (!minUs.has(thread)) {
- minUs.set(thread, us);
- } else {
- minUs.set(thread, Math.min(us, minUs.get(thread)));
- }
- }
- }
- thrNTimeZero = Number.MAX_VALUE;
- thrRTimeZero = 0;
- for (let [thread, us] of minUs) {
- thrNTimeZero = Math.min(thrNTimeZero, us);
- thrRTimeZero = Math.max(thrRTimeZero, us);
- }
- // Comple data for bands
- for (let bandCfg of config.bands) {
- function applyScale(func, scaleName) {
- if (scaleName) {
- let scale = scales[scaleName];
- return (record) => {
- let value = func(record);
- if (value != null) {
- value = scale(value);
- }
- return value;
- };
- } else {
- return func;
- }
- }
- let t1f = applyScale(compile(bandCfg.t1), bandCfg.t1Scale);
- let t2f = applyScale(compile(bandCfg.t2), bandCfg.t2Scale);
- let bandf = applyScale(compile(bandCfg.band), bandCfg.bandScale);
- let colorf = applyScale(compile(bandCfg.color), bandCfg.colorScale);
- let minTime = Number.MAX_VALUE;
- let maxTime = -Number.MAX_VALUE;
- for (record of logs.depot) {
- let t1 = t1f(record),
- t2 = t2f(record),
- band = bandf(record),
- color = colorf(record)
- ;
- if (t1 != null && t2 != null && band != null && color != null) {
- data.push({t1, t2, band, color, record});
- minTime = Math.min(minTime, t1);
- maxTime = Math.max(maxTime, t2);
- }
- }
- if (minTime != Number.MAX_VALUE) {
- minT = minTime;
- maxT = maxTime;
- }
- }
- }
-
-// public:
-
- gantt.width = function(value) {
- if (!arguments.length)
- return width;
- width = +value;
- return gantt;
- }
-
- gantt.height = function(value) {
- if (!arguments.length)
- return height;
- height = +value;
- return gantt;
- }
-
- gantt.selector = function(value) {
- if (!arguments.length)
- return selector;
- selector = value;
- return gantt;
- }
-
- gantt.timeDomain = function(value) {
- if (!arguments.length)
- return [timeDomainStart, timeDomainEnd];
- timeDomainStart = value[0];
- timeDomainEnd = value[1];
- return gantt;
- }
-
- gantt.data = function() {
- return data;
- }
-
- // constructor
-
- // Log Format
- const
- THREAD = 0,
- US = 1,
- PROBEID = 2,
- PARAMS = 3
- ;
-
- // Config
- var margin = { top: 20, right: 40, bottom: 20, left: 100, footer: 100 },
- height = document.body.clientHeight - margin.top - margin.bottom - 5,
- width = document.body.clientWidth - margin.right - margin.left - 5,
- selector = 'body',
- timeDomainStart = 0,
- timeDomainEnd = 1000,
- scales = {};
- ;
-
- // View
- var x = null,
- xZoomed = null,
- y = null,
- xAxis = null,
- yAxis = null,
- svg = null,
- defs = null,
- svgChartContainer = null,
- svgChart = null,
- zoomPanel = null,
- zoomContainer1 = null,
- zoomContainer2 = null,
- fixedContainer = null,
- zoom = null,
- bandsSvg = null,
- bands = null,
- tip = null,
- tipShown = null,
- ruler = null
- ;
-
- // Model
- var data = null,
- probes = null,
- thrRTimeZero = 0,
- thrNTimeZero = 0,
- minT,
- maxT
- ;
-
- return gantt;
-} \ No newline at end of file
+d3.gantt = function() {
+ function gantt(config, logs, autoscale) {
+ parseLogs(config, logs);
+
+ if (autoscale) {
+ gantt.timeDomain([minT, maxT]);
+ }
+
+ initAxis();
+
+ // create svg element
+ svg = d3.select(selector)
+ .append("svg")
+ .attr("class", "chart")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ ;
+
+ // create arrowhead marker
+ defs = svg.append("defs");
+ defs.append("marker")
+ .attr("id", "arrow")
+ .attr("viewBox", "0 -5 10 10")
+ .attr("refX", 5)
+ .attr("refY", 0)
+ .attr("markerWidth", 4)
+ .attr("markerHeight", 4)
+ .attr("orient", "auto")
+ .append("path")
+ .attr("d", "M0,-5L10,0L0,5")
+ .attr("class","arrowHead")
+ ;
+
+ zoom = d3.zoom()
+ .scaleExtent([0.1, 1000])
+ //.translateExtent([0, 0], [1000,0])
+ .on("zoom", function() {
+ if (tipShown != null) {
+ tip.hide(tipShown);
+ }
+ var tr = d3.event.transform;
+ xZoomed = tr.rescaleX(x);
+ svg.select("g.x.axis").call(xAxis.scale(xZoomed));
+
+ var dy = d3.event.sourceEvent.screenY - zoom.startScreenY;
+ var newScrollTop = documentBodyScrollTop() - dy;
+ window.scrollTo(documentBodyScrollLeft(), newScrollTop);
+ documentBodyScrollTop(newScrollTop);
+ zoom.startScreenY = d3.event.sourceEvent.screenY;
+
+ zoomContainer1.attr("transform", "translate(" + tr.x + ",0) scale(" + tr.k + ",1)");
+ zoomContainer2.attr("transform", "translate(" + tr.x + ",0) scale(" + tr.k + ",1)");
+
+ render();
+ })
+ .on("start", function() {
+ zoom.startScreenY = d3.event.sourceEvent.screenY;
+ })
+ .on("end", function() {
+ })
+ ;
+
+ svgChartContainer = svg.append('g')
+ .attr("transform", "translate(" + margin.left + ", " + margin.top + ")")
+ ;
+ svgChart = svgChartContainer.append("svg")
+ .attr("top", 0)
+ .attr("left", 0)
+ .attr("width", width)
+ .attr("height", height)
+ .attr("viewBox", "0 0 " + width + " " + height)
+ ;
+
+ zoomContainer1 = svgChart.append("g");
+
+ zoomPanel = svgChart.append("rect")
+ .attr("class", "zoom-panel")
+ .attr("width", width)
+ .attr("height", height)
+ .call(zoom)
+ ;
+
+ zoomContainer2 = svgChart.append("g");
+ bandsSvg = zoomContainer2.append("g");
+
+ // tooltips for bands
+ var maxTipHeight = 130;
+ const tipDirection = d => y(d.band) - maxTipHeight < documentBodyScrollTop()? 's': 'n';
+ tip = d3.tip()
+ .attr("class", "d3-tip")
+ .offset(function(d) {
+ // compute x to return tip in chart region
+ var t0 = (d.t1 + d.t2) / 2;
+ var t1 = Math.min(Math.max(t0, xZoomed.invert(0)), xZoomed.invert(width));
+ var dir = tipDirection(d);
+ return [dir === 'n'? -10 : 10, xZoomed(t1) - xZoomed(t0)];
+ })
+ .direction(tipDirection)
+ .html(function(d) {
+ let text = '';
+ for (let item of d.record) {
+ text += probes[item[PROBEID]].provider + "." + probes[item[PROBEID]].name + "(";
+ let first = true;
+ for (let [param, value] of Object.entries(item[PARAMS])) {
+ text += (first? "": ", ") + param + "='" + value + "'";
+ first = false;
+ }
+ text += ")\n";
+ }
+ return "<pre>" + text + "</pre>";
+ })
+ ;
+
+ bandsSvg.call(tip);
+
+ render();
+
+ // container for non-zoomable elements
+ fixedContainer = svg.append("g")
+ .attr("transform", "translate(" + margin.left + ", " + margin.top + ")")
+ ;
+
+ // create x axis
+ fixedContainer.append("g")
+ .attr("class", "x axis")
+ .attr("transform", "translate(0, " + (height - margin.top - margin.bottom) + ")")
+ .transition()
+ .call(xAxis)
+ ;
+
+ // create y axis
+ fixedContainer.append("g")
+ .attr("class", "y axis")
+ .transition()
+ .call(yAxis)
+ ;
+
+ // make y axis ticks draggable
+ var ytickdrag = d3.drag()
+ .on("drag", function(d) {
+ var ypos = d3.event.y - margin.top;
+ var index = Math.floor((ypos / y.step()));
+ index = Math.min(Math.max(index, 0), this.initDomain.length - 1);
+ if (index != this.curIndex) {
+ var newDomain = [];
+ for (var i = 0; i < this.initDomain.length; ++i) {
+ newDomain.push(this.initDomain[i]);
+ }
+ newDomain.splice(this.initIndex, 1);
+ newDomain.splice(index, 0, this.initDomain[this.initIndex]);
+
+ this.curIndex = index;
+ this.curDomain = newDomain;
+ y.domain(newDomain);
+
+ // rearange y scale and axis
+ svg.select("g.y.axis").transition().call(yAxis);
+
+ // rearange other stuff
+ render(-1, true);
+ }
+ })
+ .on("start", function(d) {
+ var ypos = d3.event.y - margin.top;
+ this.initIndex = Math.floor((ypos / y.step()));
+ this.initDomain = y.domain();
+ })
+ .on("end", function(d) {
+ svg.select("g.y.axis").call(yAxis);
+ })
+ ;
+ svg.selectAll("g.y.axis .tick")
+ .call(ytickdrag)
+ ;
+
+ // right margin
+ var rmargin = fixedContainer.append("g")
+ .attr("id", "right-margin")
+ .attr("transform", "translate(" + width + ", 0)")
+ ;
+ rmargin.append("rect")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("width", 1)
+ .attr("height", height - margin.top - margin.bottom)
+ ;
+
+ // top margin
+ var tmargin = fixedContainer.append("g")
+ .attr("id", "top-margin")
+ .attr("transform", "translate(0, 0)")
+ ;
+ tmargin.append("rect")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("width", width)
+ .attr("height", 1)
+ ;
+
+ // ruler
+ ruler = fixedContainer.append("g")
+ .attr("id", "ruler")
+ .attr("transform", "translate(0, 0)")
+ ;
+ ruler.append("rect")
+ .attr("id", "ruler-line")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("width", "1")
+ .attr("height", height - margin.top - margin.bottom + 8)
+ ;
+ ruler.append("rect")
+ .attr("id", "bgrect")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("width", 0)
+ .attr("height", 0)
+ .style("fill", "white")
+ ;
+ ruler.append("text")
+ .attr("x", 0)
+ .attr("y", height - margin.top - margin.bottom + 16)
+ .attr("dy", "0.71em")
+ .text("0")
+ ;
+
+ svg.on('mousemove', function() {
+ positionRuler(d3.event.pageX);
+ });
+
+ // scroll handling
+ window.onscroll = function myFunction() {
+ documentBodyScrollLeft(document.body.scrollLeft);
+ documentBodyScrollTop(document.body.scrollTop);
+ var scroll = scrollParams();
+
+ svgChartContainer
+ .attr("transform", "translate(" + margin.left
+ + ", " + (margin.top + scroll.y1) + ")");
+ svgChart
+ .attr("viewBox", "0 " + scroll.y1 + " " + width + " " + scroll.h)
+ .attr("height", scroll.h);
+ tmargin
+ .attr("transform", "translate(0," + scroll.y1 + ")");
+ fixedContainer.select(".x.axis")
+ .attr("transform", "translate(0," + scroll.y2 + ")");
+ rmargin.select("rect")
+ .attr("y", scroll.y1)
+ .attr("height", scroll.h);
+ ruler.select("#ruler-line")
+ .attr("y", scroll.y1)
+ .attr("height", scroll.h);
+
+ positionRuler();
+ }
+
+ // render axis
+ svg.select("g.x.axis").call(xAxis);
+ svg.select("g.y.axis").call(yAxis);
+
+ // update to initiale state
+ window.onscroll(0);
+
+ return gantt;
+ }
+
+// private:
+
+ var keyFunction = function(d) {
+ return d.t1.toString() + d.t2.toString() + d.band.toString();
+ }
+
+ var bandTransform = function(d) {
+ return "translate(" + x(d.t1) + "," + y(d.band) + ")";
+ }
+
+ var xPixel = function(d) {
+ return xZoomed.invert(1) - xZoomed.invert(0);
+ }
+
+ var render = function(t0, smooth) {
+ // Save/restore last t0 value
+ if (!arguments.length || t0 == -1) {
+ t0 = render.t0;
+ }
+ render.t0 = t0;
+ smooth = smooth || false;
+
+ // Create rectangles for bands
+ bands = bandsSvg.selectAll("rect.bar")
+ .data(data, keyFunction);
+ bands.exit().remove();
+ bands.enter().append("rect")
+ .attr("class", "bar")
+ .attr("vector-effect", "non-scaling-stroke")
+ .style("fill", d => d.color)
+ .on('click', function(d) {
+ if (tipShown != d) {
+ tipShown = d;
+ tip.show(d);
+ } else {
+ tipShown = null;
+ tip.hide(d);
+ }
+ })
+ .merge(bands)
+ .transition().duration(smooth? 250: 0)
+ .attr("y", 0)
+ .attr("transform", bandTransform)
+ .attr("height", y.bandwidth())
+ .attr("width", d => Math.max(1*xPixel(), x(d.t2) - x(d.t1)))
+ ;
+
+ var emptyMarker = bandsSvg.selectAll("text")
+ .data(data.length == 0? ["no data to show"]: []);
+ emptyMarker.exit().remove();
+ emptyMarker.enter().append("text")
+ .text(d => d)
+ ;
+ }
+
+ function initAxis() {
+ x = d3.scaleLinear()
+ .domain([timeDomainStart, timeDomainEnd])
+ .range([0, width])
+ //.clamp(true); // dosn't work with zoom/pan
+ xZoomed = x;
+ y = d3.scaleBand()
+ .domain(Object.values(data).map(d => d.band).sort())
+ .rangeRound([0, height - margin.top - margin.bottom])
+ .padding(0.5);
+ xAxis = d3.axisBottom()
+ .scale(x)
+ //.tickSubdivide(true)
+ .tickSize(8)
+ .tickPadding(8);
+ yAxis = d3.axisLeft()
+ .scale(y)
+ .tickSize(0);
+ }
+
+ // slow function wrapper
+ var documentBodyScrollLeft = function(value) {
+ if (!arguments.length) {
+ if (documentBodyScrollLeft.value === undefined) {
+ documentBodyScrollLeft.value = document.body.scrollLeft;
+ }
+ return documentBodyScrollLeft.value;
+ } else {
+ documentBodyScrollLeft.value = value;
+ }
+ }
+
+ // slow function wrapper
+ var documentBodyScrollTop = function(value) {
+ if (!arguments.length) {
+ if (!documentBodyScrollTop.value === undefined) {
+ documentBodyScrollTop.value = document.body.scrollTop;
+ }
+ return documentBodyScrollTop.value;
+ } else {
+ documentBodyScrollTop.value = value;
+ }
+ }
+
+ var scrollParams = function() {
+ var y1 = documentBodyScrollTop();
+ var y2 = y1 + window.innerHeight - margin.footer;
+ y2 = Math.min(y2, height - margin.top - margin.bottom);
+ var h = y2 - y1;
+ return {
+ y1: y1,
+ y2: y2,
+ h: h
+ };
+ }
+
+ var posTextFormat = d3.format(".1f");
+
+ var positionRuler = function(pageX) {
+ if (!arguments.length) {
+ pageX = positionRuler.pageX || 0;
+ } else {
+ positionRuler.pageX = pageX;
+ }
+
+ // x-coordinate
+ if (!positionRuler.svgLeft) {
+ positionRuler.svgLeft = svg.node().getBoundingClientRect().x;
+ }
+
+ var xpos = pageX - margin.left + 1 - positionRuler.svgLeft;
+ var tpos = xZoomed.invert(xpos);
+ tpos = Math.min(Math.max(tpos, xZoomed.invert(0)), xZoomed.invert(width));
+ ruler.attr("transform", "translate(" + xZoomed(tpos) + ", 0)");
+ var posText = posTextFormat(tpos);
+
+ // scroll-related
+ var scroll = scrollParams();
+
+ var text = ruler.select("text")
+ .attr("y", scroll.y2 + 16)
+ ;
+
+ // getBBox() is very slow, so compute symbol width once
+ var xpadding = 5;
+ var ypadding = 5;
+ if (!positionRuler.bbox) {
+ positionRuler.bbox = text.node().getBBox();
+ }
+
+ text.text(posText);
+ var textWidth = 10 * posText.length;
+ ruler.select("#bgrect")
+ .attr("x", -textWidth/2 - xpadding)
+ .attr("y", positionRuler.bbox.y - ypadding)
+ .attr("width", textWidth + (xpadding*2))
+ .attr("height", positionRuler.bbox.height + (ypadding*2))
+ ;
+
+ render(tpos);
+ }
+
+ /*
+ * Log Query Language:
+ * Data expressions:
+ * 1) myparam[0], myparam[-1] // the first and the last myparam in any probe/provider
+ * 2) myparam // the first (the same as [0])
+ * 3) PROVIDER..myparam // any probe with myparam in PROVIDER
+ * 4) MyProbe._elapsedMs // Ms since track begin for the first MyProbe event
+ * 5) PROVIDER.MyProbe._sliceUs // Us since previous event in track for the first PROVIDER.MyProbe event
+ */
+ function compile(query) {
+ query = query.replace(/\s/g, "");
+ let [compiled, rest] = sum(query);
+ if (rest.length != 0) {
+ throw "parse error: unexpected expression starting at: '" + query + "'";
+ }
+ return record => {
+ try {
+ return compiled(record);
+ } catch (e) {
+ return null;
+ }
+ };
+
+ function sum(query) {
+ let term0;
+ if (query[0] == '-') {
+ let [term, rest] = product(query.substr(1));
+ query = rest;
+ term0 = x => -term(x);
+ } else {
+ let [term, rest] = product(query);
+ query = rest;
+ term0 = term;
+ }
+ let terms = [];
+ while (query.length > 0) {
+ let negate;
+ if (query[0] == '+') {
+ negate = false;
+ } else if (query[0] == '-') {
+ negate = true;
+ } else {
+ break;
+ }
+ let [term, rest] = product(query.substr(1));
+ query = rest;
+ terms.push(negate? x => -term(x): term);
+ }
+ const cast = x => (isNaN(+x)? x: +x);
+ return [terms.reduce((a, f) => x => cast(a(x)) + cast(f(x)), term0), query];
+ }
+
+ function product(query) {
+ let [factor0, rest] = parentheses(query);
+ query = rest;
+ let factors = [];
+ while (query.length > 0) {
+ let invert;
+ if (query[0] == '*') {
+ invert = false;
+ } else if (query[0] == '/') {
+ invert = true;
+ } else {
+ break;
+ }
+ let [factor, rest] = parentheses(query.substr(1));
+ query = rest;
+ factors.push(invert? x => 1 / factor(x): factor);
+ }
+ return [factors.reduce((a, f) => x => a(x) * f(x), factor0), query];
+ }
+
+ function parentheses(query) {
+ if (query[0] == "(") {
+ let [expr, rest] = sum(query.substr(1));
+ if (rest[0] != ")") {
+ throw "parse error: missing ')' before '" + rest + "'";
+ }
+ return [expr, rest.substr(1)];
+ } else {
+ return atom(query);
+ }
+ }
+
+ function atom(query) {
+ specialParam = {
+ _thrNTime: item => (item[US] - thrNTimeZero) * 1e-6,
+ _thrRTime: item => (item[US] - thrRTimeZero) * 1e-6,
+ _thrTime: item => item[US] * 1e-6,
+ _thrNTimeMs: item => (item[US] - thrNTimeZero) * 1e-3,
+ _thrRTimeMs: item => (item[US] - thrRTimeZero) * 1e-3,
+ _thrTimeMs: item => item[US] * 1e-3,
+ _thrNTimeUs: item => item[US] - thrNTimeZero,
+ _thrRTimeUs: item => item[US] - thrRTimeZero,
+ _thrTimeUs: item => item[US],
+ _thrNTimeNs: item => (item[US] - thrNTimeZero) * 1e+3,
+ _thrRTimeNs: item => (item[US] - thrRTimeZero) * 1e+3,
+ _thrTimeNs: item => item[US] * 1e+3,
+ _thread: item => item[THREAD],
+ };
+ var match;
+ if (match = query.match(/^\d+(\.\d+)?/)) { // number literals
+ let literal = match[0];
+ return [record => literal, query.substr(match[0].length)];
+ } else if (match = query.match(/^#[0-9a-fA-F]+/)) { // color literals
+ let literal = match[0];
+ return [record => literal, query.substr(match[0].length)];
+ } else if (match = query.match(/^'(.*)'/)) { // string literal
+ let literal = match[1].replace(/\\'/, "'").replace(/\\\\/, "\\");
+ return [record => literal, query.substr(match[0].length)];
+ } else if (match = query.match(/^(?:(?:(\w+)\.)?(\w*)\.)?(\w+)(?:\[(-?\d+)\])?/)) {
+ let provider = match[1] || "";
+ let probe = match[2] || "";
+ let param = match[3];
+ let index = +(match[4] || 0);
+ let probeId = new Set();
+ for (let id = 0; id < probes.length; id++) {
+ if ((!probe || probes[id].name == probe) &&
+ (!provider || probes[id].provider == provider))
+ {
+ probeId.add(id);
+ }
+ }
+ let isSpecial = specialParam.hasOwnProperty(param);
+ return [record => {
+ let end = index >= 0? record.length: -1;
+ let step = index >= 0? 1: -1;
+ let skip = index >= 0? index: -index - 1;
+ for (let i = index >= 0? 0: record.length - 1; i != end; i += step) {
+ let item = record[i];
+ if (probeId.has(item[PROBEID]) && (isSpecial || item[PARAMS].hasOwnProperty(param))) {
+ if (skip == 0) {
+ return isSpecial? specialParam[param](item): item[PARAMS][param];
+ } else {
+ skip--;
+ }
+ }
+ }
+ throw "no data";
+ }, query.substr(match[0].length)];
+ } else {
+ throw "parse error: invalid expression starting at '" + query + "'";
+ }
+ }
+ }
+
+ // ex1: "linear().domain([-1, 0, 1]).range(['red', 'white', 'green'])",
+ // ex2: "ordinal().domain(['a1', 'a2']).range(['blue', 'yellow'])"
+ function parseScale(query) {
+ query = query.replaceAll("'","\"");
+ var match, scale;
+ if (match = query.match(/^linear\(\)/)) {
+ scale = d3.scaleLinear();
+ } else if (match = query.match(/^pow\(\)/)) {
+ scale = d3.scalePow();
+ } else if (match = query.match(/^log\(\)/)) {
+ scale = d3.scaleLog();
+ } else if (match = query.match(/^identity\(\)/)) {
+ scale = d3.scaleIdentity();
+ } else if (match = query.match(/^time\(\)/)) {
+ scale = d3.scaleTime();
+ } else if (match = query.match(/^threshold\(\)/)) {
+ scale = d3.scaleThreshold();
+ } else if (match = query.match(/^ordinal\(\)/)) {
+ scale = d3.scaleOrdinal();
+ } else {
+ throw "Unable to parse scale: " + query;
+ }
+ if (match = query.match(/\.domain\(([^\)]+)\)/)) {
+ scale.domain(JSON.parse(match[1]));
+ }
+ if (match = query.match(/\.range\(([^\)]+)\)/)) {
+ scale.range(JSON.parse(match[1]));
+ }
+ if (match = query.match(/\.unknown\(([^\)]+)\)/)) {
+ scale.unknown(JSON.parse(match[1]));
+ }
+ return scale;
+ }
+
+ function parseLogs(config, logs) {
+ data = [];
+ probes = logs.probes;
+ if (config.hasOwnProperty('scales'))
+ for (let [name, text] of Object.entries(config.scales)) {
+ scales[name] = parseScale(text);
+ }
+ // Compute aggregates
+ let minUs = new Map();
+ for (record of logs.depot) {
+ if (record.length > 0) {
+ let item = record[0];
+ let us = item[US];
+ let thread = item[US];
+ if (!minUs.has(thread)) {
+ minUs.set(thread, us);
+ } else {
+ minUs.set(thread, Math.min(us, minUs.get(thread)));
+ }
+ }
+ }
+ thrNTimeZero = Number.MAX_VALUE;
+ thrRTimeZero = 0;
+ for (let [thread, us] of minUs) {
+ thrNTimeZero = Math.min(thrNTimeZero, us);
+ thrRTimeZero = Math.max(thrRTimeZero, us);
+ }
+ // Comple data for bands
+ for (let bandCfg of config.bands) {
+ function applyScale(func, scaleName) {
+ if (scaleName) {
+ let scale = scales[scaleName];
+ return (record) => {
+ let value = func(record);
+ if (value != null) {
+ value = scale(value);
+ }
+ return value;
+ };
+ } else {
+ return func;
+ }
+ }
+ let t1f = applyScale(compile(bandCfg.t1), bandCfg.t1Scale);
+ let t2f = applyScale(compile(bandCfg.t2), bandCfg.t2Scale);
+ let bandf = applyScale(compile(bandCfg.band), bandCfg.bandScale);
+ let colorf = applyScale(compile(bandCfg.color), bandCfg.colorScale);
+ let minTime = Number.MAX_VALUE;
+ let maxTime = -Number.MAX_VALUE;
+ for (record of logs.depot) {
+ let t1 = t1f(record),
+ t2 = t2f(record),
+ band = bandf(record),
+ color = colorf(record)
+ ;
+ if (t1 != null && t2 != null && band != null && color != null) {
+ data.push({t1, t2, band, color, record});
+ minTime = Math.min(minTime, t1);
+ maxTime = Math.max(maxTime, t2);
+ }
+ }
+ if (minTime != Number.MAX_VALUE) {
+ minT = minTime;
+ maxT = maxTime;
+ }
+ }
+ }
+
+// public:
+
+ gantt.width = function(value) {
+ if (!arguments.length)
+ return width;
+ width = +value;
+ return gantt;
+ }
+
+ gantt.height = function(value) {
+ if (!arguments.length)
+ return height;
+ height = +value;
+ return gantt;
+ }
+
+ gantt.selector = function(value) {
+ if (!arguments.length)
+ return selector;
+ selector = value;
+ return gantt;
+ }
+
+ gantt.timeDomain = function(value) {
+ if (!arguments.length)
+ return [timeDomainStart, timeDomainEnd];
+ timeDomainStart = value[0];
+ timeDomainEnd = value[1];
+ return gantt;
+ }
+
+ gantt.data = function() {
+ return data;
+ }
+
+ // constructor
+
+ // Log Format
+ const
+ THREAD = 0,
+ US = 1,
+ PROBEID = 2,
+ PARAMS = 3
+ ;
+
+ // Config
+ var margin = { top: 20, right: 40, bottom: 20, left: 100, footer: 100 },
+ height = document.body.clientHeight - margin.top - margin.bottom - 5,
+ width = document.body.clientWidth - margin.right - margin.left - 5,
+ selector = 'body',
+ timeDomainStart = 0,
+ timeDomainEnd = 1000,
+ scales = {};
+ ;
+
+ // View
+ var x = null,
+ xZoomed = null,
+ y = null,
+ xAxis = null,
+ yAxis = null,
+ svg = null,
+ defs = null,
+ svgChartContainer = null,
+ svgChart = null,
+ zoomPanel = null,
+ zoomContainer1 = null,
+ zoomContainer2 = null,
+ fixedContainer = null,
+ zoom = null,
+ bandsSvg = null,
+ bands = null,
+ tip = null,
+ tipShown = null,
+ ruler = null
+ ;
+
+ // Model
+ var data = null,
+ probes = null,
+ thrRTimeZero = 0,
+ thrNTimeZero = 0,
+ minT,
+ maxT
+ ;
+
+ return gantt;
+} \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js b/library/cpp/lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js
index ad3a6c0d19..2b2e61ad4c 100644
--- a/library/cpp/lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js
+++ b/library/cpp/lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js
@@ -1,352 +1,352 @@
-/**
- * d3.tip
- * Copyright (c) 2013 Justin Palmer
- *
- * Tooltips for d3.js SVG visualizations
- */
-// eslint-disable-next-line no-extra-semi
-;(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module with d3 as a dependency.
- define([
- 'd3-collection',
- 'd3-selection'
- ], factory)
- } else if (typeof module === 'object' && module.exports) {
- /* eslint-disable global-require */
- // CommonJS
- var d3Collection = require('d3-collection'),
- d3Selection = require('d3-selection')
- module.exports = factory(d3Collection, d3Selection)
- /* eslint-enable global-require */
- } else {
- // Browser global.
- var d3 = root.d3
- // eslint-disable-next-line no-param-reassign
- root.d3.tip = factory(d3, d3)
- }
-}(this, function(d3Collection, d3Selection) {
- // Public - contructs a new tooltip
- //
- // Returns a tip
- return function() {
- var direction = d3TipDirection,
- offset = d3TipOffset,
- html = d3TipHTML,
- rootElement = document.body,
- node = initNode(),
- svg = null,
- point = null,
- target = null
-
- function tip(vis) {
- svg = getSVGNode(vis)
- if (!svg) return
- point = svg.createSVGPoint()
- rootElement.appendChild(node)
- }
-
- // Public - show the tooltip on the screen
- //
- // Returns a tip
- tip.show = function() {
- var args = Array.prototype.slice.call(arguments)
- if (args[args.length - 1] instanceof SVGElement) target = args.pop()
-
- var content = html.apply(this, args),
- poffset = offset.apply(this, args),
- dir = direction.apply(this, args),
- nodel = getNodeEl(),
- i = directions.length,
- coords,
- scrollTop = document.documentElement.scrollTop ||
- rootElement.scrollTop,
- scrollLeft = document.documentElement.scrollLeft ||
- rootElement.scrollLeft
-
- nodel.html(content)
- .style('opacity', 1).style('pointer-events', 'all')
-
- while (i--) nodel.classed(directions[i], false)
- coords = directionCallbacks.get(dir).apply(this)
- nodel.classed(dir, true)
- .style('top', (coords.top + poffset[0]) + scrollTop + 'px')
- .style('left', (coords.left + poffset[1]) + scrollLeft + 'px')
-
- return tip
- }
-
- // Public - hide the tooltip
- //
- // Returns a tip
- tip.hide = function() {
- var nodel = getNodeEl()
- nodel.style('opacity', 0).style('pointer-events', 'none')
- return tip
- }
-
- // Public: Proxy attr calls to the d3 tip container.
- // Sets or gets attribute value.
- //
- // n - name of the attribute
- // v - value of the attribute
- //
- // Returns tip or attribute value
- // eslint-disable-next-line no-unused-vars
- tip.attr = function(n, v) {
- if (arguments.length < 2 && typeof n === 'string') {
- return getNodeEl().attr(n)
- }
-
- var args = Array.prototype.slice.call(arguments)
- d3Selection.selection.prototype.attr.apply(getNodeEl(), args)
- return tip
- }
-
- // Public: Proxy style calls to the d3 tip container.
- // Sets or gets a style value.
- //
- // n - name of the property
- // v - value of the property
- //
- // Returns tip or style property value
- // eslint-disable-next-line no-unused-vars
- tip.style = function(n, v) {
- if (arguments.length < 2 && typeof n === 'string') {
- return getNodeEl().style(n)
- }
-
- var args = Array.prototype.slice.call(arguments)
- d3Selection.selection.prototype.style.apply(getNodeEl(), args)
- return tip
- }
-
- // Public: Set or get the direction of the tooltip
- //
- // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
- // sw(southwest), ne(northeast) or se(southeast)
- //
- // Returns tip or direction
- tip.direction = function(v) {
- if (!arguments.length) return direction
- direction = v == null ? v : functor(v)
-
- return tip
- }
-
- // Public: Sets or gets the offset of the tip
- //
- // v - Array of [x, y] offset
- //
- // Returns offset or
- tip.offset = function(v) {
- if (!arguments.length) return offset
- offset = v == null ? v : functor(v)
-
- return tip
- }
-
- // Public: sets or gets the html value of the tooltip
- //
- // v - String value of the tip
- //
- // Returns html value or tip
- tip.html = function(v) {
- if (!arguments.length) return html
- html = v == null ? v : functor(v)
-
- return tip
- }
-
- // Public: sets or gets the root element anchor of the tooltip
- //
- // v - root element of the tooltip
- //
- // Returns root node of tip
- tip.rootElement = function(v) {
- if (!arguments.length) return rootElement
- rootElement = v == null ? v : functor(v)
-
- return tip
- }
-
- // Public: destroys the tooltip and removes it from the DOM
- //
- // Returns a tip
- tip.destroy = function() {
- if (node) {
- getNodeEl().remove()
- node = null
- }
- return tip
- }
-
- function d3TipDirection() { return 'n' }
- function d3TipOffset() { return [0, 0] }
- function d3TipHTML() { return ' ' }
-
- var directionCallbacks = d3Collection.map({
- n: directionNorth,
- s: directionSouth,
- e: directionEast,
- w: directionWest,
- nw: directionNorthWest,
- ne: directionNorthEast,
- sw: directionSouthWest,
- se: directionSouthEast
- }),
- directions = directionCallbacks.keys()
-
- function directionNorth() {
- var bbox = getScreenBBox()
- return {
- top: bbox.n.y - node.offsetHeight,
- left: bbox.n.x - node.offsetWidth / 2
- }
- }
-
- function directionSouth() {
- var bbox = getScreenBBox()
- return {
- top: bbox.s.y,
- left: bbox.s.x - node.offsetWidth / 2
- }
- }
-
- function directionEast() {
- var bbox = getScreenBBox()
- return {
- top: bbox.e.y - node.offsetHeight / 2,
- left: bbox.e.x
- }
- }
-
- function directionWest() {
- var bbox = getScreenBBox()
- return {
- top: bbox.w.y - node.offsetHeight / 2,
- left: bbox.w.x - node.offsetWidth
- }
- }
-
- function directionNorthWest() {
- var bbox = getScreenBBox()
- return {
- top: bbox.nw.y - node.offsetHeight,
- left: bbox.nw.x - node.offsetWidth
- }
- }
-
- function directionNorthEast() {
- var bbox = getScreenBBox()
- return {
- top: bbox.ne.y - node.offsetHeight,
- left: bbox.ne.x
- }
- }
-
- function directionSouthWest() {
- var bbox = getScreenBBox()
- return {
- top: bbox.sw.y,
- left: bbox.sw.x - node.offsetWidth
- }
- }
-
- function directionSouthEast() {
- var bbox = getScreenBBox()
- return {
- top: bbox.se.y,
- left: bbox.se.x
- }
- }
-
- function initNode() {
- var div = d3Selection.select(document.createElement('div'))
- div
- .style('position', 'absolute')
- .style('top', 0)
- .style('opacity', 0)
- .style('pointer-events', 'none')
- .style('box-sizing', 'border-box')
-
- return div.node()
- }
-
- function getSVGNode(element) {
- var svgNode = element.node()
- if (!svgNode) return null
- if (svgNode.tagName.toLowerCase() === 'svg') return svgNode
- return svgNode.ownerSVGElement
- }
-
- function getNodeEl() {
- if (node == null) {
- node = initNode()
- // re-add node to DOM
- rootElement.appendChild(node)
- }
- return d3Selection.select(node)
- }
-
- // Private - gets the screen coordinates of a shape
- //
- // Given a shape on the screen, will return an SVGPoint for the directions
- // n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
- // nw(northwest), sw(southwest).
- //
- // +-+-+
- // | |
- // + +
- // | |
- // +-+-+
- //
- // Returns an Object {n, s, e, w, nw, sw, ne, se}
- function getScreenBBox() {
- var targetel = target || d3Selection.event.target
-
- while (targetel.getScreenCTM == null && targetel.parentNode == null) {
- targetel = targetel.parentNode
- }
-
- var bbox = {},
- matrix = targetel.getScreenCTM(),
- tbbox = targetel.getBBox(),
- width = tbbox.width,
- height = tbbox.height,
- x = tbbox.x,
- y = tbbox.y
-
- point.x = x
- point.y = y
- bbox.nw = point.matrixTransform(matrix)
- point.x += width
- bbox.ne = point.matrixTransform(matrix)
- point.y += height
- bbox.se = point.matrixTransform(matrix)
- point.x -= width
- bbox.sw = point.matrixTransform(matrix)
- point.y -= height / 2
- bbox.w = point.matrixTransform(matrix)
- point.x += width
- bbox.e = point.matrixTransform(matrix)
- point.x -= width / 2
- point.y -= height / 2
- bbox.n = point.matrixTransform(matrix)
- point.y += height
- bbox.s = point.matrixTransform(matrix)
-
- return bbox
- }
-
- // Private - replace D3JS 3.X d3.functor() function
- function functor(v) {
- return typeof v === 'function' ? v : function() {
- return v
- }
- }
-
- return tip
- }
-// eslint-disable-next-line semi
-}));
+/**
+ * d3.tip
+ * Copyright (c) 2013 Justin Palmer
+ *
+ * Tooltips for d3.js SVG visualizations
+ */
+// eslint-disable-next-line no-extra-semi
+;(function(root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module with d3 as a dependency.
+ define([
+ 'd3-collection',
+ 'd3-selection'
+ ], factory)
+ } else if (typeof module === 'object' && module.exports) {
+ /* eslint-disable global-require */
+ // CommonJS
+ var d3Collection = require('d3-collection'),
+ d3Selection = require('d3-selection')
+ module.exports = factory(d3Collection, d3Selection)
+ /* eslint-enable global-require */
+ } else {
+ // Browser global.
+ var d3 = root.d3
+ // eslint-disable-next-line no-param-reassign
+ root.d3.tip = factory(d3, d3)
+ }
+}(this, function(d3Collection, d3Selection) {
+ // Public - contructs a new tooltip
+ //
+ // Returns a tip
+ return function() {
+ var direction = d3TipDirection,
+ offset = d3TipOffset,
+ html = d3TipHTML,
+ rootElement = document.body,
+ node = initNode(),
+ svg = null,
+ point = null,
+ target = null
+
+ function tip(vis) {
+ svg = getSVGNode(vis)
+ if (!svg) return
+ point = svg.createSVGPoint()
+ rootElement.appendChild(node)
+ }
+
+ // Public - show the tooltip on the screen
+ //
+ // Returns a tip
+ tip.show = function() {
+ var args = Array.prototype.slice.call(arguments)
+ if (args[args.length - 1] instanceof SVGElement) target = args.pop()
+
+ var content = html.apply(this, args),
+ poffset = offset.apply(this, args),
+ dir = direction.apply(this, args),
+ nodel = getNodeEl(),
+ i = directions.length,
+ coords,
+ scrollTop = document.documentElement.scrollTop ||
+ rootElement.scrollTop,
+ scrollLeft = document.documentElement.scrollLeft ||
+ rootElement.scrollLeft
+
+ nodel.html(content)
+ .style('opacity', 1).style('pointer-events', 'all')
+
+ while (i--) nodel.classed(directions[i], false)
+ coords = directionCallbacks.get(dir).apply(this)
+ nodel.classed(dir, true)
+ .style('top', (coords.top + poffset[0]) + scrollTop + 'px')
+ .style('left', (coords.left + poffset[1]) + scrollLeft + 'px')
+
+ return tip
+ }
+
+ // Public - hide the tooltip
+ //
+ // Returns a tip
+ tip.hide = function() {
+ var nodel = getNodeEl()
+ nodel.style('opacity', 0).style('pointer-events', 'none')
+ return tip
+ }
+
+ // Public: Proxy attr calls to the d3 tip container.
+ // Sets or gets attribute value.
+ //
+ // n - name of the attribute
+ // v - value of the attribute
+ //
+ // Returns tip or attribute value
+ // eslint-disable-next-line no-unused-vars
+ tip.attr = function(n, v) {
+ if (arguments.length < 2 && typeof n === 'string') {
+ return getNodeEl().attr(n)
+ }
+
+ var args = Array.prototype.slice.call(arguments)
+ d3Selection.selection.prototype.attr.apply(getNodeEl(), args)
+ return tip
+ }
+
+ // Public: Proxy style calls to the d3 tip container.
+ // Sets or gets a style value.
+ //
+ // n - name of the property
+ // v - value of the property
+ //
+ // Returns tip or style property value
+ // eslint-disable-next-line no-unused-vars
+ tip.style = function(n, v) {
+ if (arguments.length < 2 && typeof n === 'string') {
+ return getNodeEl().style(n)
+ }
+
+ var args = Array.prototype.slice.call(arguments)
+ d3Selection.selection.prototype.style.apply(getNodeEl(), args)
+ return tip
+ }
+
+ // Public: Set or get the direction of the tooltip
+ //
+ // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
+ // sw(southwest), ne(northeast) or se(southeast)
+ //
+ // Returns tip or direction
+ tip.direction = function(v) {
+ if (!arguments.length) return direction
+ direction = v == null ? v : functor(v)
+
+ return tip
+ }
+
+ // Public: Sets or gets the offset of the tip
+ //
+ // v - Array of [x, y] offset
+ //
+ // Returns offset or
+ tip.offset = function(v) {
+ if (!arguments.length) return offset
+ offset = v == null ? v : functor(v)
+
+ return tip
+ }
+
+ // Public: sets or gets the html value of the tooltip
+ //
+ // v - String value of the tip
+ //
+ // Returns html value or tip
+ tip.html = function(v) {
+ if (!arguments.length) return html
+ html = v == null ? v : functor(v)
+
+ return tip
+ }
+
+ // Public: sets or gets the root element anchor of the tooltip
+ //
+ // v - root element of the tooltip
+ //
+ // Returns root node of tip
+ tip.rootElement = function(v) {
+ if (!arguments.length) return rootElement
+ rootElement = v == null ? v : functor(v)
+
+ return tip
+ }
+
+ // Public: destroys the tooltip and removes it from the DOM
+ //
+ // Returns a tip
+ tip.destroy = function() {
+ if (node) {
+ getNodeEl().remove()
+ node = null
+ }
+ return tip
+ }
+
+ function d3TipDirection() { return 'n' }
+ function d3TipOffset() { return [0, 0] }
+ function d3TipHTML() { return ' ' }
+
+ var directionCallbacks = d3Collection.map({
+ n: directionNorth,
+ s: directionSouth,
+ e: directionEast,
+ w: directionWest,
+ nw: directionNorthWest,
+ ne: directionNorthEast,
+ sw: directionSouthWest,
+ se: directionSouthEast
+ }),
+ directions = directionCallbacks.keys()
+
+ function directionNorth() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.n.y - node.offsetHeight,
+ left: bbox.n.x - node.offsetWidth / 2
+ }
+ }
+
+ function directionSouth() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.s.y,
+ left: bbox.s.x - node.offsetWidth / 2
+ }
+ }
+
+ function directionEast() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.e.y - node.offsetHeight / 2,
+ left: bbox.e.x
+ }
+ }
+
+ function directionWest() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.w.y - node.offsetHeight / 2,
+ left: bbox.w.x - node.offsetWidth
+ }
+ }
+
+ function directionNorthWest() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.nw.y - node.offsetHeight,
+ left: bbox.nw.x - node.offsetWidth
+ }
+ }
+
+ function directionNorthEast() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.ne.y - node.offsetHeight,
+ left: bbox.ne.x
+ }
+ }
+
+ function directionSouthWest() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.sw.y,
+ left: bbox.sw.x - node.offsetWidth
+ }
+ }
+
+ function directionSouthEast() {
+ var bbox = getScreenBBox()
+ return {
+ top: bbox.se.y,
+ left: bbox.se.x
+ }
+ }
+
+ function initNode() {
+ var div = d3Selection.select(document.createElement('div'))
+ div
+ .style('position', 'absolute')
+ .style('top', 0)
+ .style('opacity', 0)
+ .style('pointer-events', 'none')
+ .style('box-sizing', 'border-box')
+
+ return div.node()
+ }
+
+ function getSVGNode(element) {
+ var svgNode = element.node()
+ if (!svgNode) return null
+ if (svgNode.tagName.toLowerCase() === 'svg') return svgNode
+ return svgNode.ownerSVGElement
+ }
+
+ function getNodeEl() {
+ if (node == null) {
+ node = initNode()
+ // re-add node to DOM
+ rootElement.appendChild(node)
+ }
+ return d3Selection.select(node)
+ }
+
+ // Private - gets the screen coordinates of a shape
+ //
+ // Given a shape on the screen, will return an SVGPoint for the directions
+ // n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
+ // nw(northwest), sw(southwest).
+ //
+ // +-+-+
+ // | |
+ // + +
+ // | |
+ // +-+-+
+ //
+ // Returns an Object {n, s, e, w, nw, sw, ne, se}
+ function getScreenBBox() {
+ var targetel = target || d3Selection.event.target
+
+ while (targetel.getScreenCTM == null && targetel.parentNode == null) {
+ targetel = targetel.parentNode
+ }
+
+ var bbox = {},
+ matrix = targetel.getScreenCTM(),
+ tbbox = targetel.getBBox(),
+ width = tbbox.width,
+ height = tbbox.height,
+ x = tbbox.x,
+ y = tbbox.y
+
+ point.x = x
+ point.y = y
+ bbox.nw = point.matrixTransform(matrix)
+ point.x += width
+ bbox.ne = point.matrixTransform(matrix)
+ point.y += height
+ bbox.se = point.matrixTransform(matrix)
+ point.x -= width
+ bbox.sw = point.matrixTransform(matrix)
+ point.y -= height / 2
+ bbox.w = point.matrixTransform(matrix)
+ point.x += width
+ bbox.e = point.matrixTransform(matrix)
+ point.x -= width / 2
+ point.y -= height / 2
+ bbox.n = point.matrixTransform(matrix)
+ point.y += height
+ bbox.s = point.matrixTransform(matrix)
+
+ return bbox
+ }
+
+ // Private - replace D3JS 3.X d3.functor() function
+ function functor(v) {
+ return typeof v === 'function' ? v : function() {
+ return v
+ }
+ }
+
+ return tip
+ }
+// eslint-disable-next-line semi
+}));
diff --git a/library/cpp/lwtrace/mon/static/js/d3.v4.min.js b/library/cpp/lwtrace/mon/static/js/d3.v4.min.js
index 6a2705865c..544c4eb8cd 100644
--- a/library/cpp/lwtrace/mon/static/js/d3.v4.min.js
+++ b/library/cpp/lwtrace/mon/static/js/d3.v4.min.js
@@ -1,2 +1,2 @@
-// https://d3js.org Version 4.10.0. Copyright 2017 Mike Bostock.
-(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t){return function(n,e){return ss(t(n),e)}}function e(t,n){return[t,n]}function r(t,n,e){var r=(n-t)/Math.max(0,e),i=Math.floor(Math.log(r)/Math.LN10),o=r/Math.pow(10,i);return i>=0?(o>=Ts?10:o>=ks?5:o>=Ns?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(o>=Ts?10:o>=ks?5:o>=Ns?2:1)}function i(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Ts?i*=10:o>=ks?i*=5:o>=Ns&&(i*=2),n<t?-i:i}function o(t){return t.length}function u(t){return"translate("+(t+.5)+",0)"}function a(t){return"translate(0,"+(t+.5)+")"}function c(t){return function(n){return+t(n)}}function s(t){var n=Math.max(0,t.bandwidth()-1)/2;return t.round()&&(n=Math.round(n)),function(e){return+t(e)+n}}function f(){return!this.__axis}function l(t,n){function e(e){var u=null==i?n.ticks?n.ticks.apply(n,r):n.domain():i,a=null==o?n.tickFormat?n.tickFormat.apply(n,r):Ls:o,y=Math.max(l,0)+p,g=n.range(),m=+g[0]+.5,x=+g[g.length-1]+.5,b=(n.bandwidth?s:c)(n.copy()),w=e.selection?e.selection():e,M=w.selectAll(".domain").data([null]),T=w.selectAll(".tick").data(u,n).order(),k=T.exit(),N=T.enter().append("g").attr("class","tick"),S=T.select("line"),E=T.select("text");M=M.merge(M.enter().insert("path",".tick").attr("class","domain").attr("stroke","#000")),T=T.merge(N),S=S.merge(N.append("line").attr("stroke","#000").attr(v+"2",d*l)),E=E.merge(N.append("text").attr("fill","#000").attr(v,d*y).attr("dy",t===qs?"0em":t===Ds?"0.71em":"0.32em")),e!==w&&(M=M.transition(e),T=T.transition(e),S=S.transition(e),E=E.transition(e),k=k.transition(e).attr("opacity",Fs).attr("transform",function(t){return isFinite(t=b(t))?_(t):this.getAttribute("transform")}),N.attr("opacity",Fs).attr("transform",function(t){var n=this.parentNode.__axis;return _(n&&isFinite(n=n(t))?n:b(t))})),k.remove(),M.attr("d",t===Os||t==Us?"M"+d*h+","+m+"H0.5V"+x+"H"+d*h:"M"+m+","+d*h+"V0.5H"+x+"V"+d*h),T.attr("opacity",1).attr("transform",function(t){return _(b(t))}),S.attr(v+"2",d*l),E.attr(v,d*y).text(a),w.filter(f).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Us?"start":t===Os?"end":"middle"),w.each(function(){this.__axis=b})}var r=[],i=null,o=null,l=6,h=6,p=3,d=t===qs||t===Os?-1:1,v=t===Os||t===Us?"x":"y",_=t===qs||t===Ds?u:a;return e.scale=function(t){return arguments.length?(n=t,e):n},e.ticks=function(){return r=Rs.call(arguments),e},e.tickArguments=function(t){return arguments.length?(r=null==t?[]:Rs.call(t),e):r.slice()},e.tickValues=function(t){return arguments.length?(i=null==t?null:Rs.call(t),e):i&&i.slice()},e.tickFormat=function(t){return arguments.length?(o=t,e):o},e.tickSize=function(t){return arguments.length?(l=h=+t,e):l},e.tickSizeInner=function(t){return arguments.length?(l=+t,e):l},e.tickSizeOuter=function(t){return arguments.length?(h=+t,e):h},e.tickPadding=function(t){return arguments.length?(p=+t,e):p},e}function h(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+"")||t in r)throw new Error("illegal type: "+t);r[t]=[]}return new p(r)}function p(t){this._=t}function d(t,n){return t.trim().split(/^|\s+/).map(function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}function v(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}function _(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]=Is,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=e&&t.push({name:n,value:e}),t}function y(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===Ys&&n.documentElement.namespaceURI===Ys?n.createElement(t):n.createElementNS(e,t)}}function g(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function m(){return new x}function x(){this._="@"+(++Xs).toString(36)}function b(t,n,e){return t=w(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function w(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function M(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function T(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function k(t,n,e){var r=Gs.hasOwnProperty(t.type)?b:w;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function N(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{return e.apply(r,i)}finally{t.event=o}}function S(){}function E(){return[]}function A(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function C(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new A(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function z(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Array(l);for(a=0;a<l;++a)(c=n[a])&&(p[a]=s=of+u.call(c,c.__data__,a,n),s in f?i[a]=c:f[s]=c);for(a=0;a<h;++a)(c=f[s=of+u.call(t,o[a],a,o)])?(r[a]=c,c.__data__=o[a],f[s]=null):e[a]=new A(t,o[a]);for(a=0;a<l;++a)(c=n[a])&&f[p[a]]===c&&(i[a]=c)}function P(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function R(t){return function(){this.removeAttribute(t)}}function L(t){return function(){this.removeAttributeNS(t.space,t.local)}}function q(t,n){return function(){this.setAttribute(t,n)}}function U(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function D(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function O(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function F(t){return function(){this.style.removeProperty(t)}}function I(t,n,e){return function(){this.style.setProperty(t,n,e)}}function Y(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function B(t,n){return t.style.getPropertyValue(n)||uf(t).getComputedStyle(t,null).getPropertyValue(n)}function j(t){return function(){delete this[t]}}function H(t,n){return function(){this[t]=n}}function X(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function $(t){return t.trim().split(/^|\s+/)}function V(t){return t.classList||new W(t)}function W(t){this._node=t,this._names=$(t.getAttribute("class")||"")}function Z(t,n){for(var e=V(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function G(t,n){for(var e=V(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}function J(t){return function(){Z(this,t)}}function Q(t){return function(){G(this,t)}}function K(t,n){return function(){(n.apply(this,arguments)?Z:G)(this,t)}}function tt(){this.textContent=""}function nt(t){return function(){this.textContent=t}}function et(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}}function rt(){this.innerHTML=""}function it(t){return function(){this.innerHTML=t}}function ot(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}}function ut(){this.nextSibling&&this.parentNode.appendChild(this)}function at(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function ct(){return null}function st(){var t=this.parentNode;t&&t.removeChild(this)}function ft(t,n,e){var r=uf(t),i=r.CustomEvent;"function"==typeof i?i=new i(n,e):(i=r.document.createEvent("Event"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}function lt(t,n){return function(){return ft(this,t,n)}}function ht(t,n){return function(){return ft(this,t,n.apply(this,arguments))}}function pt(t,n){this._groups=t,this._parents=n}function dt(){return new pt([[document.documentElement]],af)}function vt(){t.event.stopImmediatePropagation()}function _t(t,n){var e=t.document.documentElement,r=cf(t).on("dragstart.drag",null);n&&(r.on("click.drag",ff,!0),setTimeout(function(){r.on("click.drag",null)},0)),"onselectstart"in e?r.on("selectstart.drag",null):(e.style.MozUserSelect=e.__noselect,delete e.__noselect)}function yt(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=e,this.identifier=r,this.active=i,this.x=o,this.y=u,this.dx=a,this.dy=c,this._=s}function gt(){return!t.event.button}function mt(){return this.parentNode}function xt(n){return null==n?{x:t.event.x,y:t.event.y}:n}function bt(){return"ontouchstart"in this}function wt(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function Mt(){}function Tt(t){var n;return t=(t+"").trim().toLowerCase(),(n=yf.exec(t))?(n=parseInt(n[1],16),new At(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1)):(n=gf.exec(t))?kt(parseInt(n[1],16)):(n=mf.exec(t))?new At(n[1],n[2],n[3],1):(n=xf.exec(t))?new At(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=bf.exec(t))?Nt(n[1],n[2],n[3],n[4]):(n=wf.exec(t))?Nt(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=Mf.exec(t))?Ct(n[1],n[2]/100,n[3]/100,1):(n=Tf.exec(t))?Ct(n[1],n[2]/100,n[3]/100,n[4]):kf.hasOwnProperty(t)?kt(kf[t]):"transparent"===t?new At(NaN,NaN,NaN,0):null}function kt(t){return new At(t>>16&255,t>>8&255,255&t,1)}function Nt(t,n,e,r){return r<=0&&(t=n=e=NaN),new At(t,n,e,r)}function St(t){return t instanceof Mt||(t=Tt(t)),t?(t=t.rgb(),new At(t.r,t.g,t.b,t.opacity)):new At}function Et(t,n,e,r){return 1===arguments.length?St(t):new At(t,n,e,null==r?1:r)}function At(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Ct(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Rt(t,n,e,r)}function zt(t){if(t instanceof Rt)return new Rt(t.h,t.s,t.l,t.opacity);if(t instanceof Mt||(t=Tt(t)),!t)return new Rt;if(t instanceof Rt)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,c=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e<r):e===o?(r-n)/a+2:(n-e)/a+4,a/=c<.5?o+i:2-o-i,u*=60):a=c>0&&c<1?0:u,new Rt(u,a,c,t.opacity)}function Pt(t,n,e,r){return 1===arguments.length?zt(t):new Rt(t,n,e,null==r?1:r)}function Rt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Lt(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function qt(t){if(t instanceof Dt)return new Dt(t.l,t.a,t.b,t.opacity);if(t instanceof Ht){var n=t.h*Nf;return new Dt(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof At||(t=St(t));var e=Yt(t.r),r=Yt(t.g),i=Yt(t.b),o=Ot((.4124564*e+.3575761*r+.1804375*i)/Ef),u=Ot((.2126729*e+.7151522*r+.072175*i)/Af);return new Dt(116*u-16,500*(o-u),200*(u-Ot((.0193339*e+.119192*r+.9503041*i)/Cf)),t.opacity)}function Ut(t,n,e,r){return 1===arguments.length?qt(t):new Dt(t,n,e,null==r?1:r)}function Dt(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function Ot(t){return t>Lf?Math.pow(t,1/3):t/Rf+zf}function Ft(t){return t>Pf?t*t*t:Rf*(t-zf)}function It(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Yt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Bt(t){if(t instanceof Ht)return new Ht(t.h,t.c,t.l,t.opacity);t instanceof Dt||(t=qt(t));var n=Math.atan2(t.b,t.a)*Sf;return new Ht(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function jt(t,n,e,r){return 1===arguments.length?Bt(t):new Ht(t,n,e,null==r?1:r)}function Ht(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}function Xt(t){if(t instanceof Vt)return new Vt(t.h,t.s,t.l,t.opacity);t instanceof At||(t=St(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=(Bf*r+If*n-Yf*e)/(Bf+If-Yf),o=r-i,u=(Ff*(e-i)-Df*o)/Of,a=Math.sqrt(u*u+o*o)/(Ff*i*(1-i)),c=a?Math.atan2(u,o)*Sf-120:NaN;return new Vt(c<0?c+360:c,a,i,t.opacity)}function $t(t,n,e,r){return 1===arguments.length?Xt(t):new Vt(t,n,e,null==r?1:r)}function Vt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Wt(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}function Zt(t,n){return function(e){return t+e*n}}function Gt(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}function Jt(t,n){var e=n-t;return e?Zt(t,e>180||e<-180?e-360*Math.round(e/360):e):Jf(isNaN(t)?n:t)}function Qt(t){return 1==(t=+t)?Kt:function(n,e){return e-n?Gt(n,e,t):Jf(isNaN(n)?e:n)}}function Kt(t,n){var e=n-t;return e?Zt(t,e):Jf(isNaN(t)?n:t)}function tn(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e<i;++e)r=Et(n[e]),o[e]=r.r||0,u[e]=r.g||0,a[e]=r.b||0;return o=t(o),u=t(u),a=t(a),r.opacity=1,function(t){return r.r=o(t),r.g=u(t),r.b=a(t),r+""}}}function nn(t){return function(){return t}}function en(t){return function(n){return t(n)+""}}function rn(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}function o(t,r,i,o,u,a){if(t!==i||r!==o){var c=u.push("translate(",null,n,null,e);a.push({i:c-4,x:rl(t,i)},{i:c-2,x:rl(r,o)})}else(i||o)&&u.push("translate("+i+n+o+e)}function u(t,n,e,o){t!==n?(t-n>180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:rl(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}function a(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:rl(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}function c(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+"scale(",null,",",null,")");u.push({i:a-4,x:rl(t,e)},{i:a-2,x:rl(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}return function(n,e){var r=[],i=[];return n=t(n),e=t(e),o(n.translateX,n.translateY,e.translateX,e.translateY,r,i),u(n.rotate,e.rotate,r,i),a(n.skewX,e.skewX,r,i),c(n.scaleX,n.scaleY,e.scaleX,e.scaleY,r,i),n=e=null,function(t){for(var n,e=-1,o=i.length;++e<o;)r[(n=i[e]).i]=n.x(t);return r.join("")}}}function on(t){return((t=Math.exp(t))+1/t)/2}function un(t){return((t=Math.exp(t))-1/t)/2}function an(t){return((t=Math.exp(2*t))-1)/(t+1)}function cn(t){return function(n,e){var r=t((n=Pt(n)).h,(e=Pt(e)).h),i=Kt(n.s,e.s),o=Kt(n.l,e.l),u=Kt(n.opacity,e.opacity);return function(t){return n.h=r(t),n.s=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function sn(t){return function(n,e){var r=t((n=jt(n)).h,(e=jt(e)).h),i=Kt(n.c,e.c),o=Kt(n.l,e.l),u=Kt(n.opacity,e.opacity);return function(t){return n.h=r(t),n.c=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function fn(t){return function n(e){function r(n,r){var i=t((n=$t(n)).h,(r=$t(r)).h),o=Kt(n.s,r.s),u=Kt(n.l,r.l),a=Kt(n.opacity,r.opacity);return function(t){return n.h=i(t),n.s=o(t),n.l=u(Math.pow(t,e)),n.opacity=a(t),n+""}}return e=+e,r.gamma=n,r}(1)}function ln(){return El||(zl(hn),El=Cl.now()+Al)}function hn(){El=0}function pn(){this._call=this._time=this._next=null}function dn(t,n,e){var r=new pn;return r.restart(t,n,e),r}function vn(){ln(),++Ml;for(var t,n=Vf;n;)(t=El-n._time)>=0&&n._call.call(null,t),n=n._next;--Ml}function _n(){El=(Sl=Cl.now())+Al,Ml=Tl=0;try{vn()}finally{Ml=0,gn(),El=0}}function yn(){var t=Cl.now(),n=t-Sl;n>Nl&&(Al-=n,Sl=t)}function gn(){for(var t,n,e=Vf,r=1/0;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Vf=n);Wf=t,mn(r)}function mn(t){if(!Ml){Tl&&(Tl=clearTimeout(Tl));var n=t-El;n>24?(t<1/0&&(Tl=setTimeout(_n,n)),kl&&(kl=clearInterval(kl))):(kl||(Sl=El,kl=setInterval(yn,Nl)),Ml=1,zl(_n))}}function xn(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>ql)throw new Error("too late");return e}function bn(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>Dl)throw new Error("too late");return e}function wn(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("too late");return e}function Mn(t,n,e){function r(c){var s,f,l,h;if(e.state!==Ul)return o();for(s in a)if((h=a[s]).name===e.name){if(h.state===Ol)return Pl(r);h.state===Fl?(h.state=Yl,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete a[s]):+s<n&&(h.state=Yl,h.timer.stop(),delete a[s])}if(Pl(function(){e.state===Ol&&(e.state=Fl,e.timer.restart(i,e.delay,e.time),i(c))}),e.state=Dl,e.on.call("start",t,t.__data__,e.index,e.group),e.state===Dl){for(e.state=Ol,u=new Array(l=e.tween.length),s=0,f=-1;s<l;++s)(h=e.tween[s].value.call(t,t.__data__,e.index,e.group))&&(u[++f]=h);u.length=f+1}}function i(n){for(var r=n<e.duration?e.ease.call(null,n/e.duration):(e.timer.restart(o),e.state=Il,1),i=-1,a=u.length;++i<a;)u[i].call(null,r);e.state===Il&&(e.on.call("end",t,t.__data__,e.index,e.group),o())}function o(){e.state=Yl,e.timer.stop(),delete a[n];for(var r in a)return;delete t.__transition}var u,a=t.__transition;a[n]=e,e.timer=dn(function(t){e.state=Ul,e.timer.restart(r,e.delay,e.time),e.delay<=t&&r(t-e.delay)},0,e.time)}function Tn(t,n){var e,r;return function(){var i=bn(this,t),o=i.tween;if(o!==e)for(var u=0,a=(r=e=o).length;u<a;++u)if(r[u].name===n){(r=r.slice()).splice(u,1);break}i.tween=r}}function kn(t,n,e){var r,i;if("function"!=typeof e)throw new Error;return function(){var o=bn(this,t),u=o.tween;if(u!==r){i=(r=u).slice();for(var a={name:n,value:e},c=0,s=i.length;c<s;++c)if(i[c].name===n){i[c]=a;break}c===s&&i.push(a)}o.tween=i}}function Nn(t,n,e){var r=t._id;return t.each(function(){var t=bn(this,r);(t.value||(t.value={}))[n]=e.apply(this,arguments)}),function(t){return wn(t,r).value[n]}}function Sn(t){return function(){this.removeAttribute(t)}}function En(t){return function(){this.removeAttributeNS(t.space,t.local)}}function An(t,n,e){var r,i;return function(){var o=this.getAttribute(t);return o===e?null:o===r?i:i=n(r=o,e)}}function Cn(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t.space,t.local);return o===e?null:o===r?i:i=n(r=o,e)}}function zn(t,n,e){var r,i,o;return function(){var u,a=e(this);{if(null!=a)return(u=this.getAttribute(t))===a?null:u===r&&a===i?o:o=n(r=u,i=a);this.removeAttribute(t)}}}function Pn(t,n,e){var r,i,o;return function(){var u,a=e(this);{if(null!=a)return(u=this.getAttributeNS(t.space,t.local))===a?null:u===r&&a===i?o:o=n(r=u,i=a);this.removeAttributeNS(t.space,t.local)}}}function Rn(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttributeNS(t.space,t.local,r(n))}}return e._value=n,e}function Ln(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttribute(t,r(n))}}return e._value=n,e}function qn(t,n){return function(){xn(this,t).delay=+n.apply(this,arguments)}}function Un(t,n){return n=+n,function(){xn(this,t).delay=n}}function Dn(t,n){return function(){bn(this,t).duration=+n.apply(this,arguments)}}function On(t,n){return n=+n,function(){bn(this,t).duration=n}}function Fn(t,n){if("function"!=typeof n)throw new Error;return function(){bn(this,t).ease=n}}function In(t){return(t+"").trim().split(/^|\s+/).every(function(t){var n=t.indexOf(".");return n>=0&&(t=t.slice(0,n)),!t||"start"===t})}function Yn(t,n,e){var r,i,o=In(n)?xn:bn;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}function Bn(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}function jn(t,n){var e,r,i;return function(){var o=B(this,t),u=(this.style.removeProperty(t),B(this,t));return o===u?null:o===e&&u===r?i:i=n(e=o,r=u)}}function Hn(t){return function(){this.style.removeProperty(t)}}function Xn(t,n,e){var r,i;return function(){var o=B(this,t);return o===e?null:o===r?i:i=n(r=o,e)}}function $n(t,n,e){var r,i,o;return function(){var u=B(this,t),a=e(this);return null==a&&(this.style.removeProperty(t),a=B(this,t)),u===a?null:u===r&&a===i?o:o=n(r=u,i=a)}}function Vn(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return i&&function(n){r.style.setProperty(t,i(n),e)}}return r._value=n,r}function Wn(t){return function(){this.textContent=t}}function Zn(t){return function(){var n=t(this);this.textContent=null==n?"":n}}function Gn(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function Jn(t){return dt().transition(t)}function Qn(){return++$l}function Kn(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function te(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}function ne(t){return(1-Math.cos(Jl*t))/2}function ee(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function re(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}function ie(t){return(t=+t)<Kl?ch*t*t:t<nh?ch*(t-=th)*t+eh:t<ih?ch*(t-=rh)*t+oh:ch*(t-=uh)*t+ah}function oe(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))return _h.time=ln(),_h;return e}function ue(){t.event.stopImmediatePropagation()}function ae(t){return{type:t}}function ce(){return!t.event.button}function se(){var t=this.ownerSVGElement||this;return[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function fe(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function le(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}function he(n){function e(t){var e=t.property("__brush",a).selectAll(".overlay").data([ae("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",Eh.overlay).merge(e).each(function(){var t=fe(this).extent;cf(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])}),t.selectAll(".selection").data([ae("selection")]).enter().append("rect").attr("class","selection").attr("cursor",Eh.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var i=t.selectAll(".handle").data(n.handles,function(t){return t.type});i.exit().remove(),i.enter().append("rect").attr("class",function(t){return"handle handle--"+t.type}).attr("cursor",function(t){return Eh[t.type]}),t.each(r).attr("fill","none").attr("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush touchstart.brush",u)}function r(){var t=cf(this),n=fe(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",function(t){return"e"===t.type[t.type.length-1]?n[1][0]-p/2:n[0][0]-p/2}).attr("y",function(t){return"s"===t.type[0]?n[1][1]-p/2:n[0][1]-p/2}).attr("width",function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+p:p}).attr("height",function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+p:p})):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function i(t,n){return t.__brush.emitter||new o(t,n)}function o(t,n){this.that=t,this.args=n,this.state=t.__brush,this.active=0}function u(){function e(){var t=Ks(w);!L||x||b||(Math.abs(t[0]-U[0])>Math.abs(t[1]-U[1])?b=!0:x=!0),U=t,m=!0,xh(),o()}function o(){var t;switch(y=U[0]-q[0],g=U[1]-q[1],T){case wh:case bh:k&&(y=Math.max(C-a,Math.min(P-p,y)),s=a+y,d=p+y),N&&(g=Math.max(z-l,Math.min(R-v,g)),h=l+g,_=v+g);break;case Mh:k<0?(y=Math.max(C-a,Math.min(P-a,y)),s=a+y,d=p):k>0&&(y=Math.max(C-p,Math.min(P-p,y)),s=a,d=p+y),N<0?(g=Math.max(z-l,Math.min(R-l,g)),h=l+g,_=v):N>0&&(g=Math.max(z-v,Math.min(R-v,g)),h=l,_=v+g);break;case Th:k&&(s=Math.max(C,Math.min(P,a-y*k)),d=Math.max(C,Math.min(P,p+y*k))),N&&(h=Math.max(z,Math.min(R,l-g*N)),_=Math.max(z,Math.min(R,v+g*N)))}d<s&&(k*=-1,t=a,a=p,p=t,t=s,s=d,d=t,M in Ah&&F.attr("cursor",Eh[M=Ah[M]])),_<h&&(N*=-1,t=l,l=v,v=t,t=h,h=_,_=t,M in Ch&&F.attr("cursor",Eh[M=Ch[M]])),S.selection&&(A=S.selection),x&&(s=A[0][0],d=A[1][0]),b&&(h=A[0][1],_=A[1][1]),A[0][0]===s&&A[0][1]===h&&A[1][0]===d&&A[1][1]===_||(S.selection=[[s,h],[d,_]],r.call(w),D.brush())}function u(){if(ue(),t.event.touches){if(t.event.touches.length)return;c&&clearTimeout(c),c=setTimeout(function(){c=null},500),O.on("touchmove.brush touchend.brush touchcancel.brush",null)}else _t(t.event.view,m),I.on("keydown.brush keyup.brush mousemove.brush mouseup.brush",null);O.attr("pointer-events","all"),F.attr("cursor",Eh.overlay),S.selection&&(A=S.selection),le(A)&&(S.selection=null,r.call(w)),D.end()}if(t.event.touches){if(t.event.changedTouches.length<t.event.touches.length)return xh()}else if(c)return;if(f.apply(this,arguments)){var a,s,l,h,p,d,v,_,y,g,m,x,b,w=this,M=t.event.target.__data__.type,T="selection"===(t.event.metaKey?M="overlay":M)?bh:t.event.altKey?Th:Mh,k=n===Nh?null:zh[M],N=n===kh?null:Ph[M],S=fe(w),E=S.extent,A=S.selection,C=E[0][0],z=E[0][1],P=E[1][0],R=E[1][1],L=k&&N&&t.event.shiftKey,q=Ks(w),U=q,D=i(w,arguments).beforestart();"overlay"===M?S.selection=A=[[a=n===Nh?C:q[0],l=n===kh?z:q[1]],[p=n===Nh?P:a,v=n===kh?R:l]]:(a=A[0][0],l=A[0][1],p=A[1][0],v=A[1][1]),s=a,h=l,d=p,_=v;var O=cf(w).attr("pointer-events","none"),F=O.selectAll(".overlay").attr("cursor",Eh[M]);if(t.event.touches)O.on("touchmove.brush",e,!0).on("touchend.brush touchcancel.brush",u,!0);else{var I=cf(t.event.view).on("keydown.brush",function(){switch(t.event.keyCode){case 16:L=k&&N;break;case 18:T===Mh&&(k&&(p=d-y*k,a=s+y*k),N&&(v=_-g*N,l=h+g*N),T=Th,o());break;case 32:T!==Mh&&T!==Th||(k<0?p=d-y:k>0&&(a=s-y),N<0?v=_-g:N>0&&(l=h-g),T=wh,F.attr("cursor",Eh.selection),o());break;default:return}xh()},!0).on("keyup.brush",function(){switch(t.event.keyCode){case 16:L&&(x=b=L=!1,o());break;case 18:T===Th&&(k<0?p=d:k>0&&(a=s),N<0?v=_:N>0&&(l=h),T=Mh,o());break;case 32:T===wh&&(t.event.altKey?(k&&(p=d-y*k,a=s+y*k),N&&(v=_-g*N,l=h+g*N),T=Th):(k<0?p=d:k>0&&(a=s),N<0?v=_:N>0&&(l=h),T=Mh),F.attr("cursor",Eh[M]),o());break;default:return}xh()},!0).on("mousemove.brush",e,!0).on("mouseup.brush",u,!0);lf(t.event.view)}ue(),jl(w),r.call(w),D.start()}}function a(){var t=this.__brush||{selection:null};return t.extent=s.apply(this,arguments),t.dim=n,t}var c,s=se,f=ce,l=h(e,"start","brush","end"),p=6;return e.move=function(t,e){t.selection?t.on("start.brush",function(){i(this,arguments).beforestart().start()}).on("interrupt.brush end.brush",function(){i(this,arguments).end()}).tween("brush",function(){function t(t){u.selection=1===t&&le(s)?null:f(t),r.call(o),a.brush()}var o=this,u=o.__brush,a=i(o,arguments),c=u.selection,s=n.input("function"==typeof e?e.apply(this,arguments):e,u.extent),f=cl(c,s);return c&&s?t:t(1)}):t.each(function(){var t=this,o=arguments,u=t.__brush,a=n.input("function"==typeof e?e.apply(t,o):e,u.extent),c=i(t,o).beforestart();jl(t),u.selection=null==a||le(a)?null:a,r.call(t),c.start().brush().end()})},o.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0==--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){N(new mh(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(s="function"==typeof t?t:gh([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):s},e.filter=function(t){return arguments.length?(f="function"==typeof t?t:gh(!!t),e):f},e.handleSize=function(t){return arguments.length?(p=+t,e):p},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function pe(t){return function(n,e){return t(n.source.value+n.target.value,e.source.value+e.target.value)}}function de(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function ve(){return new de}function _e(t){return t.source}function ye(t){return t.target}function ge(t){return t.radius}function me(t){return t.startAngle}function xe(t){return t.endAngle}function be(){}function we(t,n){var e=new be;if(t instanceof be)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==n)for(;++i<o;)e.set(i,t[i]);else for(;++i<o;)e.set(n(r=t[i],i,t),r)}else if(t)for(var u in t)e.set(u,t[u]);return e}function Me(){return{}}function Te(t,n,e){t[n]=e}function ke(){return we()}function Ne(t,n,e){t.set(n,e)}function Se(){}function Ee(t,n){var e=new Se;if(t instanceof Se)t.each(function(t){e.add(t)});else if(t){var r=-1,i=t.length;if(null==n)for(;++r<i;)e.add(t[r]);else for(;++r<i;)e.add(n(t[r],r,t))}return e}function Ae(t){return new Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}")}function Ce(t,n){var e=Ae(t);return function(r,i){return n(e(r),i,t)}}function ze(t){var n=Object.create(null),e=[];return t.forEach(function(t){for(var r in t)r in n||e.push(n[r]=r)}),e}function Pe(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,_=t._y0,y=t._x1,g=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do{i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u}while((l=f<<1|s)==(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function Re(t){return t[0]}function Le(t){return t[1]}function qe(t,n,e){var r=new Ue(null==n?Re:n,null==e?Le:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Ue(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function De(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function Oe(t){return t.x+t.vx}function Fe(t){return t.y+t.vy}function Ie(t){return t.index}function Ye(t,n){var e=t.get(n);if(!e)throw new Error("missing: "+n);return e}function Be(t){return t.x}function je(t){return t.y}function He(t){return new Xe(t)}function Xe(t){if(!(n=vp.exec(t)))throw new Error("invalid format: "+t);var n,e=n[1]||" ",r=n[2]||">",i=n[3]||"-",o=n[4]||"",u=!!n[5],a=n[6]&&+n[6],c=!!n[7],s=n[8]&&+n[8].slice(1),f=n[9]||"";"n"===f?(c=!0,f="g"):dp[f]||(f=""),(u||"0"===e&&"="===r)&&(u=!0,e="0",r="="),this.fill=e,this.align=r,this.sign=i,this.symbol=o,this.zero=u,this.width=a,this.comma=c,this.precision=s,this.type=f}function $e(n){return _p=mp(n),t.format=_p.format,t.formatPrefix=_p.formatPrefix,_p}function Ve(){this.reset()}function We(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function Ze(t){return t>1?0:t<-1?rd:Math.acos(t)}function Ge(t){return t>1?id:t<-1?-id:Math.asin(t)}function Je(t){return(t=yd(t/2))*t}function Qe(){}function Ke(t,n){t&&wd.hasOwnProperty(t.type)&&wd[t.type](t,n)}function tr(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function nr(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)tr(t[e],n,1);n.polygonEnd()}function er(){Nd.point=ir}function rr(){or(Tp,kp)}function ir(t,n){Nd.point=or,Tp=t,kp=n,Np=t*=cd,Sp=hd(n=(n*=cd)/2+od),Ep=yd(n)}function or(t,n){n=(n*=cd)/2+od;var e=(t*=cd)-Np,r=e>=0?1:-1,i=r*e,o=hd(n),u=yd(n),a=Ep*u,c=Sp*o+a*hd(i),s=a*r*yd(i);Td.add(ld(s,c)),Np=t,Sp=o,Ep=u}function ur(t){return[ld(t[1],t[0]),Ge(t[2])]}function ar(t){var n=t[0],e=t[1],r=hd(e);return[r*hd(n),r*yd(n),yd(e)]}function cr(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function sr(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function fr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function lr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function hr(t){var n=md(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function pr(t,n){Dp.push(Op=[Ap=t,zp=t]),n<Cp&&(Cp=n),n>Pp&&(Pp=n)}function dr(t,n){var e=ar([t*cd,n*cd]);if(Up){var r=sr(Up,e),i=sr([r[1],-r[0],0],r);hr(i),i=ur(i);var o,u=t-Rp,a=u>0?1:-1,c=i[0]*ad*a,s=sd(u)>180;s^(a*Rp<c&&c<a*t)?(o=i[1]*ad)>Pp&&(Pp=o):(c=(c+360)%360-180,s^(a*Rp<c&&c<a*t)?(o=-i[1]*ad)<Cp&&(Cp=o):(n<Cp&&(Cp=n),n>Pp&&(Pp=n))),s?t<Rp?xr(Ap,t)>xr(Ap,zp)&&(zp=t):xr(t,zp)>xr(Ap,zp)&&(Ap=t):zp>=Ap?(t<Ap&&(Ap=t),t>zp&&(zp=t)):t>Rp?xr(Ap,t)>xr(Ap,zp)&&(zp=t):xr(t,zp)>xr(Ap,zp)&&(Ap=t)}else Dp.push(Op=[Ap=t,zp=t]);n<Cp&&(Cp=n),n>Pp&&(Pp=n),Up=e,Rp=t}function vr(){Ed.point=dr}function _r(){Op[0]=Ap,Op[1]=zp,Ed.point=pr,Up=null}function yr(t,n){if(Up){var e=t-Rp;Sd.add(sd(e)>180?e+(e>0?360:-360):e)}else Lp=t,qp=n;Nd.point(t,n),dr(t,n)}function gr(){Nd.lineStart()}function mr(){yr(Lp,qp),Nd.lineEnd(),sd(Sd)>ed&&(Ap=-(zp=180)),Op[0]=Ap,Op[1]=zp,Up=null}function xr(t,n){return(n-=t)<0?n+360:n}function br(t,n){return t[0]-n[0]}function wr(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function Mr(t,n){t*=cd;var e=hd(n*=cd);Tr(e*hd(t),e*yd(t),yd(n))}function Tr(t,n,e){Yp+=(t-Yp)/++Fp,Bp+=(n-Bp)/Fp,jp+=(e-jp)/Fp}function kr(){Ad.point=Nr}function Nr(t,n){t*=cd;var e=hd(n*=cd);Qp=e*hd(t),Kp=e*yd(t),td=yd(n),Ad.point=Sr,Tr(Qp,Kp,td)}function Sr(t,n){t*=cd;var e=hd(n*=cd),r=e*hd(t),i=e*yd(t),o=yd(n),u=ld(md((u=Kp*o-td*i)*u+(u=td*r-Qp*o)*u+(u=Qp*i-Kp*r)*u),Qp*r+Kp*i+td*o);Ip+=u,Hp+=u*(Qp+(Qp=r)),Xp+=u*(Kp+(Kp=i)),$p+=u*(td+(td=o)),Tr(Qp,Kp,td)}function Er(){Ad.point=Mr}function Ar(){Ad.point=zr}function Cr(){Pr(Gp,Jp),Ad.point=Mr}function zr(t,n){Gp=t,Jp=n,t*=cd,n*=cd,Ad.point=Pr;var e=hd(n);Qp=e*hd(t),Kp=e*yd(t),td=yd(n),Tr(Qp,Kp,td)}function Pr(t,n){t*=cd;var e=hd(n*=cd),r=e*hd(t),i=e*yd(t),o=yd(n),u=Kp*o-td*i,a=td*r-Qp*o,c=Qp*i-Kp*r,s=md(u*u+a*a+c*c),f=Ge(s),l=s&&-f/s;Vp+=l*u,Wp+=l*a,Zp+=l*c,Ip+=f,Hp+=f*(Qp+(Qp=r)),Xp+=f*(Kp+(Kp=i)),$p+=f*(td+(td=o)),Tr(Qp,Kp,td)}function Rr(t,n){return[t>rd?t-ud:t<-rd?t+ud:t,n]}function Lr(t,n,e){return(t%=ud)?n||e?zd(Ur(t),Dr(n,e)):Ur(t):n||e?Dr(n,e):Rr}function qr(t){return function(n,e){return n+=t,[n>rd?n-ud:n<-rd?n+ud:n,e]}}function Ur(t){var n=qr(t);return n.invert=qr(-t),n}function Dr(t,n){function e(t,n){var e=hd(n),a=hd(t)*e,c=yd(t)*e,s=yd(n),f=s*r+a*i;return[ld(c*o-f*u,a*r-s*i),Ge(f*o+c*u)]}var r=hd(t),i=yd(t),o=hd(n),u=yd(n);return e.invert=function(t,n){var e=hd(n),a=hd(t)*e,c=yd(t)*e,s=yd(n),f=s*o-c*u;return[ld(c*o+s*u,a*r+f*i),Ge(f*r-a*i)]},e}function Or(t,n,e,r,i,o){if(e){var u=hd(n),a=yd(n),c=r*e;null==i?(i=n+r*ud,o=n-c/2):(i=Fr(u,i),o=Fr(u,o),(r>0?i<o:i>o)&&(i+=r*ud));for(var s,f=i;r>0?f>o:f<o;f-=c)s=ur([u,-a*hd(f),-a*yd(f)]),t.point(s[0],s[1])}}function Fr(t,n){(n=ar(n))[0]-=t,hr(n);var e=Ze(-n[1]);return((-n[2]<0?-e:e)+ud-ed)%ud}function Ir(t,n,e,r){this.x=t,this.z=n,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Yr(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r<n;)i.n=e=t[r],e.p=i,i=e;i.n=e=t[0],e.p=i}}function Br(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,a,s){var f=0,l=0;if(null==i||(f=u(i,a))!==(l=u(o,a))||c(i,o)<0^a>0)do{s.point(0===f||3===f?t:e,f>1?r:n)}while((f=(f+a+4)%4)!==l);else s.point(o[0],o[1])}function u(r,i){return sd(r[0]-t)<ed?i>0?0:3:sd(r[0]-e)<ed?i>0?2:1:sd(r[1]-n)<ed?i>0?1:0:i>0?3:2}function a(t,n){return c(t.x,n.x)}function c(t,n){var e=u(t,1),r=u(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(u){function c(t,n){i(t,n)&&w.point(t,n)}function s(){for(var n=0,e=0,i=h.length;e<i;++e)for(var o,u,a=h[e],c=1,s=a.length,f=a[0],l=f[0],p=f[1];c<s;++c)o=l,u=p,l=(f=a[c])[0],p=f[1],u<=r?p>r&&(l-o)*(r-u)>(p-u)*(t-o)&&++n:p<=r&&(l-o)*(r-u)<(p-u)*(t-o)&&--n;return n}function f(o,u){var a=i(o,u);if(h&&p.push([o,u]),x)d=o,v=u,_=a,x=!1,a&&(w.lineStart(),w.point(o,u));else if(a&&m)w.point(o,u);else{var c=[y=Math.max(Zd,Math.min(Wd,y)),g=Math.max(Zd,Math.min(Wd,g))],s=[o=Math.max(Zd,Math.min(Wd,o)),u=Math.max(Zd,Math.min(Wd,u))];Xd(c,s,t,n,e,r)?(m||(w.lineStart(),w.point(c[0],c[1])),w.point(s[0],s[1]),a||w.lineEnd(),b=!1):a&&(w.lineStart(),w.point(o,u),b=!1)}y=o,g=u,m=a}var l,h,p,d,v,_,y,g,m,x,b,w=u,M=Hd(),T={point:c,lineStart:function(){T.point=f,h&&h.push(p=[]),x=!0,m=!1,y=g=NaN},lineEnd:function(){l&&(f(d,v),_&&m&&M.rejoin(),l.push(M.result())),T.point=c,m&&w.lineEnd()},polygonStart:function(){w=M,l=[],h=[],b=!0},polygonEnd:function(){var t=s(),n=b&&t,e=(l=Cs(l)).length;(n||e)&&(u.polygonStart(),n&&(u.lineStart(),o(null,null,1,u),u.lineEnd()),e&&Vd(l,a,t,o,u),u.polygonEnd()),w=u,l=h=p=null}};return T}}function jr(){Kd.point=Kd.lineEnd=Qe}function Hr(t,n){Pd=t*=cd,Rd=yd(n*=cd),Ld=hd(n),Kd.point=Xr}function Xr(t,n){t*=cd;var e=yd(n*=cd),r=hd(n),i=sd(t-Pd),o=hd(i),u=r*yd(i),a=Ld*e-Rd*r*o,c=Rd*e+Ld*r*o;Qd.add(ld(md(u*u+a*a),c)),Pd=t,Rd=e,Ld=r}function $r(t,n){return!(!t||!ov.hasOwnProperty(t.type))&&ov[t.type](t,n)}function Vr(t,n){return 0===rv(t,n)}function Wr(t,n){var e=rv(t[0],t[1]);return rv(t[0],n)+rv(n,t[1])<=e+ed}function Zr(t,n){return!!Jd(t.map(Gr),Jr(n))}function Gr(t){return(t=t.map(Jr)).pop(),t}function Jr(t){return[t[0]*cd,t[1]*cd]}function Qr(t,n,e){var r=Ms(t,n-ed,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function Kr(t,n,e){var r=Ms(t,n-ed,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function ti(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return Ms(pd(o/_)*_,i,_).map(h).concat(Ms(pd(s/y)*y,c,y).map(p)).concat(Ms(pd(r/d)*d,e,d).filter(function(t){return sd(t%_)>ed}).map(f)).concat(Ms(pd(a/v)*v,u,v).filter(function(t){return sd(t%y)>ed}).map(l))}var e,r,i,o,u,a,c,s,f,l,h,p,d=10,v=d,_=90,y=360,g=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[h(o).concat(p(c).slice(1),h(i).reverse().slice(1),p(s).reverse().slice(1))]}},t.extent=function(n){return arguments.length?t.extentMajor(n).extentMinor(n):t.extentMinor()},t.extentMajor=function(n){return arguments.length?(o=+n[0][0],i=+n[1][0],s=+n[0][1],c=+n[1][1],o>i&&(n=o,o=i,i=n),s>c&&(n=s,s=c,c=n),t.precision(g)):[[o,s],[i,c]]},t.extentMinor=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],a=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),a>u&&(n=a,a=u,u=n),t.precision(g)):[[r,a],[e,u]]},t.step=function(n){return arguments.length?t.stepMajor(n).stepMinor(n):t.stepMinor()},t.stepMajor=function(n){return arguments.length?(_=+n[0],y=+n[1],t):[_,y]},t.stepMinor=function(n){return arguments.length?(d=+n[0],v=+n[1],t):[d,v]},t.precision=function(n){return arguments.length?(g=+n,f=Qr(a,u,90),l=Kr(r,e,g),h=Qr(s,c,90),p=Kr(o,i,g),t):g},t.extentMajor([[-180,-90+ed],[180,90-ed]]).extentMinor([[-180,-80-ed],[180,80+ed]])}function ni(){sv.point=ei}function ei(t,n){sv.point=ri,qd=Dd=t,Ud=Od=n}function ri(t,n){cv.add(Od*t-Dd*n),Dd=t,Od=n}function ii(){ri(qd,Ud)}function oi(t,n){vv+=t,_v+=n,++yv}function ui(){Tv.point=ai}function ai(t,n){Tv.point=ci,oi(Yd=t,Bd=n)}function ci(t,n){var e=t-Yd,r=n-Bd,i=md(e*e+r*r);gv+=i*(Yd+t)/2,mv+=i*(Bd+n)/2,xv+=i,oi(Yd=t,Bd=n)}function si(){Tv.point=oi}function fi(){Tv.point=hi}function li(){pi(Fd,Id)}function hi(t,n){Tv.point=pi,oi(Fd=Yd=t,Id=Bd=n)}function pi(t,n){var e=t-Yd,r=n-Bd,i=md(e*e+r*r);gv+=i*(Yd+t)/2,mv+=i*(Bd+n)/2,xv+=i,bv+=(i=Bd*t-Yd*n)*(Yd+t),wv+=i*(Bd+n),Mv+=3*i,oi(Yd=t,Bd=n)}function di(t){this._context=t}function vi(t,n){zv.point=_i,Nv=Ev=t,Sv=Av=n}function _i(t,n){Ev-=t,Av-=n,Cv.add(md(Ev*Ev+Av*Av)),Ev=t,Av=n}function yi(){this._string=[]}function gi(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function mi(t){return t.length>1}function xi(t,n){return((t=t.x)[0]<0?t[1]-id-ed:id-t[1])-((n=n.x)[0]<0?n[1]-id-ed:id-n[1])}function bi(t,n,e,r){var i,o,u=yd(t-e);return sd(u)>ed?fd((yd(n)*(o=hd(r))*yd(e)-yd(r)*(i=hd(n))*yd(t))/(i*o*u)):(n+r)/2}function wi(t){return function(n){var e=new Mi;for(var r in t)e[r]=t[r];return e.stream=n,e}}function Mi(){}function Ti(t,n,e){var r=n[1][0]-n[0][0],i=n[1][1]-n[0][1],o=t.clipExtent&&t.clipExtent();t.scale(150).translate([0,0]),null!=o&&t.clipExtent(null),Md(e,t.stream(dv));var u=dv.result(),a=Math.min(r/(u[1][0]-u[0][0]),i/(u[1][1]-u[0][1])),c=+n[0][0]+(r-a*(u[1][0]+u[0][0]))/2,s=+n[0][1]+(i-a*(u[1][1]+u[0][1]))/2;return null!=o&&t.clipExtent(o),t.scale(150*a).translate([c,s])}function ki(t,n,e){return Ti(t,[[0,0],n],e)}function Ni(t){return wi({point:function(n,e){n=t(n,e),this.stream.point(n[0],n[1])}})}function Si(t,n){function e(r,i,o,u,a,c,s,f,l,h,p,d,v,_){var y=s-r,g=f-i,m=y*y+g*g;if(m>4*n&&v--){var x=u+h,b=a+p,w=c+d,M=md(x*x+b*b+w*w),T=Ge(w/=M),k=sd(sd(w)-1)<ed||sd(o-l)<ed?(o+l)/2:ld(b,x),N=t(k,T),S=N[0],E=N[1],A=S-r,C=E-i,z=g*A-y*C;(z*z/m>n||sd((y*A+g*C)/m-.5)>.3||u*h+a*p+c*d<Uv)&&(e(r,i,o,u,a,c,S,E,k,x/=M,b/=M,w,v,_),_.point(S,E),e(S,E,k,x,b,w,s,f,l,h,p,d,v,_))}}return function(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function i(){y=NaN,w.point=o,n.lineStart()}function o(r,i){var o=ar([r,i]),u=t(r,i);e(y,g,_,m,x,b,y=u[0],g=u[1],_=r,m=o[0],x=o[1],b=o[2],qv,n),n.point(y,g)}function u(){w.point=r,n.lineEnd()}function a(){i(),w.point=c,w.lineEnd=s}function c(t,n){o(f=t,n),l=y,h=g,p=m,d=x,v=b,w.point=o}function s(){e(y,g,_,m,x,b,l,h,f,p,d,v,qv,n),w.lineEnd=u,u()}var f,l,h,p,d,v,_,y,g,m,x,b,w={point:r,lineStart:i,lineEnd:u,polygonStart:function(){n.polygonStart(),w.lineStart=a},polygonEnd:function(){n.polygonEnd(),w.lineStart=i}};return w}}function Ei(t){return Ai(function(){return t})()}function Ai(t){function n(t){return t=f(t[0]*cd,t[1]*cd),[t[0]*_+a,c-t[1]*_]}function e(t){return(t=f.invert((t[0]-a)/_,(c-t[1])/_))&&[t[0]*ad,t[1]*ad]}function r(t,n){return t=u(t,n),[t[0]*_+a,c-t[1]*_]}function i(){f=zd(s=Lr(b,w,M),u);var t=u(m,x);return a=y-t[0]*_,c=g+t[1]*_,o()}function o(){return d=v=null,n}var u,a,c,s,f,l,h,p,d,v,_=150,y=480,g=250,m=0,x=0,b=0,w=0,M=0,T=null,k=Rv,N=null,S=uv,E=.5,A=Dv(r,E);return n.stream=function(t){return d&&v===t?d:d=Ov(k(s,A(S(v=t))))},n.clipAngle=function(t){return arguments.length?(k=+t?Lv(T=t*cd,6*cd):(T=null,Rv),o()):T*ad},n.clipExtent=function(t){return arguments.length?(S=null==t?(N=l=h=p=null,uv):Br(N=+t[0][0],l=+t[0][1],h=+t[1][0],p=+t[1][1]),o()):null==N?null:[[N,l],[h,p]]},n.scale=function(t){return arguments.length?(_=+t,i()):_},n.translate=function(t){return arguments.length?(y=+t[0],g=+t[1],i()):[y,g]},n.center=function(t){return arguments.length?(m=t[0]%360*cd,x=t[1]%360*cd,i()):[m*ad,x*ad]},n.rotate=function(t){return arguments.length?(b=t[0]%360*cd,w=t[1]%360*cd,M=t.length>2?t[2]%360*cd:0,i()):[b*ad,w*ad,M*ad]},n.precision=function(t){return arguments.length?(A=Dv(r,E=t*t),o()):md(E)},n.fitExtent=function(t,e){return Ti(n,t,e)},n.fitSize=function(t,e){return ki(n,t,e)},function(){return u=t.apply(this,arguments),n.invert=u.invert&&e,i()}}function Ci(t){var n=0,e=rd/3,r=Ai(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*cd,e=t[1]*cd):[n*ad,e*ad]},i}function zi(t){function n(t,n){return[t*e,yd(n)/e]}var e=hd(t);return n.invert=function(t,n){return[t/e,Ge(n*e)]},n}function Pi(t,n){function e(t,n){var e=md(o-2*i*yd(n))/i;return[e*yd(t*=i),u-e*hd(t)]}var r=yd(t),i=(r+yd(n))/2;if(sd(i)<ed)return zi(t);var o=1+r*(2*i-r),u=md(o)/i;return e.invert=function(t,n){var e=u-n;return[ld(t,sd(e))/i*gd(e),Ge((o-(t*t+e*e)*i*i)/(2*i))]},e}function Ri(t){var n=t.length;return{point:function(e,r){for(var i=-1;++i<n;)t[i].point(e,r)},sphere:function(){for(var e=-1;++e<n;)t[e].sphere()},lineStart:function(){for(var e=-1;++e<n;)t[e].lineStart()},lineEnd:function(){for(var e=-1;++e<n;)t[e].lineEnd()},polygonStart:function(){for(var e=-1;++e<n;)t[e].polygonStart()},polygonEnd:function(){for(var e=-1;++e<n;)t[e].polygonEnd()}}}function Li(t){return function(n,e){var r=hd(n),i=hd(e),o=t(r*i);return[o*i*yd(n),o*yd(e)]}}function qi(t){return function(n,e){var r=md(n*n+e*e),i=t(r),o=yd(i),u=hd(i);return[ld(n*o,r*u),Ge(r&&e*o/r)]}}function Ui(t,n){return[t,vd(xd((id+n)/2))]}function Di(t){function n(){var n=rd*a(),u=o(jd(o.rotate()).invert([0,0]));return s(null==f?[[u[0]-n,u[1]-n],[u[0]+n,u[1]+n]]:t===Ui?[[Math.max(u[0]-n,f),e],[Math.min(u[0]+n,r),i]]:[[f,Math.max(u[1]-n,e)],[r,Math.min(u[1]+n,i)]])}var e,r,i,o=Ei(t),u=o.center,a=o.scale,c=o.translate,s=o.clipExtent,f=null;return o.scale=function(t){return arguments.length?(a(t),n()):a()},o.translate=function(t){return arguments.length?(c(t),n()):c()},o.center=function(t){return arguments.length?(u(t),n()):u()},o.clipExtent=function(t){return arguments.length?(null==t?f=e=r=i=null:(f=+t[0][0],e=+t[0][1],r=+t[1][0],i=+t[1][1]),n()):null==f?null:[[f,e],[r,i]]},n()}function Oi(t){return xd((id+t)/2)}function Fi(t,n){function e(t,n){o>0?n<-id+ed&&(n=-id+ed):n>id-ed&&(n=id-ed);var e=o/_d(Oi(n),i);return[e*yd(i*t),o-e*hd(i*t)]}var r=hd(t),i=t===n?yd(t):vd(r/hd(n))/vd(Oi(n)/Oi(t)),o=r*_d(Oi(t),i)/i;return i?(e.invert=function(t,n){var e=o-n,r=gd(i)*md(t*t+e*e);return[ld(t,sd(e))/i*gd(e),2*fd(_d(o/r,1/i))-id]},e):Ui}function Ii(t,n){return[t,n]}function Yi(t,n){function e(t,n){var e=o-n,r=i*t;return[e*yd(r),o-e*hd(r)]}var r=hd(t),i=t===n?yd(t):(r-hd(n))/(n-t),o=r/i+t;return sd(i)<ed?Ii:(e.invert=function(t,n){var e=o-n;return[ld(t,sd(e))/i*gd(e),o-gd(i)*md(t*t+e*e)]},e)}function Bi(t,n){var e=hd(n),r=hd(t)*e;return[e*yd(t)/r,yd(n)/r]}function ji(t,n,e,r){return 1===t&&1===n&&0===e&&0===r?uv:wi({point:function(i,o){this.stream.point(i*t+e,o*n+r)}})}function Hi(t,n){return[hd(n)*yd(t),yd(n)]}function Xi(t,n){var e=hd(n),r=1+hd(t)*e;return[e*yd(t)/r,yd(n)/r]}function $i(t,n){return[vd(xd((id+n)/2)),-t]}function Vi(t,n){return t.parent===n.parent?1:2}function Wi(t){return t.reduce(Zi,0)/t.length}function Zi(t,n){return t+n.x}function Gi(t){return 1+t.reduce(Ji,0)}function Ji(t,n){return Math.max(t,n.y)}function Qi(t){for(var n;n=t.children;)t=n[0];return t}function Ki(t){for(var n;n=t.children;)t=n[n.length-1];return t}function to(t){var n=0,e=t.children,r=e&&e.length;if(r)for(;--r>=0;)n+=e[r].value;else n=1;t.value=n}function no(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}function eo(t,n){var e,r,i,o,u,a=new uo(t),c=+t.value&&(a.value=t.value),s=[a];for(null==n&&(n=ro);e=s.pop();)if(c&&(e.value=+e.data.value),(i=n(e.data))&&(u=i.length))for(e.children=new Array(u),o=u-1;o>=0;--o)s.push(r=e.children[o]=new uo(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(oo)}function ro(t){return t.children}function io(t){t.data=t.data.data}function oo(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function uo(t){this.data=t,this.depth=this.height=0,this.parent=null}function ao(t){for(var n,e,r=t.length;r;)e=Math.random()*r--|0,n=t[r],t[r]=t[e],t[e]=n;return t}function co(t,n){var e,r;if(lo(n,t))return[n];for(e=0;e<t.length;++e)if(so(n,t[e])&&lo(vo(t[e],n),t))return[t[e],n];for(e=0;e<t.length-1;++e)for(r=e+1;r<t.length;++r)if(so(vo(t[e],t[r]),n)&&so(vo(t[e],n),t[r])&&so(vo(t[r],n),t[e])&&lo(_o(t[e],t[r],n),t))return[t[e],t[r],n];throw new Error}function so(t,n){var e=t.r-n.r,r=n.x-t.x,i=n.y-t.y;return e<0||e*e<r*r+i*i}function fo(t,n){var e=t.r-n.r+1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function lo(t,n){for(var e=0;e<n.length;++e)if(!fo(t,n[e]))return!1;return!0}function ho(t){switch(t.length){case 1:return po(t[0]);case 2:return vo(t[0],t[1]);case 3:return _o(t[0],t[1],t[2])}}function po(t){return{x:t.x,y:t.y,r:t.r}}function vo(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a-i,l=Math.sqrt(c*c+s*s);return{x:(e+o+c/l*f)/2,y:(r+u+s/l*f)/2,r:(l+i+a)/2}}function _o(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l=e.r,h=r-u,p=r-s,d=i-a,v=i-f,_=c-o,y=l-o,g=r*r+i*i-o*o,m=g-u*u-a*a+c*c,x=g-s*s-f*f+l*l,b=p*d-h*v,w=(d*x-v*m)/(2*b)-r,M=(v*_-d*y)/b,T=(p*m-h*x)/(2*b)-i,k=(h*y-p*_)/b,N=M*M+k*k-1,S=2*(o+w*M+T*k),E=w*w+T*T-o*o,A=-(N?(S+Math.sqrt(S*S-4*N*E))/(2*N):E/S);return{x:r+w+M*A,y:i+T+k*A,r:A}}function yo(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s=a*a+c*c;if(s){var f=.5+((u*=u)-(o*=o))/(2*s),l=Math.sqrt(Math.max(0,2*o*(u+s)-(u-=s)*u-o*o))/(2*s);e.x=r+f*a+l*c,e.y=i+f*c-l*a}else e.x=r+u,e.y=i}function go(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i-1e-6>e*e+r*r}function mo(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function xo(t){this._=t,this.next=null,this.previous=null}function bo(t){if(!(i=t.length))return 0;var n,e,r,i,o,u,a,c,s,f,l;if(n=t[0],n.x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;yo(e,n,r=t[2]),n=new xo(n),e=new xo(e),r=new xo(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(a=3;a<i;++a){yo(n._,e._,r=t[a]),r=new xo(r),c=e.next,s=n.previous,f=e._.r,l=n._.r;do{if(f<=l){if(go(c._,r._)){e=c,n.next=e,e.previous=n,--a;continue t}f+=c._.r,c=c.next}else{if(go(s._,r._)){(n=s).next=e,e.previous=n,--a;continue t}l+=s._.r,s=s.previous}}while(c!==s.next);for(r.previous=n,r.next=e,n.next=e.previous=e=r,o=mo(n);(r=r.next)!==e;)(u=mo(r))<o&&(n=r,o=u);e=n.next}for(n=[e._],r=e;(r=r.next)!==e;)n.push(r._);for(r=Hv(n),a=0;a<i;++a)n=t[a],n.x-=r.x,n.y-=r.y;return r.r}function wo(t){return null==t?null:Mo(t)}function Mo(t){if("function"!=typeof t)throw new Error;return t}function To(){return 0}function ko(t){return Math.sqrt(t.value)}function No(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}function So(t,n){return function(e){if(r=e.children){var r,i,o,u=r.length,a=t(e)*n||0;if(a)for(i=0;i<u;++i)r[i].r+=a;if(o=bo(r),a)for(i=0;i<u;++i)r[i].r-=a;e.r=o+a}}}function Eo(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n.x,n.y=e.y+t*n.y)}}function Ao(t){return t.id}function Co(t){return t.parentId}function zo(t,n){return t.parent===n.parent?1:2}function Po(t){var n=t.children;return n?n[0]:t.t}function Ro(t){var n=t.children;return n?n[n.length-1]:t.t}function Lo(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function qo(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)}function Uo(t,n,e){return t.a.parent===n.parent?t.a:e}function Do(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function Oo(t){for(var n,e,r,i,o,u=new Do(t,0),a=[u];n=a.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)a.push(e=n.children[i]=new Do(r[i],i)),e.parent=n;return(u.parent=new Do(null,0)).children=[u],u}function Fo(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,_,y=[],g=n.children,m=0,x=0,b=g.length,w=n.value;m<b;){c=i-e,s=o-r;do{f=g[x++].value}while(!f&&x<b);for(l=h=f,_=f*f*(v=Math.max(s/c,c/s)/(w*t)),d=Math.max(h/_,_/l);x<b;++x){if(f+=a=g[x].value,a<l&&(l=a),a>h&&(h=a),_=f*f*v,(p=Math.max(h/_,_/l))>d){f-=a;break}d=p}y.push(u={value:f,dice:c<s,children:g.slice(m,x)}),u.dice?Vv(u,e,r,i,w?r+=s*f/w:o):Jv(u,e,r,w?e+=c*f/w:i,o),w-=f,m=x}return y}function Io(t,n){return t[0]-n[0]||t[1]-n[1]}function Yo(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&n_(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function Bo(t){this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function jo(t){if(!t._start)try{Ho(t)}catch(n){if(t._tasks[t._ended+t._active-1])$o(t,n);else if(!t._data)throw n}}function Ho(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._ended+t._active,e=t._tasks[n],r=e.length-1,i=e[r];e[r]=Xo(t,n),--t._waiting,++t._active,e=i.apply(null,e),t._tasks[n]&&(t._tasks[n]=e||r_)}}function Xo(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ended,t._tasks[n]=null,null==t._error&&(null!=e?$o(t,e):(t._data[n]=r,t._waiting?jo(t):Vo(t))))}}function $o(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t._waiting=NaN;--r>=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(n){}t._active=NaN,Vo(t)}function Vo(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._call(t._error,n)}}function Wo(t){if(null==t)t=1/0;else if(!((t=+t)>=1))throw new Error("invalid concurrency");return new Bo(t)}function Zo(t){return function(n,e){t(null==n?e:null)}}function Go(t){var n=t.responseType;return n&&"text"!==n?t.response:t.responseText}function Jo(t,n){return function(e){return t(e.responseText,n)}}function Qo(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==M_)return i;e.set(o,u=r.push(n))}return t[(u-1)%t.length]}var e=we(),r=[],i=M_;return t=null==t?[]:w_.call(t),n.domain=function(t){if(!arguments.length)return r.slice();r=[],e=we();for(var i,o,u=-1,a=t.length;++u<a;)e.has(o=(i=t[u])+"")||e.set(o,r.push(i));return n},n.range=function(e){return arguments.length?(t=w_.call(e),n):t.slice()},n.unknown=function(t){return arguments.length?(i=t,n):i},n.copy=function(){return Qo().domain(r).range(t).unknown(i)},n}function Ko(){function t(){var t=i().length,r=u[1]<u[0],l=u[r-0],h=u[1-r];n=(h-l)/Math.max(1,t-c+2*s),a&&(n=Math.floor(n)),l+=(h-l-n*(t-c))*f,e=n*(1-c),a&&(l=Math.round(l),e=Math.round(e));var p=Ms(t).map(function(t){return l+n*t});return o(r?p.reverse():p)}var n,e,r=Qo().unknown(void 0),i=r.domain,o=r.range,u=[0,1],a=!1,c=0,s=0,f=.5;return delete r.unknown,r.domain=function(n){return arguments.length?(i(n),t()):i()},r.range=function(n){return arguments.length?(u=[+n[0],+n[1]],t()):u.slice()},r.rangeRound=function(n){return u=[+n[0],+n[1]],a=!0,t()},r.bandwidth=function(){return e},r.step=function(){return n},r.round=function(n){return arguments.length?(a=!!n,t()):a},r.padding=function(n){return arguments.length?(c=s=Math.max(0,Math.min(1,n)),t()):c},r.paddingInner=function(n){return arguments.length?(c=Math.max(0,Math.min(1,n)),t()):c},r.paddingOuter=function(n){return arguments.length?(s=Math.max(0,Math.min(1,n)),t()):s},r.align=function(n){return arguments.length?(f=Math.max(0,Math.min(1,n)),t()):f},r.copy=function(){return Ko().domain(i()).range(u).round(a).paddingInner(c).paddingOuter(s).align(f)},t()}function tu(t){var n=t.copy;return t.padding=t.paddingOuter,delete t.paddingInner,delete t.paddingOuter,t.copy=function(){return tu(n())},t}function nu(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:T_(n)}function eu(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=n?0:t>=e?1:r(t)}}}function ru(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=0?n:t>=1?e:r(t)}}}function iu(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o<i?(i=e(o,i),u=r(a,u)):(i=e(i,o),u=r(u,a)),function(t){return u(i(t))}}function ou(t,n,e,r){var i=Math.min(t.length,n.length)-1,o=new Array(i),u=new Array(i),a=-1;for(t[i]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());++a<i;)o[a]=e(t[a],t[a+1]),u[a]=r(n[a],n[a+1]);return function(n){var e=hs(t,n,1,i)-1;return u[e](o[e](n))}}function uu(t,n){return n.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp())}function au(t,n){function e(){return i=Math.min(a.length,c.length)>2?ou:iu,o=u=null,r}function r(n){return(o||(o=i(a,c,f?eu(t):t,s)))(+n)}var i,o,u,a=N_,c=N_,s=cl,f=!1;return r.invert=function(t){return(u||(u=i(c,a,nu,f?ru(n):n)))(+t)},r.domain=function(t){return arguments.length?(a=b_.call(t,k_),e()):a.slice()},r.range=function(t){return arguments.length?(c=w_.call(t),e()):c.slice()},r.rangeRound=function(t){return c=w_.call(t),s=sl,e()},r.clamp=function(t){return arguments.length?(f=!!t,e()):f},r.interpolate=function(t){return arguments.length?(s=t,e()):s},e()}function cu(t){var n=t.domain;return t.ticks=function(t){var e=n();return Ss(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){return S_(n(),t,e)},t.nice=function(e){null==e&&(e=10);var i,o=n(),u=0,a=o.length-1,c=o[u],s=o[a];return s<c&&(i=c,c=s,s=i,i=u,u=a,a=i),(i=r(c,s,e))>0?i=r(c=Math.floor(c/i)*i,s=Math.ceil(s/i)*i,e):i<0&&(i=r(c=Math.ceil(c*i)/i,s=Math.floor(s*i)/i,e)),i>0?(o[u]=Math.floor(c/i)*i,o[a]=Math.ceil(s/i)*i,n(o)):i<0&&(o[u]=Math.ceil(c*i)/i,o[a]=Math.floor(s*i)/i,n(o)),t},t}function su(){var t=au(nu,rl);return t.copy=function(){return uu(t,su())},cu(t)}function fu(){function t(t){return+t}var n=[0,1];return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=b_.call(e,k_),t):n.slice()},t.copy=function(){return fu().domain(n)},cu(t)}function lu(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t)/n}:T_(n)}function hu(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-t,1-e)}:function(e){return Math.pow(n,e)*Math.pow(t,1-e)}}function pu(t){return isFinite(t)?+("1e"+t):t<0?0:t}function du(t){return 10===t?pu:t===Math.E?Math.exp:function(n){return Math.pow(t,n)}}function vu(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),function(n){return Math.log(n)/t})}function _u(t){return function(n){return-t(-n)}}function yu(){function n(){return o=vu(i),u=du(i),r()[0]<0&&(o=_u(o),u=_u(u)),e}var e=au(lu,hu).domain([1,10]),r=e.domain,i=10,o=vu(10),u=du(10);return e.base=function(t){return arguments.length?(i=+t,n()):i},e.domain=function(t){return arguments.length?(r(t),n()):r()},e.ticks=function(t){var n,e=r(),a=e[0],c=e[e.length-1];(n=c<a)&&(h=a,a=c,c=h);var s,f,l,h=o(a),p=o(c),d=null==t?10:+t,v=[];if(!(i%1)&&p-h<d){if(h=Math.round(h)-1,p=Math.round(p)+1,a>0){for(;h<p;++h)for(f=1,s=u(h);f<i;++f)if(!((l=s*f)<a)){if(l>c)break;v.push(l)}}else for(;h<p;++h)for(f=i-1,s=u(h);f>=1;--f)if(!((l=s*f)<a)){if(l>c)break;v.push(l)}}else v=Ss(h,p,Math.min(p-h,d)).map(u);return n?v.reverse():v},e.tickFormat=function(n,r){if(null==r&&(r=10===i?".0e":","),"function"!=typeof r&&(r=t.format(r)),n===1/0)return r;null==n&&(n=10);var a=Math.max(1,i*n/e.ticks().length);return function(t){var n=t/u(Math.round(o(t)));return n*i<i-.5&&(n*=i),n<=a?r(t):""}},e.nice=function(){return r(E_(r(),{floor:function(t){return u(Math.floor(o(t)))},ceil:function(t){return u(Math.ceil(o(t)))}}))},e.copy=function(){return uu(e,yu().base(i))},e}function gu(t,n){return t<0?-Math.pow(-t,n):Math.pow(t,n)}function mu(){var t=1,n=au(function(n,e){return(e=gu(e,t)-(n=gu(n,t)))?function(r){return(gu(r,t)-n)/e}:T_(e)},function(n,e){return e=gu(e,t)-(n=gu(n,t)),function(r){return gu(n+e*r,1/t)}}),e=n.domain;return n.exponent=function(n){return arguments.length?(t=+n,e(e())):t},n.copy=function(){return uu(n,mu().exponent(t))},cu(n)}function xu(){function t(){var t=0,o=Math.max(1,r.length);for(i=new Array(o-1);++t<o;)i[t-1]=As(e,t/o);return n}function n(t){if(!isNaN(t=+t))return r[hs(i,t)]}var e=[],r=[],i=[];return n.invertExtent=function(t){var n=r.indexOf(t);return n<0?[NaN,NaN]:[n>0?i[n-1]:e[0],n<i.length?i[n]:e[e.length-1]]},n.domain=function(n){if(!arguments.length)return e.slice();e=[];for(var r,i=0,o=n.length;i<o;++i)null==(r=n[i])||isNaN(r=+r)||e.push(r);return e.sort(ss),t()},n.range=function(n){return arguments.length?(r=w_.call(n),t()):r.slice()},n.quantiles=function(){return i.slice()},n.copy=function(){return xu().domain(e).range(r)},n}function bu(){function t(t){if(t<=t)return u[hs(o,t,0,i)]}function n(){var n=-1;for(o=new Array(i);++n<i;)o[n]=((n+1)*r-(n-i)*e)/(i+1);return t}var e=0,r=1,i=1,o=[.5],u=[0,1];return t.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n()):[e,r]},t.range=function(t){return arguments.length?(i=(u=w_.call(t)).length-1,n()):u.slice()},t.invertExtent=function(t){var n=u.indexOf(t);return n<0?[NaN,NaN]:n<1?[e,o[0]]:n>=i?[o[i-1],r]:[o[n-1],o[n]]},t.copy=function(){return bu().domain([e,r]).range(u)},cu(t)}function wu(){function t(t){if(t<=t)return e[hs(n,t,0,r)]}var n=[.5],e=[0,1],r=1;return t.domain=function(i){return arguments.length?(n=w_.call(i),r=Math.min(n.length,e.length-1),t):n.slice()},t.range=function(i){return arguments.length?(e=w_.call(i),r=Math.min(n.length,e.length-1),t):e.slice()},t.invertExtent=function(t){var r=e.indexOf(t);return[n[r-1],n[r]]},t.copy=function(){return wu().domain(n).range(e)},t}function Mu(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.floor=i,i.ceil=function(e){return t(e=new Date(e-1)),n(e,1),t(e),e},i.round=function(t){var n=i(t),e=i.ceil(t);return t-n<e-t?n:e},i.offset=function(t,e){return n(t=new Date(+t),null==e?1:Math.floor(e)),t},i.range=function(e,r,o){var u=[];if(e=i.ceil(e),o=null==o?1:Math.floor(o),!(e<r&&o>0))return u;do{u.push(new Date(+e))}while(n(e,o),t(e),e<r);return u},i.filter=function(e){return Mu(function(n){if(n>=n)for(;t(n),!e(n);)n.setTime(n-1)},function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;n(t,-1),!e(t););else for(;--r>=0;)for(;n(t,1),!e(t););})},e&&(i.count=function(n,r){return A_.setTime(+n),C_.setTime(+r),t(A_),t(C_),Math.floor(e(A_,C_))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(n){return r(n)%t==0}:function(n){return i.count(0,n)%t==0}):i:null}),i}function Tu(t){return Mu(function(n){n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+7*n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*R_)/L_})}function ku(t){return Mu(function(n){n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+7*n)},function(t,n){return(n-t)/L_})}function Nu(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return n.setFullYear(t.y),n}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Su(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return n.setUTCFullYear(t.y),n}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Eu(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}function Au(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=0,s=t.length;for(e instanceof Date||(e=new Date(+e));++a<s;)37===t.charCodeAt(a)&&(u.push(t.slice(c,a)),null!=(i=Py[r=t.charAt(++a)])?r=t.charAt(++a):i="e"===r?" ":"0",(o=n[r])&&(r=o(e,i)),u.push(r),c=a+1);return u.push(t.slice(c,a)),u.join("")}}function e(t,n){return function(e){var i=Eu(1900);if(r(i,t,e+="",0)!=e.length)return null;if("p"in i&&(i.H=i.H%12+12*i.p),"W"in i||"U"in i){"w"in i||(i.w="W"in i?1:0);var o="Z"in i?Su(Eu(i.y)).getUTCDay():n(Eu(i.y)).getDay();i.m=0,i.d="W"in i?(i.w+6)%7+7*i.W-(o+5)%7:i.w+7*i.U-(o+6)%7}return"Z"in i?(i.H+=i.Z/100|0,i.M+=i.Z%100,Su(i)):n(i)}}function r(t,n,e,r){for(var i,o,u=0,a=n.length,c=e.length;u<a;){if(r>=c)return-1;if(37===(i=n.charCodeAt(u++))){if(i=n.charAt(u++),!(o=T[i in Py?n.charAt(u++):i])||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}var i=t.dateTime,o=t.date,u=t.time,a=t.periods,c=t.days,s=t.shortDays,f=t.months,l=t.shortMonths,h=Pu(a),p=Ru(a),d=Pu(c),v=Ru(c),_=Pu(s),y=Ru(s),g=Pu(f),m=Ru(f),x=Pu(l),b=Ru(l),w={a:function(t){return s[t.getDay()]},A:function(t){return c[t.getDay()]},b:function(t){return l[t.getMonth()]},B:function(t){return f[t.getMonth()]},c:null,d:Wu,e:Wu,H:Zu,I:Gu,j:Ju,L:Qu,m:Ku,M:ta,p:function(t){return a[+(t.getHours()>=12)]},S:na,U:ea,w:ra,W:ia,x:null,X:null,y:oa,Y:ua,Z:aa,"%":wa},M={a:function(t){return s[t.getUTCDay()]},A:function(t){return c[t.getUTCDay()]},b:function(t){return l[t.getUTCMonth()]},B:function(t){return f[t.getUTCMonth()]},c:null,d:ca,e:ca,H:sa,I:fa,j:la,L:ha,m:pa,M:da,p:function(t){return a[+(t.getUTCHours()>=12)]},S:va,U:_a,w:ya,W:ga,x:null,X:null,y:ma,Y:xa,Z:ba,"%":wa},T={a:function(t,n,e){var r=_.exec(n.slice(e));return r?(t.w=y[r[0].toLowerCase()],e+r[0].length):-1},A:function(t,n,e){var r=d.exec(n.slice(e));return r?(t.w=v[r[0].toLowerCase()],e+r[0].length):-1},b:function(t,n,e){var r=x.exec(n.slice(e));return r?(t.m=b[r[0].toLowerCase()],e+r[0].length):-1},B:function(t,n,e){var r=g.exec(n.slice(e));return r?(t.m=m[r[0].toLowerCase()],e+r[0].length):-1},c:function(t,n,e){return r(t,i,n,e)},d:Yu,e:Yu,H:ju,I:ju,j:Bu,L:$u,m:Iu,M:Hu,p:function(t,n,e){var r=h.exec(n.slice(e));return r?(t.p=p[r[0].toLowerCase()],e+r[0].length):-1},S:Xu,U:qu,w:Lu,W:Uu,x:function(t,n,e){return r(t,o,n,e)},X:function(t,n,e){return r(t,u,n,e)},y:Ou,Y:Du,Z:Fu,"%":Vu};return w.x=n(o,w),w.X=n(u,w),w.c=n(i,w),M.x=n(o,M),M.X=n(u,M),M.c=n(i,M),{format:function(t){var e=n(t+="",w);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",Nu);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",M);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,Su);return n.toString=function(){return t},n}}}function Cu(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o<e?new Array(e-o+1).join(n)+i:i)}function zu(t){return t.replace(qy,"\\$&")}function Pu(t){return new RegExp("^(?:"+t.map(zu).join("|")+")","i")}function Ru(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]=e;return n}function Lu(t,n,e){var r=Ry.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function qu(t,n,e){var r=Ry.exec(n.slice(e));return r?(t.U=+r[0],e+r[0].length):-1}function Uu(t,n,e){var r=Ry.exec(n.slice(e));return r?(t.W=+r[0],e+r[0].length):-1}function Du(t,n,e){var r=Ry.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function Ou(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function Fu(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function Iu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function Yu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function Bu(t,n,e){var r=Ry.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function ju(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function Hu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function Xu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function $u(t,n,e){var r=Ry.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function Vu(t,n,e){var r=Ly.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function Wu(t,n){return Cu(t.getDate(),n,2)}function Zu(t,n){return Cu(t.getHours(),n,2)}function Gu(t,n){return Cu(t.getHours()%12||12,n,2)}function Ju(t,n){return Cu(1+Y_.count(oy(t),t),n,3)}function Qu(t,n){return Cu(t.getMilliseconds(),n,3)}function Ku(t,n){return Cu(t.getMonth()+1,n,2)}function ta(t,n){return Cu(t.getMinutes(),n,2)}function na(t,n){return Cu(t.getSeconds(),n,2)}function ea(t,n){return Cu(j_.count(oy(t),t),n,2)}function ra(t){return t.getDay()}function ia(t,n){return Cu(H_.count(oy(t),t),n,2)}function oa(t,n){return Cu(t.getFullYear()%100,n,2)}function ua(t,n){return Cu(t.getFullYear()%1e4,n,4)}function aa(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+Cu(n/60|0,"0",2)+Cu(n%60,"0",2)}function ca(t,n){return Cu(t.getUTCDate(),n,2)}function sa(t,n){return Cu(t.getUTCHours(),n,2)}function fa(t,n){return Cu(t.getUTCHours()%12||12,n,2)}function la(t,n){return Cu(1+ly.count(Ay(t),t),n,3)}function ha(t,n){return Cu(t.getUTCMilliseconds(),n,3)}function pa(t,n){return Cu(t.getUTCMonth()+1,n,2)}function da(t,n){return Cu(t.getUTCMinutes(),n,2)}function va(t,n){return Cu(t.getUTCSeconds(),n,2)}function _a(t,n){return Cu(py.count(Ay(t),t),n,2)}function ya(t){return t.getUTCDay()}function ga(t,n){return Cu(dy.count(Ay(t),t),n,2)}function ma(t,n){return Cu(t.getUTCFullYear()%100,n,2)}function xa(t,n){return Cu(t.getUTCFullYear()%1e4,n,4)}function ba(){return"+0000"}function wa(){return"%"}function Ma(n){return Cy=Au(n),t.timeFormat=Cy.format,t.timeParse=Cy.parse,t.utcFormat=Cy.utcFormat,t.utcParse=Cy.utcParse,Cy}function Ta(t){return new Date(t)}function ka(t){return t instanceof Date?+t:+new Date(+t)}function Na(t,n,e,r,o,u,a,c,s){function f(i){return(a(i)<i?v:u(i)<i?_:o(i)<i?y:r(i)<i?g:n(i)<i?e(i)<i?m:x:t(i)<i?b:w)(i)}function l(n,e,r,o){if(null==n&&(n=10),"number"==typeof n){var u=Math.abs(r-e)/n,a=fs(function(t){return t[2]}).right(M,u);a===M.length?(o=i(e/Hy,r/Hy,n),n=t):a?(o=(a=M[u/M[a-1][2]<M[a][2]/u?a-1:a])[1],n=a[0]):(o=i(e,r,n),n=c)}return null==o?n:n.every(o)}var h=au(nu,rl),p=h.invert,d=h.domain,v=s(".%L"),_=s(":%S"),y=s("%I:%M"),g=s("%I %p"),m=s("%a %d"),x=s("%b %d"),b=s("%B"),w=s("%Y"),M=[[a,1,Oy],[a,5,5*Oy],[a,15,15*Oy],[a,30,30*Oy],[u,1,Fy],[u,5,5*Fy],[u,15,15*Fy],[u,30,30*Fy],[o,1,Iy],[o,3,3*Iy],[o,6,6*Iy],[o,12,12*Iy],[r,1,Yy],[r,2,2*Yy],[e,1,By],[n,1,jy],[n,3,3*jy],[t,1,Hy]];return h.invert=function(t){return new Date(p(t))},h.domain=function(t){return arguments.length?d(b_.call(t,ka)):d().map(Ta)},h.ticks=function(t,n){var e,r=d(),i=r[0],o=r[r.length-1],u=o<i;return u&&(e=i,i=o,o=e),e=l(t,i,o,n),e=e?e.range(i,o+1):[],u?e.reverse():e},h.tickFormat=function(t,n){return null==n?f:s(n)},h.nice=function(t,n){var e=d();return(t=l(t,e[0],e[e.length-1],n))?d(E_(e,t)):h},h.copy=function(){return uu(h,Na(t,n,e,r,o,u,a,c,s))},h}function Sa(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}function Ea(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Math.min(1,o)):o)}var e=0,r=1,i=!1;return n.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n):[e,r]},n.clamp=function(t){return arguments.length?(i=!!t,n):i},n.interpolator=function(e){return arguments.length?(t=e,n):t},n.copy=function(){return Ea(t).domain([e,r]).clamp(i)},cu(n)}function Aa(t){return t>1?0:t<-1?pg:Math.acos(t)}function Ca(t){return t>=1?dg:t<=-1?-dg:Math.asin(t)}function za(t){return t.innerRadius}function Pa(t){return t.outerRadius}function Ra(t){return t.startAngle}function La(t){return t.endAngle}function qa(t){return t&&t.padAngle}function Ua(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}function Da(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/lg(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,_=(h+d)/2,y=(p+v)/2,g=d-h,m=v-p,x=g*g+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*lg(cg(0,b*b*x-w*w)),T=(w*m-g*M)/x,k=(-w*g-m*M)/x,N=(w*m+g*M)/x,S=(-w*g+m*M)/x,E=T-_,A=k-y,C=N-_,z=S-y;return E*E+A*A>C*C+z*z&&(T=N,k=S),{cx:T,cy:k,x01:-f,y01:-l,x11:T*(i/b-1),y11:k*(i/b-1)}}function Oa(t){this._context=t}function Fa(t){return t[0]}function Ia(t){return t[1]}function Ya(t){this._curve=t}function Ba(t){function n(n){return new Ya(t(n))}return n._curve=t,n}function ja(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(Ba(t)):n()._curve},t}function Ha(t){return t.source}function Xa(t){return t.target}function $a(t){function n(){var n,a=kg.call(arguments),c=e.apply(this,a),s=r.apply(this,a);if(u||(u=n=ve()),t(u,+i.apply(this,(a[0]=c,a)),+o.apply(this,a),+i.apply(this,(a[0]=s,a)),+o.apply(this,a)),n)return u=null,n+""||null}var e=Ha,r=Xa,i=Fa,o=Ia,u=null;return n.source=function(t){return arguments.length?(e=t,n):e},n.target=function(t){return arguments.length?(r=t,n):r},n.x=function(t){return arguments.length?(i="function"==typeof t?t:ig(+t),n):i},n.y=function(t){return arguments.length?(o="function"==typeof t?t:ig(+t),n):o},n.context=function(t){return arguments.length?(u=null==t?null:t,n):u},n}function Va(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n=(n+r)/2,e,n,i,r,i)}function Wa(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n,e=(e+i)/2,r,e,r,i)}function Za(t,n,e,r,i){var o=Tg(n,e),u=Tg(n,e=(e+i)/2),a=Tg(r,e),c=Tg(r,i);t.moveTo(o[0],o[1]),t.bezierCurveTo(u[0],u[1],a[0],a[1],c[0],c[1])}function Ga(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Ja(t){this._context=t}function Qa(t){this._context=t}function Ka(t){this._context=t}function tc(t,n){this._basis=new Ja(t),this._beta=n}function nc(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function ec(t,n){this._context=t,this._k=(1-n)/6}function rc(t,n){this._context=t,this._k=(1-n)/6}function ic(t,n){this._context=t,this._k=(1-n)/6}function oc(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>hg){var a=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*a-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*a-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>hg){var s=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,f=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*s+t._x1*t._l23_2a-n*t._l12_2a)/f,u=(u*s+t._y1*t._l23_2a-e*t._l12_2a)/f}t._context.bezierCurveTo(r,i,o,u,t._x2,t._y2)}function uc(t,n){this._context=t,this._alpha=n}function ac(t,n){this._context=t,this._alpha=n}function cc(t,n){this._context=t,this._alpha=n}function sc(t){this._context=t}function fc(t){return t<0?-1:1}function lc(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),u=(e-t._y1)/(i||r<0&&-0),a=(o*i+u*r)/(r+i);return(fc(o)+fc(u))*Math.min(Math.abs(o),Math.abs(u),.5*Math.abs(a))||0}function hc(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function pc(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._context.bezierCurveTo(r+a,i+a*n,o-a,u-a*e,o,u)}function dc(t){this._context=t}function vc(t){this._context=new _c(t)}function _c(t){this._context=t}function yc(t){this._context=t}function gc(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new Array(r);for(i[0]=0,o[0]=2,u[0]=t[0]+2*t[1],n=1;n<r-1;++n)i[n]=1,o[n]=4,u[n]=4*t[n]+2*t[n+1];for(i[r-1]=2,o[r-1]=7,u[r-1]=8*t[r-1]+t[r],n=1;n<r;++n)e=i[n]/o[n-1],o[n]-=e,u[n]-=e*u[n-1];for(i[r-1]=u[r-1]/o[r-1],n=r-2;n>=0;--n)i[n]=(u[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n<r-1;++n)o[n]=2*t[n+1]-i[n+1];return[i,o]}function mc(t,n){this._context=t,this._t=n}function xc(t,n){return t[n]}function bc(t){for(var n,e=0,r=-1,i=t.length;++r<i;)(n=+t[r][1])&&(e+=n);return e}function wc(t){return t[0]}function Mc(t){return t[1]}function Tc(){this._=null}function kc(t){t.U=t.C=t.L=t.R=t.P=t.N=null}function Nc(t,n){var e=n,r=n.R,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Sc(t,n){var e=n,r=n.L,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Ec(t){for(;t.L;)t=t.L;return t}function Ac(t,n,e,r){var i=[null,null],o=um.push(i)-1;return i.left=t,i.right=n,e&&zc(i,t,n,e),r&&zc(i,n,t,r),im[t.index].halfedges.push(o),im[n.index].halfedges.push(o),i}function Cc(t,n,e){var r=[n,e];return r.left=t,r}function zc(t,n,e,r){t[0]||t[1]?t.left===e?t[1]=r:t[0]=r:(t[0]=r,t.left=n,t.right=e)}function Pc(t,n,e,r,i){var o,u=t[0],a=t[1],c=u[0],s=u[1],f=0,l=1,h=a[0]-c,p=a[1]-s;if(o=n-c,h||!(o>0)){if(o/=h,h<0){if(o<f)return;o<l&&(l=o)}else if(h>0){if(o>l)return;o>f&&(f=o)}if(o=r-c,h||!(o<0)){if(o/=h,h<0){if(o>l)return;o>f&&(f=o)}else if(h>0){if(o<f)return;o<l&&(l=o)}if(o=e-s,p||!(o>0)){if(o/=p,p<0){if(o<f)return;o<l&&(l=o)}else if(p>0){if(o>l)return;o>f&&(f=o)}if(o=i-s,p||!(o<0)){if(o/=p,p<0){if(o>l)return;o>f&&(f=o)}else if(p>0){if(o<f)return;o<l&&(l=o)}return!(f>0||l<1)||(f>0&&(t[0]=[c+f*h,s+f*p]),l<1&&(t[1]=[c+l*h,s+l*p]),!0)}}}}}function Rc(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,f=t.right,l=s[0],h=s[1],p=f[0],d=f[1],v=(l+p)/2,_=(h+d)/2;if(d===h){if(v<n||v>=r)return;if(l>p){if(c){if(c[1]>=i)return}else c=[v,e];o=[v,i]}else{if(c){if(c[1]<e)return}else c=[v,i];o=[v,e]}}else if(u=(l-p)/(d-h),a=_-u*v,u<-1||u>1)if(l>p){if(c){if(c[1]>=i)return}else c=[(e-a)/u,e];o=[(i-a)/u,i]}else{if(c){if(c[1]<e)return}else c=[(i-a)/u,i];o=[(e-a)/u,e]}else if(h<d){if(c){if(c[0]>=r)return}else c=[n,u*n+a];o=[r,u*r+a]}else{if(c){if(c[0]<n)return}else c=[r,u*r+a];o=[n,u*n+a]}return t[0]=c,t[1]=o,!0}function Lc(t,n,e,r){for(var i,o=um.length;o--;)Rc(i=um[o],t,n,e,r)&&Pc(i,t,n,e,r)&&(Math.abs(i[0][0]-i[1][0])>sm||Math.abs(i[0][1]-i[1][1])>sm)||delete um[o]}function qc(t){return im[t.index]={site:t,halfedges:[]}}function Uc(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e),i?Math.atan2(i[1]-r[1],i[0]-r[0]):(e===r?(r=n[1],i=n[0]):(r=n[0],i=n[1]),Math.atan2(r[0]-i[0],i[1]-r[1]))}function Dc(t,n){return n[+(n.left!==t.site)]}function Oc(t,n){return n[+(n.left===t.site)]}function Fc(){for(var t,n,e,r,i=0,o=im.length;i<o;++i)if((t=im[i])&&(r=(n=t.halfedges).length)){var u=new Array(r),a=new Array(r);for(e=0;e<r;++e)u[e]=e,a[e]=Uc(t,um[n[e]]);for(u.sort(function(t,n){return a[n]-a[t]}),e=0;e<r;++e)a[e]=n[u[e]];for(e=0;e<r;++e)n[e]=a[e]}}function Ic(t,n,e,r){var i,o,u,a,c,s,f,l,h,p,d,v,_=im.length,y=!0;for(i=0;i<_;++i)if(o=im[i]){for(u=o.site,a=(c=o.halfedges).length;a--;)um[c[a]]||c.splice(a,1);for(a=0,s=c.length;a<s;)d=(p=Oc(o,um[c[a]]))[0],v=p[1],l=(f=Dc(o,um[c[++a%s]]))[0],h=f[1],(Math.abs(d-l)>sm||Math.abs(v-h)>sm)&&(c.splice(a,0,um.push(Cc(u,p,Math.abs(d-t)<sm&&r-v>sm?[t,Math.abs(l-t)<sm?h:r]:Math.abs(v-r)<sm&&e-d>sm?[Math.abs(h-r)<sm?l:e,r]:Math.abs(d-e)<sm&&v-n>sm?[e,Math.abs(l-e)<sm?h:n]:Math.abs(v-n)<sm&&d-t>sm?[Math.abs(h-n)<sm?l:t,n]:null))-1),++s);s&&(y=!1)}if(y){var g,m,x,b=1/0;for(i=0,y=null;i<_;++i)(o=im[i])&&(x=(g=(u=o.site)[0]-t)*g+(m=u[1]-n)*m)<b&&(b=x,y=o);if(y){var w=[t,n],M=[t,r],T=[e,r],k=[e,n];y.halfedges.push(um.push(Cc(u=y.site,w,M))-1,um.push(Cc(u,M,T))-1,um.push(Cc(u,T,k))-1,um.push(Cc(u,k,w))-1)}}for(i=0;i<_;++i)(o=im[i])&&(o.halfedges.length||delete im[i])}function Yc(){kc(this),this.x=this.y=this.arc=this.site=this.cy=null}function Bc(t){var n=t.P,e=t.N;if(n&&e){var r=n.site,i=t.site,o=e.site;if(r!==o){var u=i[0],a=i[1],c=r[0]-u,s=r[1]-a,f=o[0]-u,l=o[1]-a,h=2*(c*l-s*f);if(!(h>=-fm)){var p=c*c+s*s,d=f*f+l*l,v=(l*p-s*d)/h,_=(c*d-f*p)/h,y=am.pop()||new Yc;y.arc=t,y.site=i,y.x=v+u,y.y=(y.cy=_+a)+Math.sqrt(v*v+_*_),t.circle=y;for(var g=null,m=om._;m;)if(y.y<m.y||y.y===m.y&&y.x<=m.x){if(!m.L){g=m.P;break}m=m.L}else{if(!m.R){g=m;break}m=m.R}om.insert(g,y),g||(em=y)}}}}function jc(t){var n=t.circle;n&&(n.P||(em=n.N),om.remove(n),am.push(n),kc(n),t.circle=null)}function Hc(){kc(this),this.edge=this.site=this.circle=null}function Xc(t){var n=cm.pop()||new Hc;return n.site=t,n}function $c(t){jc(t),rm.remove(t),cm.push(t),kc(t)}function Vc(t){var n=t.circle,e=n.x,r=n.cy,i=[e,r],o=t.P,u=t.N,a=[t];$c(t);for(var c=o;c.circle&&Math.abs(e-c.circle.x)<sm&&Math.abs(r-c.circle.cy)<sm;)o=c.P,a.unshift(c),$c(c),c=o;a.unshift(c),jc(c);for(var s=u;s.circle&&Math.abs(e-s.circle.x)<sm&&Math.abs(r-s.circle.cy)<sm;)u=s.N,a.push(s),$c(s),s=u;a.push(s),jc(s);var f,l=a.length;for(f=1;f<l;++f)s=a[f],c=a[f-1],zc(s.edge,c.site,s.site,i);c=a[0],(s=a[l-1]).edge=Ac(c.site,s.site,null,i),Bc(c),Bc(s)}function Wc(t){for(var n,e,r,i,o=t[0],u=t[1],a=rm._;a;)if((r=Zc(a,u)-o)>sm)a=a.L;else{if(!((i=o-Gc(a,u))>sm)){r>-sm?(n=a.P,e=a):i>-sm?(n=a,e=a.N):n=e=a;break}if(!a.R){n=a;break}a=a.R}qc(t);var c=Xc(t);if(rm.insert(n,c),n||e){if(n===e)return jc(n),e=Xc(n.site),rm.insert(c,e),c.edge=e.edge=Ac(n.site,c.site),Bc(n),void Bc(e);if(e){jc(n),jc(e);var s=n.site,f=s[0],l=s[1],h=t[0]-f,p=t[1]-l,d=e.site,v=d[0]-f,_=d[1]-l,y=2*(h*_-p*v),g=h*h+p*p,m=v*v+_*_,x=[(_*g-p*m)/y+f,(h*m-v*g)/y+l];zc(e.edge,s,d,x),c.edge=Ac(s,t,null,x),e.edge=Ac(t,d,null,x),Bc(n),Bc(e)}else c.edge=Ac(n.site,c.site)}}function Zc(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var u=t.P;if(!u)return-1/0;var a=(e=u.site)[0],c=e[1],s=c-n;if(!s)return a;var f=a-r,l=1/o-1/s,h=f/s;return l?(-h+Math.sqrt(h*h-2*l*(f*f/(-2*s)-c+s/2+i-o/2)))/l+r:(r+a)/2}function Gc(t,n){var e=t.N;if(e)return Zc(e,n);var r=t.site;return r[1]===n?r[0]:1/0}function Jc(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}function Qc(t,n){return n[1]-t[1]||n[0]-t[0]}function Kc(t,n){var e,r,i,o=t.sort(Qc).pop();for(um=[],im=new Array(t.length),rm=new Tc,om=new Tc;;)if(i=em,o&&(!i||o[1]<i.y||o[1]===i.y&&o[0]<i.x))o[0]===e&&o[1]===r||(Wc(o),e=o[0],r=o[1]),o=t.pop();else{if(!i)break;Vc(i.arc)}if(Fc(),n){var u=+n[0][0],a=+n[0][1],c=+n[1][0],s=+n[1][1];Lc(u,a,c,s),Ic(u,a,c,s)}this.edges=um,this.cells=im,rm=om=um=im=null}function ts(t,n,e){this.target=t,this.type=n,this.transform=e}function ns(t,n,e){this.k=t,this.x=n,this.y=e}function es(t){return t.__zoom||hm}function rs(){t.event.stopImmediatePropagation()}function is(){return!t.event.button}function os(){var t,n,e=this;return e instanceof SVGElement?(t=(e=e.ownerSVGElement||e).width.baseVal.value,n=e.height.baseVal.value):(t=e.clientWidth,n=e.clientHeight),[[0,0],[t,n]]}function us(){return this.__zoom||hm}function as(){return-t.event.deltaY*(t.event.deltaMode?120:1)/500}function cs(){return"ontouchstart"in this}var ss=function(t,n){return t<n?-1:t>n?1:t>=n?0:NaN},fs=function(t){return 1===t.length&&(t=n(t)),{left:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)<0?r=o+1:i=o}return r},right:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)>0?i=o:r=o+1}return r}}},ls=fs(ss),hs=ls.right,ps=ls.left,ds=function(t){return null===t?NaN:+t},vs=function(t,n){var e,r,i=t.length,o=0,u=-1,a=0,c=0;if(null==n)for(;++u<i;)isNaN(e=ds(t[u]))||(c+=(r=e-a)*(e-(a+=r/++o)));else for(;++u<i;)isNaN(e=ds(n(t[u],u,t)))||(c+=(r=e-a)*(e-(a+=r/++o)));if(o>1)return c/(o-1)},_s=function(t,n){var e=vs(t,n);return e?Math.sqrt(e):e},ys=function(t,n){var e,r,i,o=t.length,u=-1;if(null==n){for(;++u<o;)if(null!=(e=t[u])&&e>=e)for(r=i=e;++u<o;)null!=(e=t[u])&&(r>e&&(r=e),i<e&&(i=e))}else for(;++u<o;)if(null!=(e=n(t[u],u,t))&&e>=e)for(r=i=e;++u<o;)null!=(e=n(t[u],u,t))&&(r>e&&(r=e),i<e&&(i=e));return[r,i]},gs=Array.prototype,ms=gs.slice,xs=gs.map,bs=function(t){return function(){return t}},ws=function(t){return t},Ms=function(t,n,e){t=+t,n=+n,e=(i=arguments.length)<2?(n=t,t=0,1):i<3?1:+e;for(var r=-1,i=0|Math.max(0,Math.ceil((n-t)/e)),o=new Array(i);++r<i;)o[r]=t+r*e;return o},Ts=Math.sqrt(50),ks=Math.sqrt(10),Ns=Math.sqrt(2),Ss=function(t,n,e){var i,o,u,a=n<t,c=-1;if(a&&(i=t,t=n,n=i),0===(u=r(t,n,e))||!isFinite(u))return[];if(u>0)for(t=Math.ceil(t/u),n=Math.floor(n/u),o=new Array(i=Math.ceil(n-t+1));++c<i;)o[c]=(t+c)*u;else for(t=Math.floor(t*u),n=Math.ceil(n*u),o=new Array(i=Math.ceil(t-n+1));++c<i;)o[c]=(t-c)/u;return a&&o.reverse(),o},Es=function(t){return Math.ceil(Math.log(t.length)/Math.LN2)+1},As=function(t,n,e){if(null==e&&(e=ds),r=t.length){if((n=+n)<=0||r<2)return+e(t[0],0,t);if(n>=1)return+e(t[r-1],r-1,t);var r,i=(r-1)*n,o=Math.floor(i),u=+e(t[o],o,t);return u+(+e(t[o+1],o+1,t)-u)*(i-o)}},Cs=function(t){for(var n,e,r,i=t.length,o=-1,u=0;++o<i;)u+=t[o].length;for(e=new Array(u);--i>=0;)for(n=(r=t[i]).length;--n>=0;)e[--u]=r[n];return e},zs=function(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o<i;)if(null!=(e=t[o])&&e>=e)for(r=e;++o<i;)null!=(e=t[o])&&r>e&&(r=e)}else for(;++o<i;)if(null!=(e=n(t[o],o,t))&&e>=e)for(r=e;++o<i;)null!=(e=n(t[o],o,t))&&r>e&&(r=e);return r},Ps=function(t){if(!(i=t.length))return[];for(var n=-1,e=zs(t,o),r=new Array(e);++n<e;)for(var i,u=-1,a=r[n]=new Array(i);++u<i;)a[u]=t[u][n];return r},Rs=Array.prototype.slice,Ls=function(t){return t},qs=1,Us=2,Ds=3,Os=4,Fs=1e-6,Is={value:function(){}};p.prototype=h.prototype={constructor:p,on:function(t,n){var e,r=this._,i=d(t+"",r),o=-1,u=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=_(r[e],t.name,n);else if(null==n)for(e in r)r[e]=_(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=v(r[e],t.name)))return e}},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new p(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(o=0,e=(r=this._[t]).length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var Ys="http://www.w3.org/1999/xhtml",Bs={svg:"http://www.w3.org/2000/svg",xhtml:Ys,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},js=function(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Bs.hasOwnProperty(n)?{space:Bs[n],local:t}:t},Hs=function(t){var n=js(t);return(n.local?g:y)(n)},Xs=0;x.prototype=m.prototype={constructor:x,get:function(t){for(var n=this._;!(n in t);)if(!(t=t.parentNode))return;return t[n]},set:function(t,n){return t[this._]=n},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var $s=function(t){return function(){return this.matches(t)}};if("undefined"!=typeof document){var Vs=document.documentElement;if(!Vs.matches){var Ws=Vs.webkitMatchesSelector||Vs.msMatchesSelector||Vs.mozMatchesSelector||Vs.oMatchesSelector;$s=function(t){return function(){return Ws.call(this,t)}}}}var Zs=$s,Gs={};t.event=null,"undefined"!=typeof document&&("onmouseenter"in document.documentElement||(Gs={mouseenter:"mouseover",mouseleave:"mouseout"}));var Js=function(){for(var n,e=t.event;n=e.sourceEvent;)e=n;return e},Qs=function(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=n.clientX,r.y=n.clientY,r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]},Ks=function(t){var n=Js();return n.changedTouches&&(n=n.changedTouches[0]),Qs(t,n)},tf=function(t){return null==t?S:function(){return this.querySelector(t)}},nf=function(t){return null==t?E:function(){return this.querySelectorAll(t)}},ef=function(t){return new Array(t.length)};A.prototype={constructor:A,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var rf=function(t){return function(){return t}},of="$",uf=function(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView};W.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var af=[null];pt.prototype=dt.prototype={constructor:pt,select:function(t){"function"!=typeof t&&(t=tf(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u,a=n[i],c=a.length,s=r[i]=new Array(c),f=0;f<c;++f)(o=a[f])&&(u=t.call(o,o.__data__,f,a))&&("__data__"in o&&(u.__data__=o.__data__),s[f]=u);return new pt(r,this._parents)},selectAll:function(t){"function"!=typeof t&&(t=nf(t));for(var n=this._groups,e=n.length,r=[],i=[],o=0;o<e;++o)for(var u,a=n[o],c=a.length,s=0;s<c;++s)(u=a[s])&&(r.push(t.call(u,u.__data__,s,a)),i.push(u));return new pt(r,i)},filter:function(t){"function"!=typeof t&&(t=Zs(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new pt(r,this._parents)},data:function(t,n){if(!t)return p=new Array(this.size()),s=-1,this.each(function(t){p[++s]=t}),p;var e=n?z:C,r=this._parents,i=this._groups;"function"!=typeof t&&(t=rf(t));for(var o=i.length,u=new Array(o),a=new Array(o),c=new Array(o),s=0;s<o;++s){var f=r[s],l=i[s],h=l.length,p=t.call(f,f&&f.__data__,s,r),d=p.length,v=a[s]=new Array(d),_=u[s]=new Array(d);e(f,l,v,_,c[s]=new Array(h),p,n);for(var y,g,m=0,x=0;m<d;++m)if(y=v[m]){for(m>=x&&(x=m+1);!(g=_[x])&&++x<d;);y._next=g||null}}return u=new pt(u,r),u._enter=a,u._exit=c,u},enter:function(){return new pt(this._enter||this._groups.map(ef),this._parents)},exit:function(){return new pt(this._exit||this._groups.map(ef),this._parents)},merge:function(t){for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new pt(u,this._parents)},order:function(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&u!==r.nextSibling&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(t){t||(t=P);for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i){for(var o,u=n[i],a=u.length,c=r[i]=new Array(a),s=0;s<a;++s)(o=u[s])&&(c[s]=o);c.sort(function(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e})}return new pt(r,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){var t=new Array(this.size()),n=-1;return this.each(function(){t[++n]=this}),t},node:function(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null},size:function(){var t=0;return this.each(function(){++t}),t},empty:function(){return!this.node()},each:function(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this},attr:function(t,n){var e=js(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?L:R:"function"==typeof n?e.local?O:D:e.local?U:q)(e,n))},style:function(t,n,e){return arguments.length>1?this.each((null==n?F:"function"==typeof n?Y:I)(t,n,null==e?"":e)):B(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?j:"function"==typeof n?X:H)(t,n)):this.node()[t]},classed:function(t,n){var e=$(t+"");if(arguments.length<2){for(var r=V(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each(("function"==typeof n?K:n?J:Q)(e,n))},text:function(t){return arguments.length?this.each(null==t?tt:("function"==typeof t?et:nt)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?rt:("function"==typeof t?ot:it)(t)):this.node().innerHTML},raise:function(){return this.each(ut)},lower:function(){return this.each(at)},append:function(t){var n="function"==typeof t?t:Hs(t);return this.select(function(){return this.appendChild(n.apply(this,arguments))})},insert:function(t,n){var e="function"==typeof t?t:Hs(t),r=null==n?ct:"function"==typeof n?n:tf(n);return this.select(function(){return this.insertBefore(e.apply(this,arguments),r.apply(this,arguments)||null)})},remove:function(){return this.each(st)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,n,e){var r,i,o=M(t+""),u=o.length;{if(!(arguments.length<2)){for(a=n?k:T,null==e&&(e=!1),r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var c,s=0,f=a.length;s<f;++s)for(r=0,c=a[s];r<u;++r)if((i=o[r]).type===c.type&&i.name===c.name)return c.value}},dispatch:function(t,n){return this.each(("function"==typeof n?ht:lt)(t,n))}};var cf=function(t){return"string"==typeof t?new pt([[document.querySelector(t)]],[document.documentElement]):new pt([[t]],af)},sf=function(t,n,e){arguments.length<3&&(e=n,n=Js().changedTouches);for(var r,i=0,o=n?n.length:0;i<o;++i)if((r=n[i]).identifier===e)return Qs(t,r);return null},ff=function(){t.event.preventDefault(),t.event.stopImmediatePropagation()},lf=function(t){var n=t.document.documentElement,e=cf(t).on("dragstart.drag",ff,!0);"onselectstart"in n?e.on("selectstart.drag",ff,!0):(n.__noselect=n.style.MozUserSelect,n.style.MozUserSelect="none")},hf=function(t){return function(){return t}};yt.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var pf=function(t,n,e){t.prototype=n.prototype=e,e.constructor=t},df="\\s*([+-]?\\d+)\\s*",vf="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",_f="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",yf=/^#([0-9a-f]{3})$/,gf=/^#([0-9a-f]{6})$/,mf=new RegExp("^rgb\\("+[df,df,df]+"\\)$"),xf=new RegExp("^rgb\\("+[_f,_f,_f]+"\\)$"),bf=new RegExp("^rgba\\("+[df,df,df,vf]+"\\)$"),wf=new RegExp("^rgba\\("+[_f,_f,_f,vf]+"\\)$"),Mf=new RegExp("^hsl\\("+[vf,_f,_f]+"\\)$"),Tf=new RegExp("^hsla\\("+[vf,_f,_f,vf]+"\\)$"),kf={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};pf(Mt,Tt,{displayable:function(){return this.rgb().displayable()},toString:function(){return this.rgb()+""}}),pf(At,Et,wt(Mt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new At(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new At(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},toString:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),pf(Rt,Pt,wt(Mt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Rt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Rt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new At(Lt(t>=240?t-240:t+120,i,r),Lt(t,i,r),Lt(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var Nf=Math.PI/180,Sf=180/Math.PI,Ef=.95047,Af=1,Cf=1.08883,zf=4/29,Pf=6/29,Rf=3*Pf*Pf,Lf=Pf*Pf*Pf;pf(Dt,Ut,wt(Mt,{brighter:function(t){return new Dt(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Dt(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return t=Af*Ft(t),n=Ef*Ft(n),e=Cf*Ft(e),new At(It(3.2404542*n-1.5371385*t-.4985314*e),It(-.969266*n+1.8760108*t+.041556*e),It(.0556434*n-.2040259*t+1.0572252*e),this.opacity)}})),pf(Ht,jt,wt(Mt,{brighter:function(t){return new Ht(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new Ht(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return qt(this).rgb()}}));var qf=-.14861,Uf=1.78277,Df=-.29227,Of=-.90649,Ff=1.97294,If=Ff*Of,Yf=Ff*Uf,Bf=Uf*Df-Of*qf;pf(Vt,$t,wt(Mt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Vt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Vt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*Nf,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new At(255*(n+e*(qf*r+Uf*i)),255*(n+e*(Df*r+Of*i)),255*(n+e*(Ff*r)),this.opacity)}}));var jf,Hf,Xf,$f,Vf,Wf,Zf=function(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=r<n-1?t[r+2]:2*o-i;return Wt((e-r/n)*n,u,i,o,a)}},Gf=function(t){var n=t.length;return function(e){var r=Math.floor(((e%=1)<0?++e:e)*n),i=t[(r+n-1)%n],o=t[r%n],u=t[(r+1)%n],a=t[(r+2)%n];return Wt((e-r/n)*n,i,o,u,a)}},Jf=function(t){return function(){return t}},Qf=function t(n){function e(t,n){var e=r((t=Et(t)).r,(n=Et(n)).r),i=r(t.g,n.g),o=r(t.b,n.b),u=Kt(t.opacity,n.opacity);return function(n){return t.r=e(n),t.g=i(n),t.b=o(n),t.opacity=u(n),t+""}}var r=Qt(n);return e.gamma=t,e}(1),Kf=tn(Zf),tl=tn(Gf),nl=function(t,n){var e,r=n?n.length:0,i=t?Math.min(r,t.length):0,o=new Array(r),u=new Array(r);for(e=0;e<i;++e)o[e]=cl(t[e],n[e]);for(;e<r;++e)u[e]=n[e];return function(t){for(e=0;e<i;++e)u[e]=o[e](t);return u}},el=function(t,n){var e=new Date;return t=+t,n-=t,function(r){return e.setTime(t+n*r),e}},rl=function(t,n){return t=+t,n-=t,function(e){return t+n*e}},il=function(t,n){var e,r={},i={};null!==t&&"object"==typeof t||(t={}),null!==n&&"object"==typeof n||(n={});for(e in n)e in t?r[e]=cl(t[e],n[e]):i[e]=n[e];return function(t){for(e in r)i[e]=r[e](t);return i}},ol=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,ul=new RegExp(ol.source,"g"),al=function(t,n){var e,r,i,o=ol.lastIndex=ul.lastIndex=0,u=-1,a=[],c=[];for(t+="",n+="";(e=ol.exec(t))&&(r=ul.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,c.push({i:u,x:rl(e,r)})),o=ul.lastIndex;return o<n.length&&(i=n.slice(o),a[u]?a[u]+=i:a[++u]=i),a.length<2?c[0]?en(c[0].x):nn(n):(n=c.length,function(t){for(var e,r=0;r<n;++r)a[(e=c[r]).i]=e.x(t);return a.join("")})},cl=function(t,n){var e,r=typeof n;return null==n||"boolean"===r?Jf(n):("number"===r?rl:"string"===r?(e=Tt(n))?(n=e,Qf):al:n instanceof Tt?Qf:n instanceof Date?el:Array.isArray(n)?nl:"function"!=typeof n.valueOf&&"function"!=typeof n.toString||isNaN(n)?il:rl)(t,n)},sl=function(t,n){return t=+t,n-=t,function(e){return Math.round(t+n*e)}},fl=180/Math.PI,ll={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},hl=function(t,n,e,r,i,o){var u,a,c;return(u=Math.sqrt(t*t+n*n))&&(t/=u,n/=u),(c=t*e+n*r)&&(e-=t*c,r-=n*c),(a=Math.sqrt(e*e+r*r))&&(e/=a,r/=a,c/=a),t*r<n*e&&(t=-t,n=-n,c=-c,u=-u),{translateX:i,translateY:o,rotate:Math.atan2(n,t)*fl,skewX:Math.atan(c)*fl,scaleX:u,scaleY:a}},pl=rn(function(t){return"none"===t?ll:(jf||(jf=document.createElement("DIV"),Hf=document.documentElement,Xf=document.defaultView),jf.style.transform=t,t=Xf.getComputedStyle(Hf.appendChild(jf),null).getPropertyValue("transform"),Hf.removeChild(jf),t=t.slice(7,-1).split(","),hl(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))},"px, ","px)","deg)"),dl=rn(function(t){return null==t?ll:($f||($f=document.createElementNS("http://www.w3.org/2000/svg","g")),$f.setAttribute("transform",t),(t=$f.transform.baseVal.consolidate())?(t=t.matrix,hl(t.a,t.b,t.c,t.d,t.e,t.f)):ll)},", ",")",")"),vl=Math.SQRT2,_l=function(t,n){var e,r,i=t[0],o=t[1],u=t[2],a=n[0],c=n[1],s=n[2],f=a-i,l=c-o,h=f*f+l*l;if(h<1e-12)r=Math.log(s/u)/vl,e=function(t){return[i+t*f,o+t*l,u*Math.exp(vl*t*r)]};else{var p=Math.sqrt(h),d=(s*s-u*u+4*h)/(2*u*2*p),v=(s*s-u*u-4*h)/(2*s*2*p),_=Math.log(Math.sqrt(d*d+1)-d),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-_)/vl,e=function(t){var n=t*r,e=on(_),a=u/(2*p)*(e*an(vl*n+_)-un(_));return[i+a*f,o+a*l,u*e/on(vl*n+_)]}}return e.duration=1e3*r,e},yl=cn(Jt),gl=cn(Kt),ml=sn(Jt),xl=sn(Kt),bl=fn(Jt),wl=fn(Kt),Ml=0,Tl=0,kl=0,Nl=1e3,Sl=0,El=0,Al=0,Cl="object"==typeof performance&&performance.now?performance:Date,zl="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};pn.prototype=dn.prototype={constructor:pn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?ln():+e)+(null==n?0:+n),this._next||Wf===this||(Wf?Wf._next=this:Vf=this,Wf=this),this._call=t,this._time=e,mn()},stop:function(){this._call&&(this._call=null,this._time=1/0,mn())}};var Pl=function(t,n,e){var r=new pn;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r},Rl=h("start","end","interrupt"),Ll=[],ql=0,Ul=1,Dl=2,Ol=3,Fl=4,Il=5,Yl=6,Bl=function(t,n,e,r,i,o){var u=t.__transition;if(u){if(e in u)return}else t.__transition={};Mn(t,e,{name:n,index:r,group:i,on:Rl,tween:Ll,time:o.time,delay:o.delay,duration:o.duration,ease:o.ease,timer:null,state:ql})},jl=function(t,n){var e,r,i,o=t.__transition,u=!0;if(o){n=null==n?null:n+"";for(i in o)(e=o[i]).name===n?(r=e.state>Dl&&e.state<Il,e.state=Yl,e.timer.stop(),r&&e.on.call("interrupt",t,t.__data__,e.index,e.group),delete o[i]):u=!1;u&&delete t.__transition}},Hl=function(t,n){var e;return("number"==typeof n?rl:n instanceof Tt?Qf:(e=Tt(n))?(n=e,Qf):al)(t,n)},Xl=dt.prototype.constructor,$l=0,Vl=dt.prototype;Gn.prototype=Jn.prototype={constructor:Gn,select:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=tf(t));for(var r=this._groups,i=r.length,o=new Array(i),u=0;u<i;++u)for(var a,c,s=r[u],f=s.length,l=o[u]=new Array(f),h=0;h<f;++h)(a=s[h])&&(c=t.call(a,a.__data__,h,s))&&("__data__"in a&&(c.__data__=a.__data__),l[h]=c,Bl(l[h],n,e,h,l,wn(a,e)));return new Gn(o,this._parents,n,e)},selectAll:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=nf(t));for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,s=r[a],f=s.length,l=0;l<f;++l)if(c=s[l]){for(var h,p=t.call(c,c.__data__,l,s),d=wn(c,e),v=0,_=p.length;v<_;++v)(h=p[v])&&Bl(h,n,e,v,p,d);o.push(p),u.push(c)}return new Gn(o,u,n,e)},filter:function(t){"function"!=typeof t&&(t=Zs(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new Gn(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new Gn(u,this._parents,this._name,this._id)},selection:function(){return new Xl(this._groups,this._parents)},transition:function(){for(var t=this._name,n=this._id,e=Qn(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var f=wn(u,n);Bl(u,t,e,s,a,{time:f.time+f.delay+f.duration,delay:0,duration:f.duration,ease:f.ease})}return new Gn(r,this._parents,t,e)},call:Vl.call,nodes:Vl.nodes,node:Vl.node,size:Vl.size,empty:Vl.empty,each:Vl.each,on:function(t,n){var e=this._id;return arguments.length<2?wn(this.node(),e).on.on(t):this.each(Yn(e,t,n))},attr:function(t,n){var e=js(t),r="transform"===e?dl:Hl;return this.attrTween(t,"function"==typeof n?(e.local?Pn:zn)(e,r,Nn(this,"attr."+t,n)):null==n?(e.local?En:Sn)(e):(e.local?Cn:An)(e,r,n+""))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=js(t);return this.tween(e,(r.local?Rn:Ln)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?pl:Hl;return null==n?this.styleTween(t,jn(t,r)).on("end.style."+t,Hn(t)):this.styleTween(t,"function"==typeof n?$n(t,r,Nn(this,"style."+t,n)):Xn(t,r,n+""),e)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,Vn(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?Zn(Nn(this,"text",t)):Wn(null==t?"":t+""))},remove:function(){return this.on("end.remove",Bn(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=wn(this.node(),e).tween,o=0,u=i.length;o<u;++o)if((r=i[o]).name===t)return r.value;return null}return this.each((null==n?Tn:kn)(e,t,n))},delay:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?qn:Un)(n,t)):wn(this.node(),n).delay},duration:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?Dn:On)(n,t)):wn(this.node(),n).duration},ease:function(t){var n=this._id;return arguments.length?this.each(Fn(n,t)):wn(this.node(),n).ease}};var Wl=function t(n){function e(t){return Math.pow(t,n)}return n=+n,e.exponent=t,e}(3),Zl=function t(n){function e(t){return 1-Math.pow(1-t,n)}return n=+n,e.exponent=t,e}(3),Gl=function t(n){function e(t){return((t*=2)<=1?Math.pow(t,n):2-Math.pow(2-t,n))/2}return n=+n,e.exponent=t,e}(3),Jl=Math.PI,Ql=Jl/2,Kl=4/11,th=6/11,nh=8/11,eh=.75,rh=9/11,ih=10/11,oh=.9375,uh=21/22,ah=63/64,ch=1/Kl/Kl,sh=function t(n){function e(t){return t*t*((n+1)*t-n)}return n=+n,e.overshoot=t,e}(1.70158),fh=function t(n){function e(t){return--t*t*((n+1)*t+n)+1}return n=+n,e.overshoot=t,e}(1.70158),lh=function t(n){function e(t){return((t*=2)<1?t*t*((n+1)*t-n):(t-=2)*t*((n+1)*t+n)+2)/2}return n=+n,e.overshoot=t,e}(1.70158),hh=2*Math.PI,ph=function t(n,e){function r(t){return n*Math.pow(2,10*--t)*Math.sin((i-t)/e)}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=hh);return r.amplitude=function(n){return t(n,e*hh)},r.period=function(e){return t(n,e)},r}(1,.3),dh=function t(n,e){function r(t){return 1-n*Math.pow(2,-10*(t=+t))*Math.sin((t+i)/e)}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=hh);return r.amplitude=function(n){return t(n,e*hh)},r.period=function(e){return t(n,e)},r}(1,.3),vh=function t(n,e){function r(t){return((t=2*t-1)<0?n*Math.pow(2,10*t)*Math.sin((i-t)/e):2-n*Math.pow(2,-10*t)*Math.sin((i+t)/e))/2}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=hh);return r.amplitude=function(n){return t(n,e*hh)},r.period=function(e){return t(n,e)},r}(1,.3),_h={time:null,delay:0,duration:250,ease:te};dt.prototype.interrupt=function(t){return this.each(function(){jl(this,t)})},dt.prototype.transition=function(t){var n,e;t instanceof Gn?(n=t._id,t=t._name):(n=Qn(),(e=_h).time=ln(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&Bl(u,t,n,s,a,e||oe(u,n));return new Gn(r,this._parents,t,n)};var yh=[null],gh=function(t){return function(){return t}},mh=function(t,n,e){this.target=t,this.type=n,this.selection=e},xh=function(){t.event.preventDefault(),t.event.stopImmediatePropagation()},bh={name:"drag"},wh={name:"space"},Mh={name:"handle"},Th={name:"center"},kh={name:"x",handles:["e","w"].map(ae),input:function(t,n){return t&&[[t[0],n[0][1]],[t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},Nh={name:"y",handles:["n","s"].map(ae),input:function(t,n){return t&&[[n[0][0],t[0]],[n[1][0],t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},Sh={name:"xy",handles:["n","e","s","w","nw","ne","se","sw"].map(ae),input:function(t){return t},output:function(t){return t}},Eh={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ah={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},Ch={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},zh={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},Ph={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1},Rh=Math.cos,Lh=Math.sin,qh=Math.PI,Uh=qh/2,Dh=2*qh,Oh=Math.max,Fh=Array.prototype.slice,Ih=function(t){return function(){return t}},Yh=Math.PI,Bh=2*Yh,jh=Bh-1e-6;de.prototype=ve.prototype={constructor:de,moveTo:function(t,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,n){this._+="L"+(this._x1=+t)+","+(this._y1=+n)},quadraticCurveTo:function(t,n,e,r){this._+="Q"+ +t+","+ +n+","+(this._x1=+e)+","+(this._y1=+r)},bezierCurveTo:function(t,n,e,r,i,o){this._+="C"+ +t+","+ +n+","+ +e+","+ +r+","+(this._x1=+i)+","+(this._y1=+o)},arcTo:function(t,n,e,r,i){t=+t,n=+n,e=+e,r=+r,i=+i;var o=this._x1,u=this._y1,a=e-t,c=r-n,s=o-t,f=u-n,l=s*s+f*f;if(i<0)throw new Error("negative radius: "+i);if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=n);else if(l>1e-6)if(Math.abs(f*a-c*s)>1e-6&&i){var h=e-o,p=r-u,d=a*a+c*c,v=h*h+p*p,_=Math.sqrt(d),y=Math.sqrt(l),g=i*Math.tan((Yh-Math.acos((d+l-v)/(2*_*y)))/2),m=g/y,x=g/_;Math.abs(m-1)>1e-6&&(this._+="L"+(t+m*s)+","+(n+m*f)),this._+="A"+i+","+i+",0,0,"+ +(f*h>s*p)+","+(this._x1=t+x*a)+","+(this._y1=n+x*c)}else this._+="L"+(this._x1=t)+","+(this._y1=n);else;},arc:function(t,n,e,r,i,o){t=+t,n=+n;var u=(e=+e)*Math.cos(r),a=e*Math.sin(r),c=t+u,s=n+a,f=1^o,l=o?r-i:i-r;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._+="M"+c+","+s:(Math.abs(this._x1-c)>1e-6||Math.abs(this._y1-s)>1e-6)&&(this._+="L"+c+","+s),e&&(l<0&&(l=l%Bh+Bh),l>jh?this._+="A"+e+","+e+",0,1,"+f+","+(t-u)+","+(n-a)+"A"+e+","+e+",0,1,"+f+","+(this._x1=c)+","+(this._y1=s):l>1e-6&&(this._+="A"+e+","+e+",0,"+ +(l>=Yh)+","+f+","+(this._x1=t+e*Math.cos(i))+","+(this._y1=n+e*Math.sin(i))))},rect:function(t,n,e,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +e+"v"+ +r+"h"+-e+"Z"},toString:function(){return this._}};be.prototype=we.prototype={constructor:be,has:function(t){return"$"+t in this},get:function(t){return this["$"+t]},set:function(t,n){return this["$"+t]=n,this},remove:function(t){var n="$"+t;return n in this&&delete this[n]},clear:function(){for(var t in this)"$"===t[0]&&delete this[t]},keys:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(n.slice(1));return t},values:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(this[n]);return t},entries:function(){var t=[];for(var n in this)"$"===n[0]&&t.push({key:n.slice(1),value:this[n]});return t},size:function(){var t=0;for(var n in this)"$"===n[0]&&++t;return t},empty:function(){for(var t in this)if("$"===t[0])return!1;return!0},each:function(t){for(var n in this)"$"===n[0]&&t(this[n],n.slice(1),this)}};var Hh=we.prototype;Se.prototype=Ee.prototype={constructor:Se,has:Hh.has,add:function(t){return t+="",this["$"+t]=t,this},remove:Hh.remove,clear:Hh.clear,values:Hh.keys,size:Hh.size,empty:Hh.empty,each:Hh.each};var Xh=function(t){function n(t,n){function e(){if(f>=s)return a;if(i)return i=!1,u;var n,e=f;if(34===t.charCodeAt(e)){for(var r=e;r++<s;)if(34===t.charCodeAt(r)){if(34!==t.charCodeAt(r+1))break;++r}return f=r+2,13===(n=t.charCodeAt(r+1))?(i=!0,10===t.charCodeAt(r+2)&&++f):10===n&&(i=!0),t.slice(e+1,r).replace(/""/g,'"')}for(;f<s;){var c=1;if(10===(n=t.charCodeAt(f++)))i=!0;else if(13===n)i=!0,10===t.charCodeAt(f)&&(++f,++c);else if(n!==o)continue;return t.slice(e,f-c)}return t.slice(e)}for(var r,i,u={},a={},c=[],s=t.length,f=0,l=0;(r=e())!==a;){for(var h=[];r!==u&&r!==a;)h.push(r),r=e();n&&null==(h=n(h,l++))||c.push(h)}return c}function e(n){return n.map(r).join(t)}function r(t){return null==t?"":i.test(t+="")?'"'+t.replace(/\"/g,'""')+'"':t}var i=new RegExp('["'+t+"\n\r]"),o=t.charCodeAt(0);return{parse:function(t,e){var r,i,o=n(t,function(t,n){if(r)return r(t,n-1);i=t,r=e?Ce(t,e):Ae(t)});return o.columns=i,o},parseRows:n,format:function(n,e){return null==e&&(e=ze(n)),[e.map(r).join(t)].concat(n.map(function(n){return e.map(function(t){return r(n[t])}).join(t)})).join("\n")},formatRows:function(t){return t.map(e).join("\n")}}},$h=Xh(","),Vh=$h.parse,Wh=$h.parseRows,Zh=$h.format,Gh=$h.formatRows,Jh=Xh("\t"),Qh=Jh.parse,Kh=Jh.parseRows,tp=Jh.format,np=Jh.formatRows,ep=function(t){return function(){return t}},rp=function(){return 1e-6*(Math.random()-.5)},ip=function(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i},op=qe.prototype=Ue.prototype;op.copy=function(){var t,n,e=new Ue(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=De(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=De(n));return e},op.add=function(t){var n=+this._x.call(null,t),e=+this._y.call(null,t);return Pe(this.cover(n,e),n,e,t)},op.addAll=function(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-1/0,l=-1/0;for(e=0;e<o;++e)isNaN(r=+this._x.call(null,n=t[e]))||isNaN(i=+this._y.call(null,n))||(u[e]=r,a[e]=i,r<c&&(c=r),r>f&&(f=r),i<s&&(s=i),i>l&&(l=i));for(f<c&&(c=this._x0,f=this._x1),l<s&&(s=this._y0,l=this._y1),this.cover(c,s).cover(f,l),e=0;e<o;++e)Pe(this,u[e],a[e],t[e]);return this},op.cover=function(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var e=this._x0,r=this._y0,i=this._x1,o=this._y1;if(isNaN(e))i=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1;else{if(!(e>t||t>i||r>n||n>o))return this;var u,a,c=i-e,s=this._root;switch(a=(n<(r+o)/2)<<1|t<(e+i)/2){case 0:do{u=new Array(4),u[a]=s,s=u}while(c*=2,i=e+c,o=r+c,t>i||n>o);break;case 1:do{u=new Array(4),u[a]=s,s=u}while(c*=2,e=i-c,o=r+c,e>t||n>o);break;case 2:do{u=new Array(4),u[a]=s,s=u}while(c*=2,i=e+c,r=o-c,t>i||r>n);break;case 3:do{u=new Array(4),u[a]=s,s=u}while(c*=2,e=i-c,r=o-c,e>t||r>n)}this._root&&this._root.length&&(this._root=s)}return this._x0=e,this._y0=r,this._x1=i,this._y1=o,this},op.data=function(){var t=[];return this.visit(function(n){if(!n.length)do{t.push(n.data)}while(n=n.next)}),t},op.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},op.find=function(t,n,e){var r,i,o,u,a,c,s,f=this._x0,l=this._y0,h=this._x1,p=this._y1,d=[],v=this._root;for(v&&d.push(new ip(v,f,l,h,p)),null==e?e=1/0:(f=t-e,l=n-e,h=t+e,p=n+e,e*=e);c=d.pop();)if(!(!(v=c.node)||(i=c.x0)>h||(o=c.y0)>p||(u=c.x1)<f||(a=c.y1)<l))if(v.length){var _=(i+u)/2,y=(o+a)/2;d.push(new ip(v[3],_,y,u,a),new ip(v[2],i,y,_,a),new ip(v[1],_,o,u,y),new ip(v[0],i,o,_,y)),(s=(n>=y)<<1|t>=_)&&(c=d[d.length-1],d[d.length-1]=d[d.length-1-s],d[d.length-1-s]=c)}else{var g=t-+this._x.call(null,v.data),m=n-+this._y.call(null,v.data),x=g*g+m*m;if(x<e){var b=Math.sqrt(e=x);f=t-b,l=n-b,h=t+b,p=n+b,r=v.data}}return r},op.remove=function(t){if(isNaN(o=+this._x.call(null,t))||isNaN(u=+this._y.call(null,t)))return this;var n,e,r,i,o,u,a,c,s,f,l,h,p=this._root,d=this._x0,v=this._y0,_=this._x1,y=this._y1;if(!p)return this;if(p.length)for(;;){if((s=o>=(a=(d+_)/2))?d=a:_=a,(f=u>=(c=(v+y)/2))?v=c:y=c,n=p,!(p=p[l=f<<1|s]))return this;if(!p.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;p.data!==t;)if(r=p,!(p=p.next))return this;return(i=p.next)&&delete p.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(p=n[0]||n[1]||n[2]||n[3])&&p===(n[3]||n[2]||n[1]||n[0])&&!p.length&&(e?e[h]=p:this._root=p),this):(this._root=i,this)},op.removeAll=function(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this},op.root=function(){return this._root},op.size=function(){var t=0;return this.visit(function(n){if(!n.length)do{++t}while(n=n.next)}),t},op.visit=function(t){var n,e,r,i,o,u,a=[],c=this._root;for(c&&a.push(new ip(c,this._x0,this._y0,this._x1,this._y1));n=a.pop();)if(!t(c=n.node,r=n.x0,i=n.y0,o=n.x1,u=n.y1)&&c.length){var s=(r+o)/2,f=(i+u)/2;(e=c[3])&&a.push(new ip(e,s,f,o,u)),(e=c[2])&&a.push(new ip(e,r,f,s,u)),(e=c[1])&&a.push(new ip(e,s,i,o,f)),(e=c[0])&&a.push(new ip(e,r,i,s,f))}return this},op.visitAfter=function(t){var n,e=[],r=[];for(this._root&&e.push(new ip(this._root,this._x0,this._y0,this._x1,this._y1));n=e.pop();){var i=n.node;if(i.length){var o,u=n.x0,a=n.y0,c=n.x1,s=n.y1,f=(u+c)/2,l=(a+s)/2;(o=i[0])&&e.push(new ip(o,u,a,f,l)),(o=i[1])&&e.push(new ip(o,f,a,c,l)),(o=i[2])&&e.push(new ip(o,u,l,f,s)),(o=i[3])&&e.push(new ip(o,f,l,c,s))}r.push(n)}for(;n=r.pop();)t(n.node,n.x0,n.y0,n.x1,n.y1);return this},op.x=function(t){return arguments.length?(this._x=t,this):this._x},op.y=function(t){return arguments.length?(this._y=t,this):this._y};var up,ap=10,cp=Math.PI*(3-Math.sqrt(5)),sp=function(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]},fp=function(t){return(t=sp(Math.abs(t)))?t[1]:NaN},lp=function(t,n){return function(e,r){for(var i=e.length,o=[],u=0,a=t[0],c=0;i>0&&a>0&&(c+a+1>r&&(a=Math.max(1,r-c)),o.push(e.substring(i-=a,i+a)),!((c+=a+1)>r));)a=t[u=(u+1)%t.length];return o.reverse().join(n)}},hp=function(t){return function(n){return n.replace(/[0-9]/g,function(n){return t[+n]})}},pp=function(t,n){var e=sp(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")},dp={"":function(t,n){t:for(var e,r=(t=t.toPrecision(n)).length,i=1,o=-1;i<r;++i)switch(t[i]){case".":o=e=i;break;case"0":0===o&&(o=i),e=i;break;case"e":break t;default:o>0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t},"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return pp(100*t,n)},r:pp,s:function(t,n){var e=sp(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(up=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+sp(t,Math.max(0,n+o-1))[0]},X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},vp=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;He.prototype=Xe.prototype,Xe.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var _p,yp=function(t){return t},gp=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"],mp=function(t){function n(t){function n(t){var n,r,u,f=_,x=y;if("c"===v)x=g(t)+x,t="";else{var b=(t=+t)<0;if(t=g(Math.abs(t),d),b&&0==+t&&(b=!1),f=(b?"("===s?s:"-":"-"===s||"("===s?"":s)+f,x=x+("s"===v?gp[8+up/3]:"")+(b&&"("===s?")":""),m)for(n=-1,r=t.length;++n<r;)if(48>(u=t.charCodeAt(n))||u>57){x=(46===u?i+t.slice(n+1):t.slice(n))+x,t=t.slice(0,n);break}}p&&!l&&(t=e(t,1/0));var w=f.length+t.length+x.length,M=w<h?new Array(h-w+1).join(a):"";switch(p&&l&&(t=e(M+t,M.length?h-x.length:1/0),M=""),c){case"<":t=f+t+x+M;break;case"=":t=f+M+t+x;break;case"^":t=M.slice(0,w=M.length>>1)+f+t+x+M.slice(w);break;default:t=M+f+t+x}return o(t)}var a=(t=He(t)).fill,c=t.align,s=t.sign,f=t.symbol,l=t.zero,h=t.width,p=t.comma,d=t.precision,v=t.type,_="$"===f?r[0]:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",y="$"===f?r[1]:/[%p]/.test(v)?u:"",g=dp[v],m=!v||/[defgprs%]/.test(v);return d=null==d?v?6:12:/[gprs]/.test(v)?Math.max(1,Math.min(21,d)):Math.max(0,Math.min(20,d)),n.toString=function(){return t+""},n}var e=t.grouping&&t.thousands?lp(t.grouping,t.thousands):yp,r=t.currency,i=t.decimal,o=t.numerals?hp(t.numerals):yp,u=t.percent||"%";return{format:n,formatPrefix:function(t,e){var r=n((t=He(t),t.type="f",t)),i=3*Math.max(-8,Math.min(8,Math.floor(fp(e)/3))),o=Math.pow(10,-i),u=gp[8+i/3];return function(t){return r(o*t)+u}}}};$e({decimal:".",thousands:",",grouping:[3],currency:["$",""]});var xp=function(t){return Math.max(0,-fp(Math.abs(t)))},bp=function(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(fp(n)/3)))-fp(Math.abs(t)))},wp=function(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,fp(n)-fp(t))+1},Mp=function(){return new Ve};Ve.prototype={constructor:Ve,reset:function(){this.s=this.t=0},add:function(t){We(nd,t,this.t),We(this,nd.s,this.s),this.s?this.t+=nd.t:this.s=nd.t},valueOf:function(){return this.s}};var Tp,kp,Np,Sp,Ep,Ap,Cp,zp,Pp,Rp,Lp,qp,Up,Dp,Op,Fp,Ip,Yp,Bp,jp,Hp,Xp,$p,Vp,Wp,Zp,Gp,Jp,Qp,Kp,td,nd=new Ve,ed=1e-6,rd=Math.PI,id=rd/2,od=rd/4,ud=2*rd,ad=180/rd,cd=rd/180,sd=Math.abs,fd=Math.atan,ld=Math.atan2,hd=Math.cos,pd=Math.ceil,dd=Math.exp,vd=Math.log,_d=Math.pow,yd=Math.sin,gd=Math.sign||function(t){return t>0?1:t<0?-1:0},md=Math.sqrt,xd=Math.tan,bd={Feature:function(t,n){Ke(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)Ke(e[r].geometry,n)}},wd={Sphere:function(t,n){n.sphere()},Point:function(t,n){t=t.coordinates,n.point(t[0],t[1],t[2])},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)t=e[r],n.point(t[0],t[1],t[2])},LineString:function(t,n){tr(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)tr(e[r],n,0)},Polygon:function(t,n){nr(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)nr(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)Ke(e[r],n)}},Md=function(t,n){t&&bd.hasOwnProperty(t.type)?bd[t.type](t,n):Ke(t,n)},Td=Mp(),kd=Mp(),Nd={point:Qe,lineStart:Qe,lineEnd:Qe,polygonStart:function(){Td.reset(),Nd.lineStart=er,Nd.lineEnd=rr},polygonEnd:function(){var t=+Td;kd.add(t<0?ud+t:t),this.lineStart=this.lineEnd=this.point=Qe},sphere:function(){kd.add(ud)}},Sd=Mp(),Ed={point:pr,lineStart:vr,lineEnd:_r,polygonStart:function(){Ed.point=yr,Ed.lineStart=gr,Ed.lineEnd=mr,Sd.reset(),Nd.polygonStart()},polygonEnd:function(){Nd.polygonEnd(),Ed.point=pr,Ed.lineStart=vr,Ed.lineEnd=_r,Td<0?(Ap=-(zp=180),Cp=-(Pp=90)):Sd>ed?Pp=90:Sd<-ed&&(Cp=-90),Op[0]=Ap,Op[1]=zp}},Ad={sphere:Qe,point:Mr,lineStart:kr,lineEnd:Er,polygonStart:function(){Ad.lineStart=Ar,Ad.lineEnd=Cr},polygonEnd:function(){Ad.lineStart=kr,Ad.lineEnd=Er}},Cd=function(t){return function(){return t}},zd=function(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return(e=n.invert(e,r))&&t.invert(e[0],e[1])}),e};Rr.invert=Rr;var Pd,Rd,Ld,qd,Ud,Dd,Od,Fd,Id,Yd,Bd,jd=function(t){function n(n){return n=t(n[0]*cd,n[1]*cd),n[0]*=ad,n[1]*=ad,n}return t=Lr(t[0]*cd,t[1]*cd,t.length>2?t[2]*cd:0),n.invert=function(n){return n=t.invert(n[0]*cd,n[1]*cd),n[0]*=ad,n[1]*=ad,n},n},Hd=function(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:Qe,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}},Xd=function(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=0,f=1,l=n[0]-a,h=n[1]-c;if(u=e-a,l||!(u>0)){if(u/=l,l<0){if(u<s)return;u<f&&(f=u)}else if(l>0){if(u>f)return;u>s&&(s=u)}if(u=i-a,l||!(u<0)){if(u/=l,l<0){if(u>f)return;u>s&&(s=u)}else if(l>0){if(u<s)return;u<f&&(f=u)}if(u=r-c,h||!(u>0)){if(u/=h,h<0){if(u<s)return;u<f&&(f=u)}else if(h>0){if(u>f)return;u>s&&(s=u)}if(u=o-c,h||!(u<0)){if(u/=h,h<0){if(u>f)return;u>s&&(s=u)}else if(h>0){if(u<s)return;u<f&&(f=u)}return s>0&&(t[0]=a+s*l,t[1]=c+s*h),f<1&&(n[0]=a+f*l,n[1]=c+f*h),!0}}}}},$d=function(t,n){return sd(t[0]-n[0])<ed&&sd(t[1]-n[1])<ed},Vd=function(t,n,e,r,i){var o,u,a=[],c=[];if(t.forEach(function(t){if(!((n=t.length-1)<=0)){var n,e,r=t[0],u=t[n];if($d(r,u)){for(i.lineStart(),o=0;o<n;++o)i.point((r=t[o])[0],r[1]);i.lineEnd()}else a.push(e=new Ir(r,t,null,!0)),c.push(e.o=new Ir(r,null,e,!1)),a.push(e=new Ir(u,t,null,!1)),c.push(e.o=new Ir(u,null,e,!0))}}),a.length){for(c.sort(n),Yr(a),Yr(c),o=0,u=c.length;o<u;++o)c[o].e=e=!e;for(var s,f,l=a[0];;){for(var h=l,p=!0;h.v;)if((h=h.n)===l)return;s=h.z,i.lineStart();do{if(h.v=h.o.v=!0,h.e){if(p)for(o=0,u=s.length;o<u;++o)i.point((f=s[o])[0],f[1]);else r(h.x,h.n.x,1,i);h=h.n}else{if(p)for(s=h.p.z,o=s.length-1;o>=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}s=(h=h.o).z,p=!p}while(!h.v);i.lineEnd()}}},Wd=1e9,Zd=-Wd,Gd=Mp(),Jd=function(t,n){var e=n[0],r=n[1],i=[yd(e),-hd(e),0],o=0,u=0;Gd.reset();for(var a=0,c=t.length;a<c;++a)if(f=(s=t[a]).length)for(var s,f,l=s[f-1],h=l[0],p=l[1]/2+od,d=yd(p),v=hd(p),_=0;_<f;++_,h=g,d=x,v=b,l=y){var y=s[_],g=y[0],m=y[1]/2+od,x=yd(m),b=hd(m),w=g-h,M=w>=0?1:-1,T=M*w,k=T>rd,N=d*x;if(Gd.add(ld(N*M*yd(T),v*b+N*hd(T))),o+=k?w+M*ud:w,k^h>=e^g>=e){var S=sr(ar(l),ar(y));hr(S);var E=sr(i,S);hr(E);var A=(k^w>=0?-1:1)*Ge(E[2]);(r>A||r===A&&(S[0]||S[1]))&&(u+=k^w>=0?1:-1)}}return(o<-ed||o<ed&&Gd<-ed)^1&u},Qd=Mp(),Kd={sphere:Qe,point:Qe,lineStart:function(){Kd.point=Hr,Kd.lineEnd=jr},lineEnd:Qe,polygonStart:Qe,polygonEnd:Qe},tv=function(t){return Qd.reset(),Md(t,Kd),+Qd},nv=[null,null],ev={type:"LineString",coordinates:nv},rv=function(t,n){return nv[0]=t,nv[1]=n,tv(ev)},iv={Feature:function(t,n){return $r(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)if($r(e[r].geometry,n))return!0;return!1}},ov={Sphere:function(){return!0},Point:function(t,n){return Vr(t.coordinates,n)},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(Vr(e[r],n))return!0;return!1},LineString:function(t,n){return Wr(t.coordinates,n)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(Wr(e[r],n))return!0;return!1},Polygon:function(t,n){return Zr(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(Zr(e[r],n))return!0;return!1},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)if($r(e[r],n))return!0;return!1}},uv=function(t){return t},av=Mp(),cv=Mp(),sv={point:Qe,lineStart:Qe,lineEnd:Qe,polygonStart:function(){sv.lineStart=ni,sv.lineEnd=ii},polygonEnd:function(){sv.lineStart=sv.lineEnd=sv.point=Qe,av.add(sd(cv)),cv.reset()},result:function(){var t=av/2;return av.reset(),t}},fv=1/0,lv=fv,hv=-fv,pv=hv,dv={point:function(t,n){t<fv&&(fv=t),t>hv&&(hv=t),n<lv&&(lv=n),n>pv&&(pv=n)},lineStart:Qe,lineEnd:Qe,polygonStart:Qe,polygonEnd:Qe,result:function(){var t=[[fv,lv],[hv,pv]];return hv=pv=-(lv=fv=1/0),t}},vv=0,_v=0,yv=0,gv=0,mv=0,xv=0,bv=0,wv=0,Mv=0,Tv={point:oi,lineStart:ui,lineEnd:si,polygonStart:function(){Tv.lineStart=fi,Tv.lineEnd=li},polygonEnd:function(){Tv.point=oi,Tv.lineStart=ui,Tv.lineEnd=si},result:function(){var t=Mv?[bv/Mv,wv/Mv]:xv?[gv/xv,mv/xv]:yv?[vv/yv,_v/yv]:[NaN,NaN];return vv=_v=yv=gv=mv=xv=bv=wv=Mv=0,t}};di.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,ud)}},result:Qe};var kv,Nv,Sv,Ev,Av,Cv=Mp(),zv={point:Qe,lineStart:function(){zv.point=vi},lineEnd:function(){kv&&_i(Nv,Sv),zv.point=Qe},polygonStart:function(){kv=!0},polygonEnd:function(){kv=null},result:function(){var t=+Cv;return Cv.reset(),t}};yi.prototype={_radius:4.5,_circle:gi(4.5),pointRadius:function(t){return(t=+t)!==this._radius&&(this._radius=t,this._circle=null),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._string.push("M",t,",",n),this._point=1;break;case 1:this._string.push("L",t,",",n);break;default:null==this._circle&&(this._circle=gi(this._radius)),this._string.push("M",t,",",n,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}return null}};var Pv=function(t,n,e,r){return function(i,o){function u(n,e){var r=i(n,e);t(n=r[0],e=r[1])&&o.point(n,e)}function a(t,n){var e=i(t,n);_.point(e[0],e[1])}function c(){b.point=a,_.lineStart()}function s(){b.point=u,_.lineEnd()}function f(t,n){v.push([t,n]);var e=i(t,n);m.point(e[0],e[1])}function l(){m.lineStart(),v=[]}function h(){f(v[0][0],v[0][1]),m.lineEnd();var t,n,e,r,i=m.clean(),u=g.result(),a=u.length;if(v.pop(),p.push(v),v=null,a)if(1&i){if(e=u[0],(n=e.length-1)>0){for(x||(o.polygonStart(),x=!0),o.lineStart(),t=0;t<n;++t)o.point((r=e[t])[0],r[1]);o.lineEnd()}}else a>1&&2&i&&u.push(u.pop().concat(u.shift())),d.push(u.filter(mi))}var p,d,v,_=n(o),y=i.invert(r[0],r[1]),g=Hd(),m=n(g),x=!1,b={point:u,lineStart:c,lineEnd:s,polygonStart:function(){b.point=f,b.lineStart=l,b.lineEnd=h,d=[],p=[]},polygonEnd:function(){b.point=u,b.lineStart=c,b.lineEnd=s,d=Cs(d);var t=Jd(p,y);d.length?(x||(o.polygonStart(),x=!0),Vd(d,xi,t,e,o)):t&&(x||(o.polygonStart(),x=!0),o.lineStart(),e(null,null,1,o),o.lineEnd()),x&&(o.polygonEnd(),x=!1),d=p=null},sphere:function(){o.polygonStart(),o.lineStart(),e(null,null,1,o),o.lineEnd(),o.polygonEnd()}};return b}},Rv=Pv(function(){return!0},function(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,u){var a=o>0?rd:-rd,c=sd(o-e);sd(c-rd)<ed?(t.point(e,r=(r+u)/2>0?id:-id),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),t.point(o,r),n=0):i!==a&&c>=rd&&(sd(e-i)<ed&&(e-=i*ed),sd(o-a)<ed&&(o-=a*ed),r=bi(e,r,o,u),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),n=0),t.point(e=o,r=u),i=a},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}},function(t,n,e,r){var i;if(null==t)i=e*id,r.point(-rd,i),r.point(0,i),r.point(rd,i),r.point(rd,0),r.point(rd,-i),r.point(0,-i),r.point(-rd,-i),r.point(-rd,0),r.point(-rd,i);else if(sd(t[0]-n[0])>ed){var o=t[0]<n[0]?rd:-rd;i=e*o/2,r.point(-o,i),r.point(0,i),r.point(o,i)}else r.point(n[0],n[1])},[-rd,-id]),Lv=function(t,n){function e(t,n){return hd(t)*hd(n)>o}function r(t,n,e){var r=[1,0,0],i=sr(ar(t),ar(n)),u=cr(i,i),a=i[0],c=u-a*a;if(!c)return!e&&t;var s=o*u/c,f=-o*a/c,l=sr(r,i),h=lr(r,s);fr(h,lr(i,f));var p=l,d=cr(h,p),v=cr(p,p),_=d*d-v*(cr(h,h)-1);if(!(_<0)){var y=md(_),g=lr(p,(-d-y)/v);if(fr(g,h),g=ur(g),!e)return g;var m,x=t[0],b=n[0],w=t[1],M=n[1];b<x&&(m=x,x=b,b=m);var T=b-x,k=sd(T-rd)<ed,N=k||T<ed;if(!k&&M<w&&(m=w,w=M,M=m),N?k?w+M>0^g[1]<(sd(g[0]-x)<ed?w:M):w<=g[1]&&g[1]<=M:T>rd^(x<=g[0]&&g[0]<=b)){var S=lr(p,(-d+y)/v);return fr(S,h),[g,ur(S)]}}}function i(n,e){var r=u?t:rd-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=4:e>r&&(i|=8),i}var o=hd(t),u=o>0,a=sd(o)>ed;return Pv(e,function(t){var n,o,c,s,f;return{lineStart:function(){s=c=!1,f=1},point:function(l,h){var p,d=[l,h],v=e(l,h),_=u?v?0:i(l,h):v?i(l+(l<0?rd:-rd),h):0;if(!n&&(s=c=v)&&t.lineStart(),v!==c&&(!(p=r(n,d))||$d(n,p)||$d(d,p))&&(d[0]+=ed,d[1]+=ed,v=e(d[0],d[1])),v!==c)f=0,v?(t.lineStart(),p=r(d,n),t.point(p[0],p[1])):(p=r(n,d),t.point(p[0],p[1]),t.lineEnd()),n=p;else if(a&&n&&u^v){var y;_&o||!(y=r(d,n,!0))||(f=0,u?(t.lineStart(),t.point(y[0][0],y[0][1]),t.point(y[1][0],y[1][1]),t.lineEnd()):(t.point(y[1][0],y[1][1]),t.lineEnd(),t.lineStart(),t.point(y[0][0],y[0][1])))}!v||n&&$d(n,d)||t.point(d[0],d[1]),n=d,c=v,o=_},lineEnd:function(){c&&t.lineEnd(),n=null},clean:function(){return f|(s&&c)<<1}}},function(e,r,i,o){Or(o,t,n,i,e,r)},u?[0,-t]:[-rd,t-rd])};Mi.prototype={constructor:Mi,point:function(t,n){this.stream.point(t,n)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var qv=16,Uv=hd(30*cd),Dv=function(t,n){return+n?Si(t,n):Ni(t)},Ov=wi({point:function(t,n){this.stream.point(t*cd,n*cd)}}),Fv=function(){return Ci(Pi).scale(155.424).center([0,33.6442])},Iv=function(){return Fv().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])},Yv=Li(function(t){return md(2/(1+t))});Yv.invert=qi(function(t){return 2*Ge(t/2)});var Bv=Li(function(t){return(t=Ze(t))&&t/yd(t)});Bv.invert=qi(function(t){return t});Ui.invert=function(t,n){return[t,2*fd(dd(n))-id]};Ii.invert=Ii;Bi.invert=qi(fd);Hi.invert=qi(Ge);Xi.invert=qi(function(t){return 2*fd(t)});$i.invert=function(t,n){return[-n,2*fd(dd(t))-id]};uo.prototype=eo.prototype={constructor:uo,count:function(){return this.eachAfter(to)},each:function(t){var n,e,r,i,o=this,u=[o];do{for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r])}while(u.length);return this},eachAfter:function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this},eachBefore:function(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this},sum:function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},sort:function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},path:function(t){for(var n=this,e=no(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){var t=[];return this.each(function(n){t.push(n)}),t},leaves:function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},links:function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n},copy:function(){return eo(this).eachBefore(io)}};var jv=Array.prototype.slice,Hv=function(t){for(var n,e,r=0,i=(t=ao(jv.call(t))).length,o=[];r<i;)n=t[r],e&&fo(e,n)?++r:(e=ho(o=co(o,n)),r=0);return e},Xv=function(t){return function(){return t}},$v=function(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)},Vv=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)(o=u[a]).y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s},Wv="$",Zv={depth:-1},Gv={};Do.prototype=Object.create(uo.prototype);var Jv=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(i-e)/t.value;++a<c;)(o=u[a]).x0=n,o.x1=r,o.y0=e,o.y1=e+=o.value*s},Qv=(1+Math.sqrt(5))/2,Kv=function t(n){function e(t,e,r,i,o){Fo(n,t,e,r,i,o)}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(Qv),t_=function t(n){function e(t,e,r,i,o){if((u=t._squarify)&&u.ratio===n)for(var u,a,c,s,f,l=-1,h=u.length,p=t.value;++l<h;){for(c=(a=u[l]).children,s=a.value=0,f=c.length;s<f;++s)a.value+=c[s].value;a.dice?Vv(a,e,r,i,r+=(o-r)*a.value/p):Jv(a,e,r,e+=(i-e)*a.value/p,o),p-=a.value}else t._squarify=u=Fo(n,t,e,r,i,o),u.ratio=n}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(Qv),n_=function(t,n,e){return(n[0]-t[0])*(e[1]-t[1])-(n[1]-t[1])*(e[0]-t[0])},e_=[].slice,r_={};Bo.prototype=Wo.prototype={constructor:Bo,defer:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("defer after await");if(null!=this._error)return this;var n=e_.call(arguments,1);return n.push(t),++this._waiting,this._tasks.push(n),jo(this),this},abort:function(){return null==this._error&&$o(this,new Error("abort")),this},await:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("multiple await");return this._call=function(n,e){t.apply(null,[n].concat(e))},Vo(this),this},awaitAll:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("multiple await");return this._call=t,Vo(this),this}};var i_=function(){return Math.random()},o_=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,1===arguments.length?(e=t,t=0):e-=t,function(){return n()*e+t}}return e.source=t,e}(i_),u_=function t(n){function e(t,e){var r,i;return t=null==t?0:+t,e=null==e?1:+e,function(){var o;if(null!=r)o=r,r=null;else do{r=2*n()-1,o=2*n()-1,i=r*r+o*o}while(!i||i>1);return t+e*o*Math.sqrt(-2*Math.log(i)/i)}}return e.source=t,e}(i_),a_=function t(n){function e(){var t=u_.source(n).apply(this,arguments);return function(){return Math.exp(t())}}return e.source=t,e}(i_),c_=function t(n){function e(t){return function(){for(var e=0,r=0;r<t;++r)e+=n();return e}}return e.source=t,e}(i_),s_=function t(n){function e(t){var e=c_.source(n)(t);return function(){return e()/t}}return e.source=t,e}(i_),f_=function t(n){function e(t){return function(){return-Math.log(1-n())/t}}return e.source=t,e}(i_),l_=function(t,n){function e(t){var n,e=s.status;if(!e&&Go(s)||e>=200&&e<300||304===e){if(o)try{n=o.call(r,s)}catch(t){return void a.call("error",r,t)}else n=s;a.call("load",r,n)}else a.call("error",r,t)}var r,i,o,u,a=h("beforesend","progress","load","error"),c=we(),s=new XMLHttpRequest,f=null,l=null,p=0;if("undefined"==typeof XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=s.ontimeout=e:s.onreadystatechange=function(t){s.readyState>3&&e(t)},s.onprogress=function(t){a.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?c.get(t):(null==n?c.remove(t):c.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(u=t,r):u},timeout:function(t){return arguments.length?(p=+t,r):p},user:function(t){return arguments.length<1?f:(f=null==t?null:t+"",r)},password:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},response:function(t){return o=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return s.open(n,t,!0,f,l),null==i||c.has("accept")||c.set("accept",i+",*/*"),s.setRequestHeader&&c.each(function(t,n){s.setRequestHeader(n,t)}),null!=i&&s.overrideMimeType&&s.overrideMimeType(i),null!=u&&(s.responseType=u),p>0&&(s.timeout=p),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=Zo(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),a.call("beforesend",r,s),s.send(null==e?null:e),r},abort:function(){return s.abort(),r},on:function(){var t=a.on.apply(a,arguments);return t===a?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r},h_=function(t,n){return function(e,r){var i=l_(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}},p_=h_("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),d_=h_("application/json",function(t){return JSON.parse(t.responseText)}),v_=h_("text/plain",function(t){return t.responseText}),__=h_("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),y_=function(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=l_(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(Jo(n,r=t)):r},o.row(r),i?o.get(i):o}},g_=y_("text/csv",Vh),m_=y_("text/tab-separated-values",Qh),x_=Array.prototype,b_=x_.map,w_=x_.slice,M_={name:"implicit"},T_=function(t){return function(){return t}},k_=function(t){return+t},N_=[0,1],S_=function(n,e,r){var o,u=n[0],a=n[n.length-1],c=i(u,a,null==e?10:e);switch((r=He(null==r?",f":r)).type){case"s":var s=Math.max(Math.abs(u),Math.abs(a));return null!=r.precision||isNaN(o=bp(c,s))||(r.precision=o),t.formatPrefix(r,s);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(o=wp(c,Math.max(Math.abs(u),Math.abs(a))))||(r.precision=o-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(o=xp(c))||(r.precision=o-2*("%"===r.type))}return t.format(r)},E_=function(t,n){var e,r=0,i=(t=t.slice()).length-1,o=t[r],u=t[i];return u<o&&(e=r,r=i,i=e,e=o,o=u,u=e),t[r]=n.floor(o),t[i]=n.ceil(u),t},A_=new Date,C_=new Date,z_=Mu(function(){},function(t,n){t.setTime(+t+n)},function(t,n){return n-t});z_.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Mu(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):z_:null};var P_=z_.range,R_=6e4,L_=6048e5,q_=Mu(function(t){t.setTime(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(+t+1e3*n)},function(t,n){return(n-t)/1e3},function(t){return t.getUTCSeconds()}),U_=q_.range,D_=Mu(function(t){t.setTime(Math.floor(t/R_)*R_)},function(t,n){t.setTime(+t+n*R_)},function(t,n){return(n-t)/R_},function(t){return t.getMinutes()}),O_=D_.range,F_=Mu(function(t){var n=t.getTimezoneOffset()*R_%36e5;n<0&&(n+=36e5),t.setTime(36e5*Math.floor((+t-n)/36e5)+n)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getHours()}),I_=F_.range,Y_=Mu(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*R_)/864e5},function(t){return t.getDate()-1}),B_=Y_.range,j_=Tu(0),H_=Tu(1),X_=Tu(2),$_=Tu(3),V_=Tu(4),W_=Tu(5),Z_=Tu(6),G_=j_.range,J_=H_.range,Q_=X_.range,K_=$_.range,ty=V_.range,ny=W_.range,ey=Z_.range,ry=Mu(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),iy=ry.range,oy=Mu(function(t){t.setMonth(0,1),t.setHours(0,0,0,0)},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t,n){return n.getFullYear()-t.getFullYear()},function(t){return t.getFullYear()});oy.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Mu(function(n){n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)},function(n,e){n.setFullYear(n.getFullYear()+e*t)}):null};var uy=oy.range,ay=Mu(function(t){t.setUTCSeconds(0,0)},function(t,n){t.setTime(+t+n*R_)},function(t,n){return(n-t)/R_},function(t){return t.getUTCMinutes()}),cy=ay.range,sy=Mu(function(t){t.setUTCMinutes(0,0,0)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getUTCHours()}),fy=sy.range,ly=Mu(function(t){t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+n)},function(t,n){return(n-t)/864e5},function(t){return t.getUTCDate()-1}),hy=ly.range,py=ku(0),dy=ku(1),vy=ku(2),_y=ku(3),yy=ku(4),gy=ku(5),my=ku(6),xy=py.range,by=dy.range,wy=vy.range,My=_y.range,Ty=yy.range,ky=gy.range,Ny=my.range,Sy=Mu(function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCMonth(t.getUTCMonth()+n)},function(t,n){return n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())},function(t){return t.getUTCMonth()}),Ey=Sy.range,Ay=Mu(function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCFullYear(t.getUTCFullYear()+n)},function(t,n){return n.getUTCFullYear()-t.getUTCFullYear()},function(t){return t.getUTCFullYear()});Ay.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Mu(function(n){n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)},function(n,e){n.setUTCFullYear(n.getUTCFullYear()+e*t)}):null};var Cy,zy=Ay.range,Py={"-":"",_:" ",0:"0"},Ry=/^\s*\d+/,Ly=/^%/,qy=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;Ma({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Uy=Date.prototype.toISOString?function(t){return t.toISOString()}:t.utcFormat("%Y-%m-%dT%H:%M:%S.%LZ"),Dy=+new Date("2000-01-01T00:00:00.000Z")?function(t){var n=new Date(t);return isNaN(n)?null:n}:t.utcParse("%Y-%m-%dT%H:%M:%S.%LZ"),Oy=1e3,Fy=60*Oy,Iy=60*Fy,Yy=24*Iy,By=7*Yy,jy=30*Yy,Hy=365*Yy,Xy=function(t){return t.match(/.{6}/g).map(function(t){return"#"+t})},$y=Xy("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),Vy=Xy("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"),Wy=Xy("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"),Zy=Xy("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"),Gy=wl($t(300,.5,0),$t(-240,.5,1)),Jy=wl($t(-100,.75,.35),$t(80,1.5,.8)),Qy=wl($t(260,.75,.35),$t(80,1.5,.8)),Ky=$t(),tg=Sa(Xy("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),ng=Sa(Xy("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),eg=Sa(Xy("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),rg=Sa(Xy("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")),ig=function(t){return function(){return t}},og=Math.abs,ug=Math.atan2,ag=Math.cos,cg=Math.max,sg=Math.min,fg=Math.sin,lg=Math.sqrt,hg=1e-12,pg=Math.PI,dg=pg/2,vg=2*pg;Oa.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var _g=function(t){return new Oa(t)},yg=function(){function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=ve())),a=0;a<=f;++a)!(a<f&&r(c=t[a],a,t))===l&&((l=!l)?u.lineStart():u.lineEnd()),l&&u.point(+n(c,a,t),+e(c,a,t));if(s)return u=null,s+""||null}var n=Fa,e=Ia,r=ig(!0),i=null,o=_g,u=null;return t.x=function(e){return arguments.length?(n="function"==typeof e?e:ig(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.defined=function(n){return arguments.length?(r="function"==typeof n?n:ig(!!n),t):r},t.curve=function(n){return arguments.length?(o=n,null!=i&&(u=o(i)),t):o},t.context=function(n){return arguments.length?(null==n?i=u=null:u=o(i=n),t):i},t},gg=function(){function t(t){var n,f,l,h,p,d=t.length,v=!1,_=new Array(d),y=new Array(d);for(null==a&&(s=c(p=ve())),n=0;n<=d;++n){if(!(n<d&&u(h=t[n],n,t))===v)if(v=!v)f=n,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),l=n-1;l>=f;--l)s.point(_[l],y[l]);s.lineEnd(),s.areaEnd()}v&&(_[n]=+e(h,n,t),y[n]=+i(h,n,t),s.point(r?+r(h,n,t):_[n],o?+o(h,n,t):y[n]))}if(p)return s=null,p+""||null}function n(){return yg().defined(u).curve(c).context(a)}var e=Fa,r=null,i=ig(0),o=Ia,u=ig(!0),a=null,c=_g,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:ig(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),o=null,t):i},t.y0=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),t):i},t.y1=function(n){return arguments.length?(o=null==n?null:"function"==typeof n?n:ig(+n),t):o},t.lineX0=t.lineY0=function(){return n().x(e).y(i)},t.lineY1=function(){return n().x(e).y(o)},t.lineX1=function(){return n().x(r).y(i)},t.defined=function(n){return arguments.length?(u="function"==typeof n?n:ig(!!n),t):u},t.curve=function(n){return arguments.length?(c=n,null!=a&&(s=c(a)),t):c},t.context=function(n){return arguments.length?(null==n?a=s=null:s=c(a=n),t):a},t},mg=function(t,n){return n<t?-1:n>t?1:n>=t?0:NaN},xg=function(t){return t},bg=Ba(_g);Ya.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};var wg=function(){return ja(yg().curve(bg))},Mg=function(){var t=gg().curve(bg),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return ja(e())},delete t.lineX0,t.lineEndAngle=function(){return ja(r())},delete t.lineX1,t.lineInnerRadius=function(){return ja(i())},delete t.lineY0,t.lineOuterRadius=function(){return ja(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(Ba(t)):n()._curve},t},Tg=function(t,n){return[(n=+n)*Math.cos(t-=Math.PI/2),n*Math.sin(t)]},kg=Array.prototype.slice,Ng={draw:function(t,n){var e=Math.sqrt(n/pg);t.moveTo(e,0),t.arc(0,0,e,0,vg)}},Sg={draw:function(t,n){var e=Math.sqrt(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}},Eg=Math.sqrt(1/3),Ag=2*Eg,Cg={draw:function(t,n){var e=Math.sqrt(n/Ag),r=e*Eg;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},zg=Math.sin(pg/10)/Math.sin(7*pg/10),Pg=Math.sin(vg/10)*zg,Rg=-Math.cos(vg/10)*zg,Lg={draw:function(t,n){var e=Math.sqrt(.8908130915292852*n),r=Pg*e,i=Rg*e;t.moveTo(0,-e),t.lineTo(r,i);for(var o=1;o<5;++o){var u=vg*o/5,a=Math.cos(u),c=Math.sin(u);t.lineTo(c*e,-a*e),t.lineTo(a*r-c*i,c*r+a*i)}t.closePath()}},qg={draw:function(t,n){var e=Math.sqrt(n),r=-e/2;t.rect(r,r,e,e)}},Ug=Math.sqrt(3),Dg={draw:function(t,n){var e=-Math.sqrt(n/(3*Ug));t.moveTo(0,2*e),t.lineTo(-Ug*e,-e),t.lineTo(Ug*e,-e),t.closePath()}},Og=-.5,Fg=Math.sqrt(3)/2,Ig=1/Math.sqrt(12),Yg=3*(Ig/2+1),Bg={draw:function(t,n){var e=Math.sqrt(n/Yg),r=e/2,i=e*Ig,o=r,u=e*Ig+e,a=-o,c=u;t.moveTo(r,i),t.lineTo(o,u),t.lineTo(a,c),t.lineTo(Og*r-Fg*i,Fg*r+Og*i),t.lineTo(Og*o-Fg*u,Fg*o+Og*u),t.lineTo(Og*a-Fg*c,Fg*a+Og*c),t.lineTo(Og*r+Fg*i,Og*i-Fg*r),t.lineTo(Og*o+Fg*u,Og*u-Fg*o),t.lineTo(Og*a+Fg*c,Og*c-Fg*a),t.closePath()}},jg=[Ng,Sg,Cg,qg,Lg,Dg,Bg],Hg=function(){};Ja.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Ga(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Ga(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};Qa.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Ga(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};Ka.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Ga(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};tc.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],u=t[e]-i,a=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*u),this._beta*n[c]+(1-this._beta)*(o+r*a));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var Xg=function t(n){function e(t){return 1===n?new Ja(t):new tc(t,n)}return e.beta=function(n){return t(+n)},e}(.85);ec.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:nc(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:nc(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var $g=function t(n){function e(t){return new ec(t,n)}return e.tension=function(n){return t(+n)},e}(0);rc.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:nc(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Vg=function t(n){function e(t){return new rc(t,n)}return e.tension=function(n){return t(+n)},e}(0);ic.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:nc(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Wg=function t(n){function e(t){return new ic(t,n)}return e.tension=function(n){return t(+n)},e}(0);uc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:oc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Zg=function t(n){function e(t){return n?new uc(t,n):new ec(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);ac.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:oc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Gg=function t(n){function e(t){return n?new ac(t,n):new rc(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);cc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:oc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Jg=function t(n){function e(t){return n?new cc(t,n):new ic(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);sc.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}};dc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:pc(this,this._t0,hc(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,pc(this,hc(this,e=lc(this,t,n)),e);break;default:pc(this,this._t0,e=lc(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(vc.prototype=Object.create(dc.prototype)).point=function(t,n){dc.prototype.point.call(this,n,t)},_c.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},yc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=gc(t),i=gc(n),o=0,u=1;u<e;++o,++u)this._context.bezierCurveTo(r[0][o],i[0][o],r[1][o],i[1][o],t[u],n[u]);(this._line||0!==this._line&&1===e)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,n){this._x.push(+t),this._y.push(+n)}};mc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var Qg=function(t,n){if((i=t.length)>1)for(var e,r,i,o=1,u=t[n[0]],a=u.length;o<i;++o)for(r=u,u=t[n[o]],e=0;e<a;++e)u[e][1]+=u[e][0]=isNaN(r[e][1])?r[e][0]:r[e][1]},Kg=function(t){for(var n=t.length,e=new Array(n);--n>=0;)e[n]=n;return e},tm=function(t){var n=t.map(bc);return Kg(t).sort(function(t,e){return n[t]-n[e]})},nm=function(t){return function(){return t}};Tc.prototype={constructor:Tc,insert:function(t,n){var e,r,i;if(t){if(n.P=t,n.N=t.N,t.N&&(t.N.P=n),t.N=n,t.R){for(t=t.R;t.L;)t=t.L;t.L=n}else t.R=n;e=t}else this._?(t=Ec(this._),n.P=null,n.N=t,t.P=t.L=n,e=t):(n.P=n.N=null,this._=n,e=null);for(n.L=n.R=null,n.U=e,n.C=!0,t=n;e&&e.C;)e===(r=e.U).L?(i=r.R)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.R&&(Nc(this,e),e=(t=e).U),e.C=!1,r.C=!0,Sc(this,r)):(i=r.L)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.L&&(Sc(this,e),e=(t=e).U),e.C=!1,r.C=!0,Nc(this,r)),e=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var n,e,r,i=t.U,o=t.L,u=t.R;if(e=o?u?Ec(u):o:u,i?i.L===t?i.L=e:i.R=e:this._=e,o&&u?(r=e.C,e.C=t.C,e.L=o,o.U=e,e!==u?(i=e.U,e.U=t.U,t=e.R,i.L=t,e.R=u,u.U=e):(e.U=i,i=e,t=e.R)):(r=t.C,t=e),t&&(t.U=i),!r)if(t&&t.C)t.C=!1;else{do{if(t===this._)break;if(t===i.L){if((n=i.R).C&&(n.C=!1,i.C=!0,Nc(this,i),n=i.R),n.L&&n.L.C||n.R&&n.R.C){n.R&&n.R.C||(n.L.C=!1,n.C=!0,Sc(this,n),n=i.R),n.C=i.C,i.C=n.R.C=!1,Nc(this,i),t=this._;break}}else if((n=i.L).C&&(n.C=!1,i.C=!0,Sc(this,i),n=i.L),n.L&&n.L.C||n.R&&n.R.C){n.L&&n.L.C||(n.R.C=!1,n.C=!0,Nc(this,n),n=i.L),n.C=i.C,i.C=n.L.C=!1,Sc(this,i),t=this._;break}n.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};var em,rm,im,om,um,am=[],cm=[],sm=1e-6,fm=1e-12;Kc.prototype={constructor:Kc,polygons:function(){var t=this.edges;return this.cells.map(function(n){var e=n.halfedges.map(function(e){return Dc(n,t[e])});return e.data=n.site.data,e})},triangles:function(){var t=[],n=this.edges;return this.cells.forEach(function(e,r){if(o=(i=e.halfedges).length)for(var i,o,u,a=e.site,c=-1,s=n[i[o-1]],f=s.left===a?s.right:s.left;++c<o;)u=f,f=(s=n[i[c]]).left===a?s.right:s.left,u&&f&&r<u.index&&r<f.index&&Jc(a,u,f)<0&&t.push([a.data,u.data,f.data])}),t},links:function(){return this.edges.filter(function(t){return t.right}).map(function(t){return{source:t.left.data,target:t.right.data}})},find:function(t,n,e){for(var r,i,o=this,u=o._found||0,a=o.cells.length;!(i=o.cells[u]);)if(++u>=a)return null;var c=t-i.site[0],s=n-i.site[1],f=c*c+s*s;do{i=o.cells[r=u],u=null,i.halfedges.forEach(function(e){var r=o.edges[e],a=r.left;if(a!==i.site&&a||(a=r.right)){var c=t-a[0],s=n-a[1],l=c*c+s*s;l<f&&(f=l,u=a.index)}})}while(null!==u);return o._found=r,null==e||f<=e*e?i.site:null}};var lm=function(t){return function(){return t}};ns.prototype={constructor:ns,scale:function(t){return 1===t?this:new ns(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new ns(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var hm=new ns(1,0,0);es.prototype=ns.prototype;var pm=function(){t.event.preventDefault(),t.event.stopImmediatePropagation()};t.version="4.10.0",t.bisect=hs,t.bisectRight=hs,t.bisectLeft=ps,t.ascending=ss,t.bisector=fs,t.cross=function(t,n,r){var i,o,u,a,c=t.length,s=n.length,f=new Array(c*s);for(null==r&&(r=e),i=u=0;i<c;++i)for(a=t[i],o=0;o<s;++o,++u)f[u]=r(a,n[o]);return f},t.descending=function(t,n){return n<t?-1:n>t?1:n>=t?0:NaN},t.deviation=_s,t.extent=ys,t.histogram=function(){function t(t){var o,u,a=t.length,c=new Array(a);for(o=0;o<a;++o)c[o]=n(t[o],o,t);var s=e(c),f=s[0],l=s[1],h=r(c,f,l);Array.isArray(h)||(h=i(f,l,h),h=Ms(Math.ceil(f/h)*h,Math.floor(l/h)*h,h));for(var p=h.length;h[0]<=f;)h.shift(),--p;for(;h[p-1]>l;)h.pop(),--p;var d,v=new Array(p+1);for(o=0;o<=p;++o)(d=v[o]=[]).x0=o>0?h[o-1]:f,d.x1=o<p?h[o]:l;for(o=0;o<a;++o)f<=(u=c[o])&&u<=l&&v[hs(h,u,0,p)].push(t[o]);return v}var n=ws,e=ys,r=Es;return t.value=function(e){return arguments.length?(n="function"==typeof e?e:bs(e),t):n},t.domain=function(n){return arguments.length?(e="function"==typeof n?n:bs([n[0],n[1]]),t):e},t.thresholds=function(n){return arguments.length?(r="function"==typeof n?n:bs(Array.isArray(n)?ms.call(n):n),t):r},t},t.thresholdFreedmanDiaconis=function(t,n,e){return t=xs.call(t,ds).sort(ss),Math.ceil((e-n)/(2*(As(t,.75)-As(t,.25))*Math.pow(t.length,-1/3)))},t.thresholdScott=function(t,n,e){return Math.ceil((e-n)/(3.5*_s(t)*Math.pow(t.length,-1/3)))},t.thresholdSturges=Es,t.max=function(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o<i;)if(null!=(e=t[o])&&e>=e)for(r=e;++o<i;)null!=(e=t[o])&&e>r&&(r=e)}else for(;++o<i;)if(null!=(e=n(t[o],o,t))&&e>=e)for(r=e;++o<i;)null!=(e=n(t[o],o,t))&&e>r&&(r=e);return r},t.mean=function(t,n){var e,r=t.length,i=r,o=-1,u=0;if(null==n)for(;++o<r;)isNaN(e=ds(t[o]))?--i:u+=e;else for(;++o<r;)isNaN(e=ds(n(t[o],o,t)))?--i:u+=e;if(i)return u/i},t.median=function(t,n){var e,r=t.length,i=-1,o=[];if(null==n)for(;++i<r;)isNaN(e=ds(t[i]))||o.push(e);else for(;++i<r;)isNaN(e=ds(n(t[i],i,t)))||o.push(e);return As(o.sort(ss),.5)},t.merge=Cs,t.min=zs,t.pairs=function(t,n){null==n&&(n=e);for(var r=0,i=t.length-1,o=t[0],u=new Array(i<0?0:i);r<i;)u[r]=n(o,o=t[++r]);return u},t.permute=function(t,n){for(var e=n.length,r=new Array(e);e--;)r[e]=t[n[e]];return r},t.quantile=As,t.range=Ms,t.scan=function(t,n){if(e=t.length){var e,r,i=0,o=0,u=t[o];for(null==n&&(n=ss);++i<e;)(n(r=t[i],u)<0||0!==n(u,u))&&(u=r,o=i);return 0===n(u,u)?o:void 0}},t.shuffle=function(t,n,e){for(var r,i,o=(null==e?t.length:e)-(n=null==n?0:+n);o;)i=Math.random()*o--|0,r=t[o+n],t[o+n]=t[i+n],t[i+n]=r;return t},t.sum=function(t,n){var e,r=t.length,i=-1,o=0;if(null==n)for(;++i<r;)(e=+t[i])&&(o+=e);else for(;++i<r;)(e=+n(t[i],i,t))&&(o+=e);return o},t.ticks=Ss,t.tickIncrement=r,t.tickStep=i,t.transpose=Ps,t.variance=vs,t.zip=function(){return Ps(arguments)},t.axisTop=function(t){return l(qs,t)},t.axisRight=function(t){return l(Us,t)},t.axisBottom=function(t){return l(Ds,t)},t.axisLeft=function(t){return l(Os,t)},t.brush=function(){return he(Sh)},t.brushX=function(){return he(kh)},t.brushY=function(){return he(Nh)},t.brushSelection=function(t){var n=t.__brush;return n?n.dim.output(n.selection):null},t.chord=function(){function t(t){var o,u,a,c,s,f,l=t.length,h=[],p=Ms(l),d=[],v=[],_=v.groups=new Array(l),y=new Array(l*l);for(o=0,s=-1;++s<l;){for(u=0,f=-1;++f<l;)u+=t[s][f];h.push(u),d.push(Ms(l)),o+=u}for(e&&p.sort(function(t,n){return e(h[t],h[n])}),r&&d.forEach(function(n,e){n.sort(function(n,i){return r(t[e][n],t[e][i])})}),c=(o=Oh(0,Dh-n*l)/o)?n:Dh/l,u=0,s=-1;++s<l;){for(a=u,f=-1;++f<l;){var g=p[s],m=d[g][f],x=t[g][m],b=u,w=u+=x*o;y[m*l+g]={index:g,subindex:m,startAngle:b,endAngle:w,value:x}}_[g]={index:g,startAngle:a,endAngle:u,value:h[g]},u+=c}for(s=-1;++s<l;)for(f=s-1;++f<l;){var M=y[f*l+s],T=y[s*l+f];(M.value||T.value)&&v.push(M.value<T.value?{source:T,target:M}:{source:M,target:T})}return i?v.sort(i):v}var n=0,e=null,r=null,i=null;return t.padAngle=function(e){return arguments.length?(n=Oh(0,e),t):n},t.sortGroups=function(n){return arguments.length?(e=n,t):e},t.sortSubgroups=function(n){return arguments.length?(r=n,t):r},t.sortChords=function(n){return arguments.length?(null==n?i=null:(i=pe(n))._=n,t):i&&i._},t},t.ribbon=function(){function t(){var t,a=Fh.call(arguments),c=n.apply(this,a),s=e.apply(this,a),f=+r.apply(this,(a[0]=c,a)),l=i.apply(this,a)-Uh,h=o.apply(this,a)-Uh,p=f*Rh(l),d=f*Lh(l),v=+r.apply(this,(a[0]=s,a)),_=i.apply(this,a)-Uh,y=o.apply(this,a)-Uh;if(u||(u=t=ve()),u.moveTo(p,d),u.arc(0,0,f,l,h),l===_&&h===y||(u.quadraticCurveTo(0,0,v*Rh(_),v*Lh(_)),u.arc(0,0,v,_,y)),u.quadraticCurveTo(0,0,p,d),u.closePath(),t)return u=null,t+""||null}var n=_e,e=ye,r=ge,i=me,o=xe,u=null;return t.radius=function(n){return arguments.length?(r="function"==typeof n?n:Ih(+n),t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:Ih(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:Ih(+n),t):o},t.source=function(e){return arguments.length?(n=e,t):n},t.target=function(n){return arguments.length?(e=n,t):e},t.context=function(n){return arguments.length?(u=null==n?null:n,t):u},t},t.nest=function(){function t(n,i,u,a){if(i>=o.length)return null!=e&&n.sort(e),null!=r?r(n):n;for(var c,s,f,l=-1,h=n.length,p=o[i++],d=we(),v=u();++l<h;)(f=d.get(c=p(s=n[l])+""))?f.push(s):d.set(c,[s]);return d.each(function(n,e){a(v,e,t(n,i,u,a))}),v}function n(t,e){if(++e>o.length)return t;var i,a=u[e-1];return null!=r&&e>=o.length?i=t.entries():(i=[],t.each(function(t,r){i.push({key:r,values:n(t,e)})})),null!=a?i.sort(function(t,n){return a(t.key,n.key)}):i}var e,r,i,o=[],u=[];return i={object:function(n){return t(n,0,Me,Te)},map:function(n){return t(n,0,ke,Ne)},entries:function(e){return n(t(e,0,ke,Ne),0)},key:function(t){return o.push(t),i},sortKeys:function(t){return u[o.length-1]=t,i},sortValues:function(t){return e=t,i},rollup:function(t){return r=t,i}}},t.set=Ee,t.map=we,t.keys=function(t){var n=[];for(var e in t)n.push(e);return n},t.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},t.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},t.color=Tt,t.rgb=Et,t.hsl=Pt,t.lab=Ut,t.hcl=jt,t.cubehelix=$t,t.dispatch=h,t.drag=function(){function n(t){t.on("mousedown.drag",e).filter(bt).on("touchstart.drag",o).on("touchmove.drag",u).on("touchend.drag touchcancel.drag",a).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(){if(!p&&d.apply(this,arguments)){var n=c("mouse",v.apply(this,arguments),Ks,this,arguments);n&&(cf(t.event.view).on("mousemove.drag",r,!0).on("mouseup.drag",i,!0),lf(t.event.view),vt(),l=!1,s=t.event.clientX,f=t.event.clientY,n("start"))}}function r(){if(ff(),!l){var n=t.event.clientX-s,e=t.event.clientY-f;l=n*n+e*e>x}y.mouse("drag")}function i(){cf(t.event.view).on("mousemove.drag mouseup.drag",null),_t(t.event.view,l),ff(),y.mouse("end")}function o(){if(d.apply(this,arguments)){var n,e,r=t.event.changedTouches,i=v.apply(this,arguments),o=r.length;for(n=0;n<o;++n)(e=c(r[n].identifier,i,sf,this,arguments))&&(vt(),e("start"))}}function u(){var n,e,r=t.event.changedTouches,i=r.length;for(n=0;n<i;++n)(e=y[r[n].identifier])&&(ff(),e("drag"))}function a(){var n,e,r=t.event.changedTouches,i=r.length;for(p&&clearTimeout(p),p=setTimeout(function(){p=null},500),n=0;n<i;++n)(e=y[r[n].identifier])&&(vt(),e("end"))}function c(e,r,i,o,u){var a,c,s,f=i(r,e),l=g.copy();if(N(new yt(n,"beforestart",a,e,m,f[0],f[1],0,0,l),function(){return null!=(t.event.subject=a=_.apply(o,u))&&(c=a.x-f[0]||0,s=a.y-f[1]||0,!0)}))return function t(h){var p,d=f;switch(h){case"start":y[e]=t,p=m++;break;case"end":delete y[e],--m;case"drag":f=i(r,e),p=m}N(new yt(n,h,a,e,p,f[0]+c,f[1]+s,f[0]-d[0],f[1]-d[1],l),l.apply,l,[h,o,u])}}var s,f,l,p,d=gt,v=mt,_=xt,y={},g=h("start","drag","end"),m=0,x=0;return n.filter=function(t){return arguments.length?(d="function"==typeof t?t:hf(!!t),n):d},n.container=function(t){return arguments.length?(v="function"==typeof t?t:hf(t),n):v},n.subject=function(t){return arguments.length?(_="function"==typeof t?t:hf(t),n):_},n.on=function(){var t=g.on.apply(g,arguments);return t===g?n:t},n.clickDistance=function(t){return arguments.length?(x=(t=+t)*t,n):Math.sqrt(x)},n},t.dragDisable=lf,t.dragEnable=_t,t.dsvFormat=Xh,t.csvParse=Vh,t.csvParseRows=Wh,t.csvFormat=Zh,t.csvFormatRows=Gh,t.tsvParse=Qh,t.tsvParseRows=Kh,t.tsvFormat=tp,t.tsvFormatRows=np,t.easeLinear=function(t){return+t},t.easeQuad=Kn,t.easeQuadIn=function(t){return t*t},t.easeQuadOut=function(t){return t*(2-t)},t.easeQuadInOut=Kn,t.easeCubic=te,t.easeCubicIn=function(t){return t*t*t},t.easeCubicOut=function(t){return--t*t*t+1},t.easeCubicInOut=te,t.easePoly=Gl,t.easePolyIn=Wl,t.easePolyOut=Zl,t.easePolyInOut=Gl,t.easeSin=ne,t.easeSinIn=function(t){return 1-Math.cos(t*Ql)},t.easeSinOut=function(t){return Math.sin(t*Ql)},t.easeSinInOut=ne,t.easeExp=ee,t.easeExpIn=function(t){return Math.pow(2,10*t-10)},t.easeExpOut=function(t){return 1-Math.pow(2,-10*t)},t.easeExpInOut=ee,t.easeCircle=re,t.easeCircleIn=function(t){return 1-Math.sqrt(1-t*t)},t.easeCircleOut=function(t){return Math.sqrt(1- --t*t)},t.easeCircleInOut=re,t.easeBounce=ie,t.easeBounceIn=function(t){return 1-ie(1-t)},t.easeBounceOut=ie,t.easeBounceInOut=function(t){return((t*=2)<=1?1-ie(1-t):ie(t-1)+1)/2},t.easeBack=lh,t.easeBackIn=sh,t.easeBackOut=fh,t.easeBackInOut=lh,t.easeElastic=dh,t.easeElasticIn=ph,t.easeElasticOut=dh,t.easeElasticInOut=vh,t.forceCenter=function(t,n){function e(){var e,i,o=r.length,u=0,a=0;for(e=0;e<o;++e)u+=(i=r[e]).x,a+=i.y;for(u=u/o-t,a=a/o-n,e=0;e<o;++e)(i=r[e]).x-=u,i.y-=a}var r;return null==t&&(t=0),null==n&&(n=0),e.initialize=function(t){r=t},e.x=function(n){return arguments.length?(t=+n,e):t},e.y=function(t){return arguments.length?(n=+t,e):n},e},t.forceCollide=function(t){function n(){for(var t,n,r,c,s,f,l,h=i.length,p=0;p<a;++p)for(n=qe(i,Oe,Fe).visitAfter(e),t=0;t<h;++t)r=i[t],f=o[r.index],l=f*f,c=r.x+r.vx,s=r.y+r.vy,n.visit(function(t,n,e,i,o){var a=t.data,h=t.r,p=f+h;if(!a)return n>c+p||i<c-p||e>s+p||o<s-p;if(a.index>r.index){var d=c-a.x-a.vx,v=s-a.y-a.vy,_=d*d+v*v;_<p*p&&(0===d&&(d=rp(),_+=d*d),0===v&&(v=rp(),_+=v*v),_=(p-(_=Math.sqrt(_)))/_*u,r.vx+=(d*=_)*(p=(h*=h)/(l+h)),r.vy+=(v*=_)*p,a.vx-=d*(p=1-p),a.vy-=v*p)}})}function e(t){if(t.data)return t.r=o[t.data.index];for(var n=t.r=0;n<4;++n)t[n]&&t[n].r>t.r&&(t.r=t[n].r)}function r(){if(i){var n,e,r=i.length;for(o=new Array(r),n=0;n<r;++n)e=i[n],o[e.index]=+t(e,n,i)}}var i,o,u=1,a=1;return"function"!=typeof t&&(t=ep(null==t?1:+t)),n.initialize=function(t){i=t,r()},n.iterations=function(t){return arguments.length?(a=+t,n):a},n.strength=function(t){return arguments.length?(u=+t,n):u},n.radius=function(e){return arguments.length?(t="function"==typeof e?e:ep(+e),r(),n):t},n},t.forceLink=function(t){function n(n){for(var e=0,r=t.length;e<p;++e)for(var i,a,c,f,l,h,d,v=0;v<r;++v)a=(i=t[v]).source,f=(c=i.target).x+c.vx-a.x-a.vx||rp(),l=c.y+c.vy-a.y-a.vy||rp(),f*=h=((h=Math.sqrt(f*f+l*l))-u[v])/h*n*o[v],l*=h,c.vx-=f*(d=s[v]),c.vy-=l*d,a.vx+=f*(d=1-d),a.vy+=l*d}function e(){if(a){var n,e,l=a.length,h=t.length,p=we(a,f);for(n=0,c=new Array(l);n<h;++n)(e=t[n]).index=n,"object"!=typeof e.source&&(e.source=Ye(p,e.source)),"object"!=typeof e.target&&(e.target=Ye(p,e.target)),c[e.source.index]=(c[e.source.index]||0)+1,c[e.target.index]=(c[e.target.index]||0)+1;for(n=0,s=new Array(h);n<h;++n)e=t[n],s[n]=c[e.source.index]/(c[e.source.index]+c[e.target.index]);o=new Array(h),r(),u=new Array(h),i()}}function r(){if(a)for(var n=0,e=t.length;n<e;++n)o[n]=+l(t[n],n,t)}function i(){if(a)for(var n=0,e=t.length;n<e;++n)u[n]=+h(t[n],n,t)}var o,u,a,c,s,f=Ie,l=function(t){return 1/Math.min(c[t.source.index],c[t.target.index])},h=ep(30),p=1;return null==t&&(t=[]),n.initialize=function(t){a=t,e()},n.links=function(r){return arguments.length?(t=r,e(),n):t},n.id=function(t){return arguments.length?(f=t,n):f},n.iterations=function(t){return arguments.length?(p=+t,n):p},n.strength=function(t){return arguments.length?(l="function"==typeof t?t:ep(+t),r(),n):l},n.distance=function(t){return arguments.length?(h="function"==typeof t?t:ep(+t),i(),n):h},n},t.forceManyBody=function(){function t(t){var n,a=i.length,c=qe(i,Be,je).visitAfter(e);for(u=t,n=0;n<a;++n)o=i[n],c.visit(r)}function n(){if(i){var t,n,e=i.length;for(a=new Array(e),t=0;t<e;++t)n=i[t],a[n.index]=+c(n,t,i)}}function e(t){var n,e,r,i,o,u=0;if(t.length){for(r=i=o=0;o<4;++o)(n=t[o])&&(e=n.value)&&(u+=e,r+=e*n.x,i+=e*n.y);t.x=r/u,t.y=i/u}else{(n=t).x=n.data.x,n.y=n.data.y;do{u+=a[n.data.index]}while(n=n.next)}t.value=u}function r(t,n,e,r){if(!t.value)return!0;var i=t.x-o.x,c=t.y-o.y,h=r-n,p=i*i+c*c;if(h*h/l<p)return p<f&&(0===i&&(i=rp(),p+=i*i),0===c&&(c=rp(),p+=c*c),p<s&&(p=Math.sqrt(s*p)),o.vx+=i*t.value*u/p,o.vy+=c*t.value*u/p),!0;if(!(t.length||p>=f)){(t.data!==o||t.next)&&(0===i&&(i=rp(),p+=i*i),0===c&&(c=rp(),p+=c*c),p<s&&(p=Math.sqrt(s*p)));do{t.data!==o&&(h=a[t.data.index]*u/p,o.vx+=i*h,o.vy+=c*h)}while(t=t.next)}}var i,o,u,a,c=ep(-30),s=1,f=1/0,l=.81;return t.initialize=function(t){i=t,n()},t.strength=function(e){return arguments.length?(c="function"==typeof e?e:ep(+e),n(),t):c},t.distanceMin=function(n){return arguments.length?(s=n*n,t):Math.sqrt(s)},t.distanceMax=function(n){return arguments.length?(f=n*n,t):Math.sqrt(f)},t.theta=function(n){return arguments.length?(l=n*n,t):Math.sqrt(l)},t},t.forceSimulation=function(t){function n(){e(),d.call("tick",o),u<a&&(p.stop(),d.call("end",o))}function e(){var n,e,r=t.length;for(u+=(s-u)*c,l.each(function(t){t(u)}),n=0;n<r;++n)null==(e=t[n]).fx?e.x+=e.vx*=f:(e.x=e.fx,e.vx=0),null==e.fy?e.y+=e.vy*=f:(e.y=e.fy,e.vy=0)}function r(){for(var n,e=0,r=t.length;e<r;++e){if(n=t[e],n.index=e,isNaN(n.x)||isNaN(n.y)){var i=ap*Math.sqrt(e),o=e*cp;n.x=i*Math.cos(o),n.y=i*Math.sin(o)}(isNaN(n.vx)||isNaN(n.vy))&&(n.vx=n.vy=0)}}function i(n){return n.initialize&&n.initialize(t),n}var o,u=1,a=.001,c=1-Math.pow(a,1/300),s=0,f=.6,l=we(),p=dn(n),d=h("tick","end");return null==t&&(t=[]),r(),o={tick:e,restart:function(){return p.restart(n),o},stop:function(){return p.stop(),o},nodes:function(n){return arguments.length?(t=n,r(),l.each(i),o):t},alpha:function(t){return arguments.length?(u=+t,o):u},alphaMin:function(t){return arguments.length?(a=+t,o):a},alphaDecay:function(t){return arguments.length?(c=+t,o):+c},alphaTarget:function(t){return arguments.length?(s=+t,o):s},velocityDecay:function(t){return arguments.length?(f=1-t,o):1-f},force:function(t,n){return arguments.length>1?(null==n?l.remove(t):l.set(t,i(n)),o):l.get(t)},find:function(n,e,r){var i,o,u,a,c,s=0,f=t.length;for(null==r?r=1/0:r*=r,s=0;s<f;++s)(u=(i=n-(a=t[s]).x)*i+(o=e-a.y)*o)<r&&(c=a,r=u);return c},on:function(t,n){return arguments.length>1?(d.on(t,n),o):d.on(t)}}},t.forceX=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)(n=r[e]).vx+=(o[e]-n.x)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=ep(.1);return"function"!=typeof t&&(t=ep(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:ep(+t),e(),n):u},n.x=function(r){return arguments.length?(t="function"==typeof r?r:ep(+r),e(),n):t},n},t.forceY=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)(n=r[e]).vy+=(o[e]-n.y)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=ep(.1);return"function"!=typeof t&&(t=ep(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:ep(+t),e(),n):u},n.y=function(r){return arguments.length?(t="function"==typeof r?r:ep(+r),e(),n):t},n},t.formatDefaultLocale=$e,t.formatLocale=mp,t.formatSpecifier=He,t.precisionFixed=xp,t.precisionPrefix=bp,t.precisionRound=wp,t.geoArea=function(t){return kd.reset(),Md(t,Nd),2*kd},t.geoBounds=function(t){var n,e,r,i,o,u,a;if(Pp=zp=-(Ap=Cp=1/0),Dp=[],Md(t,Ed),e=Dp.length){for(Dp.sort(br),n=1,o=[r=Dp[0]];n<e;++n)wr(r,(i=Dp[n])[0])||wr(r,i[1])?(xr(r[0],i[1])>xr(r[0],r[1])&&(r[1]=i[1]),xr(i[0],r[1])>xr(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-1/0,n=0,r=o[e=o.length-1];n<=e;r=i,++n)i=o[n],(a=xr(r[1],i[0]))>u&&(u=a,Ap=i[0],zp=r[1])}return Dp=Op=null,Ap===1/0||Cp===1/0?[[NaN,NaN],[NaN,NaN]]:[[Ap,Cp],[zp,Pp]]},t.geoCentroid=function(t){Fp=Ip=Yp=Bp=jp=Hp=Xp=$p=Vp=Wp=Zp=0,Md(t,Ad);var n=Vp,e=Wp,r=Zp,i=n*n+e*e+r*r;return i<1e-12&&(n=Hp,e=Xp,r=$p,Ip<ed&&(n=Yp,e=Bp,r=jp),(i=n*n+e*e+r*r)<1e-12)?[NaN,NaN]:[ld(e,n)*ad,Ge(r/md(i))*ad]},t.geoCircle=function(){function t(){var t=r.apply(this,arguments),a=i.apply(this,arguments)*cd,c=o.apply(this,arguments)*cd;return n=[],e=Lr(-t[0]*cd,-t[1]*cd,0).invert,Or(u,a,c,1),t={type:"Polygon",coordinates:[n]},n=e=null,t}var n,e,r=Cd([0,0]),i=Cd(90),o=Cd(6),u={point:function(t,r){n.push(t=e(t,r)),t[0]*=ad,t[1]*=ad}};return t.center=function(n){return arguments.length?(r="function"==typeof n?n:Cd([+n[0],+n[1]]),t):r},t.radius=function(n){return arguments.length?(i="function"==typeof n?n:Cd(+n),t):i},t.precision=function(n){return arguments.length?(o="function"==typeof n?n:Cd(+n),t):o},t},t.geoClipExtent=function(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=Br(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][1],o=+a[1][0],u=+a[1][1],t=n=null,e):[[r,i],[o,u]]}}},t.geoContains=function(t,n){return(t&&iv.hasOwnProperty(t.type)?iv[t.type]:$r)(t,n)},t.geoDistance=rv,t.geoGraticule=ti,t.geoGraticule10=function(){return ti()()},t.geoInterpolate=function(t,n){var e=t[0]*cd,r=t[1]*cd,i=n[0]*cd,o=n[1]*cd,u=hd(r),a=yd(r),c=hd(o),s=yd(o),f=u*hd(e),l=u*yd(e),h=c*hd(i),p=c*yd(i),d=2*Ge(md(Je(o-r)+u*c*Je(i-e))),v=yd(d),_=d?function(t){var n=yd(t*=d)/v,e=yd(d-t)/v,r=e*f+n*h,i=e*l+n*p,o=e*a+n*s;return[ld(i,r)*ad,ld(o,md(r*r+i*i))*ad]}:function(){return[e*ad,r*ad]};return _.distance=d,_},t.geoLength=tv,t.geoPath=function(t,n){function e(t){return t&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),Md(t,r(i))),i.result()}var r,i,o=4.5;return e.area=function(t){return Md(t,r(sv)),sv.result()},e.measure=function(t){return Md(t,r(zv)),zv.result()},e.bounds=function(t){return Md(t,r(dv)),dv.result()},e.centroid=function(t){return Md(t,r(Tv)),Tv.result()},e.projection=function(n){return arguments.length?(r=null==n?(t=null,uv):(t=n).stream,e):t},e.context=function(t){return arguments.length?(i=null==t?(n=null,new yi):new di(n=t),"function"!=typeof o&&i.pointRadius(o),e):n},e.pointRadius=function(t){return arguments.length?(o="function"==typeof t?t:(i.pointRadius(+t),+t),e):o},e.projection(t).context(n)},t.geoAlbers=Iv,t.geoAlbersUsa=function(){function t(t){var n=t[0],e=t[1];return a=null,i.point(n,e),a||(o.point(n,e),a)||(u.point(n,e),a)}function n(){return e=r=null,t}var e,r,i,o,u,a,c=Iv(),s=Fv().rotate([154,0]).center([-2,58.5]).parallels([55,65]),f=Fv().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,n){a=[t,n]}};return t.invert=function(t){var n=c.scale(),e=c.translate(),r=(t[0]-e[0])/n,i=(t[1]-e[1])/n;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?f:c).invert(t)},t.stream=function(t){return e&&r===t?e:e=Ri([c.stream(r=t),s.stream(t),f.stream(t)])},t.precision=function(t){return arguments.length?(c.precision(t),s.precision(t),f.precision(t),n()):c.precision()},t.scale=function(n){return arguments.length?(c.scale(n),s.scale(.35*n),f.scale(n),t.translate(c.translate())):c.scale()},t.translate=function(t){if(!arguments.length)return c.translate();var e=c.scale(),r=+t[0],a=+t[1];return i=c.translate(t).clipExtent([[r-.455*e,a-.238*e],[r+.455*e,a+.238*e]]).stream(l),o=s.translate([r-.307*e,a+.201*e]).clipExtent([[r-.425*e+ed,a+.12*e+ed],[r-.214*e-ed,a+.234*e-ed]]).stream(l),u=f.translate([r-.205*e,a+.212*e]).clipExtent([[r-.214*e+ed,a+.166*e+ed],[r-.115*e-ed,a+.234*e-ed]]).stream(l),n()},t.fitExtent=function(n,e){return Ti(t,n,e)},t.fitSize=function(n,e){return ki(t,n,e)},t.scale(1070)},t.geoAzimuthalEqualArea=function(){return Ei(Yv).scale(124.75).clipAngle(179.999)},t.geoAzimuthalEqualAreaRaw=Yv,t.geoAzimuthalEquidistant=function(){return Ei(Bv).scale(79.4188).clipAngle(179.999)},t.geoAzimuthalEquidistantRaw=Bv,t.geoConicConformal=function(){return Ci(Fi).scale(109.5).parallels([30,30])},t.geoConicConformalRaw=Fi,t.geoConicEqualArea=Fv,t.geoConicEqualAreaRaw=Pi,t.geoConicEquidistant=function(){return Ci(Yi).scale(131.154).center([0,13.9389])},t.geoConicEquidistantRaw=Yi,t.geoEquirectangular=function(){return Ei(Ii).scale(152.63)},t.geoEquirectangularRaw=Ii,t.geoGnomonic=function(){return Ei(Bi).scale(144.049).clipAngle(60)},t.geoGnomonicRaw=Bi,t.geoIdentity=function(){function t(){return i=o=null,u}var n,e,r,i,o,u,a=1,c=0,s=0,f=1,l=1,h=uv,p=null,d=uv;return u={stream:function(t){return i&&o===t?i:i=h(d(o=t))},clipExtent:function(i){return arguments.length?(d=null==i?(p=n=e=r=null,uv):Br(p=+i[0][0],n=+i[0][1],e=+i[1][0],r=+i[1][1]),t()):null==p?null:[[p,n],[e,r]]},scale:function(n){return arguments.length?(h=ji((a=+n)*f,a*l,c,s),t()):a},translate:function(n){return arguments.length?(h=ji(a*f,a*l,c=+n[0],s=+n[1]),t()):[c,s]},reflectX:function(n){return arguments.length?(h=ji(a*(f=n?-1:1),a*l,c,s),t()):f<0},reflectY:function(n){return arguments.length?(h=ji(a*f,a*(l=n?-1:1),c,s),t()):l<0},fitExtent:function(t,n){return Ti(u,t,n)},fitSize:function(t,n){return ki(u,t,n)}}},t.geoProjection=Ei,t.geoProjectionMutator=Ai,t.geoMercator=function(){return Di(Ui).scale(961/ud)},t.geoMercatorRaw=Ui,t.geoOrthographic=function(){return Ei(Hi).scale(249.5).clipAngle(90+ed)},t.geoOrthographicRaw=Hi,t.geoStereographic=function(){return Ei(Xi).scale(250).clipAngle(142)},t.geoStereographicRaw=Xi,t.geoTransverseMercator=function(){var t=Di($i),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):(t=n(),[t[1],-t[0]])},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):(t=e(),[t[0],t[1],t[2]-90])},e([0,0,90]).scale(159.155)},t.geoTransverseMercatorRaw=$i,t.geoRotation=jd,t.geoStream=Md,t.geoTransform=function(t){return{stream:wi(t)}},t.cluster=function(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=Wi(e),t.y=Gi(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=Qi(t),c=Ki(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=Vi,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},t.hierarchy=eo,t.pack=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(No(n)).eachAfter(So(i,.5)).eachBefore(Eo(1)):t.eachBefore(No(ko)).eachAfter(So(To,1)).eachAfter(So(i,t.r/Math.min(e,r))).eachBefore(Eo(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=To;return t.radius=function(e){return arguments.length?(n=wo(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:Xv(+n),t):i},t},t.packSiblings=function(t){return bo(t),t},t.packEnclose=Hv,t.partition=function(){function t(t){var u=t.height+1;return t.x0=t.y0=i,t.x1=e,t.y1=r/u,t.eachBefore(n(r,u)),o&&t.eachBefore($v),t}function n(t,n){return function(e){e.children&&Vv(e,e.x0,t*(e.depth+1)/n,e.x1,t*(e.depth+2)/n);var r=e.x0,o=e.y0,u=e.x1-i,a=e.y1-i;u<r&&(r=u=(r+u)/2),a<o&&(o=a=(o+a)/2),e.x0=r,e.y0=o,e.x1=u,e.y1=a}}var e=1,r=1,i=0,o=!1;return t.round=function(n){return arguments.length?(o=!!n,t):o},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i=+n,t):i},t},t.stratify=function(){function t(t){var r,i,o,u,a,c,s,f=t.length,l=new Array(f),h={};for(i=0;i<f;++i)r=t[i],a=l[i]=new uo(r),null!=(c=n(r,i,t))&&(c+="")&&(h[s=Wv+(a.id=c)]=s in h?Gv:a);for(i=0;i<f;++i)if(a=l[i],null!=(c=e(t[i],i,t))&&(c+="")){if(!(u=h[Wv+c]))throw new Error("missing: "+c);if(u===Gv)throw new Error("ambiguous: "+c);u.children?u.children.push(a):u.children=[a],a.parent=u}else{if(o)throw new Error("multiple roots");o=a}if(!o)throw new Error("no root");if(o.parent=Zv,o.eachBefore(function(t){t.depth=t.parent.depth+1,--f}).eachBefore(oo),o.parent=null,f>0)throw new Error("cycle");return o}var n=Ao,e=Co;return t.id=function(e){return arguments.length?(n=Mo(e),t):n},t.parentId=function(n){return arguments.length?(e=Mo(n),t):e},t},t.tree=function(){function t(t){var r=Oo(t);if(r.eachAfter(n),r.parent.m=-r.z,r.eachBefore(e),c)t.eachBefore(i);else{var s=t,f=t,l=t;t.eachBefore(function(t){t.x<s.x&&(s=t),t.x>f.x&&(f=t),t.depth>l.depth&&(l=t)});var h=s===f?1:o(s,f)/2,p=h-s.x,d=u/(f.x+h+p),v=a/(l.depth||1);t.eachBefore(function(t){t.x=(t.x+p)*d,t.y=t.depth*v})}return t}function n(t){var n=t.children,e=t.parent.children,i=t.i?e[t.i-1]:null;if(n){qo(t);var u=(n[0].z+n[n.length-1].z)/2;i?(t.z=i.z+o(t._,i._),t.m=t.z-u):t.z=u}else i&&(t.z=i.z+o(t._,i._));t.parent.A=r(t,i,t.parent.A||e[0])}function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function r(t,n,e){if(n){for(var r,i=t,u=t,a=n,c=i.parent.children[0],s=i.m,f=u.m,l=a.m,h=c.m;a=Ro(a),i=Po(i),a&&i;)c=Po(c),(u=Ro(u)).a=t,(r=a.z+l-i.z-s+o(a._,i._))>0&&(Lo(Uo(a,t,e),t,r),s+=r,f+=r),l+=a.m,s+=i.m,h+=c.m,f+=u.m;a&&!Ro(u)&&(u.t=a,u.m+=l-f),i&&!Po(c)&&(c.t=i,c.m+=s-h,e=t)}return e}function i(t){t.x*=u,t.y=t.depth*a}var o=zo,u=1,a=1,c=null;return t.separation=function(n){return arguments.length?(o=n,t):o},t.size=function(n){return arguments.length?(c=!1,u=+n[0],a=+n[1],t):c?null:[u,a]},t.nodeSize=function(n){return arguments.length?(c=!0,u=+n[0],a=+n[1],t):c?[u,a]:null},t},t.treemap=function(){function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),u=[0],r&&t.eachBefore($v),t}function n(t){var n=u[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),t.x0=r,t.y0=i,t.x1=o,t.y1=h,t.children&&(n=u[t.depth+1]=a(t)/2,r+=l(t)-n,i+=c(t)-n,o-=s(t)-n,h-=f(t)-n,o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),e(t,r,i,o,h))}var e=Kv,r=!1,i=1,o=1,u=[0],a=To,c=To,s=To,f=To,l=To;return t.round=function(n){return arguments.length?(r=!!n,t):r},t.size=function(n){return arguments.length?(i=+n[0],o=+n[1],t):[i,o]},t.tile=function(n){return arguments.length?(e=Mo(n),t):e},t.padding=function(n){return arguments.length?t.paddingInner(n).paddingOuter(n):t.paddingInner()},t.paddingInner=function(n){return arguments.length?(a="function"==typeof n?n:Xv(+n),t):a},t.paddingOuter=function(n){return arguments.length?t.paddingTop(n).paddingRight(n).paddingBottom(n).paddingLeft(n):t.paddingTop()},t.paddingTop=function(n){return arguments.length?(c="function"==typeof n?n:Xv(+n),t):c},t.paddingRight=function(n){return arguments.length?(s="function"==typeof n?n:Xv(+n),t):s},t.paddingBottom=function(n){return arguments.length?(f="function"==typeof n?n:Xv(+n),t):f},t.paddingLeft=function(n){return arguments.length?(l="function"==typeof n?n:Xv(+n),t):l},t},t.treemapBinary=function(t,n,e,r,i){function o(t,n,e,r,i,u,a){if(t>=n-1){var s=c[t];return s.x0=r,s.y0=i,s.x1=u,void(s.y1=a)}for(var l=f[t],h=e/2+l,p=t+1,d=n-1;p<d;){var v=p+d>>>1;f[v]<h?p=v+1:d=v}h-f[p-1]<f[p]-h&&t+1<p&&--p;var _=f[p]-l,y=e-_;if(u-r>a-i){var g=(r*y+u*_)/e;o(t,p,_,r,i,g,a),o(p,n,y,g,i,u,a)}else{var m=(i*y+a*_)/e;o(t,p,_,r,i,u,m),o(p,n,y,r,m,u,a)}}var u,a,c=t.children,s=c.length,f=new Array(s+1);for(f[0]=a=u=0;u<s;++u)f[u+1]=a+=c[u].value;o(0,s,t.value,n,e,r,i)},t.treemapDice=Vv,t.treemapSlice=Jv,t.treemapSliceDice=function(t,n,e,r,i){(1&t.depth?Jv:Vv)(t,n,e,r,i)},t.treemapSquarify=Kv,t.treemapResquarify=t_,t.interpolate=cl,t.interpolateArray=nl,t.interpolateBasis=Zf,t.interpolateBasisClosed=Gf,t.interpolateDate=el,t.interpolateNumber=rl,t.interpolateObject=il,t.interpolateRound=sl,t.interpolateString=al,t.interpolateTransformCss=pl,t.interpolateTransformSvg=dl,t.interpolateZoom=_l,t.interpolateRgb=Qf,t.interpolateRgbBasis=Kf,t.interpolateRgbBasisClosed=tl,t.interpolateHsl=yl,t.interpolateHslLong=gl,t.interpolateLab=function(t,n){var e=Kt((t=Ut(t)).l,(n=Ut(n)).l),r=Kt(t.a,n.a),i=Kt(t.b,n.b),o=Kt(t.opacity,n.opacity);return function(n){return t.l=e(n),t.a=r(n),t.b=i(n),t.opacity=o(n),t+""}},t.interpolateHcl=ml,t.interpolateHclLong=xl,t.interpolateCubehelix=bl,t.interpolateCubehelixLong=wl,t.quantize=function(t,n){for(var e=new Array(n),r=0;r<n;++r)e[r]=t(r/(n-1));return e},t.path=ve,t.polygonArea=function(t){for(var n,e=-1,r=t.length,i=t[r-1],o=0;++e<r;)n=i,i=t[e],o+=n[1]*i[0]-n[0]*i[1];return o/2},t.polygonCentroid=function(t){for(var n,e,r=-1,i=t.length,o=0,u=0,a=t[i-1],c=0;++r<i;)n=a,a=t[r],c+=e=n[0]*a[1]-a[0]*n[1],o+=(n[0]+a[0])*e,u+=(n[1]+a[1])*e;return c*=3,[o/c,u/c]},t.polygonHull=function(t){if((e=t.length)<3)return null;var n,e,r=new Array(e),i=new Array(e);for(n=0;n<e;++n)r[n]=[+t[n][0],+t[n][1],n];for(r.sort(Io),n=0;n<e;++n)i[n]=[r[n][0],-r[n][1]];var o=Yo(r),u=Yo(i),a=u[0]===o[0],c=u[u.length-1]===o[o.length-1],s=[];for(n=o.length-1;n>=0;--n)s.push(t[r[o[n]][2]]);for(n=+a;n<u.length-c;++n)s.push(t[r[u[n]][2]]);return s},t.polygonContains=function(t,n){for(var e,r,i=t.length,o=t[i-1],u=n[0],a=n[1],c=o[0],s=o[1],f=!1,l=0;l<i;++l)e=(o=t[l])[0],(r=o[1])>a!=s>a&&u<(c-e)*(a-r)/(s-r)+e&&(f=!f),c=e,s=r;return f},t.polygonLength=function(t){for(var n,e,r=-1,i=t.length,o=t[i-1],u=o[0],a=o[1],c=0;++r<i;)n=u,e=a,n-=u=(o=t[r])[0],e-=a=o[1],c+=Math.sqrt(n*n+e*e);return c},t.quadtree=qe,t.queue=Wo,t.randomUniform=o_,t.randomNormal=u_,t.randomLogNormal=a_,t.randomBates=s_,t.randomIrwinHall=c_,t.randomExponential=f_,t.request=l_,t.html=p_,t.json=d_,t.text=v_,t.xml=__,t.csv=g_,t.tsv=m_,t.scaleBand=Ko,t.scalePoint=function(){return tu(Ko().paddingInner(1))},t.scaleIdentity=fu,t.scaleLinear=su,t.scaleLog=yu,t.scaleOrdinal=Qo,t.scaleImplicit=M_,t.scalePow=mu,t.scaleSqrt=function(){return mu().exponent(.5)},t.scaleQuantile=xu,t.scaleQuantize=bu,t.scaleThreshold=wu,t.scaleTime=function(){return Na(oy,ry,j_,Y_,F_,D_,q_,z_,t.timeFormat).domain([new Date(2e3,0,1),new Date(2e3,0,2)])},t.scaleUtc=function(){return Na(Ay,Sy,py,ly,sy,ay,q_,z_,t.utcFormat).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)])},t.schemeCategory10=$y,t.schemeCategory20b=Vy,t.schemeCategory20c=Wy,t.schemeCategory20=Zy,t.interpolateCubehelixDefault=Gy,t.interpolateRainbow=function(t){(t<0||t>1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return Ky.h=360*t-100,Ky.s=1.5-1.5*n,Ky.l=.8-.9*n,Ky+""},t.interpolateWarm=Jy,t.interpolateCool=Qy,t.interpolateViridis=tg,t.interpolateMagma=ng,t.interpolateInferno=eg,t.interpolatePlasma=rg,t.scaleSequential=Ea,t.creator=Hs,t.local=m,t.matcher=Zs,t.mouse=Ks,t.namespace=js,t.namespaces=Bs,t.select=cf,t.selectAll=function(t){return"string"==typeof t?new pt([document.querySelectorAll(t)],[document.documentElement]):new pt([null==t?[]:t],af)},t.selection=dt,t.selector=tf,t.selectorAll=nf,t.style=B,t.touch=sf,t.touches=function(t,n){null==n&&(n=Js().touches);for(var e=0,r=n?n.length:0,i=new Array(r);e<r;++e)i[e]=Qs(t,n[e]);return i},t.window=uf,t.customEvent=N,t.arc=function(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-dg,p=u.apply(this,arguments)-dg,d=og(p-h),v=p>h;if(c||(c=t=ve()),l<f&&(s=l,l=f,f=s),l>hg)if(d>vg-hg)c.moveTo(l*ag(h),l*fg(h)),c.arc(0,0,l,h,p,!v),f>hg&&(c.moveTo(f*ag(p),f*fg(p)),c.arc(0,0,f,p,h,v));else{var _,y,g=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,k=T>hg&&(i?+i.apply(this,arguments):lg(f*f+l*l)),N=sg(og(l-f)/2,+r.apply(this,arguments)),S=N,E=N;if(k>hg){var A=Ca(k/f*fg(T)),C=Ca(k/l*fg(T));(w-=2*A)>hg?(A*=v?1:-1,x+=A,b-=A):(w=0,x=b=(h+p)/2),(M-=2*C)>hg?(C*=v?1:-1,g+=C,m-=C):(M=0,g=m=(h+p)/2)}var z=l*ag(g),P=l*fg(g),R=f*ag(b),L=f*fg(b);if(N>hg){var q=l*ag(m),U=l*fg(m),D=f*ag(x),O=f*fg(x);if(d<pg){var F=w>hg?Ua(z,P,D,O,q,U,R,L):[R,L],I=z-F[0],Y=P-F[1],B=q-F[0],j=U-F[1],H=1/fg(Aa((I*B+Y*j)/(lg(I*I+Y*Y)*lg(B*B+j*j)))/2),X=lg(F[0]*F[0]+F[1]*F[1]);S=sg(N,(f-X)/(H-1)),E=sg(N,(l-X)/(H+1))}}M>hg?E>hg?(_=Da(D,O,z,P,l,E,v),y=Da(q,U,R,L,l,E,v),c.moveTo(_.cx+_.x01,_.cy+_.y01),E<N?c.arc(_.cx,_.cy,E,ug(_.y01,_.x01),ug(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,E,ug(_.y01,_.x01),ug(_.y11,_.x11),!v),c.arc(0,0,l,ug(_.cy+_.y11,_.cx+_.x11),ug(y.cy+y.y11,y.cx+y.x11),!v),c.arc(y.cx,y.cy,E,ug(y.y11,y.x11),ug(y.y01,y.x01),!v))):(c.moveTo(z,P),c.arc(0,0,l,g,m,!v)):c.moveTo(z,P),f>hg&&w>hg?S>hg?(_=Da(R,L,q,U,f,-S,v),y=Da(z,P,D,O,f,-S,v),c.lineTo(_.cx+_.x01,_.cy+_.y01),S<N?c.arc(_.cx,_.cy,S,ug(_.y01,_.x01),ug(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,S,ug(_.y01,_.x01),ug(_.y11,_.x11),!v),c.arc(0,0,f,ug(_.cy+_.y11,_.cx+_.x11),ug(y.cy+y.y11,y.cx+y.x11),v),c.arc(y.cx,y.cy,S,ug(y.y11,y.x11),ug(y.y01,y.x01),!v))):c.arc(0,0,f,b,x,v):c.lineTo(R,L)}else c.moveTo(0,0);if(c.closePath(),t)return c=null,t+""||null}var n=za,e=Pa,r=ig(0),i=null,o=Ra,u=La,a=qa,c=null;return t.centroid=function(){var t=(+n.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+o.apply(this,arguments)+ +u.apply(this,arguments))/2-pg/2;return[ag(r)*t,fg(r)*t]},t.innerRadius=function(e){return arguments.length?(n="function"==typeof e?e:ig(+e),t):n},t.outerRadius=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.cornerRadius=function(n){return arguments.length?(r="function"==typeof n?n:ig(+n),t):r},t.padRadius=function(n){return arguments.length?(i=null==n?null:"function"==typeof n?n:ig(+n),t):i},t.startAngle=function(n){return arguments.length?(o="function"==typeof n?n:ig(+n),t):o},t.endAngle=function(n){return arguments.length?(u="function"==typeof n?n:ig(+n),t):u},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:ig(+n),t):a},t.context=function(n){return arguments.length?(c=null==n?null:n,t):c},t},t.area=gg,t.line=yg,t.pie=function(){function t(t){var a,c,s,f,l,h=t.length,p=0,d=new Array(h),v=new Array(h),_=+i.apply(this,arguments),y=Math.min(vg,Math.max(-vg,o.apply(this,arguments)-_)),g=Math.min(Math.abs(y)/h,u.apply(this,arguments)),m=g*(y<0?-1:1);for(a=0;a<h;++a)(l=v[d[a]=a]=+n(t[a],a,t))>0&&(p+=l);for(null!=e?d.sort(function(t,n){return e(v[t],v[n])}):null!=r&&d.sort(function(n,e){return r(t[n],t[e])}),a=0,s=p?(y-h*m)/p:0;a<h;++a,_=f)c=d[a],f=_+((l=v[c])>0?l*s:0)+m,v[c]={data:t[c],index:a,value:l,startAngle:_,endAngle:f,padAngle:g};return v}var n=xg,e=mg,r=null,i=ig(0),o=ig(vg),u=ig(0);return t.value=function(e){return arguments.length?(n="function"==typeof e?e:ig(+e),t):n},t.sortValues=function(n){return arguments.length?(e=n,r=null,t):e},t.sort=function(n){return arguments.length?(r=n,e=null,t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:ig(+n),t):o},t.padAngle=function(n){return arguments.length?(u="function"==typeof n?n:ig(+n),t):u},t},t.areaRadial=Mg,t.radialArea=Mg,t.lineRadial=wg,t.radialLine=wg,t.pointRadial=Tg,t.linkHorizontal=function(){return $a(Va)},t.linkVertical=function(){return $a(Wa)},t.linkRadial=function(){var t=$a(Za);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t},t.symbol=function(){function t(){var t;if(r||(r=t=ve()),n.apply(this,arguments).draw(r,+e.apply(this,arguments)),t)return r=null,t+""||null}var n=ig(Ng),e=ig(64),r=null;return t.type=function(e){return arguments.length?(n="function"==typeof e?e:ig(e),t):n},t.size=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.context=function(n){return arguments.length?(r=null==n?null:n,t):r},t},t.symbols=jg,t.symbolCircle=Ng,t.symbolCross=Sg,t.symbolDiamond=Cg,t.symbolSquare=qg,t.symbolStar=Lg,t.symbolTriangle=Dg,t.symbolWye=Bg,t.curveBasisClosed=function(t){return new Qa(t)},t.curveBasisOpen=function(t){return new Ka(t)},t.curveBasis=function(t){return new Ja(t)},t.curveBundle=Xg,t.curveCardinalClosed=Vg,t.curveCardinalOpen=Wg,t.curveCardinal=$g,t.curveCatmullRomClosed=Gg,t.curveCatmullRomOpen=Jg,t.curveCatmullRom=Zg,t.curveLinearClosed=function(t){return new sc(t)},t.curveLinear=_g,t.curveMonotoneX=function(t){return new dc(t)},t.curveMonotoneY=function(t){return new vc(t)},t.curveNatural=function(t){return new yc(t)},t.curveStep=function(t){return new mc(t,.5)},t.curveStepAfter=function(t){return new mc(t,1)},t.curveStepBefore=function(t){return new mc(t,0)},t.stack=function(){function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=new Array(s);for(o=0;o<s;++o){for(var l,h=a[o],p=f[o]=new Array(c),d=0;d<c;++d)p[d]=l=[0,+i(t[d],h,d,t)],l.data=t[d];p.key=h}for(o=0,u=e(f);o<s;++o)f[u[o]].index=o;return r(f,u),f}var n=ig([]),e=Kg,r=Qg,i=xc;return t.keys=function(e){return arguments.length?(n="function"==typeof e?e:ig(kg.call(e)),t):n},t.value=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),t):i},t.order=function(n){return arguments.length?(e=null==n?Kg:"function"==typeof n?n:ig(kg.call(n)),t):e},t.offset=function(n){return arguments.length?(r=null==n?Qg:n,t):r},t},t.stackOffsetExpand=function(t,n){if((r=t.length)>0){for(var e,r,i,o=0,u=t[0].length;o<u;++o){for(i=e=0;e<r;++e)i+=t[e][o][1]||0;if(i)for(e=0;e<r;++e)t[e][o][1]/=i}Qg(t,n)}},t.stackOffsetDiverging=function(t,n){if((a=t.length)>1)for(var e,r,i,o,u,a,c=0,s=t[n[0]].length;c<s;++c)for(o=u=0,e=0;e<a;++e)(i=(r=t[n[e]][c])[1]-r[0])>=0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=u,r[0]=u+=i):r[0]=o},t.stackOffsetNone=Qg,t.stackOffsetSilhouette=function(t,n){if((e=t.length)>0){for(var e,r=0,i=t[n[0]],o=i.length;r<o;++r){for(var u=0,a=0;u<e;++u)a+=t[u][r][1]||0;i[r][1]+=i[r][0]=-a/2}Qg(t,n)}},t.stackOffsetWiggle=function(t,n){if((i=t.length)>0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,u=1;u<r;++u){for(var a=0,c=0,s=0;a<i;++a){for(var f=t[n[a]],l=f[u][1]||0,h=(l-(f[u-1][1]||0))/2,p=0;p<a;++p){var d=t[n[p]];h+=(d[u][1]||0)-(d[u-1][1]||0)}c+=l,s+=h*l}e[u-1][1]+=e[u-1][0]=o,c&&(o-=s/c)}e[u-1][1]+=e[u-1][0]=o,Qg(t,n)}},t.stackOrderAscending=tm,t.stackOrderDescending=function(t){return tm(t).reverse()},t.stackOrderInsideOut=function(t){var n,e,r=t.length,i=t.map(bc),o=Kg(t).sort(function(t,n){return i[n]-i[t]}),u=0,a=0,c=[],s=[];for(n=0;n<r;++n)e=o[n],u<a?(u+=i[e],c.push(e)):(a+=i[e],s.push(e));return s.reverse().concat(c)},t.stackOrderNone=Kg,t.stackOrderReverse=function(t){return Kg(t).reverse()},t.timeInterval=Mu,t.timeMillisecond=z_,t.timeMilliseconds=P_,t.utcMillisecond=z_,t.utcMilliseconds=P_,t.timeSecond=q_,t.timeSeconds=U_,t.utcSecond=q_,t.utcSeconds=U_,t.timeMinute=D_,t.timeMinutes=O_,t.timeHour=F_,t.timeHours=I_,t.timeDay=Y_,t.timeDays=B_,t.timeWeek=j_,t.timeWeeks=G_,t.timeSunday=j_,t.timeSundays=G_,t.timeMonday=H_,t.timeMondays=J_,t.timeTuesday=X_,t.timeTuesdays=Q_,t.timeWednesday=$_,t.timeWednesdays=K_,t.timeThursday=V_,t.timeThursdays=ty,t.timeFriday=W_,t.timeFridays=ny,t.timeSaturday=Z_,t.timeSaturdays=ey,t.timeMonth=ry,t.timeMonths=iy,t.timeYear=oy,t.timeYears=uy,t.utcMinute=ay,t.utcMinutes=cy,t.utcHour=sy,t.utcHours=fy,t.utcDay=ly,t.utcDays=hy,t.utcWeek=py,t.utcWeeks=xy,t.utcSunday=py,t.utcSundays=xy,t.utcMonday=dy,t.utcMondays=by,t.utcTuesday=vy,t.utcTuesdays=wy,t.utcWednesday=_y,t.utcWednesdays=My,t.utcThursday=yy,t.utcThursdays=Ty,t.utcFriday=gy,t.utcFridays=ky,t.utcSaturday=my,t.utcSaturdays=Ny,t.utcMonth=Sy,t.utcMonths=Ey,t.utcYear=Ay,t.utcYears=zy,t.timeFormatDefaultLocale=Ma,t.timeFormatLocale=Au,t.isoFormat=Uy,t.isoParse=Dy,t.now=ln,t.timer=dn,t.timerFlush=vn,t.timeout=Pl,t.interval=function(t,n,e){var r=new pn,i=n;return null==n?(r.restart(t,n,e),r):(n=+n,e=null==e?ln():+e,r.restart(function o(u){u+=i,r.restart(o,i+=n,e),t(u)},n,e),r)},t.transition=Jn,t.active=function(t,n){var e,r,i=t.__transition;if(i){n=null==n?null:n+"";for(r in i)if((e=i[r]).state>Ul&&e.name===n)return new Gn([[t]],yh,n,+r)}return null},t.interrupt=jl,t.voronoi=function(){function t(t){return new Kc(t.map(function(r,i){var o=[Math.round(n(r,i,t)/sm)*sm,Math.round(e(r,i,t)/sm)*sm];return o.index=i,o.data=r,o}),r)}var n=wc,e=Mc,r=null;return t.polygons=function(n){return t(n).polygons()},t.links=function(n){return t(n).links()},t.triangles=function(n){return t(n).triangles()},t.x=function(e){return arguments.length?(n="function"==typeof e?e:nm(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:nm(+n),t):e},t.extent=function(n){return arguments.length?(r=null==n?null:[[+n[0][0],+n[0][1]],[+n[1][0],+n[1][1]]],t):r&&[[r[0][0],r[0][1]],[r[1][0],r[1][1]]]},t.size=function(n){return arguments.length?(r=null==n?null:[[0,0],[+n[0],+n[1]]],t):r&&[r[1][0]-r[0][0],r[1][1]-r[0][1]]},t},t.zoom=function(){function n(t){t.property("__zoom",us).on("wheel.zoom",s).on("mousedown.zoom",f).on("dblclick.zoom",l).filter(cs).on("touchstart.zoom",p).on("touchmove.zoom",d).on("touchend.zoom touchcancel.zoom",v).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(t,n){return(n=Math.max(b,Math.min(w,n)))===t.k?t:new ns(n,t.x,t.y)}function r(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new ns(t.k,r,i)}function i(t,n){var e=t.invertX(n[0][0])-M,r=t.invertX(n[1][0])-T,i=t.invertY(n[0][1])-k,o=t.invertY(n[1][1])-S;return t.translate(r>e?(e+r)/2:Math.min(0,e)||Math.max(0,r),o>i?(i+o)/2:Math.min(0,i)||Math.max(0,o))}function o(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function u(t,n,e){t.on("start.zoom",function(){a(this,arguments).start()}).on("interrupt.zoom end.zoom",function(){a(this,arguments).end()}).tween("zoom",function(){var t=this,r=arguments,i=a(t,r),u=m.apply(t,r),c=e||o(u),s=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),f=t.__zoom,l="function"==typeof n?n.apply(t,r):n,h=A(f.invert(c).concat(s/f.k),l.invert(c).concat(s/l.k));return function(t){if(1===t)t=l;else{var n=h(t),e=s/n[2];t=new ns(e,c[0]-n[0]*e,c[1]-n[1]*e)}i.zoom(null,t)}})}function a(t,n){for(var e,r=0,i=C.length;r<i;++r)if((e=C[r]).that===t)return e;return new c(t,n)}function c(t,n){this.that=t,this.args=n,this.index=-1,this.active=0,this.extent=m.apply(t,n)}function s(){if(g.apply(this,arguments)){var t=a(this,arguments),n=this.__zoom,o=Math.max(b,Math.min(w,n.k*Math.pow(2,x.apply(this,arguments)))),u=Ks(this);if(t.wheel)t.mouse[0][0]===u[0]&&t.mouse[0][1]===u[1]||(t.mouse[1]=n.invert(t.mouse[0]=u)),clearTimeout(t.wheel);else{if(n.k===o)return;t.mouse=[u,n.invert(u)],jl(this),t.start()}pm(),t.wheel=setTimeout(function(){t.wheel=null,t.end()},R),t.zoom("mouse",i(r(e(n,o),t.mouse[0],t.mouse[1]),t.extent))}}function f(){if(!y&&g.apply(this,arguments)){var n=a(this,arguments),e=cf(t.event.view).on("mousemove.zoom",function(){if(pm(),!n.moved){var e=t.event.clientX-u,o=t.event.clientY-c;n.moved=e*e+o*o>L}n.zoom("mouse",i(r(n.that.__zoom,n.mouse[0]=Ks(n.that),n.mouse[1]),n.extent))},!0).on("mouseup.zoom",function(){e.on("mousemove.zoom mouseup.zoom",null),_t(t.event.view,n.moved),pm(),n.end()},!0),o=Ks(this),u=t.event.clientX,c=t.event.clientY;lf(t.event.view),rs(),n.mouse=[o,this.__zoom.invert(o)],jl(this),n.start()}}function l(){if(g.apply(this,arguments)){var o=this.__zoom,a=Ks(this),c=o.invert(a),s=i(r(e(o,o.k*(t.event.shiftKey?.5:2)),a,c),m.apply(this,arguments));pm(),E>0?cf(this).transition().duration(E).call(u,s,a):cf(this).call(n.transform,s)}}function p(){if(g.apply(this,arguments)){var n,e,r,i,o=a(this,arguments),u=t.event.changedTouches,c=u.length;for(rs(),e=0;e<c;++e)r=u[e],i=[i=sf(this,u,r.identifier),this.__zoom.invert(i),r.identifier],o.touch0?o.touch1||(o.touch1=i):(o.touch0=i,n=!0);if(_&&(_=clearTimeout(_),!o.touch1))return o.end(),void((i=cf(this).on("dblclick.zoom"))&&i.apply(this,arguments));n&&(_=setTimeout(function(){_=null},P),jl(this),o.start())}}function d(){var n,o,u,c,s=a(this,arguments),f=t.event.changedTouches,l=f.length;for(pm(),_&&(_=clearTimeout(_)),n=0;n<l;++n)o=f[n],u=sf(this,f,o.identifier),s.touch0&&s.touch0[2]===o.identifier?s.touch0[0]=u:s.touch1&&s.touch1[2]===o.identifier&&(s.touch1[0]=u);if(o=s.that.__zoom,s.touch1){var h=s.touch0[0],p=s.touch0[1],d=s.touch1[0],v=s.touch1[1],y=(y=d[0]-h[0])*y+(y=d[1]-h[1])*y,g=(g=v[0]-p[0])*g+(g=v[1]-p[1])*g;o=e(o,Math.sqrt(y/g)),u=[(h[0]+d[0])/2,(h[1]+d[1])/2],c=[(p[0]+v[0])/2,(p[1]+v[1])/2]}else{if(!s.touch0)return;u=s.touch0[0],c=s.touch0[1]}s.zoom("touch",i(r(o,u,c),s.extent))}function v(){var n,e,r=a(this,arguments),i=t.event.changedTouches,o=i.length;for(rs(),y&&clearTimeout(y),y=setTimeout(function(){y=null},P),n=0;n<o;++n)e=i[n],r.touch0&&r.touch0[2]===e.identifier?delete r.touch0:r.touch1&&r.touch1[2]===e.identifier&&delete r.touch1;r.touch1&&!r.touch0&&(r.touch0=r.touch1,delete r.touch1),r.touch0?r.touch0[1]=this.__zoom.invert(r.touch0[0]):r.end()}var _,y,g=is,m=os,x=as,b=0,w=1/0,M=-w,T=w,k=M,S=T,E=250,A=_l,C=[],z=h("start","zoom","end"),P=500,R=150,L=0;return n.transform=function(t,n){var e=t.selection?t.selection():t;e.property("__zoom",us),t!==e?u(t,n):e.interrupt().each(function(){a(this,arguments).start().zoom(null,"function"==typeof n?n.apply(this,arguments):n).end()})},n.scaleBy=function(t,e){n.scaleTo(t,function(){return this.__zoom.k*("function"==typeof e?e.apply(this,arguments):e)})},n.scaleTo=function(t,u){n.transform(t,function(){var t=m.apply(this,arguments),n=this.__zoom,a=o(t),c=n.invert(a);return i(r(e(n,"function"==typeof u?u.apply(this,arguments):u),a,c),t)})},n.translateBy=function(t,e,r){n.transform(t,function(){return i(this.__zoom.translate("function"==typeof e?e.apply(this,arguments):e,"function"==typeof r?r.apply(this,arguments):r),m.apply(this,arguments))})},n.translateTo=function(t,e,r){n.transform(t,function(){var t=m.apply(this,arguments),n=this.__zoom,u=o(t);return i(hm.translate(u[0],u[1]).scale(n.k).translate("function"==typeof e?-e.apply(this,arguments):-e,"function"==typeof r?-r.apply(this,arguments):-r),t)})},c.prototype={start:function(){return 1==++this.active&&(this.index=C.push(this)-1,this.emit("start")),this},zoom:function(t,n){return this.mouse&&"mouse"!==t&&(this.mouse[1]=n.invert(this.mouse[0])),this.touch0&&"touch"!==t&&(this.touch0[1]=n.invert(this.touch0[0])),this.touch1&&"touch"!==t&&(this.touch1[1]=n.invert(this.touch1[0])),this.that.__zoom=n,this.emit("zoom"),this},end:function(){return 0==--this.active&&(C.splice(this.index,1),this.index=-1,this.emit("end")),this},emit:function(t){N(new ts(n,t,this.that.__zoom),z.apply,z,[t,this.that,this.args])}},n.wheelDelta=function(t){return arguments.length?(x="function"==typeof t?t:lm(+t),n):x},n.filter=function(t){return arguments.length?(g="function"==typeof t?t:lm(!!t),n):g},n.extent=function(t){return arguments.length?(m="function"==typeof t?t:lm([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),n):m},n.scaleExtent=function(t){return arguments.length?(b=+t[0],w=+t[1],n):[b,w]},n.translateExtent=function(t){return arguments.length?(M=+t[0][0],T=+t[1][0],k=+t[0][1],S=+t[1][1],n):[[M,k],[T,S]]},n.duration=function(t){return arguments.length?(E=+t,n):E},n.interpolate=function(t){return arguments.length?(A=t,n):A},n.on=function(){var t=z.on.apply(z,arguments);return t===z?n:t},n.clickDistance=function(t){return arguments.length?(L=(t=+t)*t,n):Math.sqrt(L)},n},t.zoomTransform=es,t.zoomIdentity=hm,Object.defineProperty(t,"__esModule",{value:!0})}); \ No newline at end of file
+// https://d3js.org Version 4.10.0. Copyright 2017 Mike Bostock.
+(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t){return function(n,e){return ss(t(n),e)}}function e(t,n){return[t,n]}function r(t,n,e){var r=(n-t)/Math.max(0,e),i=Math.floor(Math.log(r)/Math.LN10),o=r/Math.pow(10,i);return i>=0?(o>=Ts?10:o>=ks?5:o>=Ns?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(o>=Ts?10:o>=ks?5:o>=Ns?2:1)}function i(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Ts?i*=10:o>=ks?i*=5:o>=Ns&&(i*=2),n<t?-i:i}function o(t){return t.length}function u(t){return"translate("+(t+.5)+",0)"}function a(t){return"translate(0,"+(t+.5)+")"}function c(t){return function(n){return+t(n)}}function s(t){var n=Math.max(0,t.bandwidth()-1)/2;return t.round()&&(n=Math.round(n)),function(e){return+t(e)+n}}function f(){return!this.__axis}function l(t,n){function e(e){var u=null==i?n.ticks?n.ticks.apply(n,r):n.domain():i,a=null==o?n.tickFormat?n.tickFormat.apply(n,r):Ls:o,y=Math.max(l,0)+p,g=n.range(),m=+g[0]+.5,x=+g[g.length-1]+.5,b=(n.bandwidth?s:c)(n.copy()),w=e.selection?e.selection():e,M=w.selectAll(".domain").data([null]),T=w.selectAll(".tick").data(u,n).order(),k=T.exit(),N=T.enter().append("g").attr("class","tick"),S=T.select("line"),E=T.select("text");M=M.merge(M.enter().insert("path",".tick").attr("class","domain").attr("stroke","#000")),T=T.merge(N),S=S.merge(N.append("line").attr("stroke","#000").attr(v+"2",d*l)),E=E.merge(N.append("text").attr("fill","#000").attr(v,d*y).attr("dy",t===qs?"0em":t===Ds?"0.71em":"0.32em")),e!==w&&(M=M.transition(e),T=T.transition(e),S=S.transition(e),E=E.transition(e),k=k.transition(e).attr("opacity",Fs).attr("transform",function(t){return isFinite(t=b(t))?_(t):this.getAttribute("transform")}),N.attr("opacity",Fs).attr("transform",function(t){var n=this.parentNode.__axis;return _(n&&isFinite(n=n(t))?n:b(t))})),k.remove(),M.attr("d",t===Os||t==Us?"M"+d*h+","+m+"H0.5V"+x+"H"+d*h:"M"+m+","+d*h+"V0.5H"+x+"V"+d*h),T.attr("opacity",1).attr("transform",function(t){return _(b(t))}),S.attr(v+"2",d*l),E.attr(v,d*y).text(a),w.filter(f).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Us?"start":t===Os?"end":"middle"),w.each(function(){this.__axis=b})}var r=[],i=null,o=null,l=6,h=6,p=3,d=t===qs||t===Os?-1:1,v=t===Os||t===Us?"x":"y",_=t===qs||t===Ds?u:a;return e.scale=function(t){return arguments.length?(n=t,e):n},e.ticks=function(){return r=Rs.call(arguments),e},e.tickArguments=function(t){return arguments.length?(r=null==t?[]:Rs.call(t),e):r.slice()},e.tickValues=function(t){return arguments.length?(i=null==t?null:Rs.call(t),e):i&&i.slice()},e.tickFormat=function(t){return arguments.length?(o=t,e):o},e.tickSize=function(t){return arguments.length?(l=h=+t,e):l},e.tickSizeInner=function(t){return arguments.length?(l=+t,e):l},e.tickSizeOuter=function(t){return arguments.length?(h=+t,e):h},e.tickPadding=function(t){return arguments.length?(p=+t,e):p},e}function h(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+"")||t in r)throw new Error("illegal type: "+t);r[t]=[]}return new p(r)}function p(t){this._=t}function d(t,n){return t.trim().split(/^|\s+/).map(function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}function v(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}function _(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]=Is,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=e&&t.push({name:n,value:e}),t}function y(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===Ys&&n.documentElement.namespaceURI===Ys?n.createElement(t):n.createElementNS(e,t)}}function g(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function m(){return new x}function x(){this._="@"+(++Xs).toString(36)}function b(t,n,e){return t=w(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function w(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function M(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function T(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function k(t,n,e){var r=Gs.hasOwnProperty(t.type)?b:w;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function N(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{return e.apply(r,i)}finally{t.event=o}}function S(){}function E(){return[]}function A(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function C(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new A(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function z(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Array(l);for(a=0;a<l;++a)(c=n[a])&&(p[a]=s=of+u.call(c,c.__data__,a,n),s in f?i[a]=c:f[s]=c);for(a=0;a<h;++a)(c=f[s=of+u.call(t,o[a],a,o)])?(r[a]=c,c.__data__=o[a],f[s]=null):e[a]=new A(t,o[a]);for(a=0;a<l;++a)(c=n[a])&&f[p[a]]===c&&(i[a]=c)}function P(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function R(t){return function(){this.removeAttribute(t)}}function L(t){return function(){this.removeAttributeNS(t.space,t.local)}}function q(t,n){return function(){this.setAttribute(t,n)}}function U(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function D(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function O(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function F(t){return function(){this.style.removeProperty(t)}}function I(t,n,e){return function(){this.style.setProperty(t,n,e)}}function Y(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function B(t,n){return t.style.getPropertyValue(n)||uf(t).getComputedStyle(t,null).getPropertyValue(n)}function j(t){return function(){delete this[t]}}function H(t,n){return function(){this[t]=n}}function X(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function $(t){return t.trim().split(/^|\s+/)}function V(t){return t.classList||new W(t)}function W(t){this._node=t,this._names=$(t.getAttribute("class")||"")}function Z(t,n){for(var e=V(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function G(t,n){for(var e=V(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}function J(t){return function(){Z(this,t)}}function Q(t){return function(){G(this,t)}}function K(t,n){return function(){(n.apply(this,arguments)?Z:G)(this,t)}}function tt(){this.textContent=""}function nt(t){return function(){this.textContent=t}}function et(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}}function rt(){this.innerHTML=""}function it(t){return function(){this.innerHTML=t}}function ot(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}}function ut(){this.nextSibling&&this.parentNode.appendChild(this)}function at(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function ct(){return null}function st(){var t=this.parentNode;t&&t.removeChild(this)}function ft(t,n,e){var r=uf(t),i=r.CustomEvent;"function"==typeof i?i=new i(n,e):(i=r.document.createEvent("Event"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}function lt(t,n){return function(){return ft(this,t,n)}}function ht(t,n){return function(){return ft(this,t,n.apply(this,arguments))}}function pt(t,n){this._groups=t,this._parents=n}function dt(){return new pt([[document.documentElement]],af)}function vt(){t.event.stopImmediatePropagation()}function _t(t,n){var e=t.document.documentElement,r=cf(t).on("dragstart.drag",null);n&&(r.on("click.drag",ff,!0),setTimeout(function(){r.on("click.drag",null)},0)),"onselectstart"in e?r.on("selectstart.drag",null):(e.style.MozUserSelect=e.__noselect,delete e.__noselect)}function yt(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=e,this.identifier=r,this.active=i,this.x=o,this.y=u,this.dx=a,this.dy=c,this._=s}function gt(){return!t.event.button}function mt(){return this.parentNode}function xt(n){return null==n?{x:t.event.x,y:t.event.y}:n}function bt(){return"ontouchstart"in this}function wt(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function Mt(){}function Tt(t){var n;return t=(t+"").trim().toLowerCase(),(n=yf.exec(t))?(n=parseInt(n[1],16),new At(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1)):(n=gf.exec(t))?kt(parseInt(n[1],16)):(n=mf.exec(t))?new At(n[1],n[2],n[3],1):(n=xf.exec(t))?new At(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=bf.exec(t))?Nt(n[1],n[2],n[3],n[4]):(n=wf.exec(t))?Nt(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=Mf.exec(t))?Ct(n[1],n[2]/100,n[3]/100,1):(n=Tf.exec(t))?Ct(n[1],n[2]/100,n[3]/100,n[4]):kf.hasOwnProperty(t)?kt(kf[t]):"transparent"===t?new At(NaN,NaN,NaN,0):null}function kt(t){return new At(t>>16&255,t>>8&255,255&t,1)}function Nt(t,n,e,r){return r<=0&&(t=n=e=NaN),new At(t,n,e,r)}function St(t){return t instanceof Mt||(t=Tt(t)),t?(t=t.rgb(),new At(t.r,t.g,t.b,t.opacity)):new At}function Et(t,n,e,r){return 1===arguments.length?St(t):new At(t,n,e,null==r?1:r)}function At(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Ct(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Rt(t,n,e,r)}function zt(t){if(t instanceof Rt)return new Rt(t.h,t.s,t.l,t.opacity);if(t instanceof Mt||(t=Tt(t)),!t)return new Rt;if(t instanceof Rt)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,c=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e<r):e===o?(r-n)/a+2:(n-e)/a+4,a/=c<.5?o+i:2-o-i,u*=60):a=c>0&&c<1?0:u,new Rt(u,a,c,t.opacity)}function Pt(t,n,e,r){return 1===arguments.length?zt(t):new Rt(t,n,e,null==r?1:r)}function Rt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Lt(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function qt(t){if(t instanceof Dt)return new Dt(t.l,t.a,t.b,t.opacity);if(t instanceof Ht){var n=t.h*Nf;return new Dt(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof At||(t=St(t));var e=Yt(t.r),r=Yt(t.g),i=Yt(t.b),o=Ot((.4124564*e+.3575761*r+.1804375*i)/Ef),u=Ot((.2126729*e+.7151522*r+.072175*i)/Af);return new Dt(116*u-16,500*(o-u),200*(u-Ot((.0193339*e+.119192*r+.9503041*i)/Cf)),t.opacity)}function Ut(t,n,e,r){return 1===arguments.length?qt(t):new Dt(t,n,e,null==r?1:r)}function Dt(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function Ot(t){return t>Lf?Math.pow(t,1/3):t/Rf+zf}function Ft(t){return t>Pf?t*t*t:Rf*(t-zf)}function It(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Yt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Bt(t){if(t instanceof Ht)return new Ht(t.h,t.c,t.l,t.opacity);t instanceof Dt||(t=qt(t));var n=Math.atan2(t.b,t.a)*Sf;return new Ht(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function jt(t,n,e,r){return 1===arguments.length?Bt(t):new Ht(t,n,e,null==r?1:r)}function Ht(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}function Xt(t){if(t instanceof Vt)return new Vt(t.h,t.s,t.l,t.opacity);t instanceof At||(t=St(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=(Bf*r+If*n-Yf*e)/(Bf+If-Yf),o=r-i,u=(Ff*(e-i)-Df*o)/Of,a=Math.sqrt(u*u+o*o)/(Ff*i*(1-i)),c=a?Math.atan2(u,o)*Sf-120:NaN;return new Vt(c<0?c+360:c,a,i,t.opacity)}function $t(t,n,e,r){return 1===arguments.length?Xt(t):new Vt(t,n,e,null==r?1:r)}function Vt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Wt(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}function Zt(t,n){return function(e){return t+e*n}}function Gt(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}function Jt(t,n){var e=n-t;return e?Zt(t,e>180||e<-180?e-360*Math.round(e/360):e):Jf(isNaN(t)?n:t)}function Qt(t){return 1==(t=+t)?Kt:function(n,e){return e-n?Gt(n,e,t):Jf(isNaN(n)?e:n)}}function Kt(t,n){var e=n-t;return e?Zt(t,e):Jf(isNaN(t)?n:t)}function tn(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e<i;++e)r=Et(n[e]),o[e]=r.r||0,u[e]=r.g||0,a[e]=r.b||0;return o=t(o),u=t(u),a=t(a),r.opacity=1,function(t){return r.r=o(t),r.g=u(t),r.b=a(t),r+""}}}function nn(t){return function(){return t}}function en(t){return function(n){return t(n)+""}}function rn(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}function o(t,r,i,o,u,a){if(t!==i||r!==o){var c=u.push("translate(",null,n,null,e);a.push({i:c-4,x:rl(t,i)},{i:c-2,x:rl(r,o)})}else(i||o)&&u.push("translate("+i+n+o+e)}function u(t,n,e,o){t!==n?(t-n>180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:rl(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}function a(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:rl(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}function c(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+"scale(",null,",",null,")");u.push({i:a-4,x:rl(t,e)},{i:a-2,x:rl(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}return function(n,e){var r=[],i=[];return n=t(n),e=t(e),o(n.translateX,n.translateY,e.translateX,e.translateY,r,i),u(n.rotate,e.rotate,r,i),a(n.skewX,e.skewX,r,i),c(n.scaleX,n.scaleY,e.scaleX,e.scaleY,r,i),n=e=null,function(t){for(var n,e=-1,o=i.length;++e<o;)r[(n=i[e]).i]=n.x(t);return r.join("")}}}function on(t){return((t=Math.exp(t))+1/t)/2}function un(t){return((t=Math.exp(t))-1/t)/2}function an(t){return((t=Math.exp(2*t))-1)/(t+1)}function cn(t){return function(n,e){var r=t((n=Pt(n)).h,(e=Pt(e)).h),i=Kt(n.s,e.s),o=Kt(n.l,e.l),u=Kt(n.opacity,e.opacity);return function(t){return n.h=r(t),n.s=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function sn(t){return function(n,e){var r=t((n=jt(n)).h,(e=jt(e)).h),i=Kt(n.c,e.c),o=Kt(n.l,e.l),u=Kt(n.opacity,e.opacity);return function(t){return n.h=r(t),n.c=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function fn(t){return function n(e){function r(n,r){var i=t((n=$t(n)).h,(r=$t(r)).h),o=Kt(n.s,r.s),u=Kt(n.l,r.l),a=Kt(n.opacity,r.opacity);return function(t){return n.h=i(t),n.s=o(t),n.l=u(Math.pow(t,e)),n.opacity=a(t),n+""}}return e=+e,r.gamma=n,r}(1)}function ln(){return El||(zl(hn),El=Cl.now()+Al)}function hn(){El=0}function pn(){this._call=this._time=this._next=null}function dn(t,n,e){var r=new pn;return r.restart(t,n,e),r}function vn(){ln(),++Ml;for(var t,n=Vf;n;)(t=El-n._time)>=0&&n._call.call(null,t),n=n._next;--Ml}function _n(){El=(Sl=Cl.now())+Al,Ml=Tl=0;try{vn()}finally{Ml=0,gn(),El=0}}function yn(){var t=Cl.now(),n=t-Sl;n>Nl&&(Al-=n,Sl=t)}function gn(){for(var t,n,e=Vf,r=1/0;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Vf=n);Wf=t,mn(r)}function mn(t){if(!Ml){Tl&&(Tl=clearTimeout(Tl));var n=t-El;n>24?(t<1/0&&(Tl=setTimeout(_n,n)),kl&&(kl=clearInterval(kl))):(kl||(Sl=El,kl=setInterval(yn,Nl)),Ml=1,zl(_n))}}function xn(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>ql)throw new Error("too late");return e}function bn(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>Dl)throw new Error("too late");return e}function wn(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("too late");return e}function Mn(t,n,e){function r(c){var s,f,l,h;if(e.state!==Ul)return o();for(s in a)if((h=a[s]).name===e.name){if(h.state===Ol)return Pl(r);h.state===Fl?(h.state=Yl,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete a[s]):+s<n&&(h.state=Yl,h.timer.stop(),delete a[s])}if(Pl(function(){e.state===Ol&&(e.state=Fl,e.timer.restart(i,e.delay,e.time),i(c))}),e.state=Dl,e.on.call("start",t,t.__data__,e.index,e.group),e.state===Dl){for(e.state=Ol,u=new Array(l=e.tween.length),s=0,f=-1;s<l;++s)(h=e.tween[s].value.call(t,t.__data__,e.index,e.group))&&(u[++f]=h);u.length=f+1}}function i(n){for(var r=n<e.duration?e.ease.call(null,n/e.duration):(e.timer.restart(o),e.state=Il,1),i=-1,a=u.length;++i<a;)u[i].call(null,r);e.state===Il&&(e.on.call("end",t,t.__data__,e.index,e.group),o())}function o(){e.state=Yl,e.timer.stop(),delete a[n];for(var r in a)return;delete t.__transition}var u,a=t.__transition;a[n]=e,e.timer=dn(function(t){e.state=Ul,e.timer.restart(r,e.delay,e.time),e.delay<=t&&r(t-e.delay)},0,e.time)}function Tn(t,n){var e,r;return function(){var i=bn(this,t),o=i.tween;if(o!==e)for(var u=0,a=(r=e=o).length;u<a;++u)if(r[u].name===n){(r=r.slice()).splice(u,1);break}i.tween=r}}function kn(t,n,e){var r,i;if("function"!=typeof e)throw new Error;return function(){var o=bn(this,t),u=o.tween;if(u!==r){i=(r=u).slice();for(var a={name:n,value:e},c=0,s=i.length;c<s;++c)if(i[c].name===n){i[c]=a;break}c===s&&i.push(a)}o.tween=i}}function Nn(t,n,e){var r=t._id;return t.each(function(){var t=bn(this,r);(t.value||(t.value={}))[n]=e.apply(this,arguments)}),function(t){return wn(t,r).value[n]}}function Sn(t){return function(){this.removeAttribute(t)}}function En(t){return function(){this.removeAttributeNS(t.space,t.local)}}function An(t,n,e){var r,i;return function(){var o=this.getAttribute(t);return o===e?null:o===r?i:i=n(r=o,e)}}function Cn(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t.space,t.local);return o===e?null:o===r?i:i=n(r=o,e)}}function zn(t,n,e){var r,i,o;return function(){var u,a=e(this);{if(null!=a)return(u=this.getAttribute(t))===a?null:u===r&&a===i?o:o=n(r=u,i=a);this.removeAttribute(t)}}}function Pn(t,n,e){var r,i,o;return function(){var u,a=e(this);{if(null!=a)return(u=this.getAttributeNS(t.space,t.local))===a?null:u===r&&a===i?o:o=n(r=u,i=a);this.removeAttributeNS(t.space,t.local)}}}function Rn(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttributeNS(t.space,t.local,r(n))}}return e._value=n,e}function Ln(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttribute(t,r(n))}}return e._value=n,e}function qn(t,n){return function(){xn(this,t).delay=+n.apply(this,arguments)}}function Un(t,n){return n=+n,function(){xn(this,t).delay=n}}function Dn(t,n){return function(){bn(this,t).duration=+n.apply(this,arguments)}}function On(t,n){return n=+n,function(){bn(this,t).duration=n}}function Fn(t,n){if("function"!=typeof n)throw new Error;return function(){bn(this,t).ease=n}}function In(t){return(t+"").trim().split(/^|\s+/).every(function(t){var n=t.indexOf(".");return n>=0&&(t=t.slice(0,n)),!t||"start"===t})}function Yn(t,n,e){var r,i,o=In(n)?xn:bn;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}function Bn(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}function jn(t,n){var e,r,i;return function(){var o=B(this,t),u=(this.style.removeProperty(t),B(this,t));return o===u?null:o===e&&u===r?i:i=n(e=o,r=u)}}function Hn(t){return function(){this.style.removeProperty(t)}}function Xn(t,n,e){var r,i;return function(){var o=B(this,t);return o===e?null:o===r?i:i=n(r=o,e)}}function $n(t,n,e){var r,i,o;return function(){var u=B(this,t),a=e(this);return null==a&&(this.style.removeProperty(t),a=B(this,t)),u===a?null:u===r&&a===i?o:o=n(r=u,i=a)}}function Vn(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return i&&function(n){r.style.setProperty(t,i(n),e)}}return r._value=n,r}function Wn(t){return function(){this.textContent=t}}function Zn(t){return function(){var n=t(this);this.textContent=null==n?"":n}}function Gn(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function Jn(t){return dt().transition(t)}function Qn(){return++$l}function Kn(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function te(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}function ne(t){return(1-Math.cos(Jl*t))/2}function ee(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function re(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}function ie(t){return(t=+t)<Kl?ch*t*t:t<nh?ch*(t-=th)*t+eh:t<ih?ch*(t-=rh)*t+oh:ch*(t-=uh)*t+ah}function oe(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))return _h.time=ln(),_h;return e}function ue(){t.event.stopImmediatePropagation()}function ae(t){return{type:t}}function ce(){return!t.event.button}function se(){var t=this.ownerSVGElement||this;return[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function fe(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function le(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}function he(n){function e(t){var e=t.property("__brush",a).selectAll(".overlay").data([ae("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",Eh.overlay).merge(e).each(function(){var t=fe(this).extent;cf(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])}),t.selectAll(".selection").data([ae("selection")]).enter().append("rect").attr("class","selection").attr("cursor",Eh.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var i=t.selectAll(".handle").data(n.handles,function(t){return t.type});i.exit().remove(),i.enter().append("rect").attr("class",function(t){return"handle handle--"+t.type}).attr("cursor",function(t){return Eh[t.type]}),t.each(r).attr("fill","none").attr("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush touchstart.brush",u)}function r(){var t=cf(this),n=fe(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",function(t){return"e"===t.type[t.type.length-1]?n[1][0]-p/2:n[0][0]-p/2}).attr("y",function(t){return"s"===t.type[0]?n[1][1]-p/2:n[0][1]-p/2}).attr("width",function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+p:p}).attr("height",function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+p:p})):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function i(t,n){return t.__brush.emitter||new o(t,n)}function o(t,n){this.that=t,this.args=n,this.state=t.__brush,this.active=0}function u(){function e(){var t=Ks(w);!L||x||b||(Math.abs(t[0]-U[0])>Math.abs(t[1]-U[1])?b=!0:x=!0),U=t,m=!0,xh(),o()}function o(){var t;switch(y=U[0]-q[0],g=U[1]-q[1],T){case wh:case bh:k&&(y=Math.max(C-a,Math.min(P-p,y)),s=a+y,d=p+y),N&&(g=Math.max(z-l,Math.min(R-v,g)),h=l+g,_=v+g);break;case Mh:k<0?(y=Math.max(C-a,Math.min(P-a,y)),s=a+y,d=p):k>0&&(y=Math.max(C-p,Math.min(P-p,y)),s=a,d=p+y),N<0?(g=Math.max(z-l,Math.min(R-l,g)),h=l+g,_=v):N>0&&(g=Math.max(z-v,Math.min(R-v,g)),h=l,_=v+g);break;case Th:k&&(s=Math.max(C,Math.min(P,a-y*k)),d=Math.max(C,Math.min(P,p+y*k))),N&&(h=Math.max(z,Math.min(R,l-g*N)),_=Math.max(z,Math.min(R,v+g*N)))}d<s&&(k*=-1,t=a,a=p,p=t,t=s,s=d,d=t,M in Ah&&F.attr("cursor",Eh[M=Ah[M]])),_<h&&(N*=-1,t=l,l=v,v=t,t=h,h=_,_=t,M in Ch&&F.attr("cursor",Eh[M=Ch[M]])),S.selection&&(A=S.selection),x&&(s=A[0][0],d=A[1][0]),b&&(h=A[0][1],_=A[1][1]),A[0][0]===s&&A[0][1]===h&&A[1][0]===d&&A[1][1]===_||(S.selection=[[s,h],[d,_]],r.call(w),D.brush())}function u(){if(ue(),t.event.touches){if(t.event.touches.length)return;c&&clearTimeout(c),c=setTimeout(function(){c=null},500),O.on("touchmove.brush touchend.brush touchcancel.brush",null)}else _t(t.event.view,m),I.on("keydown.brush keyup.brush mousemove.brush mouseup.brush",null);O.attr("pointer-events","all"),F.attr("cursor",Eh.overlay),S.selection&&(A=S.selection),le(A)&&(S.selection=null,r.call(w)),D.end()}if(t.event.touches){if(t.event.changedTouches.length<t.event.touches.length)return xh()}else if(c)return;if(f.apply(this,arguments)){var a,s,l,h,p,d,v,_,y,g,m,x,b,w=this,M=t.event.target.__data__.type,T="selection"===(t.event.metaKey?M="overlay":M)?bh:t.event.altKey?Th:Mh,k=n===Nh?null:zh[M],N=n===kh?null:Ph[M],S=fe(w),E=S.extent,A=S.selection,C=E[0][0],z=E[0][1],P=E[1][0],R=E[1][1],L=k&&N&&t.event.shiftKey,q=Ks(w),U=q,D=i(w,arguments).beforestart();"overlay"===M?S.selection=A=[[a=n===Nh?C:q[0],l=n===kh?z:q[1]],[p=n===Nh?P:a,v=n===kh?R:l]]:(a=A[0][0],l=A[0][1],p=A[1][0],v=A[1][1]),s=a,h=l,d=p,_=v;var O=cf(w).attr("pointer-events","none"),F=O.selectAll(".overlay").attr("cursor",Eh[M]);if(t.event.touches)O.on("touchmove.brush",e,!0).on("touchend.brush touchcancel.brush",u,!0);else{var I=cf(t.event.view).on("keydown.brush",function(){switch(t.event.keyCode){case 16:L=k&&N;break;case 18:T===Mh&&(k&&(p=d-y*k,a=s+y*k),N&&(v=_-g*N,l=h+g*N),T=Th,o());break;case 32:T!==Mh&&T!==Th||(k<0?p=d-y:k>0&&(a=s-y),N<0?v=_-g:N>0&&(l=h-g),T=wh,F.attr("cursor",Eh.selection),o());break;default:return}xh()},!0).on("keyup.brush",function(){switch(t.event.keyCode){case 16:L&&(x=b=L=!1,o());break;case 18:T===Th&&(k<0?p=d:k>0&&(a=s),N<0?v=_:N>0&&(l=h),T=Mh,o());break;case 32:T===wh&&(t.event.altKey?(k&&(p=d-y*k,a=s+y*k),N&&(v=_-g*N,l=h+g*N),T=Th):(k<0?p=d:k>0&&(a=s),N<0?v=_:N>0&&(l=h),T=Mh),F.attr("cursor",Eh[M]),o());break;default:return}xh()},!0).on("mousemove.brush",e,!0).on("mouseup.brush",u,!0);lf(t.event.view)}ue(),jl(w),r.call(w),D.start()}}function a(){var t=this.__brush||{selection:null};return t.extent=s.apply(this,arguments),t.dim=n,t}var c,s=se,f=ce,l=h(e,"start","brush","end"),p=6;return e.move=function(t,e){t.selection?t.on("start.brush",function(){i(this,arguments).beforestart().start()}).on("interrupt.brush end.brush",function(){i(this,arguments).end()}).tween("brush",function(){function t(t){u.selection=1===t&&le(s)?null:f(t),r.call(o),a.brush()}var o=this,u=o.__brush,a=i(o,arguments),c=u.selection,s=n.input("function"==typeof e?e.apply(this,arguments):e,u.extent),f=cl(c,s);return c&&s?t:t(1)}):t.each(function(){var t=this,o=arguments,u=t.__brush,a=n.input("function"==typeof e?e.apply(t,o):e,u.extent),c=i(t,o).beforestart();jl(t),u.selection=null==a||le(a)?null:a,r.call(t),c.start().brush().end()})},o.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0==--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){N(new mh(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(s="function"==typeof t?t:gh([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):s},e.filter=function(t){return arguments.length?(f="function"==typeof t?t:gh(!!t),e):f},e.handleSize=function(t){return arguments.length?(p=+t,e):p},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function pe(t){return function(n,e){return t(n.source.value+n.target.value,e.source.value+e.target.value)}}function de(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function ve(){return new de}function _e(t){return t.source}function ye(t){return t.target}function ge(t){return t.radius}function me(t){return t.startAngle}function xe(t){return t.endAngle}function be(){}function we(t,n){var e=new be;if(t instanceof be)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==n)for(;++i<o;)e.set(i,t[i]);else for(;++i<o;)e.set(n(r=t[i],i,t),r)}else if(t)for(var u in t)e.set(u,t[u]);return e}function Me(){return{}}function Te(t,n,e){t[n]=e}function ke(){return we()}function Ne(t,n,e){t.set(n,e)}function Se(){}function Ee(t,n){var e=new Se;if(t instanceof Se)t.each(function(t){e.add(t)});else if(t){var r=-1,i=t.length;if(null==n)for(;++r<i;)e.add(t[r]);else for(;++r<i;)e.add(n(t[r],r,t))}return e}function Ae(t){return new Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}")}function Ce(t,n){var e=Ae(t);return function(r,i){return n(e(r),i,t)}}function ze(t){var n=Object.create(null),e=[];return t.forEach(function(t){for(var r in t)r in n||e.push(n[r]=r)}),e}function Pe(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,_=t._y0,y=t._x1,g=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do{i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u}while((l=f<<1|s)==(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function Re(t){return t[0]}function Le(t){return t[1]}function qe(t,n,e){var r=new Ue(null==n?Re:n,null==e?Le:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Ue(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function De(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function Oe(t){return t.x+t.vx}function Fe(t){return t.y+t.vy}function Ie(t){return t.index}function Ye(t,n){var e=t.get(n);if(!e)throw new Error("missing: "+n);return e}function Be(t){return t.x}function je(t){return t.y}function He(t){return new Xe(t)}function Xe(t){if(!(n=vp.exec(t)))throw new Error("invalid format: "+t);var n,e=n[1]||" ",r=n[2]||">",i=n[3]||"-",o=n[4]||"",u=!!n[5],a=n[6]&&+n[6],c=!!n[7],s=n[8]&&+n[8].slice(1),f=n[9]||"";"n"===f?(c=!0,f="g"):dp[f]||(f=""),(u||"0"===e&&"="===r)&&(u=!0,e="0",r="="),this.fill=e,this.align=r,this.sign=i,this.symbol=o,this.zero=u,this.width=a,this.comma=c,this.precision=s,this.type=f}function $e(n){return _p=mp(n),t.format=_p.format,t.formatPrefix=_p.formatPrefix,_p}function Ve(){this.reset()}function We(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function Ze(t){return t>1?0:t<-1?rd:Math.acos(t)}function Ge(t){return t>1?id:t<-1?-id:Math.asin(t)}function Je(t){return(t=yd(t/2))*t}function Qe(){}function Ke(t,n){t&&wd.hasOwnProperty(t.type)&&wd[t.type](t,n)}function tr(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function nr(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)tr(t[e],n,1);n.polygonEnd()}function er(){Nd.point=ir}function rr(){or(Tp,kp)}function ir(t,n){Nd.point=or,Tp=t,kp=n,Np=t*=cd,Sp=hd(n=(n*=cd)/2+od),Ep=yd(n)}function or(t,n){n=(n*=cd)/2+od;var e=(t*=cd)-Np,r=e>=0?1:-1,i=r*e,o=hd(n),u=yd(n),a=Ep*u,c=Sp*o+a*hd(i),s=a*r*yd(i);Td.add(ld(s,c)),Np=t,Sp=o,Ep=u}function ur(t){return[ld(t[1],t[0]),Ge(t[2])]}function ar(t){var n=t[0],e=t[1],r=hd(e);return[r*hd(n),r*yd(n),yd(e)]}function cr(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function sr(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function fr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function lr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function hr(t){var n=md(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function pr(t,n){Dp.push(Op=[Ap=t,zp=t]),n<Cp&&(Cp=n),n>Pp&&(Pp=n)}function dr(t,n){var e=ar([t*cd,n*cd]);if(Up){var r=sr(Up,e),i=sr([r[1],-r[0],0],r);hr(i),i=ur(i);var o,u=t-Rp,a=u>0?1:-1,c=i[0]*ad*a,s=sd(u)>180;s^(a*Rp<c&&c<a*t)?(o=i[1]*ad)>Pp&&(Pp=o):(c=(c+360)%360-180,s^(a*Rp<c&&c<a*t)?(o=-i[1]*ad)<Cp&&(Cp=o):(n<Cp&&(Cp=n),n>Pp&&(Pp=n))),s?t<Rp?xr(Ap,t)>xr(Ap,zp)&&(zp=t):xr(t,zp)>xr(Ap,zp)&&(Ap=t):zp>=Ap?(t<Ap&&(Ap=t),t>zp&&(zp=t)):t>Rp?xr(Ap,t)>xr(Ap,zp)&&(zp=t):xr(t,zp)>xr(Ap,zp)&&(Ap=t)}else Dp.push(Op=[Ap=t,zp=t]);n<Cp&&(Cp=n),n>Pp&&(Pp=n),Up=e,Rp=t}function vr(){Ed.point=dr}function _r(){Op[0]=Ap,Op[1]=zp,Ed.point=pr,Up=null}function yr(t,n){if(Up){var e=t-Rp;Sd.add(sd(e)>180?e+(e>0?360:-360):e)}else Lp=t,qp=n;Nd.point(t,n),dr(t,n)}function gr(){Nd.lineStart()}function mr(){yr(Lp,qp),Nd.lineEnd(),sd(Sd)>ed&&(Ap=-(zp=180)),Op[0]=Ap,Op[1]=zp,Up=null}function xr(t,n){return(n-=t)<0?n+360:n}function br(t,n){return t[0]-n[0]}function wr(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function Mr(t,n){t*=cd;var e=hd(n*=cd);Tr(e*hd(t),e*yd(t),yd(n))}function Tr(t,n,e){Yp+=(t-Yp)/++Fp,Bp+=(n-Bp)/Fp,jp+=(e-jp)/Fp}function kr(){Ad.point=Nr}function Nr(t,n){t*=cd;var e=hd(n*=cd);Qp=e*hd(t),Kp=e*yd(t),td=yd(n),Ad.point=Sr,Tr(Qp,Kp,td)}function Sr(t,n){t*=cd;var e=hd(n*=cd),r=e*hd(t),i=e*yd(t),o=yd(n),u=ld(md((u=Kp*o-td*i)*u+(u=td*r-Qp*o)*u+(u=Qp*i-Kp*r)*u),Qp*r+Kp*i+td*o);Ip+=u,Hp+=u*(Qp+(Qp=r)),Xp+=u*(Kp+(Kp=i)),$p+=u*(td+(td=o)),Tr(Qp,Kp,td)}function Er(){Ad.point=Mr}function Ar(){Ad.point=zr}function Cr(){Pr(Gp,Jp),Ad.point=Mr}function zr(t,n){Gp=t,Jp=n,t*=cd,n*=cd,Ad.point=Pr;var e=hd(n);Qp=e*hd(t),Kp=e*yd(t),td=yd(n),Tr(Qp,Kp,td)}function Pr(t,n){t*=cd;var e=hd(n*=cd),r=e*hd(t),i=e*yd(t),o=yd(n),u=Kp*o-td*i,a=td*r-Qp*o,c=Qp*i-Kp*r,s=md(u*u+a*a+c*c),f=Ge(s),l=s&&-f/s;Vp+=l*u,Wp+=l*a,Zp+=l*c,Ip+=f,Hp+=f*(Qp+(Qp=r)),Xp+=f*(Kp+(Kp=i)),$p+=f*(td+(td=o)),Tr(Qp,Kp,td)}function Rr(t,n){return[t>rd?t-ud:t<-rd?t+ud:t,n]}function Lr(t,n,e){return(t%=ud)?n||e?zd(Ur(t),Dr(n,e)):Ur(t):n||e?Dr(n,e):Rr}function qr(t){return function(n,e){return n+=t,[n>rd?n-ud:n<-rd?n+ud:n,e]}}function Ur(t){var n=qr(t);return n.invert=qr(-t),n}function Dr(t,n){function e(t,n){var e=hd(n),a=hd(t)*e,c=yd(t)*e,s=yd(n),f=s*r+a*i;return[ld(c*o-f*u,a*r-s*i),Ge(f*o+c*u)]}var r=hd(t),i=yd(t),o=hd(n),u=yd(n);return e.invert=function(t,n){var e=hd(n),a=hd(t)*e,c=yd(t)*e,s=yd(n),f=s*o-c*u;return[ld(c*o+s*u,a*r+f*i),Ge(f*r-a*i)]},e}function Or(t,n,e,r,i,o){if(e){var u=hd(n),a=yd(n),c=r*e;null==i?(i=n+r*ud,o=n-c/2):(i=Fr(u,i),o=Fr(u,o),(r>0?i<o:i>o)&&(i+=r*ud));for(var s,f=i;r>0?f>o:f<o;f-=c)s=ur([u,-a*hd(f),-a*yd(f)]),t.point(s[0],s[1])}}function Fr(t,n){(n=ar(n))[0]-=t,hr(n);var e=Ze(-n[1]);return((-n[2]<0?-e:e)+ud-ed)%ud}function Ir(t,n,e,r){this.x=t,this.z=n,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Yr(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r<n;)i.n=e=t[r],e.p=i,i=e;i.n=e=t[0],e.p=i}}function Br(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,a,s){var f=0,l=0;if(null==i||(f=u(i,a))!==(l=u(o,a))||c(i,o)<0^a>0)do{s.point(0===f||3===f?t:e,f>1?r:n)}while((f=(f+a+4)%4)!==l);else s.point(o[0],o[1])}function u(r,i){return sd(r[0]-t)<ed?i>0?0:3:sd(r[0]-e)<ed?i>0?2:1:sd(r[1]-n)<ed?i>0?1:0:i>0?3:2}function a(t,n){return c(t.x,n.x)}function c(t,n){var e=u(t,1),r=u(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(u){function c(t,n){i(t,n)&&w.point(t,n)}function s(){for(var n=0,e=0,i=h.length;e<i;++e)for(var o,u,a=h[e],c=1,s=a.length,f=a[0],l=f[0],p=f[1];c<s;++c)o=l,u=p,l=(f=a[c])[0],p=f[1],u<=r?p>r&&(l-o)*(r-u)>(p-u)*(t-o)&&++n:p<=r&&(l-o)*(r-u)<(p-u)*(t-o)&&--n;return n}function f(o,u){var a=i(o,u);if(h&&p.push([o,u]),x)d=o,v=u,_=a,x=!1,a&&(w.lineStart(),w.point(o,u));else if(a&&m)w.point(o,u);else{var c=[y=Math.max(Zd,Math.min(Wd,y)),g=Math.max(Zd,Math.min(Wd,g))],s=[o=Math.max(Zd,Math.min(Wd,o)),u=Math.max(Zd,Math.min(Wd,u))];Xd(c,s,t,n,e,r)?(m||(w.lineStart(),w.point(c[0],c[1])),w.point(s[0],s[1]),a||w.lineEnd(),b=!1):a&&(w.lineStart(),w.point(o,u),b=!1)}y=o,g=u,m=a}var l,h,p,d,v,_,y,g,m,x,b,w=u,M=Hd(),T={point:c,lineStart:function(){T.point=f,h&&h.push(p=[]),x=!0,m=!1,y=g=NaN},lineEnd:function(){l&&(f(d,v),_&&m&&M.rejoin(),l.push(M.result())),T.point=c,m&&w.lineEnd()},polygonStart:function(){w=M,l=[],h=[],b=!0},polygonEnd:function(){var t=s(),n=b&&t,e=(l=Cs(l)).length;(n||e)&&(u.polygonStart(),n&&(u.lineStart(),o(null,null,1,u),u.lineEnd()),e&&Vd(l,a,t,o,u),u.polygonEnd()),w=u,l=h=p=null}};return T}}function jr(){Kd.point=Kd.lineEnd=Qe}function Hr(t,n){Pd=t*=cd,Rd=yd(n*=cd),Ld=hd(n),Kd.point=Xr}function Xr(t,n){t*=cd;var e=yd(n*=cd),r=hd(n),i=sd(t-Pd),o=hd(i),u=r*yd(i),a=Ld*e-Rd*r*o,c=Rd*e+Ld*r*o;Qd.add(ld(md(u*u+a*a),c)),Pd=t,Rd=e,Ld=r}function $r(t,n){return!(!t||!ov.hasOwnProperty(t.type))&&ov[t.type](t,n)}function Vr(t,n){return 0===rv(t,n)}function Wr(t,n){var e=rv(t[0],t[1]);return rv(t[0],n)+rv(n,t[1])<=e+ed}function Zr(t,n){return!!Jd(t.map(Gr),Jr(n))}function Gr(t){return(t=t.map(Jr)).pop(),t}function Jr(t){return[t[0]*cd,t[1]*cd]}function Qr(t,n,e){var r=Ms(t,n-ed,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function Kr(t,n,e){var r=Ms(t,n-ed,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function ti(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return Ms(pd(o/_)*_,i,_).map(h).concat(Ms(pd(s/y)*y,c,y).map(p)).concat(Ms(pd(r/d)*d,e,d).filter(function(t){return sd(t%_)>ed}).map(f)).concat(Ms(pd(a/v)*v,u,v).filter(function(t){return sd(t%y)>ed}).map(l))}var e,r,i,o,u,a,c,s,f,l,h,p,d=10,v=d,_=90,y=360,g=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[h(o).concat(p(c).slice(1),h(i).reverse().slice(1),p(s).reverse().slice(1))]}},t.extent=function(n){return arguments.length?t.extentMajor(n).extentMinor(n):t.extentMinor()},t.extentMajor=function(n){return arguments.length?(o=+n[0][0],i=+n[1][0],s=+n[0][1],c=+n[1][1],o>i&&(n=o,o=i,i=n),s>c&&(n=s,s=c,c=n),t.precision(g)):[[o,s],[i,c]]},t.extentMinor=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],a=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),a>u&&(n=a,a=u,u=n),t.precision(g)):[[r,a],[e,u]]},t.step=function(n){return arguments.length?t.stepMajor(n).stepMinor(n):t.stepMinor()},t.stepMajor=function(n){return arguments.length?(_=+n[0],y=+n[1],t):[_,y]},t.stepMinor=function(n){return arguments.length?(d=+n[0],v=+n[1],t):[d,v]},t.precision=function(n){return arguments.length?(g=+n,f=Qr(a,u,90),l=Kr(r,e,g),h=Qr(s,c,90),p=Kr(o,i,g),t):g},t.extentMajor([[-180,-90+ed],[180,90-ed]]).extentMinor([[-180,-80-ed],[180,80+ed]])}function ni(){sv.point=ei}function ei(t,n){sv.point=ri,qd=Dd=t,Ud=Od=n}function ri(t,n){cv.add(Od*t-Dd*n),Dd=t,Od=n}function ii(){ri(qd,Ud)}function oi(t,n){vv+=t,_v+=n,++yv}function ui(){Tv.point=ai}function ai(t,n){Tv.point=ci,oi(Yd=t,Bd=n)}function ci(t,n){var e=t-Yd,r=n-Bd,i=md(e*e+r*r);gv+=i*(Yd+t)/2,mv+=i*(Bd+n)/2,xv+=i,oi(Yd=t,Bd=n)}function si(){Tv.point=oi}function fi(){Tv.point=hi}function li(){pi(Fd,Id)}function hi(t,n){Tv.point=pi,oi(Fd=Yd=t,Id=Bd=n)}function pi(t,n){var e=t-Yd,r=n-Bd,i=md(e*e+r*r);gv+=i*(Yd+t)/2,mv+=i*(Bd+n)/2,xv+=i,bv+=(i=Bd*t-Yd*n)*(Yd+t),wv+=i*(Bd+n),Mv+=3*i,oi(Yd=t,Bd=n)}function di(t){this._context=t}function vi(t,n){zv.point=_i,Nv=Ev=t,Sv=Av=n}function _i(t,n){Ev-=t,Av-=n,Cv.add(md(Ev*Ev+Av*Av)),Ev=t,Av=n}function yi(){this._string=[]}function gi(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function mi(t){return t.length>1}function xi(t,n){return((t=t.x)[0]<0?t[1]-id-ed:id-t[1])-((n=n.x)[0]<0?n[1]-id-ed:id-n[1])}function bi(t,n,e,r){var i,o,u=yd(t-e);return sd(u)>ed?fd((yd(n)*(o=hd(r))*yd(e)-yd(r)*(i=hd(n))*yd(t))/(i*o*u)):(n+r)/2}function wi(t){return function(n){var e=new Mi;for(var r in t)e[r]=t[r];return e.stream=n,e}}function Mi(){}function Ti(t,n,e){var r=n[1][0]-n[0][0],i=n[1][1]-n[0][1],o=t.clipExtent&&t.clipExtent();t.scale(150).translate([0,0]),null!=o&&t.clipExtent(null),Md(e,t.stream(dv));var u=dv.result(),a=Math.min(r/(u[1][0]-u[0][0]),i/(u[1][1]-u[0][1])),c=+n[0][0]+(r-a*(u[1][0]+u[0][0]))/2,s=+n[0][1]+(i-a*(u[1][1]+u[0][1]))/2;return null!=o&&t.clipExtent(o),t.scale(150*a).translate([c,s])}function ki(t,n,e){return Ti(t,[[0,0],n],e)}function Ni(t){return wi({point:function(n,e){n=t(n,e),this.stream.point(n[0],n[1])}})}function Si(t,n){function e(r,i,o,u,a,c,s,f,l,h,p,d,v,_){var y=s-r,g=f-i,m=y*y+g*g;if(m>4*n&&v--){var x=u+h,b=a+p,w=c+d,M=md(x*x+b*b+w*w),T=Ge(w/=M),k=sd(sd(w)-1)<ed||sd(o-l)<ed?(o+l)/2:ld(b,x),N=t(k,T),S=N[0],E=N[1],A=S-r,C=E-i,z=g*A-y*C;(z*z/m>n||sd((y*A+g*C)/m-.5)>.3||u*h+a*p+c*d<Uv)&&(e(r,i,o,u,a,c,S,E,k,x/=M,b/=M,w,v,_),_.point(S,E),e(S,E,k,x,b,w,s,f,l,h,p,d,v,_))}}return function(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function i(){y=NaN,w.point=o,n.lineStart()}function o(r,i){var o=ar([r,i]),u=t(r,i);e(y,g,_,m,x,b,y=u[0],g=u[1],_=r,m=o[0],x=o[1],b=o[2],qv,n),n.point(y,g)}function u(){w.point=r,n.lineEnd()}function a(){i(),w.point=c,w.lineEnd=s}function c(t,n){o(f=t,n),l=y,h=g,p=m,d=x,v=b,w.point=o}function s(){e(y,g,_,m,x,b,l,h,f,p,d,v,qv,n),w.lineEnd=u,u()}var f,l,h,p,d,v,_,y,g,m,x,b,w={point:r,lineStart:i,lineEnd:u,polygonStart:function(){n.polygonStart(),w.lineStart=a},polygonEnd:function(){n.polygonEnd(),w.lineStart=i}};return w}}function Ei(t){return Ai(function(){return t})()}function Ai(t){function n(t){return t=f(t[0]*cd,t[1]*cd),[t[0]*_+a,c-t[1]*_]}function e(t){return(t=f.invert((t[0]-a)/_,(c-t[1])/_))&&[t[0]*ad,t[1]*ad]}function r(t,n){return t=u(t,n),[t[0]*_+a,c-t[1]*_]}function i(){f=zd(s=Lr(b,w,M),u);var t=u(m,x);return a=y-t[0]*_,c=g+t[1]*_,o()}function o(){return d=v=null,n}var u,a,c,s,f,l,h,p,d,v,_=150,y=480,g=250,m=0,x=0,b=0,w=0,M=0,T=null,k=Rv,N=null,S=uv,E=.5,A=Dv(r,E);return n.stream=function(t){return d&&v===t?d:d=Ov(k(s,A(S(v=t))))},n.clipAngle=function(t){return arguments.length?(k=+t?Lv(T=t*cd,6*cd):(T=null,Rv),o()):T*ad},n.clipExtent=function(t){return arguments.length?(S=null==t?(N=l=h=p=null,uv):Br(N=+t[0][0],l=+t[0][1],h=+t[1][0],p=+t[1][1]),o()):null==N?null:[[N,l],[h,p]]},n.scale=function(t){return arguments.length?(_=+t,i()):_},n.translate=function(t){return arguments.length?(y=+t[0],g=+t[1],i()):[y,g]},n.center=function(t){return arguments.length?(m=t[0]%360*cd,x=t[1]%360*cd,i()):[m*ad,x*ad]},n.rotate=function(t){return arguments.length?(b=t[0]%360*cd,w=t[1]%360*cd,M=t.length>2?t[2]%360*cd:0,i()):[b*ad,w*ad,M*ad]},n.precision=function(t){return arguments.length?(A=Dv(r,E=t*t),o()):md(E)},n.fitExtent=function(t,e){return Ti(n,t,e)},n.fitSize=function(t,e){return ki(n,t,e)},function(){return u=t.apply(this,arguments),n.invert=u.invert&&e,i()}}function Ci(t){var n=0,e=rd/3,r=Ai(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*cd,e=t[1]*cd):[n*ad,e*ad]},i}function zi(t){function n(t,n){return[t*e,yd(n)/e]}var e=hd(t);return n.invert=function(t,n){return[t/e,Ge(n*e)]},n}function Pi(t,n){function e(t,n){var e=md(o-2*i*yd(n))/i;return[e*yd(t*=i),u-e*hd(t)]}var r=yd(t),i=(r+yd(n))/2;if(sd(i)<ed)return zi(t);var o=1+r*(2*i-r),u=md(o)/i;return e.invert=function(t,n){var e=u-n;return[ld(t,sd(e))/i*gd(e),Ge((o-(t*t+e*e)*i*i)/(2*i))]},e}function Ri(t){var n=t.length;return{point:function(e,r){for(var i=-1;++i<n;)t[i].point(e,r)},sphere:function(){for(var e=-1;++e<n;)t[e].sphere()},lineStart:function(){for(var e=-1;++e<n;)t[e].lineStart()},lineEnd:function(){for(var e=-1;++e<n;)t[e].lineEnd()},polygonStart:function(){for(var e=-1;++e<n;)t[e].polygonStart()},polygonEnd:function(){for(var e=-1;++e<n;)t[e].polygonEnd()}}}function Li(t){return function(n,e){var r=hd(n),i=hd(e),o=t(r*i);return[o*i*yd(n),o*yd(e)]}}function qi(t){return function(n,e){var r=md(n*n+e*e),i=t(r),o=yd(i),u=hd(i);return[ld(n*o,r*u),Ge(r&&e*o/r)]}}function Ui(t,n){return[t,vd(xd((id+n)/2))]}function Di(t){function n(){var n=rd*a(),u=o(jd(o.rotate()).invert([0,0]));return s(null==f?[[u[0]-n,u[1]-n],[u[0]+n,u[1]+n]]:t===Ui?[[Math.max(u[0]-n,f),e],[Math.min(u[0]+n,r),i]]:[[f,Math.max(u[1]-n,e)],[r,Math.min(u[1]+n,i)]])}var e,r,i,o=Ei(t),u=o.center,a=o.scale,c=o.translate,s=o.clipExtent,f=null;return o.scale=function(t){return arguments.length?(a(t),n()):a()},o.translate=function(t){return arguments.length?(c(t),n()):c()},o.center=function(t){return arguments.length?(u(t),n()):u()},o.clipExtent=function(t){return arguments.length?(null==t?f=e=r=i=null:(f=+t[0][0],e=+t[0][1],r=+t[1][0],i=+t[1][1]),n()):null==f?null:[[f,e],[r,i]]},n()}function Oi(t){return xd((id+t)/2)}function Fi(t,n){function e(t,n){o>0?n<-id+ed&&(n=-id+ed):n>id-ed&&(n=id-ed);var e=o/_d(Oi(n),i);return[e*yd(i*t),o-e*hd(i*t)]}var r=hd(t),i=t===n?yd(t):vd(r/hd(n))/vd(Oi(n)/Oi(t)),o=r*_d(Oi(t),i)/i;return i?(e.invert=function(t,n){var e=o-n,r=gd(i)*md(t*t+e*e);return[ld(t,sd(e))/i*gd(e),2*fd(_d(o/r,1/i))-id]},e):Ui}function Ii(t,n){return[t,n]}function Yi(t,n){function e(t,n){var e=o-n,r=i*t;return[e*yd(r),o-e*hd(r)]}var r=hd(t),i=t===n?yd(t):(r-hd(n))/(n-t),o=r/i+t;return sd(i)<ed?Ii:(e.invert=function(t,n){var e=o-n;return[ld(t,sd(e))/i*gd(e),o-gd(i)*md(t*t+e*e)]},e)}function Bi(t,n){var e=hd(n),r=hd(t)*e;return[e*yd(t)/r,yd(n)/r]}function ji(t,n,e,r){return 1===t&&1===n&&0===e&&0===r?uv:wi({point:function(i,o){this.stream.point(i*t+e,o*n+r)}})}function Hi(t,n){return[hd(n)*yd(t),yd(n)]}function Xi(t,n){var e=hd(n),r=1+hd(t)*e;return[e*yd(t)/r,yd(n)/r]}function $i(t,n){return[vd(xd((id+n)/2)),-t]}function Vi(t,n){return t.parent===n.parent?1:2}function Wi(t){return t.reduce(Zi,0)/t.length}function Zi(t,n){return t+n.x}function Gi(t){return 1+t.reduce(Ji,0)}function Ji(t,n){return Math.max(t,n.y)}function Qi(t){for(var n;n=t.children;)t=n[0];return t}function Ki(t){for(var n;n=t.children;)t=n[n.length-1];return t}function to(t){var n=0,e=t.children,r=e&&e.length;if(r)for(;--r>=0;)n+=e[r].value;else n=1;t.value=n}function no(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}function eo(t,n){var e,r,i,o,u,a=new uo(t),c=+t.value&&(a.value=t.value),s=[a];for(null==n&&(n=ro);e=s.pop();)if(c&&(e.value=+e.data.value),(i=n(e.data))&&(u=i.length))for(e.children=new Array(u),o=u-1;o>=0;--o)s.push(r=e.children[o]=new uo(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(oo)}function ro(t){return t.children}function io(t){t.data=t.data.data}function oo(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function uo(t){this.data=t,this.depth=this.height=0,this.parent=null}function ao(t){for(var n,e,r=t.length;r;)e=Math.random()*r--|0,n=t[r],t[r]=t[e],t[e]=n;return t}function co(t,n){var e,r;if(lo(n,t))return[n];for(e=0;e<t.length;++e)if(so(n,t[e])&&lo(vo(t[e],n),t))return[t[e],n];for(e=0;e<t.length-1;++e)for(r=e+1;r<t.length;++r)if(so(vo(t[e],t[r]),n)&&so(vo(t[e],n),t[r])&&so(vo(t[r],n),t[e])&&lo(_o(t[e],t[r],n),t))return[t[e],t[r],n];throw new Error}function so(t,n){var e=t.r-n.r,r=n.x-t.x,i=n.y-t.y;return e<0||e*e<r*r+i*i}function fo(t,n){var e=t.r-n.r+1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function lo(t,n){for(var e=0;e<n.length;++e)if(!fo(t,n[e]))return!1;return!0}function ho(t){switch(t.length){case 1:return po(t[0]);case 2:return vo(t[0],t[1]);case 3:return _o(t[0],t[1],t[2])}}function po(t){return{x:t.x,y:t.y,r:t.r}}function vo(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a-i,l=Math.sqrt(c*c+s*s);return{x:(e+o+c/l*f)/2,y:(r+u+s/l*f)/2,r:(l+i+a)/2}}function _o(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l=e.r,h=r-u,p=r-s,d=i-a,v=i-f,_=c-o,y=l-o,g=r*r+i*i-o*o,m=g-u*u-a*a+c*c,x=g-s*s-f*f+l*l,b=p*d-h*v,w=(d*x-v*m)/(2*b)-r,M=(v*_-d*y)/b,T=(p*m-h*x)/(2*b)-i,k=(h*y-p*_)/b,N=M*M+k*k-1,S=2*(o+w*M+T*k),E=w*w+T*T-o*o,A=-(N?(S+Math.sqrt(S*S-4*N*E))/(2*N):E/S);return{x:r+w+M*A,y:i+T+k*A,r:A}}function yo(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s=a*a+c*c;if(s){var f=.5+((u*=u)-(o*=o))/(2*s),l=Math.sqrt(Math.max(0,2*o*(u+s)-(u-=s)*u-o*o))/(2*s);e.x=r+f*a+l*c,e.y=i+f*c-l*a}else e.x=r+u,e.y=i}function go(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i-1e-6>e*e+r*r}function mo(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function xo(t){this._=t,this.next=null,this.previous=null}function bo(t){if(!(i=t.length))return 0;var n,e,r,i,o,u,a,c,s,f,l;if(n=t[0],n.x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;yo(e,n,r=t[2]),n=new xo(n),e=new xo(e),r=new xo(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(a=3;a<i;++a){yo(n._,e._,r=t[a]),r=new xo(r),c=e.next,s=n.previous,f=e._.r,l=n._.r;do{if(f<=l){if(go(c._,r._)){e=c,n.next=e,e.previous=n,--a;continue t}f+=c._.r,c=c.next}else{if(go(s._,r._)){(n=s).next=e,e.previous=n,--a;continue t}l+=s._.r,s=s.previous}}while(c!==s.next);for(r.previous=n,r.next=e,n.next=e.previous=e=r,o=mo(n);(r=r.next)!==e;)(u=mo(r))<o&&(n=r,o=u);e=n.next}for(n=[e._],r=e;(r=r.next)!==e;)n.push(r._);for(r=Hv(n),a=0;a<i;++a)n=t[a],n.x-=r.x,n.y-=r.y;return r.r}function wo(t){return null==t?null:Mo(t)}function Mo(t){if("function"!=typeof t)throw new Error;return t}function To(){return 0}function ko(t){return Math.sqrt(t.value)}function No(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}function So(t,n){return function(e){if(r=e.children){var r,i,o,u=r.length,a=t(e)*n||0;if(a)for(i=0;i<u;++i)r[i].r+=a;if(o=bo(r),a)for(i=0;i<u;++i)r[i].r-=a;e.r=o+a}}}function Eo(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n.x,n.y=e.y+t*n.y)}}function Ao(t){return t.id}function Co(t){return t.parentId}function zo(t,n){return t.parent===n.parent?1:2}function Po(t){var n=t.children;return n?n[0]:t.t}function Ro(t){var n=t.children;return n?n[n.length-1]:t.t}function Lo(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function qo(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)}function Uo(t,n,e){return t.a.parent===n.parent?t.a:e}function Do(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function Oo(t){for(var n,e,r,i,o,u=new Do(t,0),a=[u];n=a.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)a.push(e=n.children[i]=new Do(r[i],i)),e.parent=n;return(u.parent=new Do(null,0)).children=[u],u}function Fo(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,_,y=[],g=n.children,m=0,x=0,b=g.length,w=n.value;m<b;){c=i-e,s=o-r;do{f=g[x++].value}while(!f&&x<b);for(l=h=f,_=f*f*(v=Math.max(s/c,c/s)/(w*t)),d=Math.max(h/_,_/l);x<b;++x){if(f+=a=g[x].value,a<l&&(l=a),a>h&&(h=a),_=f*f*v,(p=Math.max(h/_,_/l))>d){f-=a;break}d=p}y.push(u={value:f,dice:c<s,children:g.slice(m,x)}),u.dice?Vv(u,e,r,i,w?r+=s*f/w:o):Jv(u,e,r,w?e+=c*f/w:i,o),w-=f,m=x}return y}function Io(t,n){return t[0]-n[0]||t[1]-n[1]}function Yo(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&n_(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function Bo(t){this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function jo(t){if(!t._start)try{Ho(t)}catch(n){if(t._tasks[t._ended+t._active-1])$o(t,n);else if(!t._data)throw n}}function Ho(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._ended+t._active,e=t._tasks[n],r=e.length-1,i=e[r];e[r]=Xo(t,n),--t._waiting,++t._active,e=i.apply(null,e),t._tasks[n]&&(t._tasks[n]=e||r_)}}function Xo(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ended,t._tasks[n]=null,null==t._error&&(null!=e?$o(t,e):(t._data[n]=r,t._waiting?jo(t):Vo(t))))}}function $o(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t._waiting=NaN;--r>=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(n){}t._active=NaN,Vo(t)}function Vo(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._call(t._error,n)}}function Wo(t){if(null==t)t=1/0;else if(!((t=+t)>=1))throw new Error("invalid concurrency");return new Bo(t)}function Zo(t){return function(n,e){t(null==n?e:null)}}function Go(t){var n=t.responseType;return n&&"text"!==n?t.response:t.responseText}function Jo(t,n){return function(e){return t(e.responseText,n)}}function Qo(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==M_)return i;e.set(o,u=r.push(n))}return t[(u-1)%t.length]}var e=we(),r=[],i=M_;return t=null==t?[]:w_.call(t),n.domain=function(t){if(!arguments.length)return r.slice();r=[],e=we();for(var i,o,u=-1,a=t.length;++u<a;)e.has(o=(i=t[u])+"")||e.set(o,r.push(i));return n},n.range=function(e){return arguments.length?(t=w_.call(e),n):t.slice()},n.unknown=function(t){return arguments.length?(i=t,n):i},n.copy=function(){return Qo().domain(r).range(t).unknown(i)},n}function Ko(){function t(){var t=i().length,r=u[1]<u[0],l=u[r-0],h=u[1-r];n=(h-l)/Math.max(1,t-c+2*s),a&&(n=Math.floor(n)),l+=(h-l-n*(t-c))*f,e=n*(1-c),a&&(l=Math.round(l),e=Math.round(e));var p=Ms(t).map(function(t){return l+n*t});return o(r?p.reverse():p)}var n,e,r=Qo().unknown(void 0),i=r.domain,o=r.range,u=[0,1],a=!1,c=0,s=0,f=.5;return delete r.unknown,r.domain=function(n){return arguments.length?(i(n),t()):i()},r.range=function(n){return arguments.length?(u=[+n[0],+n[1]],t()):u.slice()},r.rangeRound=function(n){return u=[+n[0],+n[1]],a=!0,t()},r.bandwidth=function(){return e},r.step=function(){return n},r.round=function(n){return arguments.length?(a=!!n,t()):a},r.padding=function(n){return arguments.length?(c=s=Math.max(0,Math.min(1,n)),t()):c},r.paddingInner=function(n){return arguments.length?(c=Math.max(0,Math.min(1,n)),t()):c},r.paddingOuter=function(n){return arguments.length?(s=Math.max(0,Math.min(1,n)),t()):s},r.align=function(n){return arguments.length?(f=Math.max(0,Math.min(1,n)),t()):f},r.copy=function(){return Ko().domain(i()).range(u).round(a).paddingInner(c).paddingOuter(s).align(f)},t()}function tu(t){var n=t.copy;return t.padding=t.paddingOuter,delete t.paddingInner,delete t.paddingOuter,t.copy=function(){return tu(n())},t}function nu(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:T_(n)}function eu(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=n?0:t>=e?1:r(t)}}}function ru(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=0?n:t>=1?e:r(t)}}}function iu(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o<i?(i=e(o,i),u=r(a,u)):(i=e(i,o),u=r(u,a)),function(t){return u(i(t))}}function ou(t,n,e,r){var i=Math.min(t.length,n.length)-1,o=new Array(i),u=new Array(i),a=-1;for(t[i]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());++a<i;)o[a]=e(t[a],t[a+1]),u[a]=r(n[a],n[a+1]);return function(n){var e=hs(t,n,1,i)-1;return u[e](o[e](n))}}function uu(t,n){return n.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp())}function au(t,n){function e(){return i=Math.min(a.length,c.length)>2?ou:iu,o=u=null,r}function r(n){return(o||(o=i(a,c,f?eu(t):t,s)))(+n)}var i,o,u,a=N_,c=N_,s=cl,f=!1;return r.invert=function(t){return(u||(u=i(c,a,nu,f?ru(n):n)))(+t)},r.domain=function(t){return arguments.length?(a=b_.call(t,k_),e()):a.slice()},r.range=function(t){return arguments.length?(c=w_.call(t),e()):c.slice()},r.rangeRound=function(t){return c=w_.call(t),s=sl,e()},r.clamp=function(t){return arguments.length?(f=!!t,e()):f},r.interpolate=function(t){return arguments.length?(s=t,e()):s},e()}function cu(t){var n=t.domain;return t.ticks=function(t){var e=n();return Ss(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){return S_(n(),t,e)},t.nice=function(e){null==e&&(e=10);var i,o=n(),u=0,a=o.length-1,c=o[u],s=o[a];return s<c&&(i=c,c=s,s=i,i=u,u=a,a=i),(i=r(c,s,e))>0?i=r(c=Math.floor(c/i)*i,s=Math.ceil(s/i)*i,e):i<0&&(i=r(c=Math.ceil(c*i)/i,s=Math.floor(s*i)/i,e)),i>0?(o[u]=Math.floor(c/i)*i,o[a]=Math.ceil(s/i)*i,n(o)):i<0&&(o[u]=Math.ceil(c*i)/i,o[a]=Math.floor(s*i)/i,n(o)),t},t}function su(){var t=au(nu,rl);return t.copy=function(){return uu(t,su())},cu(t)}function fu(){function t(t){return+t}var n=[0,1];return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=b_.call(e,k_),t):n.slice()},t.copy=function(){return fu().domain(n)},cu(t)}function lu(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t)/n}:T_(n)}function hu(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-t,1-e)}:function(e){return Math.pow(n,e)*Math.pow(t,1-e)}}function pu(t){return isFinite(t)?+("1e"+t):t<0?0:t}function du(t){return 10===t?pu:t===Math.E?Math.exp:function(n){return Math.pow(t,n)}}function vu(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),function(n){return Math.log(n)/t})}function _u(t){return function(n){return-t(-n)}}function yu(){function n(){return o=vu(i),u=du(i),r()[0]<0&&(o=_u(o),u=_u(u)),e}var e=au(lu,hu).domain([1,10]),r=e.domain,i=10,o=vu(10),u=du(10);return e.base=function(t){return arguments.length?(i=+t,n()):i},e.domain=function(t){return arguments.length?(r(t),n()):r()},e.ticks=function(t){var n,e=r(),a=e[0],c=e[e.length-1];(n=c<a)&&(h=a,a=c,c=h);var s,f,l,h=o(a),p=o(c),d=null==t?10:+t,v=[];if(!(i%1)&&p-h<d){if(h=Math.round(h)-1,p=Math.round(p)+1,a>0){for(;h<p;++h)for(f=1,s=u(h);f<i;++f)if(!((l=s*f)<a)){if(l>c)break;v.push(l)}}else for(;h<p;++h)for(f=i-1,s=u(h);f>=1;--f)if(!((l=s*f)<a)){if(l>c)break;v.push(l)}}else v=Ss(h,p,Math.min(p-h,d)).map(u);return n?v.reverse():v},e.tickFormat=function(n,r){if(null==r&&(r=10===i?".0e":","),"function"!=typeof r&&(r=t.format(r)),n===1/0)return r;null==n&&(n=10);var a=Math.max(1,i*n/e.ticks().length);return function(t){var n=t/u(Math.round(o(t)));return n*i<i-.5&&(n*=i),n<=a?r(t):""}},e.nice=function(){return r(E_(r(),{floor:function(t){return u(Math.floor(o(t)))},ceil:function(t){return u(Math.ceil(o(t)))}}))},e.copy=function(){return uu(e,yu().base(i))},e}function gu(t,n){return t<0?-Math.pow(-t,n):Math.pow(t,n)}function mu(){var t=1,n=au(function(n,e){return(e=gu(e,t)-(n=gu(n,t)))?function(r){return(gu(r,t)-n)/e}:T_(e)},function(n,e){return e=gu(e,t)-(n=gu(n,t)),function(r){return gu(n+e*r,1/t)}}),e=n.domain;return n.exponent=function(n){return arguments.length?(t=+n,e(e())):t},n.copy=function(){return uu(n,mu().exponent(t))},cu(n)}function xu(){function t(){var t=0,o=Math.max(1,r.length);for(i=new Array(o-1);++t<o;)i[t-1]=As(e,t/o);return n}function n(t){if(!isNaN(t=+t))return r[hs(i,t)]}var e=[],r=[],i=[];return n.invertExtent=function(t){var n=r.indexOf(t);return n<0?[NaN,NaN]:[n>0?i[n-1]:e[0],n<i.length?i[n]:e[e.length-1]]},n.domain=function(n){if(!arguments.length)return e.slice();e=[];for(var r,i=0,o=n.length;i<o;++i)null==(r=n[i])||isNaN(r=+r)||e.push(r);return e.sort(ss),t()},n.range=function(n){return arguments.length?(r=w_.call(n),t()):r.slice()},n.quantiles=function(){return i.slice()},n.copy=function(){return xu().domain(e).range(r)},n}function bu(){function t(t){if(t<=t)return u[hs(o,t,0,i)]}function n(){var n=-1;for(o=new Array(i);++n<i;)o[n]=((n+1)*r-(n-i)*e)/(i+1);return t}var e=0,r=1,i=1,o=[.5],u=[0,1];return t.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n()):[e,r]},t.range=function(t){return arguments.length?(i=(u=w_.call(t)).length-1,n()):u.slice()},t.invertExtent=function(t){var n=u.indexOf(t);return n<0?[NaN,NaN]:n<1?[e,o[0]]:n>=i?[o[i-1],r]:[o[n-1],o[n]]},t.copy=function(){return bu().domain([e,r]).range(u)},cu(t)}function wu(){function t(t){if(t<=t)return e[hs(n,t,0,r)]}var n=[.5],e=[0,1],r=1;return t.domain=function(i){return arguments.length?(n=w_.call(i),r=Math.min(n.length,e.length-1),t):n.slice()},t.range=function(i){return arguments.length?(e=w_.call(i),r=Math.min(n.length,e.length-1),t):e.slice()},t.invertExtent=function(t){var r=e.indexOf(t);return[n[r-1],n[r]]},t.copy=function(){return wu().domain(n).range(e)},t}function Mu(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.floor=i,i.ceil=function(e){return t(e=new Date(e-1)),n(e,1),t(e),e},i.round=function(t){var n=i(t),e=i.ceil(t);return t-n<e-t?n:e},i.offset=function(t,e){return n(t=new Date(+t),null==e?1:Math.floor(e)),t},i.range=function(e,r,o){var u=[];if(e=i.ceil(e),o=null==o?1:Math.floor(o),!(e<r&&o>0))return u;do{u.push(new Date(+e))}while(n(e,o),t(e),e<r);return u},i.filter=function(e){return Mu(function(n){if(n>=n)for(;t(n),!e(n);)n.setTime(n-1)},function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;n(t,-1),!e(t););else for(;--r>=0;)for(;n(t,1),!e(t););})},e&&(i.count=function(n,r){return A_.setTime(+n),C_.setTime(+r),t(A_),t(C_),Math.floor(e(A_,C_))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(n){return r(n)%t==0}:function(n){return i.count(0,n)%t==0}):i:null}),i}function Tu(t){return Mu(function(n){n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+7*n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*R_)/L_})}function ku(t){return Mu(function(n){n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+7*n)},function(t,n){return(n-t)/L_})}function Nu(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return n.setFullYear(t.y),n}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Su(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return n.setUTCFullYear(t.y),n}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Eu(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}function Au(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=0,s=t.length;for(e instanceof Date||(e=new Date(+e));++a<s;)37===t.charCodeAt(a)&&(u.push(t.slice(c,a)),null!=(i=Py[r=t.charAt(++a)])?r=t.charAt(++a):i="e"===r?" ":"0",(o=n[r])&&(r=o(e,i)),u.push(r),c=a+1);return u.push(t.slice(c,a)),u.join("")}}function e(t,n){return function(e){var i=Eu(1900);if(r(i,t,e+="",0)!=e.length)return null;if("p"in i&&(i.H=i.H%12+12*i.p),"W"in i||"U"in i){"w"in i||(i.w="W"in i?1:0);var o="Z"in i?Su(Eu(i.y)).getUTCDay():n(Eu(i.y)).getDay();i.m=0,i.d="W"in i?(i.w+6)%7+7*i.W-(o+5)%7:i.w+7*i.U-(o+6)%7}return"Z"in i?(i.H+=i.Z/100|0,i.M+=i.Z%100,Su(i)):n(i)}}function r(t,n,e,r){for(var i,o,u=0,a=n.length,c=e.length;u<a;){if(r>=c)return-1;if(37===(i=n.charCodeAt(u++))){if(i=n.charAt(u++),!(o=T[i in Py?n.charAt(u++):i])||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}var i=t.dateTime,o=t.date,u=t.time,a=t.periods,c=t.days,s=t.shortDays,f=t.months,l=t.shortMonths,h=Pu(a),p=Ru(a),d=Pu(c),v=Ru(c),_=Pu(s),y=Ru(s),g=Pu(f),m=Ru(f),x=Pu(l),b=Ru(l),w={a:function(t){return s[t.getDay()]},A:function(t){return c[t.getDay()]},b:function(t){return l[t.getMonth()]},B:function(t){return f[t.getMonth()]},c:null,d:Wu,e:Wu,H:Zu,I:Gu,j:Ju,L:Qu,m:Ku,M:ta,p:function(t){return a[+(t.getHours()>=12)]},S:na,U:ea,w:ra,W:ia,x:null,X:null,y:oa,Y:ua,Z:aa,"%":wa},M={a:function(t){return s[t.getUTCDay()]},A:function(t){return c[t.getUTCDay()]},b:function(t){return l[t.getUTCMonth()]},B:function(t){return f[t.getUTCMonth()]},c:null,d:ca,e:ca,H:sa,I:fa,j:la,L:ha,m:pa,M:da,p:function(t){return a[+(t.getUTCHours()>=12)]},S:va,U:_a,w:ya,W:ga,x:null,X:null,y:ma,Y:xa,Z:ba,"%":wa},T={a:function(t,n,e){var r=_.exec(n.slice(e));return r?(t.w=y[r[0].toLowerCase()],e+r[0].length):-1},A:function(t,n,e){var r=d.exec(n.slice(e));return r?(t.w=v[r[0].toLowerCase()],e+r[0].length):-1},b:function(t,n,e){var r=x.exec(n.slice(e));return r?(t.m=b[r[0].toLowerCase()],e+r[0].length):-1},B:function(t,n,e){var r=g.exec(n.slice(e));return r?(t.m=m[r[0].toLowerCase()],e+r[0].length):-1},c:function(t,n,e){return r(t,i,n,e)},d:Yu,e:Yu,H:ju,I:ju,j:Bu,L:$u,m:Iu,M:Hu,p:function(t,n,e){var r=h.exec(n.slice(e));return r?(t.p=p[r[0].toLowerCase()],e+r[0].length):-1},S:Xu,U:qu,w:Lu,W:Uu,x:function(t,n,e){return r(t,o,n,e)},X:function(t,n,e){return r(t,u,n,e)},y:Ou,Y:Du,Z:Fu,"%":Vu};return w.x=n(o,w),w.X=n(u,w),w.c=n(i,w),M.x=n(o,M),M.X=n(u,M),M.c=n(i,M),{format:function(t){var e=n(t+="",w);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",Nu);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",M);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,Su);return n.toString=function(){return t},n}}}function Cu(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o<e?new Array(e-o+1).join(n)+i:i)}function zu(t){return t.replace(qy,"\\$&")}function Pu(t){return new RegExp("^(?:"+t.map(zu).join("|")+")","i")}function Ru(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]=e;return n}function Lu(t,n,e){var r=Ry.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function qu(t,n,e){var r=Ry.exec(n.slice(e));return r?(t.U=+r[0],e+r[0].length):-1}function Uu(t,n,e){var r=Ry.exec(n.slice(e));return r?(t.W=+r[0],e+r[0].length):-1}function Du(t,n,e){var r=Ry.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function Ou(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function Fu(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function Iu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function Yu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function Bu(t,n,e){var r=Ry.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function ju(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function Hu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function Xu(t,n,e){var r=Ry.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function $u(t,n,e){var r=Ry.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function Vu(t,n,e){var r=Ly.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function Wu(t,n){return Cu(t.getDate(),n,2)}function Zu(t,n){return Cu(t.getHours(),n,2)}function Gu(t,n){return Cu(t.getHours()%12||12,n,2)}function Ju(t,n){return Cu(1+Y_.count(oy(t),t),n,3)}function Qu(t,n){return Cu(t.getMilliseconds(),n,3)}function Ku(t,n){return Cu(t.getMonth()+1,n,2)}function ta(t,n){return Cu(t.getMinutes(),n,2)}function na(t,n){return Cu(t.getSeconds(),n,2)}function ea(t,n){return Cu(j_.count(oy(t),t),n,2)}function ra(t){return t.getDay()}function ia(t,n){return Cu(H_.count(oy(t),t),n,2)}function oa(t,n){return Cu(t.getFullYear()%100,n,2)}function ua(t,n){return Cu(t.getFullYear()%1e4,n,4)}function aa(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+Cu(n/60|0,"0",2)+Cu(n%60,"0",2)}function ca(t,n){return Cu(t.getUTCDate(),n,2)}function sa(t,n){return Cu(t.getUTCHours(),n,2)}function fa(t,n){return Cu(t.getUTCHours()%12||12,n,2)}function la(t,n){return Cu(1+ly.count(Ay(t),t),n,3)}function ha(t,n){return Cu(t.getUTCMilliseconds(),n,3)}function pa(t,n){return Cu(t.getUTCMonth()+1,n,2)}function da(t,n){return Cu(t.getUTCMinutes(),n,2)}function va(t,n){return Cu(t.getUTCSeconds(),n,2)}function _a(t,n){return Cu(py.count(Ay(t),t),n,2)}function ya(t){return t.getUTCDay()}function ga(t,n){return Cu(dy.count(Ay(t),t),n,2)}function ma(t,n){return Cu(t.getUTCFullYear()%100,n,2)}function xa(t,n){return Cu(t.getUTCFullYear()%1e4,n,4)}function ba(){return"+0000"}function wa(){return"%"}function Ma(n){return Cy=Au(n),t.timeFormat=Cy.format,t.timeParse=Cy.parse,t.utcFormat=Cy.utcFormat,t.utcParse=Cy.utcParse,Cy}function Ta(t){return new Date(t)}function ka(t){return t instanceof Date?+t:+new Date(+t)}function Na(t,n,e,r,o,u,a,c,s){function f(i){return(a(i)<i?v:u(i)<i?_:o(i)<i?y:r(i)<i?g:n(i)<i?e(i)<i?m:x:t(i)<i?b:w)(i)}function l(n,e,r,o){if(null==n&&(n=10),"number"==typeof n){var u=Math.abs(r-e)/n,a=fs(function(t){return t[2]}).right(M,u);a===M.length?(o=i(e/Hy,r/Hy,n),n=t):a?(o=(a=M[u/M[a-1][2]<M[a][2]/u?a-1:a])[1],n=a[0]):(o=i(e,r,n),n=c)}return null==o?n:n.every(o)}var h=au(nu,rl),p=h.invert,d=h.domain,v=s(".%L"),_=s(":%S"),y=s("%I:%M"),g=s("%I %p"),m=s("%a %d"),x=s("%b %d"),b=s("%B"),w=s("%Y"),M=[[a,1,Oy],[a,5,5*Oy],[a,15,15*Oy],[a,30,30*Oy],[u,1,Fy],[u,5,5*Fy],[u,15,15*Fy],[u,30,30*Fy],[o,1,Iy],[o,3,3*Iy],[o,6,6*Iy],[o,12,12*Iy],[r,1,Yy],[r,2,2*Yy],[e,1,By],[n,1,jy],[n,3,3*jy],[t,1,Hy]];return h.invert=function(t){return new Date(p(t))},h.domain=function(t){return arguments.length?d(b_.call(t,ka)):d().map(Ta)},h.ticks=function(t,n){var e,r=d(),i=r[0],o=r[r.length-1],u=o<i;return u&&(e=i,i=o,o=e),e=l(t,i,o,n),e=e?e.range(i,o+1):[],u?e.reverse():e},h.tickFormat=function(t,n){return null==n?f:s(n)},h.nice=function(t,n){var e=d();return(t=l(t,e[0],e[e.length-1],n))?d(E_(e,t)):h},h.copy=function(){return uu(h,Na(t,n,e,r,o,u,a,c,s))},h}function Sa(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}function Ea(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Math.min(1,o)):o)}var e=0,r=1,i=!1;return n.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n):[e,r]},n.clamp=function(t){return arguments.length?(i=!!t,n):i},n.interpolator=function(e){return arguments.length?(t=e,n):t},n.copy=function(){return Ea(t).domain([e,r]).clamp(i)},cu(n)}function Aa(t){return t>1?0:t<-1?pg:Math.acos(t)}function Ca(t){return t>=1?dg:t<=-1?-dg:Math.asin(t)}function za(t){return t.innerRadius}function Pa(t){return t.outerRadius}function Ra(t){return t.startAngle}function La(t){return t.endAngle}function qa(t){return t&&t.padAngle}function Ua(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}function Da(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/lg(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,_=(h+d)/2,y=(p+v)/2,g=d-h,m=v-p,x=g*g+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*lg(cg(0,b*b*x-w*w)),T=(w*m-g*M)/x,k=(-w*g-m*M)/x,N=(w*m+g*M)/x,S=(-w*g+m*M)/x,E=T-_,A=k-y,C=N-_,z=S-y;return E*E+A*A>C*C+z*z&&(T=N,k=S),{cx:T,cy:k,x01:-f,y01:-l,x11:T*(i/b-1),y11:k*(i/b-1)}}function Oa(t){this._context=t}function Fa(t){return t[0]}function Ia(t){return t[1]}function Ya(t){this._curve=t}function Ba(t){function n(n){return new Ya(t(n))}return n._curve=t,n}function ja(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(Ba(t)):n()._curve},t}function Ha(t){return t.source}function Xa(t){return t.target}function $a(t){function n(){var n,a=kg.call(arguments),c=e.apply(this,a),s=r.apply(this,a);if(u||(u=n=ve()),t(u,+i.apply(this,(a[0]=c,a)),+o.apply(this,a),+i.apply(this,(a[0]=s,a)),+o.apply(this,a)),n)return u=null,n+""||null}var e=Ha,r=Xa,i=Fa,o=Ia,u=null;return n.source=function(t){return arguments.length?(e=t,n):e},n.target=function(t){return arguments.length?(r=t,n):r},n.x=function(t){return arguments.length?(i="function"==typeof t?t:ig(+t),n):i},n.y=function(t){return arguments.length?(o="function"==typeof t?t:ig(+t),n):o},n.context=function(t){return arguments.length?(u=null==t?null:t,n):u},n}function Va(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n=(n+r)/2,e,n,i,r,i)}function Wa(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n,e=(e+i)/2,r,e,r,i)}function Za(t,n,e,r,i){var o=Tg(n,e),u=Tg(n,e=(e+i)/2),a=Tg(r,e),c=Tg(r,i);t.moveTo(o[0],o[1]),t.bezierCurveTo(u[0],u[1],a[0],a[1],c[0],c[1])}function Ga(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Ja(t){this._context=t}function Qa(t){this._context=t}function Ka(t){this._context=t}function tc(t,n){this._basis=new Ja(t),this._beta=n}function nc(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function ec(t,n){this._context=t,this._k=(1-n)/6}function rc(t,n){this._context=t,this._k=(1-n)/6}function ic(t,n){this._context=t,this._k=(1-n)/6}function oc(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>hg){var a=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*a-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*a-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>hg){var s=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,f=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*s+t._x1*t._l23_2a-n*t._l12_2a)/f,u=(u*s+t._y1*t._l23_2a-e*t._l12_2a)/f}t._context.bezierCurveTo(r,i,o,u,t._x2,t._y2)}function uc(t,n){this._context=t,this._alpha=n}function ac(t,n){this._context=t,this._alpha=n}function cc(t,n){this._context=t,this._alpha=n}function sc(t){this._context=t}function fc(t){return t<0?-1:1}function lc(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),u=(e-t._y1)/(i||r<0&&-0),a=(o*i+u*r)/(r+i);return(fc(o)+fc(u))*Math.min(Math.abs(o),Math.abs(u),.5*Math.abs(a))||0}function hc(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function pc(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._context.bezierCurveTo(r+a,i+a*n,o-a,u-a*e,o,u)}function dc(t){this._context=t}function vc(t){this._context=new _c(t)}function _c(t){this._context=t}function yc(t){this._context=t}function gc(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new Array(r);for(i[0]=0,o[0]=2,u[0]=t[0]+2*t[1],n=1;n<r-1;++n)i[n]=1,o[n]=4,u[n]=4*t[n]+2*t[n+1];for(i[r-1]=2,o[r-1]=7,u[r-1]=8*t[r-1]+t[r],n=1;n<r;++n)e=i[n]/o[n-1],o[n]-=e,u[n]-=e*u[n-1];for(i[r-1]=u[r-1]/o[r-1],n=r-2;n>=0;--n)i[n]=(u[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n<r-1;++n)o[n]=2*t[n+1]-i[n+1];return[i,o]}function mc(t,n){this._context=t,this._t=n}function xc(t,n){return t[n]}function bc(t){for(var n,e=0,r=-1,i=t.length;++r<i;)(n=+t[r][1])&&(e+=n);return e}function wc(t){return t[0]}function Mc(t){return t[1]}function Tc(){this._=null}function kc(t){t.U=t.C=t.L=t.R=t.P=t.N=null}function Nc(t,n){var e=n,r=n.R,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Sc(t,n){var e=n,r=n.L,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Ec(t){for(;t.L;)t=t.L;return t}function Ac(t,n,e,r){var i=[null,null],o=um.push(i)-1;return i.left=t,i.right=n,e&&zc(i,t,n,e),r&&zc(i,n,t,r),im[t.index].halfedges.push(o),im[n.index].halfedges.push(o),i}function Cc(t,n,e){var r=[n,e];return r.left=t,r}function zc(t,n,e,r){t[0]||t[1]?t.left===e?t[1]=r:t[0]=r:(t[0]=r,t.left=n,t.right=e)}function Pc(t,n,e,r,i){var o,u=t[0],a=t[1],c=u[0],s=u[1],f=0,l=1,h=a[0]-c,p=a[1]-s;if(o=n-c,h||!(o>0)){if(o/=h,h<0){if(o<f)return;o<l&&(l=o)}else if(h>0){if(o>l)return;o>f&&(f=o)}if(o=r-c,h||!(o<0)){if(o/=h,h<0){if(o>l)return;o>f&&(f=o)}else if(h>0){if(o<f)return;o<l&&(l=o)}if(o=e-s,p||!(o>0)){if(o/=p,p<0){if(o<f)return;o<l&&(l=o)}else if(p>0){if(o>l)return;o>f&&(f=o)}if(o=i-s,p||!(o<0)){if(o/=p,p<0){if(o>l)return;o>f&&(f=o)}else if(p>0){if(o<f)return;o<l&&(l=o)}return!(f>0||l<1)||(f>0&&(t[0]=[c+f*h,s+f*p]),l<1&&(t[1]=[c+l*h,s+l*p]),!0)}}}}}function Rc(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,f=t.right,l=s[0],h=s[1],p=f[0],d=f[1],v=(l+p)/2,_=(h+d)/2;if(d===h){if(v<n||v>=r)return;if(l>p){if(c){if(c[1]>=i)return}else c=[v,e];o=[v,i]}else{if(c){if(c[1]<e)return}else c=[v,i];o=[v,e]}}else if(u=(l-p)/(d-h),a=_-u*v,u<-1||u>1)if(l>p){if(c){if(c[1]>=i)return}else c=[(e-a)/u,e];o=[(i-a)/u,i]}else{if(c){if(c[1]<e)return}else c=[(i-a)/u,i];o=[(e-a)/u,e]}else if(h<d){if(c){if(c[0]>=r)return}else c=[n,u*n+a];o=[r,u*r+a]}else{if(c){if(c[0]<n)return}else c=[r,u*r+a];o=[n,u*n+a]}return t[0]=c,t[1]=o,!0}function Lc(t,n,e,r){for(var i,o=um.length;o--;)Rc(i=um[o],t,n,e,r)&&Pc(i,t,n,e,r)&&(Math.abs(i[0][0]-i[1][0])>sm||Math.abs(i[0][1]-i[1][1])>sm)||delete um[o]}function qc(t){return im[t.index]={site:t,halfedges:[]}}function Uc(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e),i?Math.atan2(i[1]-r[1],i[0]-r[0]):(e===r?(r=n[1],i=n[0]):(r=n[0],i=n[1]),Math.atan2(r[0]-i[0],i[1]-r[1]))}function Dc(t,n){return n[+(n.left!==t.site)]}function Oc(t,n){return n[+(n.left===t.site)]}function Fc(){for(var t,n,e,r,i=0,o=im.length;i<o;++i)if((t=im[i])&&(r=(n=t.halfedges).length)){var u=new Array(r),a=new Array(r);for(e=0;e<r;++e)u[e]=e,a[e]=Uc(t,um[n[e]]);for(u.sort(function(t,n){return a[n]-a[t]}),e=0;e<r;++e)a[e]=n[u[e]];for(e=0;e<r;++e)n[e]=a[e]}}function Ic(t,n,e,r){var i,o,u,a,c,s,f,l,h,p,d,v,_=im.length,y=!0;for(i=0;i<_;++i)if(o=im[i]){for(u=o.site,a=(c=o.halfedges).length;a--;)um[c[a]]||c.splice(a,1);for(a=0,s=c.length;a<s;)d=(p=Oc(o,um[c[a]]))[0],v=p[1],l=(f=Dc(o,um[c[++a%s]]))[0],h=f[1],(Math.abs(d-l)>sm||Math.abs(v-h)>sm)&&(c.splice(a,0,um.push(Cc(u,p,Math.abs(d-t)<sm&&r-v>sm?[t,Math.abs(l-t)<sm?h:r]:Math.abs(v-r)<sm&&e-d>sm?[Math.abs(h-r)<sm?l:e,r]:Math.abs(d-e)<sm&&v-n>sm?[e,Math.abs(l-e)<sm?h:n]:Math.abs(v-n)<sm&&d-t>sm?[Math.abs(h-n)<sm?l:t,n]:null))-1),++s);s&&(y=!1)}if(y){var g,m,x,b=1/0;for(i=0,y=null;i<_;++i)(o=im[i])&&(x=(g=(u=o.site)[0]-t)*g+(m=u[1]-n)*m)<b&&(b=x,y=o);if(y){var w=[t,n],M=[t,r],T=[e,r],k=[e,n];y.halfedges.push(um.push(Cc(u=y.site,w,M))-1,um.push(Cc(u,M,T))-1,um.push(Cc(u,T,k))-1,um.push(Cc(u,k,w))-1)}}for(i=0;i<_;++i)(o=im[i])&&(o.halfedges.length||delete im[i])}function Yc(){kc(this),this.x=this.y=this.arc=this.site=this.cy=null}function Bc(t){var n=t.P,e=t.N;if(n&&e){var r=n.site,i=t.site,o=e.site;if(r!==o){var u=i[0],a=i[1],c=r[0]-u,s=r[1]-a,f=o[0]-u,l=o[1]-a,h=2*(c*l-s*f);if(!(h>=-fm)){var p=c*c+s*s,d=f*f+l*l,v=(l*p-s*d)/h,_=(c*d-f*p)/h,y=am.pop()||new Yc;y.arc=t,y.site=i,y.x=v+u,y.y=(y.cy=_+a)+Math.sqrt(v*v+_*_),t.circle=y;for(var g=null,m=om._;m;)if(y.y<m.y||y.y===m.y&&y.x<=m.x){if(!m.L){g=m.P;break}m=m.L}else{if(!m.R){g=m;break}m=m.R}om.insert(g,y),g||(em=y)}}}}function jc(t){var n=t.circle;n&&(n.P||(em=n.N),om.remove(n),am.push(n),kc(n),t.circle=null)}function Hc(){kc(this),this.edge=this.site=this.circle=null}function Xc(t){var n=cm.pop()||new Hc;return n.site=t,n}function $c(t){jc(t),rm.remove(t),cm.push(t),kc(t)}function Vc(t){var n=t.circle,e=n.x,r=n.cy,i=[e,r],o=t.P,u=t.N,a=[t];$c(t);for(var c=o;c.circle&&Math.abs(e-c.circle.x)<sm&&Math.abs(r-c.circle.cy)<sm;)o=c.P,a.unshift(c),$c(c),c=o;a.unshift(c),jc(c);for(var s=u;s.circle&&Math.abs(e-s.circle.x)<sm&&Math.abs(r-s.circle.cy)<sm;)u=s.N,a.push(s),$c(s),s=u;a.push(s),jc(s);var f,l=a.length;for(f=1;f<l;++f)s=a[f],c=a[f-1],zc(s.edge,c.site,s.site,i);c=a[0],(s=a[l-1]).edge=Ac(c.site,s.site,null,i),Bc(c),Bc(s)}function Wc(t){for(var n,e,r,i,o=t[0],u=t[1],a=rm._;a;)if((r=Zc(a,u)-o)>sm)a=a.L;else{if(!((i=o-Gc(a,u))>sm)){r>-sm?(n=a.P,e=a):i>-sm?(n=a,e=a.N):n=e=a;break}if(!a.R){n=a;break}a=a.R}qc(t);var c=Xc(t);if(rm.insert(n,c),n||e){if(n===e)return jc(n),e=Xc(n.site),rm.insert(c,e),c.edge=e.edge=Ac(n.site,c.site),Bc(n),void Bc(e);if(e){jc(n),jc(e);var s=n.site,f=s[0],l=s[1],h=t[0]-f,p=t[1]-l,d=e.site,v=d[0]-f,_=d[1]-l,y=2*(h*_-p*v),g=h*h+p*p,m=v*v+_*_,x=[(_*g-p*m)/y+f,(h*m-v*g)/y+l];zc(e.edge,s,d,x),c.edge=Ac(s,t,null,x),e.edge=Ac(t,d,null,x),Bc(n),Bc(e)}else c.edge=Ac(n.site,c.site)}}function Zc(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var u=t.P;if(!u)return-1/0;var a=(e=u.site)[0],c=e[1],s=c-n;if(!s)return a;var f=a-r,l=1/o-1/s,h=f/s;return l?(-h+Math.sqrt(h*h-2*l*(f*f/(-2*s)-c+s/2+i-o/2)))/l+r:(r+a)/2}function Gc(t,n){var e=t.N;if(e)return Zc(e,n);var r=t.site;return r[1]===n?r[0]:1/0}function Jc(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}function Qc(t,n){return n[1]-t[1]||n[0]-t[0]}function Kc(t,n){var e,r,i,o=t.sort(Qc).pop();for(um=[],im=new Array(t.length),rm=new Tc,om=new Tc;;)if(i=em,o&&(!i||o[1]<i.y||o[1]===i.y&&o[0]<i.x))o[0]===e&&o[1]===r||(Wc(o),e=o[0],r=o[1]),o=t.pop();else{if(!i)break;Vc(i.arc)}if(Fc(),n){var u=+n[0][0],a=+n[0][1],c=+n[1][0],s=+n[1][1];Lc(u,a,c,s),Ic(u,a,c,s)}this.edges=um,this.cells=im,rm=om=um=im=null}function ts(t,n,e){this.target=t,this.type=n,this.transform=e}function ns(t,n,e){this.k=t,this.x=n,this.y=e}function es(t){return t.__zoom||hm}function rs(){t.event.stopImmediatePropagation()}function is(){return!t.event.button}function os(){var t,n,e=this;return e instanceof SVGElement?(t=(e=e.ownerSVGElement||e).width.baseVal.value,n=e.height.baseVal.value):(t=e.clientWidth,n=e.clientHeight),[[0,0],[t,n]]}function us(){return this.__zoom||hm}function as(){return-t.event.deltaY*(t.event.deltaMode?120:1)/500}function cs(){return"ontouchstart"in this}var ss=function(t,n){return t<n?-1:t>n?1:t>=n?0:NaN},fs=function(t){return 1===t.length&&(t=n(t)),{left:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)<0?r=o+1:i=o}return r},right:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)>0?i=o:r=o+1}return r}}},ls=fs(ss),hs=ls.right,ps=ls.left,ds=function(t){return null===t?NaN:+t},vs=function(t,n){var e,r,i=t.length,o=0,u=-1,a=0,c=0;if(null==n)for(;++u<i;)isNaN(e=ds(t[u]))||(c+=(r=e-a)*(e-(a+=r/++o)));else for(;++u<i;)isNaN(e=ds(n(t[u],u,t)))||(c+=(r=e-a)*(e-(a+=r/++o)));if(o>1)return c/(o-1)},_s=function(t,n){var e=vs(t,n);return e?Math.sqrt(e):e},ys=function(t,n){var e,r,i,o=t.length,u=-1;if(null==n){for(;++u<o;)if(null!=(e=t[u])&&e>=e)for(r=i=e;++u<o;)null!=(e=t[u])&&(r>e&&(r=e),i<e&&(i=e))}else for(;++u<o;)if(null!=(e=n(t[u],u,t))&&e>=e)for(r=i=e;++u<o;)null!=(e=n(t[u],u,t))&&(r>e&&(r=e),i<e&&(i=e));return[r,i]},gs=Array.prototype,ms=gs.slice,xs=gs.map,bs=function(t){return function(){return t}},ws=function(t){return t},Ms=function(t,n,e){t=+t,n=+n,e=(i=arguments.length)<2?(n=t,t=0,1):i<3?1:+e;for(var r=-1,i=0|Math.max(0,Math.ceil((n-t)/e)),o=new Array(i);++r<i;)o[r]=t+r*e;return o},Ts=Math.sqrt(50),ks=Math.sqrt(10),Ns=Math.sqrt(2),Ss=function(t,n,e){var i,o,u,a=n<t,c=-1;if(a&&(i=t,t=n,n=i),0===(u=r(t,n,e))||!isFinite(u))return[];if(u>0)for(t=Math.ceil(t/u),n=Math.floor(n/u),o=new Array(i=Math.ceil(n-t+1));++c<i;)o[c]=(t+c)*u;else for(t=Math.floor(t*u),n=Math.ceil(n*u),o=new Array(i=Math.ceil(t-n+1));++c<i;)o[c]=(t-c)/u;return a&&o.reverse(),o},Es=function(t){return Math.ceil(Math.log(t.length)/Math.LN2)+1},As=function(t,n,e){if(null==e&&(e=ds),r=t.length){if((n=+n)<=0||r<2)return+e(t[0],0,t);if(n>=1)return+e(t[r-1],r-1,t);var r,i=(r-1)*n,o=Math.floor(i),u=+e(t[o],o,t);return u+(+e(t[o+1],o+1,t)-u)*(i-o)}},Cs=function(t){for(var n,e,r,i=t.length,o=-1,u=0;++o<i;)u+=t[o].length;for(e=new Array(u);--i>=0;)for(n=(r=t[i]).length;--n>=0;)e[--u]=r[n];return e},zs=function(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o<i;)if(null!=(e=t[o])&&e>=e)for(r=e;++o<i;)null!=(e=t[o])&&r>e&&(r=e)}else for(;++o<i;)if(null!=(e=n(t[o],o,t))&&e>=e)for(r=e;++o<i;)null!=(e=n(t[o],o,t))&&r>e&&(r=e);return r},Ps=function(t){if(!(i=t.length))return[];for(var n=-1,e=zs(t,o),r=new Array(e);++n<e;)for(var i,u=-1,a=r[n]=new Array(i);++u<i;)a[u]=t[u][n];return r},Rs=Array.prototype.slice,Ls=function(t){return t},qs=1,Us=2,Ds=3,Os=4,Fs=1e-6,Is={value:function(){}};p.prototype=h.prototype={constructor:p,on:function(t,n){var e,r=this._,i=d(t+"",r),o=-1,u=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=_(r[e],t.name,n);else if(null==n)for(e in r)r[e]=_(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=v(r[e],t.name)))return e}},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new p(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(o=0,e=(r=this._[t]).length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var Ys="http://www.w3.org/1999/xhtml",Bs={svg:"http://www.w3.org/2000/svg",xhtml:Ys,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},js=function(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Bs.hasOwnProperty(n)?{space:Bs[n],local:t}:t},Hs=function(t){var n=js(t);return(n.local?g:y)(n)},Xs=0;x.prototype=m.prototype={constructor:x,get:function(t){for(var n=this._;!(n in t);)if(!(t=t.parentNode))return;return t[n]},set:function(t,n){return t[this._]=n},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var $s=function(t){return function(){return this.matches(t)}};if("undefined"!=typeof document){var Vs=document.documentElement;if(!Vs.matches){var Ws=Vs.webkitMatchesSelector||Vs.msMatchesSelector||Vs.mozMatchesSelector||Vs.oMatchesSelector;$s=function(t){return function(){return Ws.call(this,t)}}}}var Zs=$s,Gs={};t.event=null,"undefined"!=typeof document&&("onmouseenter"in document.documentElement||(Gs={mouseenter:"mouseover",mouseleave:"mouseout"}));var Js=function(){for(var n,e=t.event;n=e.sourceEvent;)e=n;return e},Qs=function(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=n.clientX,r.y=n.clientY,r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]},Ks=function(t){var n=Js();return n.changedTouches&&(n=n.changedTouches[0]),Qs(t,n)},tf=function(t){return null==t?S:function(){return this.querySelector(t)}},nf=function(t){return null==t?E:function(){return this.querySelectorAll(t)}},ef=function(t){return new Array(t.length)};A.prototype={constructor:A,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var rf=function(t){return function(){return t}},of="$",uf=function(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView};W.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var af=[null];pt.prototype=dt.prototype={constructor:pt,select:function(t){"function"!=typeof t&&(t=tf(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u,a=n[i],c=a.length,s=r[i]=new Array(c),f=0;f<c;++f)(o=a[f])&&(u=t.call(o,o.__data__,f,a))&&("__data__"in o&&(u.__data__=o.__data__),s[f]=u);return new pt(r,this._parents)},selectAll:function(t){"function"!=typeof t&&(t=nf(t));for(var n=this._groups,e=n.length,r=[],i=[],o=0;o<e;++o)for(var u,a=n[o],c=a.length,s=0;s<c;++s)(u=a[s])&&(r.push(t.call(u,u.__data__,s,a)),i.push(u));return new pt(r,i)},filter:function(t){"function"!=typeof t&&(t=Zs(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new pt(r,this._parents)},data:function(t,n){if(!t)return p=new Array(this.size()),s=-1,this.each(function(t){p[++s]=t}),p;var e=n?z:C,r=this._parents,i=this._groups;"function"!=typeof t&&(t=rf(t));for(var o=i.length,u=new Array(o),a=new Array(o),c=new Array(o),s=0;s<o;++s){var f=r[s],l=i[s],h=l.length,p=t.call(f,f&&f.__data__,s,r),d=p.length,v=a[s]=new Array(d),_=u[s]=new Array(d);e(f,l,v,_,c[s]=new Array(h),p,n);for(var y,g,m=0,x=0;m<d;++m)if(y=v[m]){for(m>=x&&(x=m+1);!(g=_[x])&&++x<d;);y._next=g||null}}return u=new pt(u,r),u._enter=a,u._exit=c,u},enter:function(){return new pt(this._enter||this._groups.map(ef),this._parents)},exit:function(){return new pt(this._exit||this._groups.map(ef),this._parents)},merge:function(t){for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new pt(u,this._parents)},order:function(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&u!==r.nextSibling&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(t){t||(t=P);for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i){for(var o,u=n[i],a=u.length,c=r[i]=new Array(a),s=0;s<a;++s)(o=u[s])&&(c[s]=o);c.sort(function(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e})}return new pt(r,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){var t=new Array(this.size()),n=-1;return this.each(function(){t[++n]=this}),t},node:function(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null},size:function(){var t=0;return this.each(function(){++t}),t},empty:function(){return!this.node()},each:function(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this},attr:function(t,n){var e=js(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?L:R:"function"==typeof n?e.local?O:D:e.local?U:q)(e,n))},style:function(t,n,e){return arguments.length>1?this.each((null==n?F:"function"==typeof n?Y:I)(t,n,null==e?"":e)):B(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?j:"function"==typeof n?X:H)(t,n)):this.node()[t]},classed:function(t,n){var e=$(t+"");if(arguments.length<2){for(var r=V(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each(("function"==typeof n?K:n?J:Q)(e,n))},text:function(t){return arguments.length?this.each(null==t?tt:("function"==typeof t?et:nt)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?rt:("function"==typeof t?ot:it)(t)):this.node().innerHTML},raise:function(){return this.each(ut)},lower:function(){return this.each(at)},append:function(t){var n="function"==typeof t?t:Hs(t);return this.select(function(){return this.appendChild(n.apply(this,arguments))})},insert:function(t,n){var e="function"==typeof t?t:Hs(t),r=null==n?ct:"function"==typeof n?n:tf(n);return this.select(function(){return this.insertBefore(e.apply(this,arguments),r.apply(this,arguments)||null)})},remove:function(){return this.each(st)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,n,e){var r,i,o=M(t+""),u=o.length;{if(!(arguments.length<2)){for(a=n?k:T,null==e&&(e=!1),r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var c,s=0,f=a.length;s<f;++s)for(r=0,c=a[s];r<u;++r)if((i=o[r]).type===c.type&&i.name===c.name)return c.value}},dispatch:function(t,n){return this.each(("function"==typeof n?ht:lt)(t,n))}};var cf=function(t){return"string"==typeof t?new pt([[document.querySelector(t)]],[document.documentElement]):new pt([[t]],af)},sf=function(t,n,e){arguments.length<3&&(e=n,n=Js().changedTouches);for(var r,i=0,o=n?n.length:0;i<o;++i)if((r=n[i]).identifier===e)return Qs(t,r);return null},ff=function(){t.event.preventDefault(),t.event.stopImmediatePropagation()},lf=function(t){var n=t.document.documentElement,e=cf(t).on("dragstart.drag",ff,!0);"onselectstart"in n?e.on("selectstart.drag",ff,!0):(n.__noselect=n.style.MozUserSelect,n.style.MozUserSelect="none")},hf=function(t){return function(){return t}};yt.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var pf=function(t,n,e){t.prototype=n.prototype=e,e.constructor=t},df="\\s*([+-]?\\d+)\\s*",vf="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",_f="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",yf=/^#([0-9a-f]{3})$/,gf=/^#([0-9a-f]{6})$/,mf=new RegExp("^rgb\\("+[df,df,df]+"\\)$"),xf=new RegExp("^rgb\\("+[_f,_f,_f]+"\\)$"),bf=new RegExp("^rgba\\("+[df,df,df,vf]+"\\)$"),wf=new RegExp("^rgba\\("+[_f,_f,_f,vf]+"\\)$"),Mf=new RegExp("^hsl\\("+[vf,_f,_f]+"\\)$"),Tf=new RegExp("^hsla\\("+[vf,_f,_f,vf]+"\\)$"),kf={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};pf(Mt,Tt,{displayable:function(){return this.rgb().displayable()},toString:function(){return this.rgb()+""}}),pf(At,Et,wt(Mt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new At(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new At(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},toString:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),pf(Rt,Pt,wt(Mt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Rt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Rt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new At(Lt(t>=240?t-240:t+120,i,r),Lt(t,i,r),Lt(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var Nf=Math.PI/180,Sf=180/Math.PI,Ef=.95047,Af=1,Cf=1.08883,zf=4/29,Pf=6/29,Rf=3*Pf*Pf,Lf=Pf*Pf*Pf;pf(Dt,Ut,wt(Mt,{brighter:function(t){return new Dt(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Dt(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return t=Af*Ft(t),n=Ef*Ft(n),e=Cf*Ft(e),new At(It(3.2404542*n-1.5371385*t-.4985314*e),It(-.969266*n+1.8760108*t+.041556*e),It(.0556434*n-.2040259*t+1.0572252*e),this.opacity)}})),pf(Ht,jt,wt(Mt,{brighter:function(t){return new Ht(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new Ht(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return qt(this).rgb()}}));var qf=-.14861,Uf=1.78277,Df=-.29227,Of=-.90649,Ff=1.97294,If=Ff*Of,Yf=Ff*Uf,Bf=Uf*Df-Of*qf;pf(Vt,$t,wt(Mt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Vt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Vt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*Nf,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new At(255*(n+e*(qf*r+Uf*i)),255*(n+e*(Df*r+Of*i)),255*(n+e*(Ff*r)),this.opacity)}}));var jf,Hf,Xf,$f,Vf,Wf,Zf=function(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=r<n-1?t[r+2]:2*o-i;return Wt((e-r/n)*n,u,i,o,a)}},Gf=function(t){var n=t.length;return function(e){var r=Math.floor(((e%=1)<0?++e:e)*n),i=t[(r+n-1)%n],o=t[r%n],u=t[(r+1)%n],a=t[(r+2)%n];return Wt((e-r/n)*n,i,o,u,a)}},Jf=function(t){return function(){return t}},Qf=function t(n){function e(t,n){var e=r((t=Et(t)).r,(n=Et(n)).r),i=r(t.g,n.g),o=r(t.b,n.b),u=Kt(t.opacity,n.opacity);return function(n){return t.r=e(n),t.g=i(n),t.b=o(n),t.opacity=u(n),t+""}}var r=Qt(n);return e.gamma=t,e}(1),Kf=tn(Zf),tl=tn(Gf),nl=function(t,n){var e,r=n?n.length:0,i=t?Math.min(r,t.length):0,o=new Array(r),u=new Array(r);for(e=0;e<i;++e)o[e]=cl(t[e],n[e]);for(;e<r;++e)u[e]=n[e];return function(t){for(e=0;e<i;++e)u[e]=o[e](t);return u}},el=function(t,n){var e=new Date;return t=+t,n-=t,function(r){return e.setTime(t+n*r),e}},rl=function(t,n){return t=+t,n-=t,function(e){return t+n*e}},il=function(t,n){var e,r={},i={};null!==t&&"object"==typeof t||(t={}),null!==n&&"object"==typeof n||(n={});for(e in n)e in t?r[e]=cl(t[e],n[e]):i[e]=n[e];return function(t){for(e in r)i[e]=r[e](t);return i}},ol=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,ul=new RegExp(ol.source,"g"),al=function(t,n){var e,r,i,o=ol.lastIndex=ul.lastIndex=0,u=-1,a=[],c=[];for(t+="",n+="";(e=ol.exec(t))&&(r=ul.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,c.push({i:u,x:rl(e,r)})),o=ul.lastIndex;return o<n.length&&(i=n.slice(o),a[u]?a[u]+=i:a[++u]=i),a.length<2?c[0]?en(c[0].x):nn(n):(n=c.length,function(t){for(var e,r=0;r<n;++r)a[(e=c[r]).i]=e.x(t);return a.join("")})},cl=function(t,n){var e,r=typeof n;return null==n||"boolean"===r?Jf(n):("number"===r?rl:"string"===r?(e=Tt(n))?(n=e,Qf):al:n instanceof Tt?Qf:n instanceof Date?el:Array.isArray(n)?nl:"function"!=typeof n.valueOf&&"function"!=typeof n.toString||isNaN(n)?il:rl)(t,n)},sl=function(t,n){return t=+t,n-=t,function(e){return Math.round(t+n*e)}},fl=180/Math.PI,ll={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},hl=function(t,n,e,r,i,o){var u,a,c;return(u=Math.sqrt(t*t+n*n))&&(t/=u,n/=u),(c=t*e+n*r)&&(e-=t*c,r-=n*c),(a=Math.sqrt(e*e+r*r))&&(e/=a,r/=a,c/=a),t*r<n*e&&(t=-t,n=-n,c=-c,u=-u),{translateX:i,translateY:o,rotate:Math.atan2(n,t)*fl,skewX:Math.atan(c)*fl,scaleX:u,scaleY:a}},pl=rn(function(t){return"none"===t?ll:(jf||(jf=document.createElement("DIV"),Hf=document.documentElement,Xf=document.defaultView),jf.style.transform=t,t=Xf.getComputedStyle(Hf.appendChild(jf),null).getPropertyValue("transform"),Hf.removeChild(jf),t=t.slice(7,-1).split(","),hl(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))},"px, ","px)","deg)"),dl=rn(function(t){return null==t?ll:($f||($f=document.createElementNS("http://www.w3.org/2000/svg","g")),$f.setAttribute("transform",t),(t=$f.transform.baseVal.consolidate())?(t=t.matrix,hl(t.a,t.b,t.c,t.d,t.e,t.f)):ll)},", ",")",")"),vl=Math.SQRT2,_l=function(t,n){var e,r,i=t[0],o=t[1],u=t[2],a=n[0],c=n[1],s=n[2],f=a-i,l=c-o,h=f*f+l*l;if(h<1e-12)r=Math.log(s/u)/vl,e=function(t){return[i+t*f,o+t*l,u*Math.exp(vl*t*r)]};else{var p=Math.sqrt(h),d=(s*s-u*u+4*h)/(2*u*2*p),v=(s*s-u*u-4*h)/(2*s*2*p),_=Math.log(Math.sqrt(d*d+1)-d),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-_)/vl,e=function(t){var n=t*r,e=on(_),a=u/(2*p)*(e*an(vl*n+_)-un(_));return[i+a*f,o+a*l,u*e/on(vl*n+_)]}}return e.duration=1e3*r,e},yl=cn(Jt),gl=cn(Kt),ml=sn(Jt),xl=sn(Kt),bl=fn(Jt),wl=fn(Kt),Ml=0,Tl=0,kl=0,Nl=1e3,Sl=0,El=0,Al=0,Cl="object"==typeof performance&&performance.now?performance:Date,zl="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};pn.prototype=dn.prototype={constructor:pn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?ln():+e)+(null==n?0:+n),this._next||Wf===this||(Wf?Wf._next=this:Vf=this,Wf=this),this._call=t,this._time=e,mn()},stop:function(){this._call&&(this._call=null,this._time=1/0,mn())}};var Pl=function(t,n,e){var r=new pn;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r},Rl=h("start","end","interrupt"),Ll=[],ql=0,Ul=1,Dl=2,Ol=3,Fl=4,Il=5,Yl=6,Bl=function(t,n,e,r,i,o){var u=t.__transition;if(u){if(e in u)return}else t.__transition={};Mn(t,e,{name:n,index:r,group:i,on:Rl,tween:Ll,time:o.time,delay:o.delay,duration:o.duration,ease:o.ease,timer:null,state:ql})},jl=function(t,n){var e,r,i,o=t.__transition,u=!0;if(o){n=null==n?null:n+"";for(i in o)(e=o[i]).name===n?(r=e.state>Dl&&e.state<Il,e.state=Yl,e.timer.stop(),r&&e.on.call("interrupt",t,t.__data__,e.index,e.group),delete o[i]):u=!1;u&&delete t.__transition}},Hl=function(t,n){var e;return("number"==typeof n?rl:n instanceof Tt?Qf:(e=Tt(n))?(n=e,Qf):al)(t,n)},Xl=dt.prototype.constructor,$l=0,Vl=dt.prototype;Gn.prototype=Jn.prototype={constructor:Gn,select:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=tf(t));for(var r=this._groups,i=r.length,o=new Array(i),u=0;u<i;++u)for(var a,c,s=r[u],f=s.length,l=o[u]=new Array(f),h=0;h<f;++h)(a=s[h])&&(c=t.call(a,a.__data__,h,s))&&("__data__"in a&&(c.__data__=a.__data__),l[h]=c,Bl(l[h],n,e,h,l,wn(a,e)));return new Gn(o,this._parents,n,e)},selectAll:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=nf(t));for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,s=r[a],f=s.length,l=0;l<f;++l)if(c=s[l]){for(var h,p=t.call(c,c.__data__,l,s),d=wn(c,e),v=0,_=p.length;v<_;++v)(h=p[v])&&Bl(h,n,e,v,p,d);o.push(p),u.push(c)}return new Gn(o,u,n,e)},filter:function(t){"function"!=typeof t&&(t=Zs(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new Gn(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new Gn(u,this._parents,this._name,this._id)},selection:function(){return new Xl(this._groups,this._parents)},transition:function(){for(var t=this._name,n=this._id,e=Qn(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var f=wn(u,n);Bl(u,t,e,s,a,{time:f.time+f.delay+f.duration,delay:0,duration:f.duration,ease:f.ease})}return new Gn(r,this._parents,t,e)},call:Vl.call,nodes:Vl.nodes,node:Vl.node,size:Vl.size,empty:Vl.empty,each:Vl.each,on:function(t,n){var e=this._id;return arguments.length<2?wn(this.node(),e).on.on(t):this.each(Yn(e,t,n))},attr:function(t,n){var e=js(t),r="transform"===e?dl:Hl;return this.attrTween(t,"function"==typeof n?(e.local?Pn:zn)(e,r,Nn(this,"attr."+t,n)):null==n?(e.local?En:Sn)(e):(e.local?Cn:An)(e,r,n+""))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=js(t);return this.tween(e,(r.local?Rn:Ln)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?pl:Hl;return null==n?this.styleTween(t,jn(t,r)).on("end.style."+t,Hn(t)):this.styleTween(t,"function"==typeof n?$n(t,r,Nn(this,"style."+t,n)):Xn(t,r,n+""),e)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,Vn(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?Zn(Nn(this,"text",t)):Wn(null==t?"":t+""))},remove:function(){return this.on("end.remove",Bn(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=wn(this.node(),e).tween,o=0,u=i.length;o<u;++o)if((r=i[o]).name===t)return r.value;return null}return this.each((null==n?Tn:kn)(e,t,n))},delay:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?qn:Un)(n,t)):wn(this.node(),n).delay},duration:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?Dn:On)(n,t)):wn(this.node(),n).duration},ease:function(t){var n=this._id;return arguments.length?this.each(Fn(n,t)):wn(this.node(),n).ease}};var Wl=function t(n){function e(t){return Math.pow(t,n)}return n=+n,e.exponent=t,e}(3),Zl=function t(n){function e(t){return 1-Math.pow(1-t,n)}return n=+n,e.exponent=t,e}(3),Gl=function t(n){function e(t){return((t*=2)<=1?Math.pow(t,n):2-Math.pow(2-t,n))/2}return n=+n,e.exponent=t,e}(3),Jl=Math.PI,Ql=Jl/2,Kl=4/11,th=6/11,nh=8/11,eh=.75,rh=9/11,ih=10/11,oh=.9375,uh=21/22,ah=63/64,ch=1/Kl/Kl,sh=function t(n){function e(t){return t*t*((n+1)*t-n)}return n=+n,e.overshoot=t,e}(1.70158),fh=function t(n){function e(t){return--t*t*((n+1)*t+n)+1}return n=+n,e.overshoot=t,e}(1.70158),lh=function t(n){function e(t){return((t*=2)<1?t*t*((n+1)*t-n):(t-=2)*t*((n+1)*t+n)+2)/2}return n=+n,e.overshoot=t,e}(1.70158),hh=2*Math.PI,ph=function t(n,e){function r(t){return n*Math.pow(2,10*--t)*Math.sin((i-t)/e)}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=hh);return r.amplitude=function(n){return t(n,e*hh)},r.period=function(e){return t(n,e)},r}(1,.3),dh=function t(n,e){function r(t){return 1-n*Math.pow(2,-10*(t=+t))*Math.sin((t+i)/e)}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=hh);return r.amplitude=function(n){return t(n,e*hh)},r.period=function(e){return t(n,e)},r}(1,.3),vh=function t(n,e){function r(t){return((t=2*t-1)<0?n*Math.pow(2,10*t)*Math.sin((i-t)/e):2-n*Math.pow(2,-10*t)*Math.sin((i+t)/e))/2}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=hh);return r.amplitude=function(n){return t(n,e*hh)},r.period=function(e){return t(n,e)},r}(1,.3),_h={time:null,delay:0,duration:250,ease:te};dt.prototype.interrupt=function(t){return this.each(function(){jl(this,t)})},dt.prototype.transition=function(t){var n,e;t instanceof Gn?(n=t._id,t=t._name):(n=Qn(),(e=_h).time=ln(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&Bl(u,t,n,s,a,e||oe(u,n));return new Gn(r,this._parents,t,n)};var yh=[null],gh=function(t){return function(){return t}},mh=function(t,n,e){this.target=t,this.type=n,this.selection=e},xh=function(){t.event.preventDefault(),t.event.stopImmediatePropagation()},bh={name:"drag"},wh={name:"space"},Mh={name:"handle"},Th={name:"center"},kh={name:"x",handles:["e","w"].map(ae),input:function(t,n){return t&&[[t[0],n[0][1]],[t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},Nh={name:"y",handles:["n","s"].map(ae),input:function(t,n){return t&&[[n[0][0],t[0]],[n[1][0],t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},Sh={name:"xy",handles:["n","e","s","w","nw","ne","se","sw"].map(ae),input:function(t){return t},output:function(t){return t}},Eh={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ah={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},Ch={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},zh={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},Ph={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1},Rh=Math.cos,Lh=Math.sin,qh=Math.PI,Uh=qh/2,Dh=2*qh,Oh=Math.max,Fh=Array.prototype.slice,Ih=function(t){return function(){return t}},Yh=Math.PI,Bh=2*Yh,jh=Bh-1e-6;de.prototype=ve.prototype={constructor:de,moveTo:function(t,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,n){this._+="L"+(this._x1=+t)+","+(this._y1=+n)},quadraticCurveTo:function(t,n,e,r){this._+="Q"+ +t+","+ +n+","+(this._x1=+e)+","+(this._y1=+r)},bezierCurveTo:function(t,n,e,r,i,o){this._+="C"+ +t+","+ +n+","+ +e+","+ +r+","+(this._x1=+i)+","+(this._y1=+o)},arcTo:function(t,n,e,r,i){t=+t,n=+n,e=+e,r=+r,i=+i;var o=this._x1,u=this._y1,a=e-t,c=r-n,s=o-t,f=u-n,l=s*s+f*f;if(i<0)throw new Error("negative radius: "+i);if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=n);else if(l>1e-6)if(Math.abs(f*a-c*s)>1e-6&&i){var h=e-o,p=r-u,d=a*a+c*c,v=h*h+p*p,_=Math.sqrt(d),y=Math.sqrt(l),g=i*Math.tan((Yh-Math.acos((d+l-v)/(2*_*y)))/2),m=g/y,x=g/_;Math.abs(m-1)>1e-6&&(this._+="L"+(t+m*s)+","+(n+m*f)),this._+="A"+i+","+i+",0,0,"+ +(f*h>s*p)+","+(this._x1=t+x*a)+","+(this._y1=n+x*c)}else this._+="L"+(this._x1=t)+","+(this._y1=n);else;},arc:function(t,n,e,r,i,o){t=+t,n=+n;var u=(e=+e)*Math.cos(r),a=e*Math.sin(r),c=t+u,s=n+a,f=1^o,l=o?r-i:i-r;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._+="M"+c+","+s:(Math.abs(this._x1-c)>1e-6||Math.abs(this._y1-s)>1e-6)&&(this._+="L"+c+","+s),e&&(l<0&&(l=l%Bh+Bh),l>jh?this._+="A"+e+","+e+",0,1,"+f+","+(t-u)+","+(n-a)+"A"+e+","+e+",0,1,"+f+","+(this._x1=c)+","+(this._y1=s):l>1e-6&&(this._+="A"+e+","+e+",0,"+ +(l>=Yh)+","+f+","+(this._x1=t+e*Math.cos(i))+","+(this._y1=n+e*Math.sin(i))))},rect:function(t,n,e,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +e+"v"+ +r+"h"+-e+"Z"},toString:function(){return this._}};be.prototype=we.prototype={constructor:be,has:function(t){return"$"+t in this},get:function(t){return this["$"+t]},set:function(t,n){return this["$"+t]=n,this},remove:function(t){var n="$"+t;return n in this&&delete this[n]},clear:function(){for(var t in this)"$"===t[0]&&delete this[t]},keys:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(n.slice(1));return t},values:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(this[n]);return t},entries:function(){var t=[];for(var n in this)"$"===n[0]&&t.push({key:n.slice(1),value:this[n]});return t},size:function(){var t=0;for(var n in this)"$"===n[0]&&++t;return t},empty:function(){for(var t in this)if("$"===t[0])return!1;return!0},each:function(t){for(var n in this)"$"===n[0]&&t(this[n],n.slice(1),this)}};var Hh=we.prototype;Se.prototype=Ee.prototype={constructor:Se,has:Hh.has,add:function(t){return t+="",this["$"+t]=t,this},remove:Hh.remove,clear:Hh.clear,values:Hh.keys,size:Hh.size,empty:Hh.empty,each:Hh.each};var Xh=function(t){function n(t,n){function e(){if(f>=s)return a;if(i)return i=!1,u;var n,e=f;if(34===t.charCodeAt(e)){for(var r=e;r++<s;)if(34===t.charCodeAt(r)){if(34!==t.charCodeAt(r+1))break;++r}return f=r+2,13===(n=t.charCodeAt(r+1))?(i=!0,10===t.charCodeAt(r+2)&&++f):10===n&&(i=!0),t.slice(e+1,r).replace(/""/g,'"')}for(;f<s;){var c=1;if(10===(n=t.charCodeAt(f++)))i=!0;else if(13===n)i=!0,10===t.charCodeAt(f)&&(++f,++c);else if(n!==o)continue;return t.slice(e,f-c)}return t.slice(e)}for(var r,i,u={},a={},c=[],s=t.length,f=0,l=0;(r=e())!==a;){for(var h=[];r!==u&&r!==a;)h.push(r),r=e();n&&null==(h=n(h,l++))||c.push(h)}return c}function e(n){return n.map(r).join(t)}function r(t){return null==t?"":i.test(t+="")?'"'+t.replace(/\"/g,'""')+'"':t}var i=new RegExp('["'+t+"\n\r]"),o=t.charCodeAt(0);return{parse:function(t,e){var r,i,o=n(t,function(t,n){if(r)return r(t,n-1);i=t,r=e?Ce(t,e):Ae(t)});return o.columns=i,o},parseRows:n,format:function(n,e){return null==e&&(e=ze(n)),[e.map(r).join(t)].concat(n.map(function(n){return e.map(function(t){return r(n[t])}).join(t)})).join("\n")},formatRows:function(t){return t.map(e).join("\n")}}},$h=Xh(","),Vh=$h.parse,Wh=$h.parseRows,Zh=$h.format,Gh=$h.formatRows,Jh=Xh("\t"),Qh=Jh.parse,Kh=Jh.parseRows,tp=Jh.format,np=Jh.formatRows,ep=function(t){return function(){return t}},rp=function(){return 1e-6*(Math.random()-.5)},ip=function(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i},op=qe.prototype=Ue.prototype;op.copy=function(){var t,n,e=new Ue(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=De(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=De(n));return e},op.add=function(t){var n=+this._x.call(null,t),e=+this._y.call(null,t);return Pe(this.cover(n,e),n,e,t)},op.addAll=function(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-1/0,l=-1/0;for(e=0;e<o;++e)isNaN(r=+this._x.call(null,n=t[e]))||isNaN(i=+this._y.call(null,n))||(u[e]=r,a[e]=i,r<c&&(c=r),r>f&&(f=r),i<s&&(s=i),i>l&&(l=i));for(f<c&&(c=this._x0,f=this._x1),l<s&&(s=this._y0,l=this._y1),this.cover(c,s).cover(f,l),e=0;e<o;++e)Pe(this,u[e],a[e],t[e]);return this},op.cover=function(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var e=this._x0,r=this._y0,i=this._x1,o=this._y1;if(isNaN(e))i=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1;else{if(!(e>t||t>i||r>n||n>o))return this;var u,a,c=i-e,s=this._root;switch(a=(n<(r+o)/2)<<1|t<(e+i)/2){case 0:do{u=new Array(4),u[a]=s,s=u}while(c*=2,i=e+c,o=r+c,t>i||n>o);break;case 1:do{u=new Array(4),u[a]=s,s=u}while(c*=2,e=i-c,o=r+c,e>t||n>o);break;case 2:do{u=new Array(4),u[a]=s,s=u}while(c*=2,i=e+c,r=o-c,t>i||r>n);break;case 3:do{u=new Array(4),u[a]=s,s=u}while(c*=2,e=i-c,r=o-c,e>t||r>n)}this._root&&this._root.length&&(this._root=s)}return this._x0=e,this._y0=r,this._x1=i,this._y1=o,this},op.data=function(){var t=[];return this.visit(function(n){if(!n.length)do{t.push(n.data)}while(n=n.next)}),t},op.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},op.find=function(t,n,e){var r,i,o,u,a,c,s,f=this._x0,l=this._y0,h=this._x1,p=this._y1,d=[],v=this._root;for(v&&d.push(new ip(v,f,l,h,p)),null==e?e=1/0:(f=t-e,l=n-e,h=t+e,p=n+e,e*=e);c=d.pop();)if(!(!(v=c.node)||(i=c.x0)>h||(o=c.y0)>p||(u=c.x1)<f||(a=c.y1)<l))if(v.length){var _=(i+u)/2,y=(o+a)/2;d.push(new ip(v[3],_,y,u,a),new ip(v[2],i,y,_,a),new ip(v[1],_,o,u,y),new ip(v[0],i,o,_,y)),(s=(n>=y)<<1|t>=_)&&(c=d[d.length-1],d[d.length-1]=d[d.length-1-s],d[d.length-1-s]=c)}else{var g=t-+this._x.call(null,v.data),m=n-+this._y.call(null,v.data),x=g*g+m*m;if(x<e){var b=Math.sqrt(e=x);f=t-b,l=n-b,h=t+b,p=n+b,r=v.data}}return r},op.remove=function(t){if(isNaN(o=+this._x.call(null,t))||isNaN(u=+this._y.call(null,t)))return this;var n,e,r,i,o,u,a,c,s,f,l,h,p=this._root,d=this._x0,v=this._y0,_=this._x1,y=this._y1;if(!p)return this;if(p.length)for(;;){if((s=o>=(a=(d+_)/2))?d=a:_=a,(f=u>=(c=(v+y)/2))?v=c:y=c,n=p,!(p=p[l=f<<1|s]))return this;if(!p.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;p.data!==t;)if(r=p,!(p=p.next))return this;return(i=p.next)&&delete p.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(p=n[0]||n[1]||n[2]||n[3])&&p===(n[3]||n[2]||n[1]||n[0])&&!p.length&&(e?e[h]=p:this._root=p),this):(this._root=i,this)},op.removeAll=function(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this},op.root=function(){return this._root},op.size=function(){var t=0;return this.visit(function(n){if(!n.length)do{++t}while(n=n.next)}),t},op.visit=function(t){var n,e,r,i,o,u,a=[],c=this._root;for(c&&a.push(new ip(c,this._x0,this._y0,this._x1,this._y1));n=a.pop();)if(!t(c=n.node,r=n.x0,i=n.y0,o=n.x1,u=n.y1)&&c.length){var s=(r+o)/2,f=(i+u)/2;(e=c[3])&&a.push(new ip(e,s,f,o,u)),(e=c[2])&&a.push(new ip(e,r,f,s,u)),(e=c[1])&&a.push(new ip(e,s,i,o,f)),(e=c[0])&&a.push(new ip(e,r,i,s,f))}return this},op.visitAfter=function(t){var n,e=[],r=[];for(this._root&&e.push(new ip(this._root,this._x0,this._y0,this._x1,this._y1));n=e.pop();){var i=n.node;if(i.length){var o,u=n.x0,a=n.y0,c=n.x1,s=n.y1,f=(u+c)/2,l=(a+s)/2;(o=i[0])&&e.push(new ip(o,u,a,f,l)),(o=i[1])&&e.push(new ip(o,f,a,c,l)),(o=i[2])&&e.push(new ip(o,u,l,f,s)),(o=i[3])&&e.push(new ip(o,f,l,c,s))}r.push(n)}for(;n=r.pop();)t(n.node,n.x0,n.y0,n.x1,n.y1);return this},op.x=function(t){return arguments.length?(this._x=t,this):this._x},op.y=function(t){return arguments.length?(this._y=t,this):this._y};var up,ap=10,cp=Math.PI*(3-Math.sqrt(5)),sp=function(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]},fp=function(t){return(t=sp(Math.abs(t)))?t[1]:NaN},lp=function(t,n){return function(e,r){for(var i=e.length,o=[],u=0,a=t[0],c=0;i>0&&a>0&&(c+a+1>r&&(a=Math.max(1,r-c)),o.push(e.substring(i-=a,i+a)),!((c+=a+1)>r));)a=t[u=(u+1)%t.length];return o.reverse().join(n)}},hp=function(t){return function(n){return n.replace(/[0-9]/g,function(n){return t[+n]})}},pp=function(t,n){var e=sp(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")},dp={"":function(t,n){t:for(var e,r=(t=t.toPrecision(n)).length,i=1,o=-1;i<r;++i)switch(t[i]){case".":o=e=i;break;case"0":0===o&&(o=i),e=i;break;case"e":break t;default:o>0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t},"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return pp(100*t,n)},r:pp,s:function(t,n){var e=sp(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(up=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+sp(t,Math.max(0,n+o-1))[0]},X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},vp=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;He.prototype=Xe.prototype,Xe.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var _p,yp=function(t){return t},gp=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"],mp=function(t){function n(t){function n(t){var n,r,u,f=_,x=y;if("c"===v)x=g(t)+x,t="";else{var b=(t=+t)<0;if(t=g(Math.abs(t),d),b&&0==+t&&(b=!1),f=(b?"("===s?s:"-":"-"===s||"("===s?"":s)+f,x=x+("s"===v?gp[8+up/3]:"")+(b&&"("===s?")":""),m)for(n=-1,r=t.length;++n<r;)if(48>(u=t.charCodeAt(n))||u>57){x=(46===u?i+t.slice(n+1):t.slice(n))+x,t=t.slice(0,n);break}}p&&!l&&(t=e(t,1/0));var w=f.length+t.length+x.length,M=w<h?new Array(h-w+1).join(a):"";switch(p&&l&&(t=e(M+t,M.length?h-x.length:1/0),M=""),c){case"<":t=f+t+x+M;break;case"=":t=f+M+t+x;break;case"^":t=M.slice(0,w=M.length>>1)+f+t+x+M.slice(w);break;default:t=M+f+t+x}return o(t)}var a=(t=He(t)).fill,c=t.align,s=t.sign,f=t.symbol,l=t.zero,h=t.width,p=t.comma,d=t.precision,v=t.type,_="$"===f?r[0]:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",y="$"===f?r[1]:/[%p]/.test(v)?u:"",g=dp[v],m=!v||/[defgprs%]/.test(v);return d=null==d?v?6:12:/[gprs]/.test(v)?Math.max(1,Math.min(21,d)):Math.max(0,Math.min(20,d)),n.toString=function(){return t+""},n}var e=t.grouping&&t.thousands?lp(t.grouping,t.thousands):yp,r=t.currency,i=t.decimal,o=t.numerals?hp(t.numerals):yp,u=t.percent||"%";return{format:n,formatPrefix:function(t,e){var r=n((t=He(t),t.type="f",t)),i=3*Math.max(-8,Math.min(8,Math.floor(fp(e)/3))),o=Math.pow(10,-i),u=gp[8+i/3];return function(t){return r(o*t)+u}}}};$e({decimal:".",thousands:",",grouping:[3],currency:["$",""]});var xp=function(t){return Math.max(0,-fp(Math.abs(t)))},bp=function(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(fp(n)/3)))-fp(Math.abs(t)))},wp=function(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,fp(n)-fp(t))+1},Mp=function(){return new Ve};Ve.prototype={constructor:Ve,reset:function(){this.s=this.t=0},add:function(t){We(nd,t,this.t),We(this,nd.s,this.s),this.s?this.t+=nd.t:this.s=nd.t},valueOf:function(){return this.s}};var Tp,kp,Np,Sp,Ep,Ap,Cp,zp,Pp,Rp,Lp,qp,Up,Dp,Op,Fp,Ip,Yp,Bp,jp,Hp,Xp,$p,Vp,Wp,Zp,Gp,Jp,Qp,Kp,td,nd=new Ve,ed=1e-6,rd=Math.PI,id=rd/2,od=rd/4,ud=2*rd,ad=180/rd,cd=rd/180,sd=Math.abs,fd=Math.atan,ld=Math.atan2,hd=Math.cos,pd=Math.ceil,dd=Math.exp,vd=Math.log,_d=Math.pow,yd=Math.sin,gd=Math.sign||function(t){return t>0?1:t<0?-1:0},md=Math.sqrt,xd=Math.tan,bd={Feature:function(t,n){Ke(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)Ke(e[r].geometry,n)}},wd={Sphere:function(t,n){n.sphere()},Point:function(t,n){t=t.coordinates,n.point(t[0],t[1],t[2])},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)t=e[r],n.point(t[0],t[1],t[2])},LineString:function(t,n){tr(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)tr(e[r],n,0)},Polygon:function(t,n){nr(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)nr(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)Ke(e[r],n)}},Md=function(t,n){t&&bd.hasOwnProperty(t.type)?bd[t.type](t,n):Ke(t,n)},Td=Mp(),kd=Mp(),Nd={point:Qe,lineStart:Qe,lineEnd:Qe,polygonStart:function(){Td.reset(),Nd.lineStart=er,Nd.lineEnd=rr},polygonEnd:function(){var t=+Td;kd.add(t<0?ud+t:t),this.lineStart=this.lineEnd=this.point=Qe},sphere:function(){kd.add(ud)}},Sd=Mp(),Ed={point:pr,lineStart:vr,lineEnd:_r,polygonStart:function(){Ed.point=yr,Ed.lineStart=gr,Ed.lineEnd=mr,Sd.reset(),Nd.polygonStart()},polygonEnd:function(){Nd.polygonEnd(),Ed.point=pr,Ed.lineStart=vr,Ed.lineEnd=_r,Td<0?(Ap=-(zp=180),Cp=-(Pp=90)):Sd>ed?Pp=90:Sd<-ed&&(Cp=-90),Op[0]=Ap,Op[1]=zp}},Ad={sphere:Qe,point:Mr,lineStart:kr,lineEnd:Er,polygonStart:function(){Ad.lineStart=Ar,Ad.lineEnd=Cr},polygonEnd:function(){Ad.lineStart=kr,Ad.lineEnd=Er}},Cd=function(t){return function(){return t}},zd=function(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return(e=n.invert(e,r))&&t.invert(e[0],e[1])}),e};Rr.invert=Rr;var Pd,Rd,Ld,qd,Ud,Dd,Od,Fd,Id,Yd,Bd,jd=function(t){function n(n){return n=t(n[0]*cd,n[1]*cd),n[0]*=ad,n[1]*=ad,n}return t=Lr(t[0]*cd,t[1]*cd,t.length>2?t[2]*cd:0),n.invert=function(n){return n=t.invert(n[0]*cd,n[1]*cd),n[0]*=ad,n[1]*=ad,n},n},Hd=function(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:Qe,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}},Xd=function(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=0,f=1,l=n[0]-a,h=n[1]-c;if(u=e-a,l||!(u>0)){if(u/=l,l<0){if(u<s)return;u<f&&(f=u)}else if(l>0){if(u>f)return;u>s&&(s=u)}if(u=i-a,l||!(u<0)){if(u/=l,l<0){if(u>f)return;u>s&&(s=u)}else if(l>0){if(u<s)return;u<f&&(f=u)}if(u=r-c,h||!(u>0)){if(u/=h,h<0){if(u<s)return;u<f&&(f=u)}else if(h>0){if(u>f)return;u>s&&(s=u)}if(u=o-c,h||!(u<0)){if(u/=h,h<0){if(u>f)return;u>s&&(s=u)}else if(h>0){if(u<s)return;u<f&&(f=u)}return s>0&&(t[0]=a+s*l,t[1]=c+s*h),f<1&&(n[0]=a+f*l,n[1]=c+f*h),!0}}}}},$d=function(t,n){return sd(t[0]-n[0])<ed&&sd(t[1]-n[1])<ed},Vd=function(t,n,e,r,i){var o,u,a=[],c=[];if(t.forEach(function(t){if(!((n=t.length-1)<=0)){var n,e,r=t[0],u=t[n];if($d(r,u)){for(i.lineStart(),o=0;o<n;++o)i.point((r=t[o])[0],r[1]);i.lineEnd()}else a.push(e=new Ir(r,t,null,!0)),c.push(e.o=new Ir(r,null,e,!1)),a.push(e=new Ir(u,t,null,!1)),c.push(e.o=new Ir(u,null,e,!0))}}),a.length){for(c.sort(n),Yr(a),Yr(c),o=0,u=c.length;o<u;++o)c[o].e=e=!e;for(var s,f,l=a[0];;){for(var h=l,p=!0;h.v;)if((h=h.n)===l)return;s=h.z,i.lineStart();do{if(h.v=h.o.v=!0,h.e){if(p)for(o=0,u=s.length;o<u;++o)i.point((f=s[o])[0],f[1]);else r(h.x,h.n.x,1,i);h=h.n}else{if(p)for(s=h.p.z,o=s.length-1;o>=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}s=(h=h.o).z,p=!p}while(!h.v);i.lineEnd()}}},Wd=1e9,Zd=-Wd,Gd=Mp(),Jd=function(t,n){var e=n[0],r=n[1],i=[yd(e),-hd(e),0],o=0,u=0;Gd.reset();for(var a=0,c=t.length;a<c;++a)if(f=(s=t[a]).length)for(var s,f,l=s[f-1],h=l[0],p=l[1]/2+od,d=yd(p),v=hd(p),_=0;_<f;++_,h=g,d=x,v=b,l=y){var y=s[_],g=y[0],m=y[1]/2+od,x=yd(m),b=hd(m),w=g-h,M=w>=0?1:-1,T=M*w,k=T>rd,N=d*x;if(Gd.add(ld(N*M*yd(T),v*b+N*hd(T))),o+=k?w+M*ud:w,k^h>=e^g>=e){var S=sr(ar(l),ar(y));hr(S);var E=sr(i,S);hr(E);var A=(k^w>=0?-1:1)*Ge(E[2]);(r>A||r===A&&(S[0]||S[1]))&&(u+=k^w>=0?1:-1)}}return(o<-ed||o<ed&&Gd<-ed)^1&u},Qd=Mp(),Kd={sphere:Qe,point:Qe,lineStart:function(){Kd.point=Hr,Kd.lineEnd=jr},lineEnd:Qe,polygonStart:Qe,polygonEnd:Qe},tv=function(t){return Qd.reset(),Md(t,Kd),+Qd},nv=[null,null],ev={type:"LineString",coordinates:nv},rv=function(t,n){return nv[0]=t,nv[1]=n,tv(ev)},iv={Feature:function(t,n){return $r(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)if($r(e[r].geometry,n))return!0;return!1}},ov={Sphere:function(){return!0},Point:function(t,n){return Vr(t.coordinates,n)},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(Vr(e[r],n))return!0;return!1},LineString:function(t,n){return Wr(t.coordinates,n)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(Wr(e[r],n))return!0;return!1},Polygon:function(t,n){return Zr(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(Zr(e[r],n))return!0;return!1},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)if($r(e[r],n))return!0;return!1}},uv=function(t){return t},av=Mp(),cv=Mp(),sv={point:Qe,lineStart:Qe,lineEnd:Qe,polygonStart:function(){sv.lineStart=ni,sv.lineEnd=ii},polygonEnd:function(){sv.lineStart=sv.lineEnd=sv.point=Qe,av.add(sd(cv)),cv.reset()},result:function(){var t=av/2;return av.reset(),t}},fv=1/0,lv=fv,hv=-fv,pv=hv,dv={point:function(t,n){t<fv&&(fv=t),t>hv&&(hv=t),n<lv&&(lv=n),n>pv&&(pv=n)},lineStart:Qe,lineEnd:Qe,polygonStart:Qe,polygonEnd:Qe,result:function(){var t=[[fv,lv],[hv,pv]];return hv=pv=-(lv=fv=1/0),t}},vv=0,_v=0,yv=0,gv=0,mv=0,xv=0,bv=0,wv=0,Mv=0,Tv={point:oi,lineStart:ui,lineEnd:si,polygonStart:function(){Tv.lineStart=fi,Tv.lineEnd=li},polygonEnd:function(){Tv.point=oi,Tv.lineStart=ui,Tv.lineEnd=si},result:function(){var t=Mv?[bv/Mv,wv/Mv]:xv?[gv/xv,mv/xv]:yv?[vv/yv,_v/yv]:[NaN,NaN];return vv=_v=yv=gv=mv=xv=bv=wv=Mv=0,t}};di.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,ud)}},result:Qe};var kv,Nv,Sv,Ev,Av,Cv=Mp(),zv={point:Qe,lineStart:function(){zv.point=vi},lineEnd:function(){kv&&_i(Nv,Sv),zv.point=Qe},polygonStart:function(){kv=!0},polygonEnd:function(){kv=null},result:function(){var t=+Cv;return Cv.reset(),t}};yi.prototype={_radius:4.5,_circle:gi(4.5),pointRadius:function(t){return(t=+t)!==this._radius&&(this._radius=t,this._circle=null),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._string.push("M",t,",",n),this._point=1;break;case 1:this._string.push("L",t,",",n);break;default:null==this._circle&&(this._circle=gi(this._radius)),this._string.push("M",t,",",n,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}return null}};var Pv=function(t,n,e,r){return function(i,o){function u(n,e){var r=i(n,e);t(n=r[0],e=r[1])&&o.point(n,e)}function a(t,n){var e=i(t,n);_.point(e[0],e[1])}function c(){b.point=a,_.lineStart()}function s(){b.point=u,_.lineEnd()}function f(t,n){v.push([t,n]);var e=i(t,n);m.point(e[0],e[1])}function l(){m.lineStart(),v=[]}function h(){f(v[0][0],v[0][1]),m.lineEnd();var t,n,e,r,i=m.clean(),u=g.result(),a=u.length;if(v.pop(),p.push(v),v=null,a)if(1&i){if(e=u[0],(n=e.length-1)>0){for(x||(o.polygonStart(),x=!0),o.lineStart(),t=0;t<n;++t)o.point((r=e[t])[0],r[1]);o.lineEnd()}}else a>1&&2&i&&u.push(u.pop().concat(u.shift())),d.push(u.filter(mi))}var p,d,v,_=n(o),y=i.invert(r[0],r[1]),g=Hd(),m=n(g),x=!1,b={point:u,lineStart:c,lineEnd:s,polygonStart:function(){b.point=f,b.lineStart=l,b.lineEnd=h,d=[],p=[]},polygonEnd:function(){b.point=u,b.lineStart=c,b.lineEnd=s,d=Cs(d);var t=Jd(p,y);d.length?(x||(o.polygonStart(),x=!0),Vd(d,xi,t,e,o)):t&&(x||(o.polygonStart(),x=!0),o.lineStart(),e(null,null,1,o),o.lineEnd()),x&&(o.polygonEnd(),x=!1),d=p=null},sphere:function(){o.polygonStart(),o.lineStart(),e(null,null,1,o),o.lineEnd(),o.polygonEnd()}};return b}},Rv=Pv(function(){return!0},function(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,u){var a=o>0?rd:-rd,c=sd(o-e);sd(c-rd)<ed?(t.point(e,r=(r+u)/2>0?id:-id),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),t.point(o,r),n=0):i!==a&&c>=rd&&(sd(e-i)<ed&&(e-=i*ed),sd(o-a)<ed&&(o-=a*ed),r=bi(e,r,o,u),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),n=0),t.point(e=o,r=u),i=a},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}},function(t,n,e,r){var i;if(null==t)i=e*id,r.point(-rd,i),r.point(0,i),r.point(rd,i),r.point(rd,0),r.point(rd,-i),r.point(0,-i),r.point(-rd,-i),r.point(-rd,0),r.point(-rd,i);else if(sd(t[0]-n[0])>ed){var o=t[0]<n[0]?rd:-rd;i=e*o/2,r.point(-o,i),r.point(0,i),r.point(o,i)}else r.point(n[0],n[1])},[-rd,-id]),Lv=function(t,n){function e(t,n){return hd(t)*hd(n)>o}function r(t,n,e){var r=[1,0,0],i=sr(ar(t),ar(n)),u=cr(i,i),a=i[0],c=u-a*a;if(!c)return!e&&t;var s=o*u/c,f=-o*a/c,l=sr(r,i),h=lr(r,s);fr(h,lr(i,f));var p=l,d=cr(h,p),v=cr(p,p),_=d*d-v*(cr(h,h)-1);if(!(_<0)){var y=md(_),g=lr(p,(-d-y)/v);if(fr(g,h),g=ur(g),!e)return g;var m,x=t[0],b=n[0],w=t[1],M=n[1];b<x&&(m=x,x=b,b=m);var T=b-x,k=sd(T-rd)<ed,N=k||T<ed;if(!k&&M<w&&(m=w,w=M,M=m),N?k?w+M>0^g[1]<(sd(g[0]-x)<ed?w:M):w<=g[1]&&g[1]<=M:T>rd^(x<=g[0]&&g[0]<=b)){var S=lr(p,(-d+y)/v);return fr(S,h),[g,ur(S)]}}}function i(n,e){var r=u?t:rd-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=4:e>r&&(i|=8),i}var o=hd(t),u=o>0,a=sd(o)>ed;return Pv(e,function(t){var n,o,c,s,f;return{lineStart:function(){s=c=!1,f=1},point:function(l,h){var p,d=[l,h],v=e(l,h),_=u?v?0:i(l,h):v?i(l+(l<0?rd:-rd),h):0;if(!n&&(s=c=v)&&t.lineStart(),v!==c&&(!(p=r(n,d))||$d(n,p)||$d(d,p))&&(d[0]+=ed,d[1]+=ed,v=e(d[0],d[1])),v!==c)f=0,v?(t.lineStart(),p=r(d,n),t.point(p[0],p[1])):(p=r(n,d),t.point(p[0],p[1]),t.lineEnd()),n=p;else if(a&&n&&u^v){var y;_&o||!(y=r(d,n,!0))||(f=0,u?(t.lineStart(),t.point(y[0][0],y[0][1]),t.point(y[1][0],y[1][1]),t.lineEnd()):(t.point(y[1][0],y[1][1]),t.lineEnd(),t.lineStart(),t.point(y[0][0],y[0][1])))}!v||n&&$d(n,d)||t.point(d[0],d[1]),n=d,c=v,o=_},lineEnd:function(){c&&t.lineEnd(),n=null},clean:function(){return f|(s&&c)<<1}}},function(e,r,i,o){Or(o,t,n,i,e,r)},u?[0,-t]:[-rd,t-rd])};Mi.prototype={constructor:Mi,point:function(t,n){this.stream.point(t,n)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var qv=16,Uv=hd(30*cd),Dv=function(t,n){return+n?Si(t,n):Ni(t)},Ov=wi({point:function(t,n){this.stream.point(t*cd,n*cd)}}),Fv=function(){return Ci(Pi).scale(155.424).center([0,33.6442])},Iv=function(){return Fv().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])},Yv=Li(function(t){return md(2/(1+t))});Yv.invert=qi(function(t){return 2*Ge(t/2)});var Bv=Li(function(t){return(t=Ze(t))&&t/yd(t)});Bv.invert=qi(function(t){return t});Ui.invert=function(t,n){return[t,2*fd(dd(n))-id]};Ii.invert=Ii;Bi.invert=qi(fd);Hi.invert=qi(Ge);Xi.invert=qi(function(t){return 2*fd(t)});$i.invert=function(t,n){return[-n,2*fd(dd(t))-id]};uo.prototype=eo.prototype={constructor:uo,count:function(){return this.eachAfter(to)},each:function(t){var n,e,r,i,o=this,u=[o];do{for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r])}while(u.length);return this},eachAfter:function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this},eachBefore:function(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this},sum:function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},sort:function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},path:function(t){for(var n=this,e=no(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){var t=[];return this.each(function(n){t.push(n)}),t},leaves:function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},links:function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n},copy:function(){return eo(this).eachBefore(io)}};var jv=Array.prototype.slice,Hv=function(t){for(var n,e,r=0,i=(t=ao(jv.call(t))).length,o=[];r<i;)n=t[r],e&&fo(e,n)?++r:(e=ho(o=co(o,n)),r=0);return e},Xv=function(t){return function(){return t}},$v=function(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)},Vv=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)(o=u[a]).y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s},Wv="$",Zv={depth:-1},Gv={};Do.prototype=Object.create(uo.prototype);var Jv=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(i-e)/t.value;++a<c;)(o=u[a]).x0=n,o.x1=r,o.y0=e,o.y1=e+=o.value*s},Qv=(1+Math.sqrt(5))/2,Kv=function t(n){function e(t,e,r,i,o){Fo(n,t,e,r,i,o)}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(Qv),t_=function t(n){function e(t,e,r,i,o){if((u=t._squarify)&&u.ratio===n)for(var u,a,c,s,f,l=-1,h=u.length,p=t.value;++l<h;){for(c=(a=u[l]).children,s=a.value=0,f=c.length;s<f;++s)a.value+=c[s].value;a.dice?Vv(a,e,r,i,r+=(o-r)*a.value/p):Jv(a,e,r,e+=(i-e)*a.value/p,o),p-=a.value}else t._squarify=u=Fo(n,t,e,r,i,o),u.ratio=n}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(Qv),n_=function(t,n,e){return(n[0]-t[0])*(e[1]-t[1])-(n[1]-t[1])*(e[0]-t[0])},e_=[].slice,r_={};Bo.prototype=Wo.prototype={constructor:Bo,defer:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("defer after await");if(null!=this._error)return this;var n=e_.call(arguments,1);return n.push(t),++this._waiting,this._tasks.push(n),jo(this),this},abort:function(){return null==this._error&&$o(this,new Error("abort")),this},await:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("multiple await");return this._call=function(n,e){t.apply(null,[n].concat(e))},Vo(this),this},awaitAll:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("multiple await");return this._call=t,Vo(this),this}};var i_=function(){return Math.random()},o_=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,1===arguments.length?(e=t,t=0):e-=t,function(){return n()*e+t}}return e.source=t,e}(i_),u_=function t(n){function e(t,e){var r,i;return t=null==t?0:+t,e=null==e?1:+e,function(){var o;if(null!=r)o=r,r=null;else do{r=2*n()-1,o=2*n()-1,i=r*r+o*o}while(!i||i>1);return t+e*o*Math.sqrt(-2*Math.log(i)/i)}}return e.source=t,e}(i_),a_=function t(n){function e(){var t=u_.source(n).apply(this,arguments);return function(){return Math.exp(t())}}return e.source=t,e}(i_),c_=function t(n){function e(t){return function(){for(var e=0,r=0;r<t;++r)e+=n();return e}}return e.source=t,e}(i_),s_=function t(n){function e(t){var e=c_.source(n)(t);return function(){return e()/t}}return e.source=t,e}(i_),f_=function t(n){function e(t){return function(){return-Math.log(1-n())/t}}return e.source=t,e}(i_),l_=function(t,n){function e(t){var n,e=s.status;if(!e&&Go(s)||e>=200&&e<300||304===e){if(o)try{n=o.call(r,s)}catch(t){return void a.call("error",r,t)}else n=s;a.call("load",r,n)}else a.call("error",r,t)}var r,i,o,u,a=h("beforesend","progress","load","error"),c=we(),s=new XMLHttpRequest,f=null,l=null,p=0;if("undefined"==typeof XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=s.ontimeout=e:s.onreadystatechange=function(t){s.readyState>3&&e(t)},s.onprogress=function(t){a.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?c.get(t):(null==n?c.remove(t):c.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(u=t,r):u},timeout:function(t){return arguments.length?(p=+t,r):p},user:function(t){return arguments.length<1?f:(f=null==t?null:t+"",r)},password:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},response:function(t){return o=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return s.open(n,t,!0,f,l),null==i||c.has("accept")||c.set("accept",i+",*/*"),s.setRequestHeader&&c.each(function(t,n){s.setRequestHeader(n,t)}),null!=i&&s.overrideMimeType&&s.overrideMimeType(i),null!=u&&(s.responseType=u),p>0&&(s.timeout=p),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=Zo(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),a.call("beforesend",r,s),s.send(null==e?null:e),r},abort:function(){return s.abort(),r},on:function(){var t=a.on.apply(a,arguments);return t===a?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r},h_=function(t,n){return function(e,r){var i=l_(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}},p_=h_("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),d_=h_("application/json",function(t){return JSON.parse(t.responseText)}),v_=h_("text/plain",function(t){return t.responseText}),__=h_("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),y_=function(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=l_(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(Jo(n,r=t)):r},o.row(r),i?o.get(i):o}},g_=y_("text/csv",Vh),m_=y_("text/tab-separated-values",Qh),x_=Array.prototype,b_=x_.map,w_=x_.slice,M_={name:"implicit"},T_=function(t){return function(){return t}},k_=function(t){return+t},N_=[0,1],S_=function(n,e,r){var o,u=n[0],a=n[n.length-1],c=i(u,a,null==e?10:e);switch((r=He(null==r?",f":r)).type){case"s":var s=Math.max(Math.abs(u),Math.abs(a));return null!=r.precision||isNaN(o=bp(c,s))||(r.precision=o),t.formatPrefix(r,s);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(o=wp(c,Math.max(Math.abs(u),Math.abs(a))))||(r.precision=o-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(o=xp(c))||(r.precision=o-2*("%"===r.type))}return t.format(r)},E_=function(t,n){var e,r=0,i=(t=t.slice()).length-1,o=t[r],u=t[i];return u<o&&(e=r,r=i,i=e,e=o,o=u,u=e),t[r]=n.floor(o),t[i]=n.ceil(u),t},A_=new Date,C_=new Date,z_=Mu(function(){},function(t,n){t.setTime(+t+n)},function(t,n){return n-t});z_.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Mu(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):z_:null};var P_=z_.range,R_=6e4,L_=6048e5,q_=Mu(function(t){t.setTime(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(+t+1e3*n)},function(t,n){return(n-t)/1e3},function(t){return t.getUTCSeconds()}),U_=q_.range,D_=Mu(function(t){t.setTime(Math.floor(t/R_)*R_)},function(t,n){t.setTime(+t+n*R_)},function(t,n){return(n-t)/R_},function(t){return t.getMinutes()}),O_=D_.range,F_=Mu(function(t){var n=t.getTimezoneOffset()*R_%36e5;n<0&&(n+=36e5),t.setTime(36e5*Math.floor((+t-n)/36e5)+n)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getHours()}),I_=F_.range,Y_=Mu(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*R_)/864e5},function(t){return t.getDate()-1}),B_=Y_.range,j_=Tu(0),H_=Tu(1),X_=Tu(2),$_=Tu(3),V_=Tu(4),W_=Tu(5),Z_=Tu(6),G_=j_.range,J_=H_.range,Q_=X_.range,K_=$_.range,ty=V_.range,ny=W_.range,ey=Z_.range,ry=Mu(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),iy=ry.range,oy=Mu(function(t){t.setMonth(0,1),t.setHours(0,0,0,0)},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t,n){return n.getFullYear()-t.getFullYear()},function(t){return t.getFullYear()});oy.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Mu(function(n){n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)},function(n,e){n.setFullYear(n.getFullYear()+e*t)}):null};var uy=oy.range,ay=Mu(function(t){t.setUTCSeconds(0,0)},function(t,n){t.setTime(+t+n*R_)},function(t,n){return(n-t)/R_},function(t){return t.getUTCMinutes()}),cy=ay.range,sy=Mu(function(t){t.setUTCMinutes(0,0,0)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getUTCHours()}),fy=sy.range,ly=Mu(function(t){t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+n)},function(t,n){return(n-t)/864e5},function(t){return t.getUTCDate()-1}),hy=ly.range,py=ku(0),dy=ku(1),vy=ku(2),_y=ku(3),yy=ku(4),gy=ku(5),my=ku(6),xy=py.range,by=dy.range,wy=vy.range,My=_y.range,Ty=yy.range,ky=gy.range,Ny=my.range,Sy=Mu(function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCMonth(t.getUTCMonth()+n)},function(t,n){return n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())},function(t){return t.getUTCMonth()}),Ey=Sy.range,Ay=Mu(function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCFullYear(t.getUTCFullYear()+n)},function(t,n){return n.getUTCFullYear()-t.getUTCFullYear()},function(t){return t.getUTCFullYear()});Ay.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Mu(function(n){n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)},function(n,e){n.setUTCFullYear(n.getUTCFullYear()+e*t)}):null};var Cy,zy=Ay.range,Py={"-":"",_:" ",0:"0"},Ry=/^\s*\d+/,Ly=/^%/,qy=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;Ma({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Uy=Date.prototype.toISOString?function(t){return t.toISOString()}:t.utcFormat("%Y-%m-%dT%H:%M:%S.%LZ"),Dy=+new Date("2000-01-01T00:00:00.000Z")?function(t){var n=new Date(t);return isNaN(n)?null:n}:t.utcParse("%Y-%m-%dT%H:%M:%S.%LZ"),Oy=1e3,Fy=60*Oy,Iy=60*Fy,Yy=24*Iy,By=7*Yy,jy=30*Yy,Hy=365*Yy,Xy=function(t){return t.match(/.{6}/g).map(function(t){return"#"+t})},$y=Xy("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),Vy=Xy("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"),Wy=Xy("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"),Zy=Xy("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"),Gy=wl($t(300,.5,0),$t(-240,.5,1)),Jy=wl($t(-100,.75,.35),$t(80,1.5,.8)),Qy=wl($t(260,.75,.35),$t(80,1.5,.8)),Ky=$t(),tg=Sa(Xy("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),ng=Sa(Xy("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),eg=Sa(Xy("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),rg=Sa(Xy("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")),ig=function(t){return function(){return t}},og=Math.abs,ug=Math.atan2,ag=Math.cos,cg=Math.max,sg=Math.min,fg=Math.sin,lg=Math.sqrt,hg=1e-12,pg=Math.PI,dg=pg/2,vg=2*pg;Oa.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var _g=function(t){return new Oa(t)},yg=function(){function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=ve())),a=0;a<=f;++a)!(a<f&&r(c=t[a],a,t))===l&&((l=!l)?u.lineStart():u.lineEnd()),l&&u.point(+n(c,a,t),+e(c,a,t));if(s)return u=null,s+""||null}var n=Fa,e=Ia,r=ig(!0),i=null,o=_g,u=null;return t.x=function(e){return arguments.length?(n="function"==typeof e?e:ig(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.defined=function(n){return arguments.length?(r="function"==typeof n?n:ig(!!n),t):r},t.curve=function(n){return arguments.length?(o=n,null!=i&&(u=o(i)),t):o},t.context=function(n){return arguments.length?(null==n?i=u=null:u=o(i=n),t):i},t},gg=function(){function t(t){var n,f,l,h,p,d=t.length,v=!1,_=new Array(d),y=new Array(d);for(null==a&&(s=c(p=ve())),n=0;n<=d;++n){if(!(n<d&&u(h=t[n],n,t))===v)if(v=!v)f=n,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),l=n-1;l>=f;--l)s.point(_[l],y[l]);s.lineEnd(),s.areaEnd()}v&&(_[n]=+e(h,n,t),y[n]=+i(h,n,t),s.point(r?+r(h,n,t):_[n],o?+o(h,n,t):y[n]))}if(p)return s=null,p+""||null}function n(){return yg().defined(u).curve(c).context(a)}var e=Fa,r=null,i=ig(0),o=Ia,u=ig(!0),a=null,c=_g,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:ig(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),o=null,t):i},t.y0=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),t):i},t.y1=function(n){return arguments.length?(o=null==n?null:"function"==typeof n?n:ig(+n),t):o},t.lineX0=t.lineY0=function(){return n().x(e).y(i)},t.lineY1=function(){return n().x(e).y(o)},t.lineX1=function(){return n().x(r).y(i)},t.defined=function(n){return arguments.length?(u="function"==typeof n?n:ig(!!n),t):u},t.curve=function(n){return arguments.length?(c=n,null!=a&&(s=c(a)),t):c},t.context=function(n){return arguments.length?(null==n?a=s=null:s=c(a=n),t):a},t},mg=function(t,n){return n<t?-1:n>t?1:n>=t?0:NaN},xg=function(t){return t},bg=Ba(_g);Ya.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};var wg=function(){return ja(yg().curve(bg))},Mg=function(){var t=gg().curve(bg),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return ja(e())},delete t.lineX0,t.lineEndAngle=function(){return ja(r())},delete t.lineX1,t.lineInnerRadius=function(){return ja(i())},delete t.lineY0,t.lineOuterRadius=function(){return ja(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(Ba(t)):n()._curve},t},Tg=function(t,n){return[(n=+n)*Math.cos(t-=Math.PI/2),n*Math.sin(t)]},kg=Array.prototype.slice,Ng={draw:function(t,n){var e=Math.sqrt(n/pg);t.moveTo(e,0),t.arc(0,0,e,0,vg)}},Sg={draw:function(t,n){var e=Math.sqrt(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}},Eg=Math.sqrt(1/3),Ag=2*Eg,Cg={draw:function(t,n){var e=Math.sqrt(n/Ag),r=e*Eg;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},zg=Math.sin(pg/10)/Math.sin(7*pg/10),Pg=Math.sin(vg/10)*zg,Rg=-Math.cos(vg/10)*zg,Lg={draw:function(t,n){var e=Math.sqrt(.8908130915292852*n),r=Pg*e,i=Rg*e;t.moveTo(0,-e),t.lineTo(r,i);for(var o=1;o<5;++o){var u=vg*o/5,a=Math.cos(u),c=Math.sin(u);t.lineTo(c*e,-a*e),t.lineTo(a*r-c*i,c*r+a*i)}t.closePath()}},qg={draw:function(t,n){var e=Math.sqrt(n),r=-e/2;t.rect(r,r,e,e)}},Ug=Math.sqrt(3),Dg={draw:function(t,n){var e=-Math.sqrt(n/(3*Ug));t.moveTo(0,2*e),t.lineTo(-Ug*e,-e),t.lineTo(Ug*e,-e),t.closePath()}},Og=-.5,Fg=Math.sqrt(3)/2,Ig=1/Math.sqrt(12),Yg=3*(Ig/2+1),Bg={draw:function(t,n){var e=Math.sqrt(n/Yg),r=e/2,i=e*Ig,o=r,u=e*Ig+e,a=-o,c=u;t.moveTo(r,i),t.lineTo(o,u),t.lineTo(a,c),t.lineTo(Og*r-Fg*i,Fg*r+Og*i),t.lineTo(Og*o-Fg*u,Fg*o+Og*u),t.lineTo(Og*a-Fg*c,Fg*a+Og*c),t.lineTo(Og*r+Fg*i,Og*i-Fg*r),t.lineTo(Og*o+Fg*u,Og*u-Fg*o),t.lineTo(Og*a+Fg*c,Og*c-Fg*a),t.closePath()}},jg=[Ng,Sg,Cg,qg,Lg,Dg,Bg],Hg=function(){};Ja.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Ga(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Ga(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};Qa.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Ga(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};Ka.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Ga(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};tc.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],u=t[e]-i,a=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*u),this._beta*n[c]+(1-this._beta)*(o+r*a));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var Xg=function t(n){function e(t){return 1===n?new Ja(t):new tc(t,n)}return e.beta=function(n){return t(+n)},e}(.85);ec.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:nc(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:nc(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var $g=function t(n){function e(t){return new ec(t,n)}return e.tension=function(n){return t(+n)},e}(0);rc.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:nc(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Vg=function t(n){function e(t){return new rc(t,n)}return e.tension=function(n){return t(+n)},e}(0);ic.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:nc(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Wg=function t(n){function e(t){return new ic(t,n)}return e.tension=function(n){return t(+n)},e}(0);uc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:oc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Zg=function t(n){function e(t){return n?new uc(t,n):new ec(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);ac.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:oc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Gg=function t(n){function e(t){return n?new ac(t,n):new rc(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);cc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:oc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Jg=function t(n){function e(t){return n?new cc(t,n):new ic(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);sc.prototype={areaStart:Hg,areaEnd:Hg,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}};dc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:pc(this,this._t0,hc(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,pc(this,hc(this,e=lc(this,t,n)),e);break;default:pc(this,this._t0,e=lc(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(vc.prototype=Object.create(dc.prototype)).point=function(t,n){dc.prototype.point.call(this,n,t)},_c.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},yc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=gc(t),i=gc(n),o=0,u=1;u<e;++o,++u)this._context.bezierCurveTo(r[0][o],i[0][o],r[1][o],i[1][o],t[u],n[u]);(this._line||0!==this._line&&1===e)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,n){this._x.push(+t),this._y.push(+n)}};mc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var Qg=function(t,n){if((i=t.length)>1)for(var e,r,i,o=1,u=t[n[0]],a=u.length;o<i;++o)for(r=u,u=t[n[o]],e=0;e<a;++e)u[e][1]+=u[e][0]=isNaN(r[e][1])?r[e][0]:r[e][1]},Kg=function(t){for(var n=t.length,e=new Array(n);--n>=0;)e[n]=n;return e},tm=function(t){var n=t.map(bc);return Kg(t).sort(function(t,e){return n[t]-n[e]})},nm=function(t){return function(){return t}};Tc.prototype={constructor:Tc,insert:function(t,n){var e,r,i;if(t){if(n.P=t,n.N=t.N,t.N&&(t.N.P=n),t.N=n,t.R){for(t=t.R;t.L;)t=t.L;t.L=n}else t.R=n;e=t}else this._?(t=Ec(this._),n.P=null,n.N=t,t.P=t.L=n,e=t):(n.P=n.N=null,this._=n,e=null);for(n.L=n.R=null,n.U=e,n.C=!0,t=n;e&&e.C;)e===(r=e.U).L?(i=r.R)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.R&&(Nc(this,e),e=(t=e).U),e.C=!1,r.C=!0,Sc(this,r)):(i=r.L)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.L&&(Sc(this,e),e=(t=e).U),e.C=!1,r.C=!0,Nc(this,r)),e=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var n,e,r,i=t.U,o=t.L,u=t.R;if(e=o?u?Ec(u):o:u,i?i.L===t?i.L=e:i.R=e:this._=e,o&&u?(r=e.C,e.C=t.C,e.L=o,o.U=e,e!==u?(i=e.U,e.U=t.U,t=e.R,i.L=t,e.R=u,u.U=e):(e.U=i,i=e,t=e.R)):(r=t.C,t=e),t&&(t.U=i),!r)if(t&&t.C)t.C=!1;else{do{if(t===this._)break;if(t===i.L){if((n=i.R).C&&(n.C=!1,i.C=!0,Nc(this,i),n=i.R),n.L&&n.L.C||n.R&&n.R.C){n.R&&n.R.C||(n.L.C=!1,n.C=!0,Sc(this,n),n=i.R),n.C=i.C,i.C=n.R.C=!1,Nc(this,i),t=this._;break}}else if((n=i.L).C&&(n.C=!1,i.C=!0,Sc(this,i),n=i.L),n.L&&n.L.C||n.R&&n.R.C){n.L&&n.L.C||(n.R.C=!1,n.C=!0,Nc(this,n),n=i.L),n.C=i.C,i.C=n.L.C=!1,Sc(this,i),t=this._;break}n.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};var em,rm,im,om,um,am=[],cm=[],sm=1e-6,fm=1e-12;Kc.prototype={constructor:Kc,polygons:function(){var t=this.edges;return this.cells.map(function(n){var e=n.halfedges.map(function(e){return Dc(n,t[e])});return e.data=n.site.data,e})},triangles:function(){var t=[],n=this.edges;return this.cells.forEach(function(e,r){if(o=(i=e.halfedges).length)for(var i,o,u,a=e.site,c=-1,s=n[i[o-1]],f=s.left===a?s.right:s.left;++c<o;)u=f,f=(s=n[i[c]]).left===a?s.right:s.left,u&&f&&r<u.index&&r<f.index&&Jc(a,u,f)<0&&t.push([a.data,u.data,f.data])}),t},links:function(){return this.edges.filter(function(t){return t.right}).map(function(t){return{source:t.left.data,target:t.right.data}})},find:function(t,n,e){for(var r,i,o=this,u=o._found||0,a=o.cells.length;!(i=o.cells[u]);)if(++u>=a)return null;var c=t-i.site[0],s=n-i.site[1],f=c*c+s*s;do{i=o.cells[r=u],u=null,i.halfedges.forEach(function(e){var r=o.edges[e],a=r.left;if(a!==i.site&&a||(a=r.right)){var c=t-a[0],s=n-a[1],l=c*c+s*s;l<f&&(f=l,u=a.index)}})}while(null!==u);return o._found=r,null==e||f<=e*e?i.site:null}};var lm=function(t){return function(){return t}};ns.prototype={constructor:ns,scale:function(t){return 1===t?this:new ns(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new ns(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var hm=new ns(1,0,0);es.prototype=ns.prototype;var pm=function(){t.event.preventDefault(),t.event.stopImmediatePropagation()};t.version="4.10.0",t.bisect=hs,t.bisectRight=hs,t.bisectLeft=ps,t.ascending=ss,t.bisector=fs,t.cross=function(t,n,r){var i,o,u,a,c=t.length,s=n.length,f=new Array(c*s);for(null==r&&(r=e),i=u=0;i<c;++i)for(a=t[i],o=0;o<s;++o,++u)f[u]=r(a,n[o]);return f},t.descending=function(t,n){return n<t?-1:n>t?1:n>=t?0:NaN},t.deviation=_s,t.extent=ys,t.histogram=function(){function t(t){var o,u,a=t.length,c=new Array(a);for(o=0;o<a;++o)c[o]=n(t[o],o,t);var s=e(c),f=s[0],l=s[1],h=r(c,f,l);Array.isArray(h)||(h=i(f,l,h),h=Ms(Math.ceil(f/h)*h,Math.floor(l/h)*h,h));for(var p=h.length;h[0]<=f;)h.shift(),--p;for(;h[p-1]>l;)h.pop(),--p;var d,v=new Array(p+1);for(o=0;o<=p;++o)(d=v[o]=[]).x0=o>0?h[o-1]:f,d.x1=o<p?h[o]:l;for(o=0;o<a;++o)f<=(u=c[o])&&u<=l&&v[hs(h,u,0,p)].push(t[o]);return v}var n=ws,e=ys,r=Es;return t.value=function(e){return arguments.length?(n="function"==typeof e?e:bs(e),t):n},t.domain=function(n){return arguments.length?(e="function"==typeof n?n:bs([n[0],n[1]]),t):e},t.thresholds=function(n){return arguments.length?(r="function"==typeof n?n:bs(Array.isArray(n)?ms.call(n):n),t):r},t},t.thresholdFreedmanDiaconis=function(t,n,e){return t=xs.call(t,ds).sort(ss),Math.ceil((e-n)/(2*(As(t,.75)-As(t,.25))*Math.pow(t.length,-1/3)))},t.thresholdScott=function(t,n,e){return Math.ceil((e-n)/(3.5*_s(t)*Math.pow(t.length,-1/3)))},t.thresholdSturges=Es,t.max=function(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o<i;)if(null!=(e=t[o])&&e>=e)for(r=e;++o<i;)null!=(e=t[o])&&e>r&&(r=e)}else for(;++o<i;)if(null!=(e=n(t[o],o,t))&&e>=e)for(r=e;++o<i;)null!=(e=n(t[o],o,t))&&e>r&&(r=e);return r},t.mean=function(t,n){var e,r=t.length,i=r,o=-1,u=0;if(null==n)for(;++o<r;)isNaN(e=ds(t[o]))?--i:u+=e;else for(;++o<r;)isNaN(e=ds(n(t[o],o,t)))?--i:u+=e;if(i)return u/i},t.median=function(t,n){var e,r=t.length,i=-1,o=[];if(null==n)for(;++i<r;)isNaN(e=ds(t[i]))||o.push(e);else for(;++i<r;)isNaN(e=ds(n(t[i],i,t)))||o.push(e);return As(o.sort(ss),.5)},t.merge=Cs,t.min=zs,t.pairs=function(t,n){null==n&&(n=e);for(var r=0,i=t.length-1,o=t[0],u=new Array(i<0?0:i);r<i;)u[r]=n(o,o=t[++r]);return u},t.permute=function(t,n){for(var e=n.length,r=new Array(e);e--;)r[e]=t[n[e]];return r},t.quantile=As,t.range=Ms,t.scan=function(t,n){if(e=t.length){var e,r,i=0,o=0,u=t[o];for(null==n&&(n=ss);++i<e;)(n(r=t[i],u)<0||0!==n(u,u))&&(u=r,o=i);return 0===n(u,u)?o:void 0}},t.shuffle=function(t,n,e){for(var r,i,o=(null==e?t.length:e)-(n=null==n?0:+n);o;)i=Math.random()*o--|0,r=t[o+n],t[o+n]=t[i+n],t[i+n]=r;return t},t.sum=function(t,n){var e,r=t.length,i=-1,o=0;if(null==n)for(;++i<r;)(e=+t[i])&&(o+=e);else for(;++i<r;)(e=+n(t[i],i,t))&&(o+=e);return o},t.ticks=Ss,t.tickIncrement=r,t.tickStep=i,t.transpose=Ps,t.variance=vs,t.zip=function(){return Ps(arguments)},t.axisTop=function(t){return l(qs,t)},t.axisRight=function(t){return l(Us,t)},t.axisBottom=function(t){return l(Ds,t)},t.axisLeft=function(t){return l(Os,t)},t.brush=function(){return he(Sh)},t.brushX=function(){return he(kh)},t.brushY=function(){return he(Nh)},t.brushSelection=function(t){var n=t.__brush;return n?n.dim.output(n.selection):null},t.chord=function(){function t(t){var o,u,a,c,s,f,l=t.length,h=[],p=Ms(l),d=[],v=[],_=v.groups=new Array(l),y=new Array(l*l);for(o=0,s=-1;++s<l;){for(u=0,f=-1;++f<l;)u+=t[s][f];h.push(u),d.push(Ms(l)),o+=u}for(e&&p.sort(function(t,n){return e(h[t],h[n])}),r&&d.forEach(function(n,e){n.sort(function(n,i){return r(t[e][n],t[e][i])})}),c=(o=Oh(0,Dh-n*l)/o)?n:Dh/l,u=0,s=-1;++s<l;){for(a=u,f=-1;++f<l;){var g=p[s],m=d[g][f],x=t[g][m],b=u,w=u+=x*o;y[m*l+g]={index:g,subindex:m,startAngle:b,endAngle:w,value:x}}_[g]={index:g,startAngle:a,endAngle:u,value:h[g]},u+=c}for(s=-1;++s<l;)for(f=s-1;++f<l;){var M=y[f*l+s],T=y[s*l+f];(M.value||T.value)&&v.push(M.value<T.value?{source:T,target:M}:{source:M,target:T})}return i?v.sort(i):v}var n=0,e=null,r=null,i=null;return t.padAngle=function(e){return arguments.length?(n=Oh(0,e),t):n},t.sortGroups=function(n){return arguments.length?(e=n,t):e},t.sortSubgroups=function(n){return arguments.length?(r=n,t):r},t.sortChords=function(n){return arguments.length?(null==n?i=null:(i=pe(n))._=n,t):i&&i._},t},t.ribbon=function(){function t(){var t,a=Fh.call(arguments),c=n.apply(this,a),s=e.apply(this,a),f=+r.apply(this,(a[0]=c,a)),l=i.apply(this,a)-Uh,h=o.apply(this,a)-Uh,p=f*Rh(l),d=f*Lh(l),v=+r.apply(this,(a[0]=s,a)),_=i.apply(this,a)-Uh,y=o.apply(this,a)-Uh;if(u||(u=t=ve()),u.moveTo(p,d),u.arc(0,0,f,l,h),l===_&&h===y||(u.quadraticCurveTo(0,0,v*Rh(_),v*Lh(_)),u.arc(0,0,v,_,y)),u.quadraticCurveTo(0,0,p,d),u.closePath(),t)return u=null,t+""||null}var n=_e,e=ye,r=ge,i=me,o=xe,u=null;return t.radius=function(n){return arguments.length?(r="function"==typeof n?n:Ih(+n),t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:Ih(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:Ih(+n),t):o},t.source=function(e){return arguments.length?(n=e,t):n},t.target=function(n){return arguments.length?(e=n,t):e},t.context=function(n){return arguments.length?(u=null==n?null:n,t):u},t},t.nest=function(){function t(n,i,u,a){if(i>=o.length)return null!=e&&n.sort(e),null!=r?r(n):n;for(var c,s,f,l=-1,h=n.length,p=o[i++],d=we(),v=u();++l<h;)(f=d.get(c=p(s=n[l])+""))?f.push(s):d.set(c,[s]);return d.each(function(n,e){a(v,e,t(n,i,u,a))}),v}function n(t,e){if(++e>o.length)return t;var i,a=u[e-1];return null!=r&&e>=o.length?i=t.entries():(i=[],t.each(function(t,r){i.push({key:r,values:n(t,e)})})),null!=a?i.sort(function(t,n){return a(t.key,n.key)}):i}var e,r,i,o=[],u=[];return i={object:function(n){return t(n,0,Me,Te)},map:function(n){return t(n,0,ke,Ne)},entries:function(e){return n(t(e,0,ke,Ne),0)},key:function(t){return o.push(t),i},sortKeys:function(t){return u[o.length-1]=t,i},sortValues:function(t){return e=t,i},rollup:function(t){return r=t,i}}},t.set=Ee,t.map=we,t.keys=function(t){var n=[];for(var e in t)n.push(e);return n},t.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},t.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},t.color=Tt,t.rgb=Et,t.hsl=Pt,t.lab=Ut,t.hcl=jt,t.cubehelix=$t,t.dispatch=h,t.drag=function(){function n(t){t.on("mousedown.drag",e).filter(bt).on("touchstart.drag",o).on("touchmove.drag",u).on("touchend.drag touchcancel.drag",a).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(){if(!p&&d.apply(this,arguments)){var n=c("mouse",v.apply(this,arguments),Ks,this,arguments);n&&(cf(t.event.view).on("mousemove.drag",r,!0).on("mouseup.drag",i,!0),lf(t.event.view),vt(),l=!1,s=t.event.clientX,f=t.event.clientY,n("start"))}}function r(){if(ff(),!l){var n=t.event.clientX-s,e=t.event.clientY-f;l=n*n+e*e>x}y.mouse("drag")}function i(){cf(t.event.view).on("mousemove.drag mouseup.drag",null),_t(t.event.view,l),ff(),y.mouse("end")}function o(){if(d.apply(this,arguments)){var n,e,r=t.event.changedTouches,i=v.apply(this,arguments),o=r.length;for(n=0;n<o;++n)(e=c(r[n].identifier,i,sf,this,arguments))&&(vt(),e("start"))}}function u(){var n,e,r=t.event.changedTouches,i=r.length;for(n=0;n<i;++n)(e=y[r[n].identifier])&&(ff(),e("drag"))}function a(){var n,e,r=t.event.changedTouches,i=r.length;for(p&&clearTimeout(p),p=setTimeout(function(){p=null},500),n=0;n<i;++n)(e=y[r[n].identifier])&&(vt(),e("end"))}function c(e,r,i,o,u){var a,c,s,f=i(r,e),l=g.copy();if(N(new yt(n,"beforestart",a,e,m,f[0],f[1],0,0,l),function(){return null!=(t.event.subject=a=_.apply(o,u))&&(c=a.x-f[0]||0,s=a.y-f[1]||0,!0)}))return function t(h){var p,d=f;switch(h){case"start":y[e]=t,p=m++;break;case"end":delete y[e],--m;case"drag":f=i(r,e),p=m}N(new yt(n,h,a,e,p,f[0]+c,f[1]+s,f[0]-d[0],f[1]-d[1],l),l.apply,l,[h,o,u])}}var s,f,l,p,d=gt,v=mt,_=xt,y={},g=h("start","drag","end"),m=0,x=0;return n.filter=function(t){return arguments.length?(d="function"==typeof t?t:hf(!!t),n):d},n.container=function(t){return arguments.length?(v="function"==typeof t?t:hf(t),n):v},n.subject=function(t){return arguments.length?(_="function"==typeof t?t:hf(t),n):_},n.on=function(){var t=g.on.apply(g,arguments);return t===g?n:t},n.clickDistance=function(t){return arguments.length?(x=(t=+t)*t,n):Math.sqrt(x)},n},t.dragDisable=lf,t.dragEnable=_t,t.dsvFormat=Xh,t.csvParse=Vh,t.csvParseRows=Wh,t.csvFormat=Zh,t.csvFormatRows=Gh,t.tsvParse=Qh,t.tsvParseRows=Kh,t.tsvFormat=tp,t.tsvFormatRows=np,t.easeLinear=function(t){return+t},t.easeQuad=Kn,t.easeQuadIn=function(t){return t*t},t.easeQuadOut=function(t){return t*(2-t)},t.easeQuadInOut=Kn,t.easeCubic=te,t.easeCubicIn=function(t){return t*t*t},t.easeCubicOut=function(t){return--t*t*t+1},t.easeCubicInOut=te,t.easePoly=Gl,t.easePolyIn=Wl,t.easePolyOut=Zl,t.easePolyInOut=Gl,t.easeSin=ne,t.easeSinIn=function(t){return 1-Math.cos(t*Ql)},t.easeSinOut=function(t){return Math.sin(t*Ql)},t.easeSinInOut=ne,t.easeExp=ee,t.easeExpIn=function(t){return Math.pow(2,10*t-10)},t.easeExpOut=function(t){return 1-Math.pow(2,-10*t)},t.easeExpInOut=ee,t.easeCircle=re,t.easeCircleIn=function(t){return 1-Math.sqrt(1-t*t)},t.easeCircleOut=function(t){return Math.sqrt(1- --t*t)},t.easeCircleInOut=re,t.easeBounce=ie,t.easeBounceIn=function(t){return 1-ie(1-t)},t.easeBounceOut=ie,t.easeBounceInOut=function(t){return((t*=2)<=1?1-ie(1-t):ie(t-1)+1)/2},t.easeBack=lh,t.easeBackIn=sh,t.easeBackOut=fh,t.easeBackInOut=lh,t.easeElastic=dh,t.easeElasticIn=ph,t.easeElasticOut=dh,t.easeElasticInOut=vh,t.forceCenter=function(t,n){function e(){var e,i,o=r.length,u=0,a=0;for(e=0;e<o;++e)u+=(i=r[e]).x,a+=i.y;for(u=u/o-t,a=a/o-n,e=0;e<o;++e)(i=r[e]).x-=u,i.y-=a}var r;return null==t&&(t=0),null==n&&(n=0),e.initialize=function(t){r=t},e.x=function(n){return arguments.length?(t=+n,e):t},e.y=function(t){return arguments.length?(n=+t,e):n},e},t.forceCollide=function(t){function n(){for(var t,n,r,c,s,f,l,h=i.length,p=0;p<a;++p)for(n=qe(i,Oe,Fe).visitAfter(e),t=0;t<h;++t)r=i[t],f=o[r.index],l=f*f,c=r.x+r.vx,s=r.y+r.vy,n.visit(function(t,n,e,i,o){var a=t.data,h=t.r,p=f+h;if(!a)return n>c+p||i<c-p||e>s+p||o<s-p;if(a.index>r.index){var d=c-a.x-a.vx,v=s-a.y-a.vy,_=d*d+v*v;_<p*p&&(0===d&&(d=rp(),_+=d*d),0===v&&(v=rp(),_+=v*v),_=(p-(_=Math.sqrt(_)))/_*u,r.vx+=(d*=_)*(p=(h*=h)/(l+h)),r.vy+=(v*=_)*p,a.vx-=d*(p=1-p),a.vy-=v*p)}})}function e(t){if(t.data)return t.r=o[t.data.index];for(var n=t.r=0;n<4;++n)t[n]&&t[n].r>t.r&&(t.r=t[n].r)}function r(){if(i){var n,e,r=i.length;for(o=new Array(r),n=0;n<r;++n)e=i[n],o[e.index]=+t(e,n,i)}}var i,o,u=1,a=1;return"function"!=typeof t&&(t=ep(null==t?1:+t)),n.initialize=function(t){i=t,r()},n.iterations=function(t){return arguments.length?(a=+t,n):a},n.strength=function(t){return arguments.length?(u=+t,n):u},n.radius=function(e){return arguments.length?(t="function"==typeof e?e:ep(+e),r(),n):t},n},t.forceLink=function(t){function n(n){for(var e=0,r=t.length;e<p;++e)for(var i,a,c,f,l,h,d,v=0;v<r;++v)a=(i=t[v]).source,f=(c=i.target).x+c.vx-a.x-a.vx||rp(),l=c.y+c.vy-a.y-a.vy||rp(),f*=h=((h=Math.sqrt(f*f+l*l))-u[v])/h*n*o[v],l*=h,c.vx-=f*(d=s[v]),c.vy-=l*d,a.vx+=f*(d=1-d),a.vy+=l*d}function e(){if(a){var n,e,l=a.length,h=t.length,p=we(a,f);for(n=0,c=new Array(l);n<h;++n)(e=t[n]).index=n,"object"!=typeof e.source&&(e.source=Ye(p,e.source)),"object"!=typeof e.target&&(e.target=Ye(p,e.target)),c[e.source.index]=(c[e.source.index]||0)+1,c[e.target.index]=(c[e.target.index]||0)+1;for(n=0,s=new Array(h);n<h;++n)e=t[n],s[n]=c[e.source.index]/(c[e.source.index]+c[e.target.index]);o=new Array(h),r(),u=new Array(h),i()}}function r(){if(a)for(var n=0,e=t.length;n<e;++n)o[n]=+l(t[n],n,t)}function i(){if(a)for(var n=0,e=t.length;n<e;++n)u[n]=+h(t[n],n,t)}var o,u,a,c,s,f=Ie,l=function(t){return 1/Math.min(c[t.source.index],c[t.target.index])},h=ep(30),p=1;return null==t&&(t=[]),n.initialize=function(t){a=t,e()},n.links=function(r){return arguments.length?(t=r,e(),n):t},n.id=function(t){return arguments.length?(f=t,n):f},n.iterations=function(t){return arguments.length?(p=+t,n):p},n.strength=function(t){return arguments.length?(l="function"==typeof t?t:ep(+t),r(),n):l},n.distance=function(t){return arguments.length?(h="function"==typeof t?t:ep(+t),i(),n):h},n},t.forceManyBody=function(){function t(t){var n,a=i.length,c=qe(i,Be,je).visitAfter(e);for(u=t,n=0;n<a;++n)o=i[n],c.visit(r)}function n(){if(i){var t,n,e=i.length;for(a=new Array(e),t=0;t<e;++t)n=i[t],a[n.index]=+c(n,t,i)}}function e(t){var n,e,r,i,o,u=0;if(t.length){for(r=i=o=0;o<4;++o)(n=t[o])&&(e=n.value)&&(u+=e,r+=e*n.x,i+=e*n.y);t.x=r/u,t.y=i/u}else{(n=t).x=n.data.x,n.y=n.data.y;do{u+=a[n.data.index]}while(n=n.next)}t.value=u}function r(t,n,e,r){if(!t.value)return!0;var i=t.x-o.x,c=t.y-o.y,h=r-n,p=i*i+c*c;if(h*h/l<p)return p<f&&(0===i&&(i=rp(),p+=i*i),0===c&&(c=rp(),p+=c*c),p<s&&(p=Math.sqrt(s*p)),o.vx+=i*t.value*u/p,o.vy+=c*t.value*u/p),!0;if(!(t.length||p>=f)){(t.data!==o||t.next)&&(0===i&&(i=rp(),p+=i*i),0===c&&(c=rp(),p+=c*c),p<s&&(p=Math.sqrt(s*p)));do{t.data!==o&&(h=a[t.data.index]*u/p,o.vx+=i*h,o.vy+=c*h)}while(t=t.next)}}var i,o,u,a,c=ep(-30),s=1,f=1/0,l=.81;return t.initialize=function(t){i=t,n()},t.strength=function(e){return arguments.length?(c="function"==typeof e?e:ep(+e),n(),t):c},t.distanceMin=function(n){return arguments.length?(s=n*n,t):Math.sqrt(s)},t.distanceMax=function(n){return arguments.length?(f=n*n,t):Math.sqrt(f)},t.theta=function(n){return arguments.length?(l=n*n,t):Math.sqrt(l)},t},t.forceSimulation=function(t){function n(){e(),d.call("tick",o),u<a&&(p.stop(),d.call("end",o))}function e(){var n,e,r=t.length;for(u+=(s-u)*c,l.each(function(t){t(u)}),n=0;n<r;++n)null==(e=t[n]).fx?e.x+=e.vx*=f:(e.x=e.fx,e.vx=0),null==e.fy?e.y+=e.vy*=f:(e.y=e.fy,e.vy=0)}function r(){for(var n,e=0,r=t.length;e<r;++e){if(n=t[e],n.index=e,isNaN(n.x)||isNaN(n.y)){var i=ap*Math.sqrt(e),o=e*cp;n.x=i*Math.cos(o),n.y=i*Math.sin(o)}(isNaN(n.vx)||isNaN(n.vy))&&(n.vx=n.vy=0)}}function i(n){return n.initialize&&n.initialize(t),n}var o,u=1,a=.001,c=1-Math.pow(a,1/300),s=0,f=.6,l=we(),p=dn(n),d=h("tick","end");return null==t&&(t=[]),r(),o={tick:e,restart:function(){return p.restart(n),o},stop:function(){return p.stop(),o},nodes:function(n){return arguments.length?(t=n,r(),l.each(i),o):t},alpha:function(t){return arguments.length?(u=+t,o):u},alphaMin:function(t){return arguments.length?(a=+t,o):a},alphaDecay:function(t){return arguments.length?(c=+t,o):+c},alphaTarget:function(t){return arguments.length?(s=+t,o):s},velocityDecay:function(t){return arguments.length?(f=1-t,o):1-f},force:function(t,n){return arguments.length>1?(null==n?l.remove(t):l.set(t,i(n)),o):l.get(t)},find:function(n,e,r){var i,o,u,a,c,s=0,f=t.length;for(null==r?r=1/0:r*=r,s=0;s<f;++s)(u=(i=n-(a=t[s]).x)*i+(o=e-a.y)*o)<r&&(c=a,r=u);return c},on:function(t,n){return arguments.length>1?(d.on(t,n),o):d.on(t)}}},t.forceX=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)(n=r[e]).vx+=(o[e]-n.x)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=ep(.1);return"function"!=typeof t&&(t=ep(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:ep(+t),e(),n):u},n.x=function(r){return arguments.length?(t="function"==typeof r?r:ep(+r),e(),n):t},n},t.forceY=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)(n=r[e]).vy+=(o[e]-n.y)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=ep(.1);return"function"!=typeof t&&(t=ep(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:ep(+t),e(),n):u},n.y=function(r){return arguments.length?(t="function"==typeof r?r:ep(+r),e(),n):t},n},t.formatDefaultLocale=$e,t.formatLocale=mp,t.formatSpecifier=He,t.precisionFixed=xp,t.precisionPrefix=bp,t.precisionRound=wp,t.geoArea=function(t){return kd.reset(),Md(t,Nd),2*kd},t.geoBounds=function(t){var n,e,r,i,o,u,a;if(Pp=zp=-(Ap=Cp=1/0),Dp=[],Md(t,Ed),e=Dp.length){for(Dp.sort(br),n=1,o=[r=Dp[0]];n<e;++n)wr(r,(i=Dp[n])[0])||wr(r,i[1])?(xr(r[0],i[1])>xr(r[0],r[1])&&(r[1]=i[1]),xr(i[0],r[1])>xr(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-1/0,n=0,r=o[e=o.length-1];n<=e;r=i,++n)i=o[n],(a=xr(r[1],i[0]))>u&&(u=a,Ap=i[0],zp=r[1])}return Dp=Op=null,Ap===1/0||Cp===1/0?[[NaN,NaN],[NaN,NaN]]:[[Ap,Cp],[zp,Pp]]},t.geoCentroid=function(t){Fp=Ip=Yp=Bp=jp=Hp=Xp=$p=Vp=Wp=Zp=0,Md(t,Ad);var n=Vp,e=Wp,r=Zp,i=n*n+e*e+r*r;return i<1e-12&&(n=Hp,e=Xp,r=$p,Ip<ed&&(n=Yp,e=Bp,r=jp),(i=n*n+e*e+r*r)<1e-12)?[NaN,NaN]:[ld(e,n)*ad,Ge(r/md(i))*ad]},t.geoCircle=function(){function t(){var t=r.apply(this,arguments),a=i.apply(this,arguments)*cd,c=o.apply(this,arguments)*cd;return n=[],e=Lr(-t[0]*cd,-t[1]*cd,0).invert,Or(u,a,c,1),t={type:"Polygon",coordinates:[n]},n=e=null,t}var n,e,r=Cd([0,0]),i=Cd(90),o=Cd(6),u={point:function(t,r){n.push(t=e(t,r)),t[0]*=ad,t[1]*=ad}};return t.center=function(n){return arguments.length?(r="function"==typeof n?n:Cd([+n[0],+n[1]]),t):r},t.radius=function(n){return arguments.length?(i="function"==typeof n?n:Cd(+n),t):i},t.precision=function(n){return arguments.length?(o="function"==typeof n?n:Cd(+n),t):o},t},t.geoClipExtent=function(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=Br(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][1],o=+a[1][0],u=+a[1][1],t=n=null,e):[[r,i],[o,u]]}}},t.geoContains=function(t,n){return(t&&iv.hasOwnProperty(t.type)?iv[t.type]:$r)(t,n)},t.geoDistance=rv,t.geoGraticule=ti,t.geoGraticule10=function(){return ti()()},t.geoInterpolate=function(t,n){var e=t[0]*cd,r=t[1]*cd,i=n[0]*cd,o=n[1]*cd,u=hd(r),a=yd(r),c=hd(o),s=yd(o),f=u*hd(e),l=u*yd(e),h=c*hd(i),p=c*yd(i),d=2*Ge(md(Je(o-r)+u*c*Je(i-e))),v=yd(d),_=d?function(t){var n=yd(t*=d)/v,e=yd(d-t)/v,r=e*f+n*h,i=e*l+n*p,o=e*a+n*s;return[ld(i,r)*ad,ld(o,md(r*r+i*i))*ad]}:function(){return[e*ad,r*ad]};return _.distance=d,_},t.geoLength=tv,t.geoPath=function(t,n){function e(t){return t&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),Md(t,r(i))),i.result()}var r,i,o=4.5;return e.area=function(t){return Md(t,r(sv)),sv.result()},e.measure=function(t){return Md(t,r(zv)),zv.result()},e.bounds=function(t){return Md(t,r(dv)),dv.result()},e.centroid=function(t){return Md(t,r(Tv)),Tv.result()},e.projection=function(n){return arguments.length?(r=null==n?(t=null,uv):(t=n).stream,e):t},e.context=function(t){return arguments.length?(i=null==t?(n=null,new yi):new di(n=t),"function"!=typeof o&&i.pointRadius(o),e):n},e.pointRadius=function(t){return arguments.length?(o="function"==typeof t?t:(i.pointRadius(+t),+t),e):o},e.projection(t).context(n)},t.geoAlbers=Iv,t.geoAlbersUsa=function(){function t(t){var n=t[0],e=t[1];return a=null,i.point(n,e),a||(o.point(n,e),a)||(u.point(n,e),a)}function n(){return e=r=null,t}var e,r,i,o,u,a,c=Iv(),s=Fv().rotate([154,0]).center([-2,58.5]).parallels([55,65]),f=Fv().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,n){a=[t,n]}};return t.invert=function(t){var n=c.scale(),e=c.translate(),r=(t[0]-e[0])/n,i=(t[1]-e[1])/n;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?f:c).invert(t)},t.stream=function(t){return e&&r===t?e:e=Ri([c.stream(r=t),s.stream(t),f.stream(t)])},t.precision=function(t){return arguments.length?(c.precision(t),s.precision(t),f.precision(t),n()):c.precision()},t.scale=function(n){return arguments.length?(c.scale(n),s.scale(.35*n),f.scale(n),t.translate(c.translate())):c.scale()},t.translate=function(t){if(!arguments.length)return c.translate();var e=c.scale(),r=+t[0],a=+t[1];return i=c.translate(t).clipExtent([[r-.455*e,a-.238*e],[r+.455*e,a+.238*e]]).stream(l),o=s.translate([r-.307*e,a+.201*e]).clipExtent([[r-.425*e+ed,a+.12*e+ed],[r-.214*e-ed,a+.234*e-ed]]).stream(l),u=f.translate([r-.205*e,a+.212*e]).clipExtent([[r-.214*e+ed,a+.166*e+ed],[r-.115*e-ed,a+.234*e-ed]]).stream(l),n()},t.fitExtent=function(n,e){return Ti(t,n,e)},t.fitSize=function(n,e){return ki(t,n,e)},t.scale(1070)},t.geoAzimuthalEqualArea=function(){return Ei(Yv).scale(124.75).clipAngle(179.999)},t.geoAzimuthalEqualAreaRaw=Yv,t.geoAzimuthalEquidistant=function(){return Ei(Bv).scale(79.4188).clipAngle(179.999)},t.geoAzimuthalEquidistantRaw=Bv,t.geoConicConformal=function(){return Ci(Fi).scale(109.5).parallels([30,30])},t.geoConicConformalRaw=Fi,t.geoConicEqualArea=Fv,t.geoConicEqualAreaRaw=Pi,t.geoConicEquidistant=function(){return Ci(Yi).scale(131.154).center([0,13.9389])},t.geoConicEquidistantRaw=Yi,t.geoEquirectangular=function(){return Ei(Ii).scale(152.63)},t.geoEquirectangularRaw=Ii,t.geoGnomonic=function(){return Ei(Bi).scale(144.049).clipAngle(60)},t.geoGnomonicRaw=Bi,t.geoIdentity=function(){function t(){return i=o=null,u}var n,e,r,i,o,u,a=1,c=0,s=0,f=1,l=1,h=uv,p=null,d=uv;return u={stream:function(t){return i&&o===t?i:i=h(d(o=t))},clipExtent:function(i){return arguments.length?(d=null==i?(p=n=e=r=null,uv):Br(p=+i[0][0],n=+i[0][1],e=+i[1][0],r=+i[1][1]),t()):null==p?null:[[p,n],[e,r]]},scale:function(n){return arguments.length?(h=ji((a=+n)*f,a*l,c,s),t()):a},translate:function(n){return arguments.length?(h=ji(a*f,a*l,c=+n[0],s=+n[1]),t()):[c,s]},reflectX:function(n){return arguments.length?(h=ji(a*(f=n?-1:1),a*l,c,s),t()):f<0},reflectY:function(n){return arguments.length?(h=ji(a*f,a*(l=n?-1:1),c,s),t()):l<0},fitExtent:function(t,n){return Ti(u,t,n)},fitSize:function(t,n){return ki(u,t,n)}}},t.geoProjection=Ei,t.geoProjectionMutator=Ai,t.geoMercator=function(){return Di(Ui).scale(961/ud)},t.geoMercatorRaw=Ui,t.geoOrthographic=function(){return Ei(Hi).scale(249.5).clipAngle(90+ed)},t.geoOrthographicRaw=Hi,t.geoStereographic=function(){return Ei(Xi).scale(250).clipAngle(142)},t.geoStereographicRaw=Xi,t.geoTransverseMercator=function(){var t=Di($i),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):(t=n(),[t[1],-t[0]])},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):(t=e(),[t[0],t[1],t[2]-90])},e([0,0,90]).scale(159.155)},t.geoTransverseMercatorRaw=$i,t.geoRotation=jd,t.geoStream=Md,t.geoTransform=function(t){return{stream:wi(t)}},t.cluster=function(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=Wi(e),t.y=Gi(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=Qi(t),c=Ki(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=Vi,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},t.hierarchy=eo,t.pack=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(No(n)).eachAfter(So(i,.5)).eachBefore(Eo(1)):t.eachBefore(No(ko)).eachAfter(So(To,1)).eachAfter(So(i,t.r/Math.min(e,r))).eachBefore(Eo(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=To;return t.radius=function(e){return arguments.length?(n=wo(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:Xv(+n),t):i},t},t.packSiblings=function(t){return bo(t),t},t.packEnclose=Hv,t.partition=function(){function t(t){var u=t.height+1;return t.x0=t.y0=i,t.x1=e,t.y1=r/u,t.eachBefore(n(r,u)),o&&t.eachBefore($v),t}function n(t,n){return function(e){e.children&&Vv(e,e.x0,t*(e.depth+1)/n,e.x1,t*(e.depth+2)/n);var r=e.x0,o=e.y0,u=e.x1-i,a=e.y1-i;u<r&&(r=u=(r+u)/2),a<o&&(o=a=(o+a)/2),e.x0=r,e.y0=o,e.x1=u,e.y1=a}}var e=1,r=1,i=0,o=!1;return t.round=function(n){return arguments.length?(o=!!n,t):o},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i=+n,t):i},t},t.stratify=function(){function t(t){var r,i,o,u,a,c,s,f=t.length,l=new Array(f),h={};for(i=0;i<f;++i)r=t[i],a=l[i]=new uo(r),null!=(c=n(r,i,t))&&(c+="")&&(h[s=Wv+(a.id=c)]=s in h?Gv:a);for(i=0;i<f;++i)if(a=l[i],null!=(c=e(t[i],i,t))&&(c+="")){if(!(u=h[Wv+c]))throw new Error("missing: "+c);if(u===Gv)throw new Error("ambiguous: "+c);u.children?u.children.push(a):u.children=[a],a.parent=u}else{if(o)throw new Error("multiple roots");o=a}if(!o)throw new Error("no root");if(o.parent=Zv,o.eachBefore(function(t){t.depth=t.parent.depth+1,--f}).eachBefore(oo),o.parent=null,f>0)throw new Error("cycle");return o}var n=Ao,e=Co;return t.id=function(e){return arguments.length?(n=Mo(e),t):n},t.parentId=function(n){return arguments.length?(e=Mo(n),t):e},t},t.tree=function(){function t(t){var r=Oo(t);if(r.eachAfter(n),r.parent.m=-r.z,r.eachBefore(e),c)t.eachBefore(i);else{var s=t,f=t,l=t;t.eachBefore(function(t){t.x<s.x&&(s=t),t.x>f.x&&(f=t),t.depth>l.depth&&(l=t)});var h=s===f?1:o(s,f)/2,p=h-s.x,d=u/(f.x+h+p),v=a/(l.depth||1);t.eachBefore(function(t){t.x=(t.x+p)*d,t.y=t.depth*v})}return t}function n(t){var n=t.children,e=t.parent.children,i=t.i?e[t.i-1]:null;if(n){qo(t);var u=(n[0].z+n[n.length-1].z)/2;i?(t.z=i.z+o(t._,i._),t.m=t.z-u):t.z=u}else i&&(t.z=i.z+o(t._,i._));t.parent.A=r(t,i,t.parent.A||e[0])}function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function r(t,n,e){if(n){for(var r,i=t,u=t,a=n,c=i.parent.children[0],s=i.m,f=u.m,l=a.m,h=c.m;a=Ro(a),i=Po(i),a&&i;)c=Po(c),(u=Ro(u)).a=t,(r=a.z+l-i.z-s+o(a._,i._))>0&&(Lo(Uo(a,t,e),t,r),s+=r,f+=r),l+=a.m,s+=i.m,h+=c.m,f+=u.m;a&&!Ro(u)&&(u.t=a,u.m+=l-f),i&&!Po(c)&&(c.t=i,c.m+=s-h,e=t)}return e}function i(t){t.x*=u,t.y=t.depth*a}var o=zo,u=1,a=1,c=null;return t.separation=function(n){return arguments.length?(o=n,t):o},t.size=function(n){return arguments.length?(c=!1,u=+n[0],a=+n[1],t):c?null:[u,a]},t.nodeSize=function(n){return arguments.length?(c=!0,u=+n[0],a=+n[1],t):c?[u,a]:null},t},t.treemap=function(){function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),u=[0],r&&t.eachBefore($v),t}function n(t){var n=u[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),t.x0=r,t.y0=i,t.x1=o,t.y1=h,t.children&&(n=u[t.depth+1]=a(t)/2,r+=l(t)-n,i+=c(t)-n,o-=s(t)-n,h-=f(t)-n,o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),e(t,r,i,o,h))}var e=Kv,r=!1,i=1,o=1,u=[0],a=To,c=To,s=To,f=To,l=To;return t.round=function(n){return arguments.length?(r=!!n,t):r},t.size=function(n){return arguments.length?(i=+n[0],o=+n[1],t):[i,o]},t.tile=function(n){return arguments.length?(e=Mo(n),t):e},t.padding=function(n){return arguments.length?t.paddingInner(n).paddingOuter(n):t.paddingInner()},t.paddingInner=function(n){return arguments.length?(a="function"==typeof n?n:Xv(+n),t):a},t.paddingOuter=function(n){return arguments.length?t.paddingTop(n).paddingRight(n).paddingBottom(n).paddingLeft(n):t.paddingTop()},t.paddingTop=function(n){return arguments.length?(c="function"==typeof n?n:Xv(+n),t):c},t.paddingRight=function(n){return arguments.length?(s="function"==typeof n?n:Xv(+n),t):s},t.paddingBottom=function(n){return arguments.length?(f="function"==typeof n?n:Xv(+n),t):f},t.paddingLeft=function(n){return arguments.length?(l="function"==typeof n?n:Xv(+n),t):l},t},t.treemapBinary=function(t,n,e,r,i){function o(t,n,e,r,i,u,a){if(t>=n-1){var s=c[t];return s.x0=r,s.y0=i,s.x1=u,void(s.y1=a)}for(var l=f[t],h=e/2+l,p=t+1,d=n-1;p<d;){var v=p+d>>>1;f[v]<h?p=v+1:d=v}h-f[p-1]<f[p]-h&&t+1<p&&--p;var _=f[p]-l,y=e-_;if(u-r>a-i){var g=(r*y+u*_)/e;o(t,p,_,r,i,g,a),o(p,n,y,g,i,u,a)}else{var m=(i*y+a*_)/e;o(t,p,_,r,i,u,m),o(p,n,y,r,m,u,a)}}var u,a,c=t.children,s=c.length,f=new Array(s+1);for(f[0]=a=u=0;u<s;++u)f[u+1]=a+=c[u].value;o(0,s,t.value,n,e,r,i)},t.treemapDice=Vv,t.treemapSlice=Jv,t.treemapSliceDice=function(t,n,e,r,i){(1&t.depth?Jv:Vv)(t,n,e,r,i)},t.treemapSquarify=Kv,t.treemapResquarify=t_,t.interpolate=cl,t.interpolateArray=nl,t.interpolateBasis=Zf,t.interpolateBasisClosed=Gf,t.interpolateDate=el,t.interpolateNumber=rl,t.interpolateObject=il,t.interpolateRound=sl,t.interpolateString=al,t.interpolateTransformCss=pl,t.interpolateTransformSvg=dl,t.interpolateZoom=_l,t.interpolateRgb=Qf,t.interpolateRgbBasis=Kf,t.interpolateRgbBasisClosed=tl,t.interpolateHsl=yl,t.interpolateHslLong=gl,t.interpolateLab=function(t,n){var e=Kt((t=Ut(t)).l,(n=Ut(n)).l),r=Kt(t.a,n.a),i=Kt(t.b,n.b),o=Kt(t.opacity,n.opacity);return function(n){return t.l=e(n),t.a=r(n),t.b=i(n),t.opacity=o(n),t+""}},t.interpolateHcl=ml,t.interpolateHclLong=xl,t.interpolateCubehelix=bl,t.interpolateCubehelixLong=wl,t.quantize=function(t,n){for(var e=new Array(n),r=0;r<n;++r)e[r]=t(r/(n-1));return e},t.path=ve,t.polygonArea=function(t){for(var n,e=-1,r=t.length,i=t[r-1],o=0;++e<r;)n=i,i=t[e],o+=n[1]*i[0]-n[0]*i[1];return o/2},t.polygonCentroid=function(t){for(var n,e,r=-1,i=t.length,o=0,u=0,a=t[i-1],c=0;++r<i;)n=a,a=t[r],c+=e=n[0]*a[1]-a[0]*n[1],o+=(n[0]+a[0])*e,u+=(n[1]+a[1])*e;return c*=3,[o/c,u/c]},t.polygonHull=function(t){if((e=t.length)<3)return null;var n,e,r=new Array(e),i=new Array(e);for(n=0;n<e;++n)r[n]=[+t[n][0],+t[n][1],n];for(r.sort(Io),n=0;n<e;++n)i[n]=[r[n][0],-r[n][1]];var o=Yo(r),u=Yo(i),a=u[0]===o[0],c=u[u.length-1]===o[o.length-1],s=[];for(n=o.length-1;n>=0;--n)s.push(t[r[o[n]][2]]);for(n=+a;n<u.length-c;++n)s.push(t[r[u[n]][2]]);return s},t.polygonContains=function(t,n){for(var e,r,i=t.length,o=t[i-1],u=n[0],a=n[1],c=o[0],s=o[1],f=!1,l=0;l<i;++l)e=(o=t[l])[0],(r=o[1])>a!=s>a&&u<(c-e)*(a-r)/(s-r)+e&&(f=!f),c=e,s=r;return f},t.polygonLength=function(t){for(var n,e,r=-1,i=t.length,o=t[i-1],u=o[0],a=o[1],c=0;++r<i;)n=u,e=a,n-=u=(o=t[r])[0],e-=a=o[1],c+=Math.sqrt(n*n+e*e);return c},t.quadtree=qe,t.queue=Wo,t.randomUniform=o_,t.randomNormal=u_,t.randomLogNormal=a_,t.randomBates=s_,t.randomIrwinHall=c_,t.randomExponential=f_,t.request=l_,t.html=p_,t.json=d_,t.text=v_,t.xml=__,t.csv=g_,t.tsv=m_,t.scaleBand=Ko,t.scalePoint=function(){return tu(Ko().paddingInner(1))},t.scaleIdentity=fu,t.scaleLinear=su,t.scaleLog=yu,t.scaleOrdinal=Qo,t.scaleImplicit=M_,t.scalePow=mu,t.scaleSqrt=function(){return mu().exponent(.5)},t.scaleQuantile=xu,t.scaleQuantize=bu,t.scaleThreshold=wu,t.scaleTime=function(){return Na(oy,ry,j_,Y_,F_,D_,q_,z_,t.timeFormat).domain([new Date(2e3,0,1),new Date(2e3,0,2)])},t.scaleUtc=function(){return Na(Ay,Sy,py,ly,sy,ay,q_,z_,t.utcFormat).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)])},t.schemeCategory10=$y,t.schemeCategory20b=Vy,t.schemeCategory20c=Wy,t.schemeCategory20=Zy,t.interpolateCubehelixDefault=Gy,t.interpolateRainbow=function(t){(t<0||t>1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return Ky.h=360*t-100,Ky.s=1.5-1.5*n,Ky.l=.8-.9*n,Ky+""},t.interpolateWarm=Jy,t.interpolateCool=Qy,t.interpolateViridis=tg,t.interpolateMagma=ng,t.interpolateInferno=eg,t.interpolatePlasma=rg,t.scaleSequential=Ea,t.creator=Hs,t.local=m,t.matcher=Zs,t.mouse=Ks,t.namespace=js,t.namespaces=Bs,t.select=cf,t.selectAll=function(t){return"string"==typeof t?new pt([document.querySelectorAll(t)],[document.documentElement]):new pt([null==t?[]:t],af)},t.selection=dt,t.selector=tf,t.selectorAll=nf,t.style=B,t.touch=sf,t.touches=function(t,n){null==n&&(n=Js().touches);for(var e=0,r=n?n.length:0,i=new Array(r);e<r;++e)i[e]=Qs(t,n[e]);return i},t.window=uf,t.customEvent=N,t.arc=function(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-dg,p=u.apply(this,arguments)-dg,d=og(p-h),v=p>h;if(c||(c=t=ve()),l<f&&(s=l,l=f,f=s),l>hg)if(d>vg-hg)c.moveTo(l*ag(h),l*fg(h)),c.arc(0,0,l,h,p,!v),f>hg&&(c.moveTo(f*ag(p),f*fg(p)),c.arc(0,0,f,p,h,v));else{var _,y,g=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,k=T>hg&&(i?+i.apply(this,arguments):lg(f*f+l*l)),N=sg(og(l-f)/2,+r.apply(this,arguments)),S=N,E=N;if(k>hg){var A=Ca(k/f*fg(T)),C=Ca(k/l*fg(T));(w-=2*A)>hg?(A*=v?1:-1,x+=A,b-=A):(w=0,x=b=(h+p)/2),(M-=2*C)>hg?(C*=v?1:-1,g+=C,m-=C):(M=0,g=m=(h+p)/2)}var z=l*ag(g),P=l*fg(g),R=f*ag(b),L=f*fg(b);if(N>hg){var q=l*ag(m),U=l*fg(m),D=f*ag(x),O=f*fg(x);if(d<pg){var F=w>hg?Ua(z,P,D,O,q,U,R,L):[R,L],I=z-F[0],Y=P-F[1],B=q-F[0],j=U-F[1],H=1/fg(Aa((I*B+Y*j)/(lg(I*I+Y*Y)*lg(B*B+j*j)))/2),X=lg(F[0]*F[0]+F[1]*F[1]);S=sg(N,(f-X)/(H-1)),E=sg(N,(l-X)/(H+1))}}M>hg?E>hg?(_=Da(D,O,z,P,l,E,v),y=Da(q,U,R,L,l,E,v),c.moveTo(_.cx+_.x01,_.cy+_.y01),E<N?c.arc(_.cx,_.cy,E,ug(_.y01,_.x01),ug(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,E,ug(_.y01,_.x01),ug(_.y11,_.x11),!v),c.arc(0,0,l,ug(_.cy+_.y11,_.cx+_.x11),ug(y.cy+y.y11,y.cx+y.x11),!v),c.arc(y.cx,y.cy,E,ug(y.y11,y.x11),ug(y.y01,y.x01),!v))):(c.moveTo(z,P),c.arc(0,0,l,g,m,!v)):c.moveTo(z,P),f>hg&&w>hg?S>hg?(_=Da(R,L,q,U,f,-S,v),y=Da(z,P,D,O,f,-S,v),c.lineTo(_.cx+_.x01,_.cy+_.y01),S<N?c.arc(_.cx,_.cy,S,ug(_.y01,_.x01),ug(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,S,ug(_.y01,_.x01),ug(_.y11,_.x11),!v),c.arc(0,0,f,ug(_.cy+_.y11,_.cx+_.x11),ug(y.cy+y.y11,y.cx+y.x11),v),c.arc(y.cx,y.cy,S,ug(y.y11,y.x11),ug(y.y01,y.x01),!v))):c.arc(0,0,f,b,x,v):c.lineTo(R,L)}else c.moveTo(0,0);if(c.closePath(),t)return c=null,t+""||null}var n=za,e=Pa,r=ig(0),i=null,o=Ra,u=La,a=qa,c=null;return t.centroid=function(){var t=(+n.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+o.apply(this,arguments)+ +u.apply(this,arguments))/2-pg/2;return[ag(r)*t,fg(r)*t]},t.innerRadius=function(e){return arguments.length?(n="function"==typeof e?e:ig(+e),t):n},t.outerRadius=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.cornerRadius=function(n){return arguments.length?(r="function"==typeof n?n:ig(+n),t):r},t.padRadius=function(n){return arguments.length?(i=null==n?null:"function"==typeof n?n:ig(+n),t):i},t.startAngle=function(n){return arguments.length?(o="function"==typeof n?n:ig(+n),t):o},t.endAngle=function(n){return arguments.length?(u="function"==typeof n?n:ig(+n),t):u},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:ig(+n),t):a},t.context=function(n){return arguments.length?(c=null==n?null:n,t):c},t},t.area=gg,t.line=yg,t.pie=function(){function t(t){var a,c,s,f,l,h=t.length,p=0,d=new Array(h),v=new Array(h),_=+i.apply(this,arguments),y=Math.min(vg,Math.max(-vg,o.apply(this,arguments)-_)),g=Math.min(Math.abs(y)/h,u.apply(this,arguments)),m=g*(y<0?-1:1);for(a=0;a<h;++a)(l=v[d[a]=a]=+n(t[a],a,t))>0&&(p+=l);for(null!=e?d.sort(function(t,n){return e(v[t],v[n])}):null!=r&&d.sort(function(n,e){return r(t[n],t[e])}),a=0,s=p?(y-h*m)/p:0;a<h;++a,_=f)c=d[a],f=_+((l=v[c])>0?l*s:0)+m,v[c]={data:t[c],index:a,value:l,startAngle:_,endAngle:f,padAngle:g};return v}var n=xg,e=mg,r=null,i=ig(0),o=ig(vg),u=ig(0);return t.value=function(e){return arguments.length?(n="function"==typeof e?e:ig(+e),t):n},t.sortValues=function(n){return arguments.length?(e=n,r=null,t):e},t.sort=function(n){return arguments.length?(r=n,e=null,t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:ig(+n),t):o},t.padAngle=function(n){return arguments.length?(u="function"==typeof n?n:ig(+n),t):u},t},t.areaRadial=Mg,t.radialArea=Mg,t.lineRadial=wg,t.radialLine=wg,t.pointRadial=Tg,t.linkHorizontal=function(){return $a(Va)},t.linkVertical=function(){return $a(Wa)},t.linkRadial=function(){var t=$a(Za);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t},t.symbol=function(){function t(){var t;if(r||(r=t=ve()),n.apply(this,arguments).draw(r,+e.apply(this,arguments)),t)return r=null,t+""||null}var n=ig(Ng),e=ig(64),r=null;return t.type=function(e){return arguments.length?(n="function"==typeof e?e:ig(e),t):n},t.size=function(n){return arguments.length?(e="function"==typeof n?n:ig(+n),t):e},t.context=function(n){return arguments.length?(r=null==n?null:n,t):r},t},t.symbols=jg,t.symbolCircle=Ng,t.symbolCross=Sg,t.symbolDiamond=Cg,t.symbolSquare=qg,t.symbolStar=Lg,t.symbolTriangle=Dg,t.symbolWye=Bg,t.curveBasisClosed=function(t){return new Qa(t)},t.curveBasisOpen=function(t){return new Ka(t)},t.curveBasis=function(t){return new Ja(t)},t.curveBundle=Xg,t.curveCardinalClosed=Vg,t.curveCardinalOpen=Wg,t.curveCardinal=$g,t.curveCatmullRomClosed=Gg,t.curveCatmullRomOpen=Jg,t.curveCatmullRom=Zg,t.curveLinearClosed=function(t){return new sc(t)},t.curveLinear=_g,t.curveMonotoneX=function(t){return new dc(t)},t.curveMonotoneY=function(t){return new vc(t)},t.curveNatural=function(t){return new yc(t)},t.curveStep=function(t){return new mc(t,.5)},t.curveStepAfter=function(t){return new mc(t,1)},t.curveStepBefore=function(t){return new mc(t,0)},t.stack=function(){function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=new Array(s);for(o=0;o<s;++o){for(var l,h=a[o],p=f[o]=new Array(c),d=0;d<c;++d)p[d]=l=[0,+i(t[d],h,d,t)],l.data=t[d];p.key=h}for(o=0,u=e(f);o<s;++o)f[u[o]].index=o;return r(f,u),f}var n=ig([]),e=Kg,r=Qg,i=xc;return t.keys=function(e){return arguments.length?(n="function"==typeof e?e:ig(kg.call(e)),t):n},t.value=function(n){return arguments.length?(i="function"==typeof n?n:ig(+n),t):i},t.order=function(n){return arguments.length?(e=null==n?Kg:"function"==typeof n?n:ig(kg.call(n)),t):e},t.offset=function(n){return arguments.length?(r=null==n?Qg:n,t):r},t},t.stackOffsetExpand=function(t,n){if((r=t.length)>0){for(var e,r,i,o=0,u=t[0].length;o<u;++o){for(i=e=0;e<r;++e)i+=t[e][o][1]||0;if(i)for(e=0;e<r;++e)t[e][o][1]/=i}Qg(t,n)}},t.stackOffsetDiverging=function(t,n){if((a=t.length)>1)for(var e,r,i,o,u,a,c=0,s=t[n[0]].length;c<s;++c)for(o=u=0,e=0;e<a;++e)(i=(r=t[n[e]][c])[1]-r[0])>=0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=u,r[0]=u+=i):r[0]=o},t.stackOffsetNone=Qg,t.stackOffsetSilhouette=function(t,n){if((e=t.length)>0){for(var e,r=0,i=t[n[0]],o=i.length;r<o;++r){for(var u=0,a=0;u<e;++u)a+=t[u][r][1]||0;i[r][1]+=i[r][0]=-a/2}Qg(t,n)}},t.stackOffsetWiggle=function(t,n){if((i=t.length)>0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,u=1;u<r;++u){for(var a=0,c=0,s=0;a<i;++a){for(var f=t[n[a]],l=f[u][1]||0,h=(l-(f[u-1][1]||0))/2,p=0;p<a;++p){var d=t[n[p]];h+=(d[u][1]||0)-(d[u-1][1]||0)}c+=l,s+=h*l}e[u-1][1]+=e[u-1][0]=o,c&&(o-=s/c)}e[u-1][1]+=e[u-1][0]=o,Qg(t,n)}},t.stackOrderAscending=tm,t.stackOrderDescending=function(t){return tm(t).reverse()},t.stackOrderInsideOut=function(t){var n,e,r=t.length,i=t.map(bc),o=Kg(t).sort(function(t,n){return i[n]-i[t]}),u=0,a=0,c=[],s=[];for(n=0;n<r;++n)e=o[n],u<a?(u+=i[e],c.push(e)):(a+=i[e],s.push(e));return s.reverse().concat(c)},t.stackOrderNone=Kg,t.stackOrderReverse=function(t){return Kg(t).reverse()},t.timeInterval=Mu,t.timeMillisecond=z_,t.timeMilliseconds=P_,t.utcMillisecond=z_,t.utcMilliseconds=P_,t.timeSecond=q_,t.timeSeconds=U_,t.utcSecond=q_,t.utcSeconds=U_,t.timeMinute=D_,t.timeMinutes=O_,t.timeHour=F_,t.timeHours=I_,t.timeDay=Y_,t.timeDays=B_,t.timeWeek=j_,t.timeWeeks=G_,t.timeSunday=j_,t.timeSundays=G_,t.timeMonday=H_,t.timeMondays=J_,t.timeTuesday=X_,t.timeTuesdays=Q_,t.timeWednesday=$_,t.timeWednesdays=K_,t.timeThursday=V_,t.timeThursdays=ty,t.timeFriday=W_,t.timeFridays=ny,t.timeSaturday=Z_,t.timeSaturdays=ey,t.timeMonth=ry,t.timeMonths=iy,t.timeYear=oy,t.timeYears=uy,t.utcMinute=ay,t.utcMinutes=cy,t.utcHour=sy,t.utcHours=fy,t.utcDay=ly,t.utcDays=hy,t.utcWeek=py,t.utcWeeks=xy,t.utcSunday=py,t.utcSundays=xy,t.utcMonday=dy,t.utcMondays=by,t.utcTuesday=vy,t.utcTuesdays=wy,t.utcWednesday=_y,t.utcWednesdays=My,t.utcThursday=yy,t.utcThursdays=Ty,t.utcFriday=gy,t.utcFridays=ky,t.utcSaturday=my,t.utcSaturdays=Ny,t.utcMonth=Sy,t.utcMonths=Ey,t.utcYear=Ay,t.utcYears=zy,t.timeFormatDefaultLocale=Ma,t.timeFormatLocale=Au,t.isoFormat=Uy,t.isoParse=Dy,t.now=ln,t.timer=dn,t.timerFlush=vn,t.timeout=Pl,t.interval=function(t,n,e){var r=new pn,i=n;return null==n?(r.restart(t,n,e),r):(n=+n,e=null==e?ln():+e,r.restart(function o(u){u+=i,r.restart(o,i+=n,e),t(u)},n,e),r)},t.transition=Jn,t.active=function(t,n){var e,r,i=t.__transition;if(i){n=null==n?null:n+"";for(r in i)if((e=i[r]).state>Ul&&e.name===n)return new Gn([[t]],yh,n,+r)}return null},t.interrupt=jl,t.voronoi=function(){function t(t){return new Kc(t.map(function(r,i){var o=[Math.round(n(r,i,t)/sm)*sm,Math.round(e(r,i,t)/sm)*sm];return o.index=i,o.data=r,o}),r)}var n=wc,e=Mc,r=null;return t.polygons=function(n){return t(n).polygons()},t.links=function(n){return t(n).links()},t.triangles=function(n){return t(n).triangles()},t.x=function(e){return arguments.length?(n="function"==typeof e?e:nm(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:nm(+n),t):e},t.extent=function(n){return arguments.length?(r=null==n?null:[[+n[0][0],+n[0][1]],[+n[1][0],+n[1][1]]],t):r&&[[r[0][0],r[0][1]],[r[1][0],r[1][1]]]},t.size=function(n){return arguments.length?(r=null==n?null:[[0,0],[+n[0],+n[1]]],t):r&&[r[1][0]-r[0][0],r[1][1]-r[0][1]]},t},t.zoom=function(){function n(t){t.property("__zoom",us).on("wheel.zoom",s).on("mousedown.zoom",f).on("dblclick.zoom",l).filter(cs).on("touchstart.zoom",p).on("touchmove.zoom",d).on("touchend.zoom touchcancel.zoom",v).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(t,n){return(n=Math.max(b,Math.min(w,n)))===t.k?t:new ns(n,t.x,t.y)}function r(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new ns(t.k,r,i)}function i(t,n){var e=t.invertX(n[0][0])-M,r=t.invertX(n[1][0])-T,i=t.invertY(n[0][1])-k,o=t.invertY(n[1][1])-S;return t.translate(r>e?(e+r)/2:Math.min(0,e)||Math.max(0,r),o>i?(i+o)/2:Math.min(0,i)||Math.max(0,o))}function o(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function u(t,n,e){t.on("start.zoom",function(){a(this,arguments).start()}).on("interrupt.zoom end.zoom",function(){a(this,arguments).end()}).tween("zoom",function(){var t=this,r=arguments,i=a(t,r),u=m.apply(t,r),c=e||o(u),s=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),f=t.__zoom,l="function"==typeof n?n.apply(t,r):n,h=A(f.invert(c).concat(s/f.k),l.invert(c).concat(s/l.k));return function(t){if(1===t)t=l;else{var n=h(t),e=s/n[2];t=new ns(e,c[0]-n[0]*e,c[1]-n[1]*e)}i.zoom(null,t)}})}function a(t,n){for(var e,r=0,i=C.length;r<i;++r)if((e=C[r]).that===t)return e;return new c(t,n)}function c(t,n){this.that=t,this.args=n,this.index=-1,this.active=0,this.extent=m.apply(t,n)}function s(){if(g.apply(this,arguments)){var t=a(this,arguments),n=this.__zoom,o=Math.max(b,Math.min(w,n.k*Math.pow(2,x.apply(this,arguments)))),u=Ks(this);if(t.wheel)t.mouse[0][0]===u[0]&&t.mouse[0][1]===u[1]||(t.mouse[1]=n.invert(t.mouse[0]=u)),clearTimeout(t.wheel);else{if(n.k===o)return;t.mouse=[u,n.invert(u)],jl(this),t.start()}pm(),t.wheel=setTimeout(function(){t.wheel=null,t.end()},R),t.zoom("mouse",i(r(e(n,o),t.mouse[0],t.mouse[1]),t.extent))}}function f(){if(!y&&g.apply(this,arguments)){var n=a(this,arguments),e=cf(t.event.view).on("mousemove.zoom",function(){if(pm(),!n.moved){var e=t.event.clientX-u,o=t.event.clientY-c;n.moved=e*e+o*o>L}n.zoom("mouse",i(r(n.that.__zoom,n.mouse[0]=Ks(n.that),n.mouse[1]),n.extent))},!0).on("mouseup.zoom",function(){e.on("mousemove.zoom mouseup.zoom",null),_t(t.event.view,n.moved),pm(),n.end()},!0),o=Ks(this),u=t.event.clientX,c=t.event.clientY;lf(t.event.view),rs(),n.mouse=[o,this.__zoom.invert(o)],jl(this),n.start()}}function l(){if(g.apply(this,arguments)){var o=this.__zoom,a=Ks(this),c=o.invert(a),s=i(r(e(o,o.k*(t.event.shiftKey?.5:2)),a,c),m.apply(this,arguments));pm(),E>0?cf(this).transition().duration(E).call(u,s,a):cf(this).call(n.transform,s)}}function p(){if(g.apply(this,arguments)){var n,e,r,i,o=a(this,arguments),u=t.event.changedTouches,c=u.length;for(rs(),e=0;e<c;++e)r=u[e],i=[i=sf(this,u,r.identifier),this.__zoom.invert(i),r.identifier],o.touch0?o.touch1||(o.touch1=i):(o.touch0=i,n=!0);if(_&&(_=clearTimeout(_),!o.touch1))return o.end(),void((i=cf(this).on("dblclick.zoom"))&&i.apply(this,arguments));n&&(_=setTimeout(function(){_=null},P),jl(this),o.start())}}function d(){var n,o,u,c,s=a(this,arguments),f=t.event.changedTouches,l=f.length;for(pm(),_&&(_=clearTimeout(_)),n=0;n<l;++n)o=f[n],u=sf(this,f,o.identifier),s.touch0&&s.touch0[2]===o.identifier?s.touch0[0]=u:s.touch1&&s.touch1[2]===o.identifier&&(s.touch1[0]=u);if(o=s.that.__zoom,s.touch1){var h=s.touch0[0],p=s.touch0[1],d=s.touch1[0],v=s.touch1[1],y=(y=d[0]-h[0])*y+(y=d[1]-h[1])*y,g=(g=v[0]-p[0])*g+(g=v[1]-p[1])*g;o=e(o,Math.sqrt(y/g)),u=[(h[0]+d[0])/2,(h[1]+d[1])/2],c=[(p[0]+v[0])/2,(p[1]+v[1])/2]}else{if(!s.touch0)return;u=s.touch0[0],c=s.touch0[1]}s.zoom("touch",i(r(o,u,c),s.extent))}function v(){var n,e,r=a(this,arguments),i=t.event.changedTouches,o=i.length;for(rs(),y&&clearTimeout(y),y=setTimeout(function(){y=null},P),n=0;n<o;++n)e=i[n],r.touch0&&r.touch0[2]===e.identifier?delete r.touch0:r.touch1&&r.touch1[2]===e.identifier&&delete r.touch1;r.touch1&&!r.touch0&&(r.touch0=r.touch1,delete r.touch1),r.touch0?r.touch0[1]=this.__zoom.invert(r.touch0[0]):r.end()}var _,y,g=is,m=os,x=as,b=0,w=1/0,M=-w,T=w,k=M,S=T,E=250,A=_l,C=[],z=h("start","zoom","end"),P=500,R=150,L=0;return n.transform=function(t,n){var e=t.selection?t.selection():t;e.property("__zoom",us),t!==e?u(t,n):e.interrupt().each(function(){a(this,arguments).start().zoom(null,"function"==typeof n?n.apply(this,arguments):n).end()})},n.scaleBy=function(t,e){n.scaleTo(t,function(){return this.__zoom.k*("function"==typeof e?e.apply(this,arguments):e)})},n.scaleTo=function(t,u){n.transform(t,function(){var t=m.apply(this,arguments),n=this.__zoom,a=o(t),c=n.invert(a);return i(r(e(n,"function"==typeof u?u.apply(this,arguments):u),a,c),t)})},n.translateBy=function(t,e,r){n.transform(t,function(){return i(this.__zoom.translate("function"==typeof e?e.apply(this,arguments):e,"function"==typeof r?r.apply(this,arguments):r),m.apply(this,arguments))})},n.translateTo=function(t,e,r){n.transform(t,function(){var t=m.apply(this,arguments),n=this.__zoom,u=o(t);return i(hm.translate(u[0],u[1]).scale(n.k).translate("function"==typeof e?-e.apply(this,arguments):-e,"function"==typeof r?-r.apply(this,arguments):-r),t)})},c.prototype={start:function(){return 1==++this.active&&(this.index=C.push(this)-1,this.emit("start")),this},zoom:function(t,n){return this.mouse&&"mouse"!==t&&(this.mouse[1]=n.invert(this.mouse[0])),this.touch0&&"touch"!==t&&(this.touch0[1]=n.invert(this.touch0[0])),this.touch1&&"touch"!==t&&(this.touch1[1]=n.invert(this.touch1[0])),this.that.__zoom=n,this.emit("zoom"),this},end:function(){return 0==--this.active&&(C.splice(this.index,1),this.index=-1,this.emit("end")),this},emit:function(t){N(new ts(n,t,this.that.__zoom),z.apply,z,[t,this.that,this.args])}},n.wheelDelta=function(t){return arguments.length?(x="function"==typeof t?t:lm(+t),n):x},n.filter=function(t){return arguments.length?(g="function"==typeof t?t:lm(!!t),n):g},n.extent=function(t){return arguments.length?(m="function"==typeof t?t:lm([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),n):m},n.scaleExtent=function(t){return arguments.length?(b=+t[0],w=+t[1],n):[b,w]},n.translateExtent=function(t){return arguments.length?(M=+t[0][0],T=+t[1][0],k=+t[0][1],S=+t[1][1],n):[[M,k],[T,S]]},n.duration=function(t){return arguments.length?(E=+t,n):E},n.interpolate=function(t){return arguments.length?(A=t,n):A},n.on=function(){var t=z.on.apply(z,arguments);return t===z?n:t},n.clickDistance=function(t){return arguments.length?(L=(t=+t)*t,n):Math.sqrt(L)},n},t.zoomTransform=es,t.zoomIdentity=hm,Object.defineProperty(t,"__esModule",{value:!0})}); \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/js/filesaver.min.js b/library/cpp/lwtrace/mon/static/js/filesaver.min.js
index b431d9bc5b..eaebca442a 100644
--- a/library/cpp/lwtrace/mon/static/js/filesaver.min.js
+++ b/library/cpp/lwtrace/mon/static/js/filesaver.min.js
@@ -1 +1 @@
-(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"undefined"!=typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}});f.saveAs=a.saveAs=a,"undefined"!=typeof module&&(module.exports=a)});
+(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"undefined"!=typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}});f.saveAs=a.saveAs=a,"undefined"!=typeof module&&(module.exports=a)});
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.flot.extents.js b/library/cpp/lwtrace/mon/static/js/jquery.flot.extents.js
index c17018b4f6..c8012fde62 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.flot.extents.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.flot.extents.js
@@ -1,196 +1,196 @@
-/*
- * Copyright 2012, Serge V. Izmaylov
- * Released under GPL Version 2 license.
- */
-
-(function ($) {
- var options = {
- series: {
- extents: {
- show: false,
- lineWidth: 1,
- barHeight: 17,
- color: "rgba(192, 192, 192, 1.0)",
- showConnections: true,
- connectionColor: "rgba(0, 192, 128, 0.8)",
- fill: true,
- fillColor: "rgba(64, 192, 255, 0.5)",
- showLabels: true,
- rowHeight: 20,
- rows: 7,
- barVAlign: "top",
- labelHAlign: "left"
- }
- }
- };
-
- function processRawData(plot, series, data, datapoints) {
- if (!series.extents || !series.extents.show)
- return;
-
- // Fool Flot with fake datapoints
- datapoints.format = [ // Fake format
- { x: true, number: true, required: true },
- { y: true, number: true, required: true },
- ];
- datapoints.points = []; // Empty data
- datapoints.pointsize = 2; // Fake size
-
- // Check if we have extents data
- if (series.extentdata == null)
- return;
-
- // Process our real data
- var row = 0;
- for (i = 0; i < series.extentdata.length; i++) {
- // Skip bad extents
- if ((series.extentdata[i].start == null) || (series.extentdata[i].end == null))
- continue;
-
- if (series.extentdata[i].end < series.extentdata[i].start) {
- var t = series.extentdata[i].end;
- series.extentdata[i].end = series.extentdata[i].start;
- series.extentdata[i].start = t;
- }
- if ((series.extentdata[i].labelHAlign != "left") && (series.extentdata[i].labelHAlign != "right"))
- series.extentdata[i].labelHAlign = series.extents.labelHAlign;
- if (series.extentdata[i].row == null) {
- series.extentdata[i].row = row;
- row = (row+1) % series.extents.rows;
- } else {
- row = (series.extentdata[i].row+1) % series.extents.rows;
- }
- if (series.extentdata[i].color == null)
- series.extentdata[i].color = series.extents.color;
- if (series.extentdata[i].fillColor == null)
- series.extentdata[i].fillColor = series.extents.fillColor;
- }
-
- };
-
- function drawSingleExtent(ctx, width, height, xfrom, xto, series, extent) {
- if (xfrom < 0) xfrom = 0;
- if (xto > width) xto = width;
- var bw = xto-xfrom;
-
- var yfrom;
- if (series.extents.barVAlign == "top")
- yfrom = 4 + series.extents.rowHeight*extent.row;
- else
- yfrom = height - 4 - series.extents.rowHeight*(extent.row) - series.extents.barHeight;
-
- if (series.extents.fill) {
- ctx.fillStyle = extent.fillColor;
- ctx.fillRect(xfrom, yfrom, bw, series.extents.barHeight);
- }
-
- ctx.strokeStyle = extent.color;
- ctx.strokeRect(xfrom, yfrom, bw, series.extents.barHeight);
- }
-
- function drawSingleConnection(ctx, width, height, xfrom, xto, rfrom, rto, series) {
- if (xfrom < 0) xfrom = 0;
- if (xto > width) xto = width;
-
- var yfrom, yto;
- if (series.extents.barVAlign == "top") {
- yfrom = 4 + Math.round(series.extents.rowHeight*rfrom) + Math.round(series.extents.barHeight*0.5);
- yto = 4 + Math.round(series.extents.rowHeight*rto) + Math.round(series.extents.barHeight*0.5);
- } else {
- yfrom = height - 4 - Math.round(series.extents.rowHeight*rfrom) - Math.round(series.extents.barHeight*0.5);
- yto = height - 4 - Math.round(series.extents.rowHeight*rto) - Math.round(series.extents.barHeight*0.5);
- }
-
- ctx.beginPath();
- ctx.moveTo(xfrom, yfrom);
- ctx.lineTo(xfrom+10, yfrom);
- ctx.lineTo(xto-10, yto);
- ctx.lineTo(xto, yto);
- ctx.lineTo(xto-6, yto-3);
- ctx.lineTo(xto-6, yto+3);
- ctx.lineTo(xto, yto);
- ctx.stroke();
- }
-
- function addExtentLabel(placeholder, plotOffset, width, xfrom, xto, series, extent) {
- var styles = [];
- if (series.extents.barVAlign == "top")
- styles.push("top:"+Math.round((plotOffset.top+series.extents.rowHeight*extent.row+4))+"px");
- else
- styles.push("bottom:"+Math.round((plotOffset.bottom+series.extents.rowHeight*extent.row+4))+"px");
- if (extent.labelHAlign == "left")
- styles.push("left:"+Math.round((plotOffset.left+xfrom+3))+"px");
- else
- styles.push("right:"+Math.round((plotOffset.right+(width-xto)+3))+"px");
- styles.push("");
-
- placeholder.append('<div '+((extent.id !=null)?('id="'+extent.id+'" '):'')+'class="extentLabel" style="font-size:smaller;position:absolute;'+(styles.join(';'))+'">'+extent.label+'</div>');
- }
-
- function drawSeries(plot, ctx, series) {
- if (!series.extents || !series.extents.show || !series.extentdata)
- return;
-
- var placeholder = plot.getPlaceholder();
- placeholder.find(".extentLabel").remove();
-
- ctx.save();
-
- var plotOffset = plot.getPlotOffset();
- var axes = plot.getAxes();
- var yf = axes.yaxis.p2c(axes.yaxis.min);
- var yt = axes.yaxis.p2c(axes.yaxis.max);
- var ytop = (yf>yt)?yt:yf;
- var ybot = (yf>yt)?yf:yt;
- var width = plot.width();
- var height = plot.height();
-
- ctx.translate(plotOffset.left, plotOffset.top);
- ctx.lineJoin = "round";
-
- for (var i = 0; i < series.extentdata.length; i++) {
- var xfrom, xto;
- if ((series.extentdata[i].start == null) || (series.extentdata[i].end == null))
- continue;
- if ((series.extentdata[i].start < axes.xaxis.max) && (series.extentdata[i].end > axes.xaxis.min)) {
- xfrom = axes.xaxis.p2c((series.extentdata[i].start<axes.xaxis.min)?axes.xaxis.min:series.extentdata[i].start);
- xto = axes.xaxis.p2c((series.extentdata[i].end>axes.xaxis.max)?axes.xaxis.max:series.extentdata[i].end);
- drawSingleExtent(ctx, width, height, xfrom, xto, series, series.extentdata[i]);
-
- if (series.extents.showConnections && (series.extentdata[i].start > axes.xaxis.min) && (series.extentdata[i].start < axes.xaxis.max))
- if ((series.extentdata[i].depends != null) && (series.extentdata[i].depends.length != null) && (series.extentdata[i].depends.length > 0))
- for (var j=0; j<series.extentdata[i].depends.length; j++) {
- var k = series.extentdata[i].depends[j];
- if ((k < 0) || (k >= series.extentdata.length))
- continue;
- if ((series.extentdata[k].start == null) || (series.extentdata[k].end == null))
- continue;
- var cxto = xfrom;
- var cxfrom = series.extentdata[k].end;
- if (cxfrom < axes.xaxis.min) cxfrom = axes.xaxis.min;
- if (cxfrom > axes.xaxis.max) cxfrom = axes.xaxis.max;
- cxfrom = axes.xaxis.p2c(cxfrom);
- ctx.strokeStyle = series.extents.connectionColor;
- drawSingleConnection(ctx, width, height, cxfrom, cxto, series.extentdata[k].row, series.extentdata[i].row, series);
- }
-
- if (series.extents.showLabels && (series.extentdata[i].label != null))
- addExtentLabel(placeholder, plotOffset, width, xfrom, xto, series, series.extentdata[i]);
- }
- }
-
- ctx.restore();
- };
-
- function init(plot) {
- plot.hooks.processRawData.push(processRawData);
- plot.hooks.drawSeries.push(drawSeries);
- };
-
- $.plot.plugins.push({
- init: init,
- name: "extents",
- options: options,
- version: "0.3"
- });
-})(jQuery);
+/*
+ * Copyright 2012, Serge V. Izmaylov
+ * Released under GPL Version 2 license.
+ */
+
+(function ($) {
+ var options = {
+ series: {
+ extents: {
+ show: false,
+ lineWidth: 1,
+ barHeight: 17,
+ color: "rgba(192, 192, 192, 1.0)",
+ showConnections: true,
+ connectionColor: "rgba(0, 192, 128, 0.8)",
+ fill: true,
+ fillColor: "rgba(64, 192, 255, 0.5)",
+ showLabels: true,
+ rowHeight: 20,
+ rows: 7,
+ barVAlign: "top",
+ labelHAlign: "left"
+ }
+ }
+ };
+
+ function processRawData(plot, series, data, datapoints) {
+ if (!series.extents || !series.extents.show)
+ return;
+
+ // Fool Flot with fake datapoints
+ datapoints.format = [ // Fake format
+ { x: true, number: true, required: true },
+ { y: true, number: true, required: true },
+ ];
+ datapoints.points = []; // Empty data
+ datapoints.pointsize = 2; // Fake size
+
+ // Check if we have extents data
+ if (series.extentdata == null)
+ return;
+
+ // Process our real data
+ var row = 0;
+ for (i = 0; i < series.extentdata.length; i++) {
+ // Skip bad extents
+ if ((series.extentdata[i].start == null) || (series.extentdata[i].end == null))
+ continue;
+
+ if (series.extentdata[i].end < series.extentdata[i].start) {
+ var t = series.extentdata[i].end;
+ series.extentdata[i].end = series.extentdata[i].start;
+ series.extentdata[i].start = t;
+ }
+ if ((series.extentdata[i].labelHAlign != "left") && (series.extentdata[i].labelHAlign != "right"))
+ series.extentdata[i].labelHAlign = series.extents.labelHAlign;
+ if (series.extentdata[i].row == null) {
+ series.extentdata[i].row = row;
+ row = (row+1) % series.extents.rows;
+ } else {
+ row = (series.extentdata[i].row+1) % series.extents.rows;
+ }
+ if (series.extentdata[i].color == null)
+ series.extentdata[i].color = series.extents.color;
+ if (series.extentdata[i].fillColor == null)
+ series.extentdata[i].fillColor = series.extents.fillColor;
+ }
+
+ };
+
+ function drawSingleExtent(ctx, width, height, xfrom, xto, series, extent) {
+ if (xfrom < 0) xfrom = 0;
+ if (xto > width) xto = width;
+ var bw = xto-xfrom;
+
+ var yfrom;
+ if (series.extents.barVAlign == "top")
+ yfrom = 4 + series.extents.rowHeight*extent.row;
+ else
+ yfrom = height - 4 - series.extents.rowHeight*(extent.row) - series.extents.barHeight;
+
+ if (series.extents.fill) {
+ ctx.fillStyle = extent.fillColor;
+ ctx.fillRect(xfrom, yfrom, bw, series.extents.barHeight);
+ }
+
+ ctx.strokeStyle = extent.color;
+ ctx.strokeRect(xfrom, yfrom, bw, series.extents.barHeight);
+ }
+
+ function drawSingleConnection(ctx, width, height, xfrom, xto, rfrom, rto, series) {
+ if (xfrom < 0) xfrom = 0;
+ if (xto > width) xto = width;
+
+ var yfrom, yto;
+ if (series.extents.barVAlign == "top") {
+ yfrom = 4 + Math.round(series.extents.rowHeight*rfrom) + Math.round(series.extents.barHeight*0.5);
+ yto = 4 + Math.round(series.extents.rowHeight*rto) + Math.round(series.extents.barHeight*0.5);
+ } else {
+ yfrom = height - 4 - Math.round(series.extents.rowHeight*rfrom) - Math.round(series.extents.barHeight*0.5);
+ yto = height - 4 - Math.round(series.extents.rowHeight*rto) - Math.round(series.extents.barHeight*0.5);
+ }
+
+ ctx.beginPath();
+ ctx.moveTo(xfrom, yfrom);
+ ctx.lineTo(xfrom+10, yfrom);
+ ctx.lineTo(xto-10, yto);
+ ctx.lineTo(xto, yto);
+ ctx.lineTo(xto-6, yto-3);
+ ctx.lineTo(xto-6, yto+3);
+ ctx.lineTo(xto, yto);
+ ctx.stroke();
+ }
+
+ function addExtentLabel(placeholder, plotOffset, width, xfrom, xto, series, extent) {
+ var styles = [];
+ if (series.extents.barVAlign == "top")
+ styles.push("top:"+Math.round((plotOffset.top+series.extents.rowHeight*extent.row+4))+"px");
+ else
+ styles.push("bottom:"+Math.round((plotOffset.bottom+series.extents.rowHeight*extent.row+4))+"px");
+ if (extent.labelHAlign == "left")
+ styles.push("left:"+Math.round((plotOffset.left+xfrom+3))+"px");
+ else
+ styles.push("right:"+Math.round((plotOffset.right+(width-xto)+3))+"px");
+ styles.push("");
+
+ placeholder.append('<div '+((extent.id !=null)?('id="'+extent.id+'" '):'')+'class="extentLabel" style="font-size:smaller;position:absolute;'+(styles.join(';'))+'">'+extent.label+'</div>');
+ }
+
+ function drawSeries(plot, ctx, series) {
+ if (!series.extents || !series.extents.show || !series.extentdata)
+ return;
+
+ var placeholder = plot.getPlaceholder();
+ placeholder.find(".extentLabel").remove();
+
+ ctx.save();
+
+ var plotOffset = plot.getPlotOffset();
+ var axes = plot.getAxes();
+ var yf = axes.yaxis.p2c(axes.yaxis.min);
+ var yt = axes.yaxis.p2c(axes.yaxis.max);
+ var ytop = (yf>yt)?yt:yf;
+ var ybot = (yf>yt)?yf:yt;
+ var width = plot.width();
+ var height = plot.height();
+
+ ctx.translate(plotOffset.left, plotOffset.top);
+ ctx.lineJoin = "round";
+
+ for (var i = 0; i < series.extentdata.length; i++) {
+ var xfrom, xto;
+ if ((series.extentdata[i].start == null) || (series.extentdata[i].end == null))
+ continue;
+ if ((series.extentdata[i].start < axes.xaxis.max) && (series.extentdata[i].end > axes.xaxis.min)) {
+ xfrom = axes.xaxis.p2c((series.extentdata[i].start<axes.xaxis.min)?axes.xaxis.min:series.extentdata[i].start);
+ xto = axes.xaxis.p2c((series.extentdata[i].end>axes.xaxis.max)?axes.xaxis.max:series.extentdata[i].end);
+ drawSingleExtent(ctx, width, height, xfrom, xto, series, series.extentdata[i]);
+
+ if (series.extents.showConnections && (series.extentdata[i].start > axes.xaxis.min) && (series.extentdata[i].start < axes.xaxis.max))
+ if ((series.extentdata[i].depends != null) && (series.extentdata[i].depends.length != null) && (series.extentdata[i].depends.length > 0))
+ for (var j=0; j<series.extentdata[i].depends.length; j++) {
+ var k = series.extentdata[i].depends[j];
+ if ((k < 0) || (k >= series.extentdata.length))
+ continue;
+ if ((series.extentdata[k].start == null) || (series.extentdata[k].end == null))
+ continue;
+ var cxto = xfrom;
+ var cxfrom = series.extentdata[k].end;
+ if (cxfrom < axes.xaxis.min) cxfrom = axes.xaxis.min;
+ if (cxfrom > axes.xaxis.max) cxfrom = axes.xaxis.max;
+ cxfrom = axes.xaxis.p2c(cxfrom);
+ ctx.strokeStyle = series.extents.connectionColor;
+ drawSingleConnection(ctx, width, height, cxfrom, cxto, series.extentdata[k].row, series.extentdata[i].row, series);
+ }
+
+ if (series.extents.showLabels && (series.extentdata[i].label != null))
+ addExtentLabel(placeholder, plotOffset, width, xfrom, xto, series, series.extentdata[i]);
+ }
+ }
+
+ ctx.restore();
+ };
+
+ function init(plot) {
+ plot.hooks.processRawData.push(processRawData);
+ plot.hooks.drawSeries.push(drawSeries);
+ };
+
+ $.plot.plugins.push({
+ init: init,
+ name: "extents",
+ options: options,
+ version: "0.3"
+ });
+})(jQuery);
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.flot.min.js b/library/cpp/lwtrace/mon/static/js/jquery.flot.min.js
index 81083f1819..c39799c804 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.flot.min.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.flot.min.js
@@ -1,8 +1,8 @@
-/* Javascript plotting library for jQuery, version 0.8.3.
-
-Copyright (c) 2007-2014 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-*/
-(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function($){var hasOwnProperty=Object.prototype.hasOwnProperty;if(!$.fn.detach){$.fn.detach=function(){return this.each(function(){if(this.parentNode){this.parentNode.removeChild(this)}})}}function Canvas(cls,container){var element=container.children("."+cls)[0];if(element==null){element=document.createElement("canvas");element.className=cls;$(element).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(container);if(!element.getContext){if(window.G_vmlCanvasManager){element=window.G_vmlCanvasManager.initElement(element)}else{throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.")}}}this.element=element;var context=this.context=element.getContext("2d");var devicePixelRatio=window.devicePixelRatio||1,backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingStorePixelRatio||context.msBackingStorePixelRatio||context.oBackingStorePixelRatio||context.backingStorePixelRatio||1;this.pixelRatio=devicePixelRatio/backingStoreRatio;this.resize(container.width(),container.height());this.textContainer=null;this.text={};this._textCache={}}Canvas.prototype.resize=function(width,height){if(width<=0||height<=0){throw new Error("Invalid dimensions for plot, width = "+width+", height = "+height)}var element=this.element,context=this.context,pixelRatio=this.pixelRatio;if(this.width!=width){element.width=width*pixelRatio;element.style.width=width+"px";this.width=width}if(this.height!=height){element.height=height*pixelRatio;element.style.height=height+"px";this.height=height}context.restore();context.save();context.scale(pixelRatio,pixelRatio)};Canvas.prototype.clear=function(){this.context.clearRect(0,0,this.width,this.height)};Canvas.prototype.render=function(){var cache=this._textCache;for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layer=this.getTextLayer(layerKey),layerCache=cache[layerKey];layer.hide();for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){if(position.active){if(!position.rendered){layer.append(position.element);position.rendered=true}}else{positions.splice(i--,1);if(position.rendered){position.element.detach()}}}if(positions.length==0){delete styleCache[key]}}}}}layer.show()}}};Canvas.prototype.getTextLayer=function(classes){var layer=this.text[classes];if(layer==null){if(this.textContainer==null){this.textContainer=$("<div class='flot-text'></div>").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)}layer=this.text[classes]=$("<div></div>").addClass(classes).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)}return layer};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px/"+font.lineHeight+"px "+font.family}else{textStyle=font}layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={}}styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={}}info=styleCache[text];if(info==null){var element=$("<div></div>").html(text).css({position:"absolute","max-width":width,top:-9999}).appendTo(this.getTextLayer(layer));if(typeof font==="object"){element.css({font:textStyle,color:font.color})}else if(typeof font==="string"){element.addClass(font)}info=styleCache[text]={width:element.outerWidth(true),height:element.outerHeight(true),element:element,positions:[]};element.detach()}return info};Canvas.prototype.addText=function(layer,x,y,text,font,angle,width,halign,valign){var info=this.getTextInfo(layer,text,font,angle,width),positions=info.positions;if(halign=="center"){x-=info.width/2}else if(halign=="right"){x-=info.width}if(valign=="middle"){y-=info.height/2}else if(valign=="bottom"){y-=info.height}for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=true;return}}position={active:true,rendered:false,element:positions.length?info.element.clone():info.element,x:x,y:y};positions.push(position);position.element.css({top:Math.round(y),left:Math.round(x),"text-align":halign})};Canvas.prototype.removeText=function(layer,x,y,text,font,angle){if(text==null){var layerCache=this._textCache[layer];if(layerCache!=null){for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){position.active=false}}}}}}}else{var positions=this.getTextInfo(layer,text,font,angle).positions;for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=false}}}};function Plot(placeholder,data_,options_,plugins){var series=[],options={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:.85,sorted:null},xaxis:{show:null,position:"bottom",mode:null,font:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null},yaxis:{autoscaleMargin:.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false,zero:true},shadowSize:3,highlightColor:null},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,margin:0,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},interaction:{redrawOverlayInterval:1e3/60},hooks:{}},surface=null,overlay=null,eventHolder=null,ctx=null,octx=null,xaxes=[],yaxes=[],plotOffset={left:0,right:0,top:0,bottom:0},plotWidth=0,plotHeight=0,hooks={processOptions:[],processRawData:[],processDatapoints:[],processOffset:[],drawBackground:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},plot=this;plot.setData=setData;plot.setupGrid=setupGrid;plot.draw=draw;plot.getPlaceholder=function(){return placeholder};plot.getCanvas=function(){return surface.element};plot.getPlotOffset=function(){return plotOffset};plot.width=function(){return plotWidth};plot.height=function(){return plotHeight};plot.offset=function(){var o=eventHolder.offset();o.left+=plotOffset.left;o.top+=plotOffset.top;return o};plot.getData=function(){return series};plot.getAxes=function(){var res={},i;$.each(xaxes.concat(yaxes),function(_,axis){if(axis)res[axis.direction+(axis.n!=1?axis.n:"")+"axis"]=axis});return res};plot.getXAxes=function(){return xaxes};plot.getYAxes=function(){return yaxes};plot.c2p=canvasToAxisCoords;plot.p2c=axisToCanvasCoords;plot.getOptions=function(){return options};plot.highlight=highlight;plot.unhighlight=unhighlight;plot.triggerRedrawOverlay=triggerRedrawOverlay;plot.pointOffset=function(point){return{left:parseInt(xaxes[axisNumber(point,"x")-1].p2c(+point.x)+plotOffset.left,10),top:parseInt(yaxes[axisNumber(point,"y")-1].p2c(+point.y)+plotOffset.top,10)}};plot.shutdown=shutdown;plot.destroy=function(){shutdown();placeholder.removeData("plot").empty();series=[];options=null;surface=null;overlay=null;eventHolder=null;ctx=null;octx=null;xaxes=[];yaxes=[];hooks=null;highlights=[];plot=null};plot.resize=function(){var width=placeholder.width(),height=placeholder.height();surface.resize(width,height);overlay.resize(width,height)};plot.hooks=hooks;initPlugins(plot);parseOptions(options_);setupCanvases();setData(data_);setupGrid();draw();bindEvents();function executeHooks(hook,args){args=[plot].concat(args);for(var i=0;i<hook.length;++i)hook[i].apply(this,args)}function initPlugins(){var classes={Canvas:Canvas};for(var i=0;i<plugins.length;++i){var p=plugins[i];p.init(plot,classes);if(p.options)$.extend(true,options,p.options)}}function parseOptions(opts){$.extend(true,options,opts);if(opts&&opts.colors){options.colors=opts.colors}if(options.xaxis.color==null)options.xaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.yaxis.color==null)options.yaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.xaxis.tickColor==null)options.xaxis.tickColor=options.grid.tickColor||options.xaxis.color;if(options.yaxis.tickColor==null)options.yaxis.tickColor=options.grid.tickColor||options.yaxis.color;if(options.grid.borderColor==null)options.grid.borderColor=options.grid.color;if(options.grid.tickColor==null)options.grid.tickColor=$.color.parse(options.grid.color).scale("a",.22).toString();var i,axisOptions,axisCount,fontSize=placeholder.css("font-size"),fontSizeDefault=fontSize?+fontSize.replace("px",""):13,fontDefaults={style:placeholder.css("font-style"),size:Math.round(.8*fontSizeDefault),variant:placeholder.css("font-variant"),weight:placeholder.css("font-weight"),family:placeholder.css("font-family")};axisCount=options.xaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.xaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.xaxis,axisOptions);options.xaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}axisCount=options.yaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.yaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.yaxis,axisOptions);options.yaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}if(options.xaxis.noTicks&&options.xaxis.ticks==null)options.xaxis.ticks=options.xaxis.noTicks;if(options.yaxis.noTicks&&options.yaxis.ticks==null)options.yaxis.ticks=options.yaxis.noTicks;if(options.x2axis){options.xaxes[1]=$.extend(true,{},options.xaxis,options.x2axis);options.xaxes[1].position="top";if(options.x2axis.min==null){options.xaxes[1].min=null}if(options.x2axis.max==null){options.xaxes[1].max=null}}if(options.y2axis){options.yaxes[1]=$.extend(true,{},options.yaxis,options.y2axis);options.yaxes[1].position="right";if(options.y2axis.min==null){options.yaxes[1].min=null}if(options.y2axis.max==null){options.yaxes[1].max=null}}if(options.grid.coloredAreas)options.grid.markings=options.grid.coloredAreas;if(options.grid.coloredAreasColor)options.grid.markingsColor=options.grid.coloredAreasColor;if(options.lines)$.extend(true,options.series.lines,options.lines);if(options.points)$.extend(true,options.series.points,options.points);if(options.bars)$.extend(true,options.series.bars,options.bars);if(options.shadowSize!=null)options.series.shadowSize=options.shadowSize;if(options.highlightColor!=null)options.series.highlightColor=options.highlightColor;for(i=0;i<options.xaxes.length;++i)getOrCreateAxis(xaxes,i+1).options=options.xaxes[i];for(i=0;i<options.yaxes.length;++i)getOrCreateAxis(yaxes,i+1).options=options.yaxes[i];for(var n in hooks)if(options.hooks[n]&&options.hooks[n].length)hooks[n]=hooks[n].concat(options.hooks[n]);executeHooks(hooks.processOptions,[options])}function setData(d){series=parseData(d);fillInSeriesOptions();processData()}function parseData(d){var res=[];for(var i=0;i<d.length;++i){var s=$.extend(true,{},options.series);if(d[i].data!=null){s.data=d[i].data;delete d[i].data;$.extend(true,s,d[i]);d[i].data=s.data}else s.data=d[i];res.push(s)}return res}function axisNumber(obj,coord){var a=obj[coord+"axis"];if(typeof a=="object")a=a.n;if(typeof a!="number")a=1;return a}function allAxes(){return $.grep(xaxes.concat(yaxes),function(a){return a})}function canvasToAxisCoords(pos){var res={},i,axis;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used)res["x"+axis.n]=axis.c2p(pos.left)}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used)res["y"+axis.n]=axis.c2p(pos.top)}if(res.x1!==undefined)res.x=res.x1;if(res.y1!==undefined)res.y=res.y1;return res}function axisToCanvasCoords(pos){var res={},i,axis,key;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used){key="x"+axis.n;if(pos[key]==null&&axis.n==1)key="x";if(pos[key]!=null){res.left=axis.p2c(pos[key]);break}}}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used){key="y"+axis.n;if(pos[key]==null&&axis.n==1)key="y";if(pos[key]!=null){res.top=axis.p2c(pos[key]);break}}}return res}function getOrCreateAxis(axes,number){if(!axes[number-1])axes[number-1]={n:number,direction:axes==xaxes?"x":"y",options:$.extend(true,{},axes==xaxes?options.xaxis:options.yaxis)};return axes[number-1]}function fillInSeriesOptions(){var neededColors=series.length,maxIndex=-1,i;for(i=0;i<series.length;++i){var sc=series[i].color;if(sc!=null){neededColors--;if(typeof sc=="number"&&sc>maxIndex){maxIndex=sc}}}if(neededColors<=maxIndex){neededColors=maxIndex+1}var c,colors=[],colorPool=options.colors,colorPoolSize=colorPool.length,variation=0;for(i=0;i<neededColors;i++){c=$.color.parse(colorPool[i%colorPoolSize]||"#666");if(i%colorPoolSize==0&&i){if(variation>=0){if(variation<.5){variation=-variation-.2}else variation=0}else variation=-variation}colors[i]=c.scale("rgb",1+variation)}var colori=0,s;for(i=0;i<series.length;++i){s=series[i];if(s.color==null){s.color=colors[colori].toString();++colori}else if(typeof s.color=="number")s.color=colors[s.color].toString();if(s.lines.show==null){var v,show=true;for(v in s)if(s[v]&&s[v].show){show=false;break}if(show)s.lines.show=true}if(s.lines.zero==null){s.lines.zero=!!s.lines.fill}s.xaxis=getOrCreateAxis(xaxes,axisNumber(s,"x"));s.yaxis=getOrCreateAxis(yaxes,axisNumber(s,"y"))}}function processData(){var topSentry=Number.POSITIVE_INFINITY,bottomSentry=Number.NEGATIVE_INFINITY,fakeInfinity=Number.MAX_VALUE,i,j,k,m,length,s,points,ps,x,y,axis,val,f,p,data,format;function updateAxis(axis,min,max){if(min<axis.datamin&&min!=-fakeInfinity)axis.datamin=min;if(max>axis.datamax&&max!=fakeInfinity)axis.datamax=max}$.each(allAxes(),function(_,axis){axis.datamin=topSentry;axis.datamax=bottomSentry;axis.used=false});for(i=0;i<series.length;++i){s=series[i];s.datapoints={points:[]};executeHooks(hooks.processRawData,[s,s.data,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];data=s.data;format=s.datapoints.format;if(!format){format=[];format.push({x:true,number:true,required:true});format.push({y:true,number:true,required:true});if(s.bars.show||s.lines.show&&s.lines.fill){var autoscale=!!(s.bars.show&&s.bars.zero||s.lines.show&&s.lines.zero);format.push({y:true,number:true,required:false,defaultValue:0,autoscale:autoscale});if(s.bars.horizontal){delete format[format.length-1].y;format[format.length-1].x=true}}s.datapoints.format=format}if(s.datapoints.pointsize!=null)continue;s.datapoints.pointsize=format.length;ps=s.datapoints.pointsize;points=s.datapoints.points;var insertSteps=s.lines.show&&s.lines.steps;s.xaxis.used=s.yaxis.used=true;for(j=k=0;j<data.length;++j,k+=ps){p=data[j];var nullify=p==null;if(!nullify){for(m=0;m<ps;++m){val=p[m];f=format[m];if(f){if(f.number&&val!=null){val=+val;if(isNaN(val))val=null;else if(val==Infinity)val=fakeInfinity;else if(val==-Infinity)val=-fakeInfinity}if(val==null){if(f.required)nullify=true;if(f.defaultValue!=null)val=f.defaultValue}}points[k+m]=val}}if(nullify){for(m=0;m<ps;++m){val=points[k+m];if(val!=null){f=format[m];if(f.autoscale!==false){if(f.x){updateAxis(s.xaxis,val,val)}if(f.y){updateAxis(s.yaxis,val,val)}}}points[k+m]=null}}else{if(insertSteps&&k>0&&points[k-ps]!=null&&points[k-ps]!=points[k]&&points[k-ps+1]!=points[k+1]){for(m=0;m<ps;++m)points[k+ps+m]=points[k+m];points[k+1]=points[k-ps+1];k+=ps}}}}for(i=0;i<series.length;++i){s=series[i];executeHooks(hooks.processDatapoints,[s,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];points=s.datapoints.points;ps=s.datapoints.pointsize;format=s.datapoints.format;var xmin=topSentry,ymin=topSentry,xmax=bottomSentry,ymax=bottomSentry;for(j=0;j<points.length;j+=ps){if(points[j]==null)continue;for(m=0;m<ps;++m){val=points[j+m];f=format[m];if(!f||f.autoscale===false||val==fakeInfinity||val==-fakeInfinity)continue;if(f.x){if(val<xmin)xmin=val;if(val>xmax)xmax=val}if(f.y){if(val<ymin)ymin=val;if(val>ymax)ymax=val}}}if(s.bars.show){var delta;switch(s.bars.align){case"left":delta=0;break;case"right":delta=-s.bars.barWidth;break;default:delta=-s.bars.barWidth/2}if(s.bars.horizontal){ymin+=delta;ymax+=delta+s.bars.barWidth}else{xmin+=delta;xmax+=delta+s.bars.barWidth}}updateAxis(s.xaxis,xmin,xmax);updateAxis(s.yaxis,ymin,ymax)}$.each(allAxes(),function(_,axis){if(axis.datamin==topSentry)axis.datamin=null;if(axis.datamax==bottomSentry)axis.datamax=null})}function setupCanvases(){placeholder.css("padding",0).children().filter(function(){return!$(this).hasClass("flot-overlay")&&!$(this).hasClass("flot-base")}).remove();if(placeholder.css("position")=="static")placeholder.css("position","relative");surface=new Canvas("flot-base",placeholder);overlay=new Canvas("flot-overlay",placeholder);ctx=surface.context;octx=overlay.context;eventHolder=$(overlay.element).unbind();var existing=placeholder.data("plot");if(existing){existing.shutdown();overlay.clear()}placeholder.data("plot",plot)}function bindEvents(){if(options.grid.hoverable){eventHolder.mousemove(onMouseMove);eventHolder.bind("mouseleave",onMouseLeave)}if(options.grid.clickable)eventHolder.click(onClick);executeHooks(hooks.bindEvents,[eventHolder])}function shutdown(){if(redrawTimeout)clearTimeout(redrawTimeout);eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mouseleave",onMouseLeave);eventHolder.unbind("click",onClick);executeHooks(hooks.shutdown,[eventHolder])}function setTransformationHelpers(axis){function identity(x){return x}var s,m,t=axis.options.transform||identity,it=axis.options.inverseTransform;if(axis.direction=="x"){s=axis.scale=plotWidth/Math.abs(t(axis.max)-t(axis.min));m=Math.min(t(axis.max),t(axis.min))}else{s=axis.scale=plotHeight/Math.abs(t(axis.max)-t(axis.min));s=-s;m=Math.max(t(axis.max),t(axis.min))}if(t==identity)axis.p2c=function(p){return(p-m)*s};else axis.p2c=function(p){return(t(p)-m)*s};if(!it)axis.c2p=function(c){return m+c/s};else axis.c2p=function(c){return it(m+c/s)}}function measureTickLabels(axis){var opts=axis.options,ticks=axis.ticks||[],labelWidth=opts.labelWidth||0,labelHeight=opts.labelHeight||0,maxWidth=labelWidth||(axis.direction=="x"?Math.floor(surface.width/(ticks.length||1)):null),legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=opts.font||"flot-tick-label tickLabel";for(var i=0;i<ticks.length;++i){var t=ticks[i];if(!t.label)continue;var info=surface.getTextInfo(layer,t.label,font,null,maxWidth);labelWidth=Math.max(labelWidth,info.width);labelHeight=Math.max(labelHeight,info.height)}axis.labelWidth=opts.labelWidth||labelWidth;axis.labelHeight=opts.labelHeight||labelHeight}function allocateAxisBoxFirstPhase(axis){var lw=axis.labelWidth,lh=axis.labelHeight,pos=axis.options.position,isXAxis=axis.direction==="x",tickLength=axis.options.tickLength,axisMargin=options.grid.axisMargin,padding=options.grid.labelMargin,innermost=true,outermost=true,first=true,found=false;$.each(isXAxis?xaxes:yaxes,function(i,a){if(a&&(a.show||a.reserveSpace)){if(a===axis){found=true}else if(a.options.position===pos){if(found){outermost=false}else{innermost=false}}if(!found){first=false}}});if(outermost){axisMargin=0}if(tickLength==null){tickLength=first?"full":5}if(!isNaN(+tickLength))padding+=+tickLength;if(isXAxis){lh+=padding;if(pos=="bottom"){plotOffset.bottom+=lh+axisMargin;axis.box={top:surface.height-plotOffset.bottom,height:lh}}else{axis.box={top:plotOffset.top+axisMargin,height:lh};plotOffset.top+=lh+axisMargin}}else{lw+=padding;if(pos=="left"){axis.box={left:plotOffset.left+axisMargin,width:lw};plotOffset.left+=lw+axisMargin}else{plotOffset.right+=lw+axisMargin;axis.box={left:surface.width-plotOffset.right,width:lw}}}axis.position=pos;axis.tickLength=tickLength;axis.box.padding=padding;axis.innermost=innermost}function allocateAxisBoxSecondPhase(axis){if(axis.direction=="x"){axis.box.left=plotOffset.left-axis.labelWidth/2;axis.box.width=surface.width-plotOffset.left-plotOffset.right+axis.labelWidth}else{axis.box.top=plotOffset.top-axis.labelHeight/2;axis.box.height=surface.height-plotOffset.bottom-plotOffset.top+axis.labelHeight}}function adjustLayoutForThingsStickingOut(){var minMargin=options.grid.minBorderMargin,axis,i;if(minMargin==null){minMargin=0;for(i=0;i<series.length;++i)minMargin=Math.max(minMargin,2*(series[i].points.radius+series[i].points.lineWidth/2))}var margins={left:minMargin,right:minMargin,top:minMargin,bottom:minMargin};$.each(allAxes(),function(_,axis){if(axis.reserveSpace&&axis.ticks&&axis.ticks.length){if(axis.direction==="x"){margins.left=Math.max(margins.left,axis.labelWidth/2);margins.right=Math.max(margins.right,axis.labelWidth/2)}else{margins.bottom=Math.max(margins.bottom,axis.labelHeight/2);margins.top=Math.max(margins.top,axis.labelHeight/2)}}});plotOffset.left=Math.ceil(Math.max(margins.left,plotOffset.left));plotOffset.right=Math.ceil(Math.max(margins.right,plotOffset.right));plotOffset.top=Math.ceil(Math.max(margins.top,plotOffset.top));plotOffset.bottom=Math.ceil(Math.max(margins.bottom,plotOffset.bottom))}function setupGrid(){var i,axes=allAxes(),showGrid=options.grid.show;for(var a in plotOffset){var margin=options.grid.margin||0;plotOffset[a]=typeof margin=="number"?margin:margin[a]||0}executeHooks(hooks.processOffset,[plotOffset]);for(var a in plotOffset){if(typeof options.grid.borderWidth=="object"){plotOffset[a]+=showGrid?options.grid.borderWidth[a]:0}else{plotOffset[a]+=showGrid?options.grid.borderWidth:0}}$.each(axes,function(_,axis){var axisOpts=axis.options;axis.show=axisOpts.show==null?axis.used:axisOpts.show;axis.reserveSpace=axisOpts.reserveSpace==null?axis.show:axisOpts.reserveSpace;setRange(axis)});if(showGrid){var allocatedAxes=$.grep(axes,function(axis){return axis.show||axis.reserveSpace});$.each(allocatedAxes,function(_,axis){setupTickGeneration(axis);setTicks(axis);snapRangeToTicks(axis,axis.ticks);measureTickLabels(axis)});for(i=allocatedAxes.length-1;i>=0;--i)allocateAxisBoxFirstPhase(allocatedAxes[i]);adjustLayoutForThingsStickingOut();$.each(allocatedAxes,function(_,axis){allocateAxisBoxSecondPhase(axis)})}plotWidth=surface.width-plotOffset.left-plotOffset.right;plotHeight=surface.height-plotOffset.bottom-plotOffset.top;$.each(axes,function(_,axis){setTransformationHelpers(axis)});if(showGrid){drawAxisLabels()}insertLegend()}function setRange(axis){var opts=axis.options,min=+(opts.min!=null?opts.min:axis.datamin),max=+(opts.max!=null?opts.max:axis.datamax),delta=max-min;if(delta==0){var widen=max==0?1:.01;if(opts.min==null)min-=widen;if(opts.max==null||opts.min!=null)max+=widen}else{var margin=opts.autoscaleMargin;if(margin!=null){if(opts.min==null){min-=delta*margin;if(min<0&&axis.datamin!=null&&axis.datamin>=0)min=0}if(opts.max==null){max+=delta*margin;if(max>0&&axis.datamax!=null&&axis.datamax<=0)max=0}}}axis.min=min;axis.max=max}function setupTickGeneration(axis){var opts=axis.options;var noTicks;if(typeof opts.ticks=="number"&&opts.ticks>0)noTicks=opts.ticks;else noTicks=.3*Math.sqrt(axis.direction=="x"?surface.width:surface.height);var delta=(axis.max-axis.min)/noTicks,dec=-Math.floor(Math.log(delta)/Math.LN10),maxDec=opts.tickDecimals;if(maxDec!=null&&dec>maxDec){dec=maxDec}var magn=Math.pow(10,-dec),norm=delta/magn,size;if(norm<1.5){size=1}else if(norm<3){size=2;if(norm>2.25&&(maxDec==null||dec+1<=maxDec)){size=2.5;++dec}}else if(norm<7.5){size=5}else{size=10}size*=magn;if(opts.minTickSize!=null&&size<opts.minTickSize){size=opts.minTickSize}axis.delta=delta;axis.tickDecimals=Math.max(0,maxDec!=null?maxDec:dec);axis.tickSize=opts.tickSize||size;if(opts.mode=="time"&&!axis.tickGenerator){throw new Error("Time mode requires the flot.time plugin.")}if(!axis.tickGenerator){axis.tickGenerator=function(axis){var ticks=[],start=floorInBase(axis.min,axis.tickSize),i=0,v=Number.NaN,prev;do{prev=v;v=start+i*axis.tickSize;ticks.push(v);++i}while(v<axis.max&&v!=prev);return ticks};axis.tickFormatter=function(value,axis){var factor=axis.tickDecimals?Math.pow(10,axis.tickDecimals):1;var formatted=""+Math.round(value*factor)/factor;if(axis.tickDecimals!=null){var decimal=formatted.indexOf(".");var precision=decimal==-1?0:formatted.length-decimal-1;if(precision<axis.tickDecimals){return(precision?formatted:formatted+".")+(""+factor).substr(1,axis.tickDecimals-precision)}}return formatted}}if($.isFunction(opts.tickFormatter))axis.tickFormatter=function(v,axis){return""+opts.tickFormatter(v,axis)};if(opts.alignTicksWithAxis!=null){var otherAxis=(axis.direction=="x"?xaxes:yaxes)[opts.alignTicksWithAxis-1];if(otherAxis&&otherAxis.used&&otherAxis!=axis){var niceTicks=axis.tickGenerator(axis);if(niceTicks.length>0){if(opts.min==null)axis.min=Math.min(axis.min,niceTicks[0]);if(opts.max==null&&niceTicks.length>1)axis.max=Math.max(axis.max,niceTicks[niceTicks.length-1])}axis.tickGenerator=function(axis){var ticks=[],v,i;for(i=0;i<otherAxis.ticks.length;++i){v=(otherAxis.ticks[i].v-otherAxis.min)/(otherAxis.max-otherAxis.min);v=axis.min+v*(axis.max-axis.min);ticks.push(v)}return ticks};if(!axis.mode&&opts.tickDecimals==null){var extraDec=Math.max(0,-Math.floor(Math.log(axis.delta)/Math.LN10)+1),ts=axis.tickGenerator(axis);if(!(ts.length>1&&/\..*0$/.test((ts[1]-ts[0]).toFixed(extraDec))))axis.tickDecimals=extraDec}}}}function setTicks(axis){var oticks=axis.options.ticks,ticks=[];if(oticks==null||typeof oticks=="number"&&oticks>0)ticks=axis.tickGenerator(axis);else if(oticks){if($.isFunction(oticks))ticks=oticks(axis);else ticks=oticks}var i,v;axis.ticks=[];for(i=0;i<ticks.length;++i){var label=null;var t=ticks[i];if(typeof t=="object"){v=+t[0];if(t.length>1)label=t[1]}else v=+t;if(label==null)label=axis.tickFormatter(v,axis);if(!isNaN(v))axis.ticks.push({v:v,label:label})}}function snapRangeToTicks(axis,ticks){if(axis.options.autoscaleMargin&&ticks.length>0){if(axis.options.min==null)axis.min=Math.min(axis.min,ticks[0].v);if(axis.options.max==null&&ticks.length>1)axis.max=Math.max(axis.max,ticks[ticks.length-1].v)}}function draw(){surface.clear();executeHooks(hooks.drawBackground,[ctx]);var grid=options.grid;if(grid.show&&grid.backgroundColor)drawBackground();if(grid.show&&!grid.aboveData){drawGrid()}for(var i=0;i<series.length;++i){executeHooks(hooks.drawSeries,[ctx,series[i]]);drawSeries(series[i])}executeHooks(hooks.draw,[ctx]);if(grid.show&&grid.aboveData){drawGrid()}surface.render();triggerRedrawOverlay()}function extractRange(ranges,coord){var axis,from,to,key,axes=allAxes();for(var i=0;i<axes.length;++i){axis=axes[i];if(axis.direction==coord){key=coord+axis.n+"axis";if(!ranges[key]&&axis.n==1)key=coord+"axis";if(ranges[key]){from=ranges[key].from;to=ranges[key].to;break}}}if(!ranges[key]){axis=coord=="x"?xaxes[0]:yaxes[0];from=ranges[coord+"1"];to=ranges[coord+"2"]}if(from!=null&&to!=null&&from>to){var tmp=from;from=to;to=tmp}return{from:from,to:to,axis:axis}}function drawBackground(){ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.fillStyle=getColorOrGradient(options.grid.backgroundColor,plotHeight,0,"rgba(255, 255, 255, 0)");ctx.fillRect(0,0,plotWidth,plotHeight);ctx.restore()}function drawGrid(){var i,axes,bw,bc;ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var markings=options.grid.markings;if(markings){if($.isFunction(markings)){axes=plot.getAxes();axes.xmin=axes.xaxis.min;axes.xmax=axes.xaxis.max;axes.ymin=axes.yaxis.min;axes.ymax=axes.yaxis.max;markings=markings(axes)}for(i=0;i<markings.length;++i){var m=markings[i],xrange=extractRange(m,"x"),yrange=extractRange(m,"y");if(xrange.from==null)xrange.from=xrange.axis.min;if(xrange.to==null)xrange.to=xrange.axis.max;
-if(yrange.from==null)yrange.from=yrange.axis.min;if(yrange.to==null)yrange.to=yrange.axis.max;if(xrange.to<xrange.axis.min||xrange.from>xrange.axis.max||yrange.to<yrange.axis.min||yrange.from>yrange.axis.max)continue;xrange.from=Math.max(xrange.from,xrange.axis.min);xrange.to=Math.min(xrange.to,xrange.axis.max);yrange.from=Math.max(yrange.from,yrange.axis.min);yrange.to=Math.min(yrange.to,yrange.axis.max);var xequal=xrange.from===xrange.to,yequal=yrange.from===yrange.to;if(xequal&&yequal){continue}xrange.from=Math.floor(xrange.axis.p2c(xrange.from));xrange.to=Math.floor(xrange.axis.p2c(xrange.to));yrange.from=Math.floor(yrange.axis.p2c(yrange.from));yrange.to=Math.floor(yrange.axis.p2c(yrange.to));if(xequal||yequal){var lineWidth=m.lineWidth||options.grid.markingsLineWidth,subPixel=lineWidth%2?.5:0;ctx.beginPath();ctx.strokeStyle=m.color||options.grid.markingsColor;ctx.lineWidth=lineWidth;if(xequal){ctx.moveTo(xrange.to+subPixel,yrange.from);ctx.lineTo(xrange.to+subPixel,yrange.to)}else{ctx.moveTo(xrange.from,yrange.to+subPixel);ctx.lineTo(xrange.to,yrange.to+subPixel)}ctx.stroke()}else{ctx.fillStyle=m.color||options.grid.markingsColor;ctx.fillRect(xrange.from,yrange.to,xrange.to-xrange.from,yrange.from-yrange.to)}}}axes=allAxes();bw=options.grid.borderWidth;for(var j=0;j<axes.length;++j){var axis=axes[j],box=axis.box,t=axis.tickLength,x,y,xoff,yoff;if(!axis.show||axis.ticks.length==0)continue;ctx.lineWidth=1;if(axis.direction=="x"){x=0;if(t=="full")y=axis.position=="top"?0:plotHeight;else y=box.top-plotOffset.top+(axis.position=="top"?box.height:0)}else{y=0;if(t=="full")x=axis.position=="left"?0:plotWidth;else x=box.left-plotOffset.left+(axis.position=="left"?box.width:0)}if(!axis.innermost){ctx.strokeStyle=axis.options.color;ctx.beginPath();xoff=yoff=0;if(axis.direction=="x")xoff=plotWidth+1;else yoff=plotHeight+1;if(ctx.lineWidth==1){if(axis.direction=="x"){y=Math.floor(y)+.5}else{x=Math.floor(x)+.5}}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff);ctx.stroke()}ctx.strokeStyle=axis.options.tickColor;ctx.beginPath();for(i=0;i<axis.ticks.length;++i){var v=axis.ticks[i].v;xoff=yoff=0;if(isNaN(v)||v<axis.min||v>axis.max||t=="full"&&(typeof bw=="object"&&bw[axis.position]>0||bw>0)&&(v==axis.min||v==axis.max))continue;if(axis.direction=="x"){x=axis.p2c(v);yoff=t=="full"?-plotHeight:t;if(axis.position=="top")yoff=-yoff}else{y=axis.p2c(v);xoff=t=="full"?-plotWidth:t;if(axis.position=="left")xoff=-xoff}if(ctx.lineWidth==1){if(axis.direction=="x")x=Math.floor(x)+.5;else y=Math.floor(y)+.5}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff)}ctx.stroke()}if(bw){bc=options.grid.borderColor;if(typeof bw=="object"||typeof bc=="object"){if(typeof bw!=="object"){bw={top:bw,right:bw,bottom:bw,left:bw}}if(typeof bc!=="object"){bc={top:bc,right:bc,bottom:bc,left:bc}}if(bw.top>0){ctx.strokeStyle=bc.top;ctx.lineWidth=bw.top;ctx.beginPath();ctx.moveTo(0-bw.left,0-bw.top/2);ctx.lineTo(plotWidth,0-bw.top/2);ctx.stroke()}if(bw.right>0){ctx.strokeStyle=bc.right;ctx.lineWidth=bw.right;ctx.beginPath();ctx.moveTo(plotWidth+bw.right/2,0-bw.top);ctx.lineTo(plotWidth+bw.right/2,plotHeight);ctx.stroke()}if(bw.bottom>0){ctx.strokeStyle=bc.bottom;ctx.lineWidth=bw.bottom;ctx.beginPath();ctx.moveTo(plotWidth+bw.right,plotHeight+bw.bottom/2);ctx.lineTo(0,plotHeight+bw.bottom/2);ctx.stroke()}if(bw.left>0){ctx.strokeStyle=bc.left;ctx.lineWidth=bw.left;ctx.beginPath();ctx.moveTo(0-bw.left/2,plotHeight+bw.bottom);ctx.lineTo(0-bw.left/2,0);ctx.stroke()}}else{ctx.lineWidth=bw;ctx.strokeStyle=options.grid.borderColor;ctx.strokeRect(-bw/2,-bw/2,plotWidth+bw,plotHeight+bw)}}ctx.restore()}function drawAxisLabels(){$.each(allAxes(),function(_,axis){var box=axis.box,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=axis.options.font||"flot-tick-label tickLabel",tick,x,y,halign,valign;surface.removeText(layer);if(!axis.show||axis.ticks.length==0)return;for(var i=0;i<axis.ticks.length;++i){tick=axis.ticks[i];if(!tick.label||tick.v<axis.min||tick.v>axis.max)continue;if(axis.direction=="x"){halign="center";x=plotOffset.left+axis.p2c(tick.v);if(axis.position=="bottom"){y=box.top+box.padding}else{y=box.top+box.height-box.padding;valign="bottom"}}else{valign="middle";y=plotOffset.top+axis.p2c(tick.v);if(axis.position=="left"){x=box.left+box.width-box.padding;halign="right"}else{x=box.left+box.padding}}surface.addText(layer,x,y,tick.label,font,null,null,halign,valign)}})}function drawSeries(series){if(series.lines.show)drawSeriesLines(series);if(series.bars.show)drawSeriesBars(series);if(series.points.show)drawSeriesPoints(series)}function drawSeriesLines(series){function plotLine(datapoints,xoffset,yoffset,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,prevx=null,prevy=null;ctx.beginPath();for(var i=ps;i<points.length;i+=ps){var x1=points[i-ps],y1=points[i-ps+1],x2=points[i],y2=points[i+1];if(x1==null||x2==null)continue;if(y1<=y2&&y1<axisy.min){if(y2<axisy.min)continue;x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min){if(y1<axisy.min)continue;x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max){if(y2>axisy.max)continue;x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max){if(y1>axisy.max)continue;x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(x1!=prevx||y1!=prevy)ctx.moveTo(axisx.p2c(x1)+xoffset,axisy.p2c(y1)+yoffset);prevx=x2;prevy=y2;ctx.lineTo(axisx.p2c(x2)+xoffset,axisy.p2c(y2)+yoffset)}ctx.stroke()}function plotLineArea(datapoints,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,bottom=Math.min(Math.max(0,axisy.min),axisy.max),i=0,top,areaOpen=false,ypos=1,segmentStart=0,segmentEnd=0;while(true){if(ps>0&&i>points.length+ps)break;i+=ps;var x1=points[i-ps],y1=points[i-ps+ypos],x2=points[i],y2=points[i+ypos];if(areaOpen){if(ps>0&&x1!=null&&x2==null){segmentEnd=i;ps=-ps;ypos=2;continue}if(ps<0&&i==segmentStart+ps){ctx.fill();areaOpen=false;ps=-ps;ypos=1;i=segmentStart=segmentEnd+ps;continue}}if(x1==null||x2==null)continue;if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(!areaOpen){ctx.beginPath();ctx.moveTo(axisx.p2c(x1),axisy.p2c(bottom));areaOpen=true}if(y1>=axisy.max&&y2>=axisy.max){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.max));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.max));continue}else if(y1<=axisy.min&&y2<=axisy.min){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.min));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.min));continue}var x1old=x1,x2old=x2;if(y1<=y2&&y1<axisy.min&&y2>=axisy.min){x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min&&y1>=axisy.min){x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max&&y2<=axisy.max){x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max&&y1<=axisy.max){x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1!=x1old){ctx.lineTo(axisx.p2c(x1old),axisy.p2c(y1))}ctx.lineTo(axisx.p2c(x1),axisy.p2c(y1));ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));if(x2!=x2old){ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));ctx.lineTo(axisx.p2c(x2old),axisy.p2c(y2))}}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineJoin="round";var lw=series.lines.lineWidth,sw=series.shadowSize;if(lw>0&&sw>0){ctx.lineWidth=sw;ctx.strokeStyle="rgba(0,0,0,0.1)";var angle=Math.PI/18;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/2),Math.cos(angle)*(lw/2+sw/2),series.xaxis,series.yaxis);ctx.lineWidth=sw/2;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/4),Math.cos(angle)*(lw/2+sw/4),series.xaxis,series.yaxis)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;var fillStyle=getFillStyle(series.lines,series.color,0,plotHeight);if(fillStyle){ctx.fillStyle=fillStyle;plotLineArea(series.datapoints,series.xaxis,series.yaxis)}if(lw>0)plotLine(series.datapoints,0,0,series.xaxis,series.yaxis);ctx.restore()}function drawSeriesPoints(series){function plotPoints(datapoints,radius,fillStyle,offset,shadow,axisx,axisy,symbol){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){var x=points[i],y=points[i+1];if(x==null||x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)continue;ctx.beginPath();x=axisx.p2c(x);y=axisy.p2c(y)+offset;if(symbol=="circle")ctx.arc(x,y,radius,0,shadow?Math.PI:Math.PI*2,false);else symbol(ctx,x,y,radius,shadow);ctx.closePath();if(fillStyle){ctx.fillStyle=fillStyle;ctx.fill()}ctx.stroke()}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var lw=series.points.lineWidth,sw=series.shadowSize,radius=series.points.radius,symbol=series.points.symbol;if(lw==0)lw=1e-4;if(lw>0&&sw>0){var w=sw/2;ctx.lineWidth=w;ctx.strokeStyle="rgba(0,0,0,0.1)";plotPoints(series.datapoints,radius,null,w+w/2,true,series.xaxis,series.yaxis,symbol);ctx.strokeStyle="rgba(0,0,0,0.2)";plotPoints(series.datapoints,radius,null,w/2,true,series.xaxis,series.yaxis,symbol)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;plotPoints(series.datapoints,radius,getFillStyle(series.points,series.color),0,false,series.xaxis,series.yaxis,symbol);ctx.restore()}function drawBar(x,y,b,barLeft,barRight,fillStyleCallback,axisx,axisy,c,horizontal,lineWidth){var left,right,bottom,top,drawLeft,drawRight,drawTop,drawBottom,tmp;if(horizontal){drawBottom=drawRight=drawTop=true;drawLeft=false;left=b;right=x;top=y+barLeft;bottom=y+barRight;if(right<left){tmp=right;right=left;left=tmp;drawLeft=true;drawRight=false}}else{drawLeft=drawRight=drawTop=true;drawBottom=false;left=x+barLeft;right=x+barRight;bottom=b;top=y;if(top<bottom){tmp=top;top=bottom;bottom=tmp;drawBottom=true;drawTop=false}}if(right<axisx.min||left>axisx.max||top<axisy.min||bottom>axisy.max)return;if(left<axisx.min){left=axisx.min;drawLeft=false}if(right>axisx.max){right=axisx.max;drawRight=false}if(bottom<axisy.min){bottom=axisy.min;drawBottom=false}if(top>axisy.max){top=axisy.max;drawTop=false}left=axisx.p2c(left);bottom=axisy.p2c(bottom);right=axisx.p2c(right);top=axisy.p2c(top);if(fillStyleCallback){c.fillStyle=fillStyleCallback(bottom,top);c.fillRect(left,top,right-left,bottom-top)}if(lineWidth>0&&(drawLeft||drawRight||drawTop||drawBottom)){c.beginPath();c.moveTo(left,bottom);if(drawLeft)c.lineTo(left,top);else c.moveTo(left,top);if(drawTop)c.lineTo(right,top);else c.moveTo(right,top);if(drawRight)c.lineTo(right,bottom);else c.moveTo(right,bottom);if(drawBottom)c.lineTo(left,bottom);else c.moveTo(left,bottom);c.stroke()}}function drawSeriesBars(series){function plotBars(datapoints,barLeft,barRight,fillStyleCallback,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){if(points[i]==null)continue;drawBar(points[i],points[i+1],points[i+2],barLeft,barRight,fillStyleCallback,axisx,axisy,ctx,series.bars.horizontal,series.bars.lineWidth)}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineWidth=series.bars.lineWidth;ctx.strokeStyle=series.color;var barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}var fillStyleCallback=series.bars.fill?function(bottom,top){return getFillStyle(series.bars,series.color,bottom,top)}:null;plotBars(series.datapoints,barLeft,barLeft+series.bars.barWidth,fillStyleCallback,series.xaxis,series.yaxis);ctx.restore()}function getFillStyle(filloptions,seriesColor,bottom,top){var fill=filloptions.fill;if(!fill)return null;if(filloptions.fillColor)return getColorOrGradient(filloptions.fillColor,bottom,top,seriesColor);var c=$.color.parse(seriesColor);c.a=typeof fill=="number"?fill:.4;c.normalize();return c.toString()}function insertLegend(){if(options.legend.container!=null){$(options.legend.container).html("")}else{placeholder.find(".legend").remove()}if(!options.legend.show){return}var fragments=[],entries=[],rowStarted=false,lf=options.legend.labelFormatter,s,label;for(var i=0;i<series.length;++i){s=series[i];if(s.label){label=lf?lf(s.label,s):s.label;if(label){entries.push({label:label,color:s.color})}}}if(options.legend.sorted){if($.isFunction(options.legend.sorted)){entries.sort(options.legend.sorted)}else if(options.legend.sorted=="reverse"){entries.reverse()}else{var ascending=options.legend.sorted!="descending";entries.sort(function(a,b){return a.label==b.label?0:a.label<b.label!=ascending?1:-1})}}for(var i=0;i<entries.length;++i){var entry=entries[i];if(i%options.legend.noColumns==0){if(rowStarted)fragments.push("</tr>");fragments.push("<tr>");rowStarted=true}fragments.push('<td class="legendColorBox"><div style="border:1px solid '+options.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+entry.color+';overflow:hidden"></div></div></td>'+'<td class="legendLabel">'+entry.label+"</td>")}if(rowStarted)fragments.push("</tr>");if(fragments.length==0)return;var table='<table style="font-size:smaller;color:'+options.grid.color+'">'+fragments.join("")+"</table>";if(options.legend.container!=null)$(options.legend.container).html(table);else{var pos="",p=options.legend.position,m=options.legend.margin;if(m[0]==null)m=[m,m];if(p.charAt(0)=="n")pos+="top:"+(m[1]+plotOffset.top)+"px;";else if(p.charAt(0)=="s")pos+="bottom:"+(m[1]+plotOffset.bottom)+"px;";if(p.charAt(1)=="e")pos+="right:"+(m[0]+plotOffset.right)+"px;";else if(p.charAt(1)=="w")pos+="left:"+(m[0]+plotOffset.left)+"px;";var legend=$('<div class="legend">'+table.replace('style="','style="position:absolute;'+pos+";")+"</div>").appendTo(placeholder);if(options.legend.backgroundOpacity!=0){var c=options.legend.backgroundColor;if(c==null){c=options.grid.backgroundColor;if(c&&typeof c=="string")c=$.color.parse(c);else c=$.color.extract(legend,"background-color");c.a=1;c=c.toString()}var div=legend.children();$('<div style="position:absolute;width:'+div.width()+"px;height:"+div.height()+"px;"+pos+"background-color:"+c+';"> </div>').prependTo(legend).css("opacity",options.legend.backgroundOpacity)}}}var highlights=[],redrawTimeout=null;function findNearbyItem(mouseX,mouseY,seriesFilter){var maxDistance=options.grid.mouseActiveRadius,smallestDistance=maxDistance*maxDistance+1,item=null,foundPoint=false,i,j,ps;for(i=series.length-1;i>=0;--i){if(!seriesFilter(series[i]))continue;var s=series[i],axisx=s.xaxis,axisy=s.yaxis,points=s.datapoints.points,mx=axisx.c2p(mouseX),my=axisy.c2p(mouseY),maxx=maxDistance/axisx.scale,maxy=maxDistance/axisy.scale;ps=s.datapoints.pointsize;if(axisx.options.inverseTransform)maxx=Number.MAX_VALUE;if(axisy.options.inverseTransform)maxy=Number.MAX_VALUE;if(s.lines.show||s.points.show){for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1];if(x==null)continue;if(x-mx>maxx||x-mx<-maxx||y-my>maxy||y-my<-maxy)continue;var dx=Math.abs(axisx.p2c(x)-mouseX),dy=Math.abs(axisy.p2c(y)-mouseY),dist=dx*dx+dy*dy;if(dist<smallestDistance){smallestDistance=dist;item=[i,j/ps]}}}if(s.bars.show&&!item){var barLeft,barRight;switch(s.bars.align){case"left":barLeft=0;break;case"right":barLeft=-s.bars.barWidth;break;default:barLeft=-s.bars.barWidth/2}barRight=barLeft+s.bars.barWidth;for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1],b=points[j+2];if(x==null)continue;if(series[i].bars.horizontal?mx<=Math.max(b,x)&&mx>=Math.min(b,x)&&my>=y+barLeft&&my<=y+barRight:mx>=x+barLeft&&mx<=x+barRight&&my>=Math.min(b,y)&&my<=Math.max(b,y))item=[i,j/ps]}}}if(item){i=item[0];j=item[1];ps=series[i].datapoints.pointsize;return{datapoint:series[i].datapoints.points.slice(j*ps,(j+1)*ps),dataIndex:j,series:series[i],seriesIndex:i}}return null}function onMouseMove(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return s["hoverable"]!=false})}function onMouseLeave(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return false})}function onClick(e){triggerClickHoverEvent("plotclick",e,function(s){return s["clickable"]!=false})}function triggerClickHoverEvent(eventname,event,seriesFilter){var offset=eventHolder.offset(),canvasX=event.pageX-offset.left-plotOffset.left,canvasY=event.pageY-offset.top-plotOffset.top,pos=canvasToAxisCoords({left:canvasX,top:canvasY});pos.pageX=event.pageX;pos.pageY=event.pageY;var item=findNearbyItem(canvasX,canvasY,seriesFilter);if(item){item.pageX=parseInt(item.series.xaxis.p2c(item.datapoint[0])+offset.left+plotOffset.left,10);item.pageY=parseInt(item.series.yaxis.p2c(item.datapoint[1])+offset.top+plotOffset.top,10)}if(options.grid.autoHighlight){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.auto==eventname&&!(item&&h.series==item.series&&h.point[0]==item.datapoint[0]&&h.point[1]==item.datapoint[1]))unhighlight(h.series,h.point)}if(item)highlight(item.series,item.datapoint,eventname)}placeholder.trigger(eventname,[pos,item])}function triggerRedrawOverlay(){var t=options.interaction.redrawOverlayInterval;if(t==-1){drawOverlay();return}if(!redrawTimeout)redrawTimeout=setTimeout(drawOverlay,t)}function drawOverlay(){redrawTimeout=null;octx.save();overlay.clear();octx.translate(plotOffset.left,plotOffset.top);var i,hi;for(i=0;i<highlights.length;++i){hi=highlights[i];if(hi.series.bars.show)drawBarHighlight(hi.series,hi.point);else drawPointHighlight(hi.series,hi.point)}octx.restore();executeHooks(hooks.drawOverlay,[octx])}function highlight(s,point,auto){if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i==-1){highlights.push({series:s,point:point,auto:auto});triggerRedrawOverlay()}else if(!auto)highlights[i].auto=false}function unhighlight(s,point){if(s==null&&point==null){highlights=[];triggerRedrawOverlay();return}if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i!=-1){highlights.splice(i,1);triggerRedrawOverlay()}}function indexOfHighlight(s,p){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.series==s&&h.point[0]==p[0]&&h.point[1]==p[1])return i}return-1}function drawPointHighlight(series,point){var x=point[0],y=point[1],axisx=series.xaxis,axisy=series.yaxis,highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString();if(x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)return;var pointRadius=series.points.radius+series.points.lineWidth/2;octx.lineWidth=pointRadius;octx.strokeStyle=highlightColor;var radius=1.5*pointRadius;x=axisx.p2c(x);y=axisy.p2c(y);octx.beginPath();if(series.points.symbol=="circle")octx.arc(x,y,radius,0,2*Math.PI,false);else series.points.symbol(octx,x,y,radius,false);octx.closePath();octx.stroke()}function drawBarHighlight(series,point){var highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString(),fillStyle=highlightColor,barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}octx.lineWidth=series.bars.lineWidth;octx.strokeStyle=highlightColor;drawBar(point[0],point[1],point[2]||0,barLeft,barLeft+series.bars.barWidth,function(){return fillStyle},series.xaxis,series.yaxis,octx,series.bars.horizontal,series.bars.lineWidth)}function getColorOrGradient(spec,bottom,top,defaultColor){if(typeof spec=="string")return spec;else{var gradient=ctx.createLinearGradient(0,top,0,bottom);for(var i=0,l=spec.colors.length;i<l;++i){var c=spec.colors[i];if(typeof c!="string"){var co=$.color.parse(defaultColor);if(c.brightness!=null)co=co.scale("rgb",c.brightness);if(c.opacity!=null)co.a*=c.opacity;c=co.toString()}gradient.addColorStop(i/(l-1),c)}return gradient}}}$.plot=function(placeholder,data,options){var plot=new Plot($(placeholder),data,options,$.plot.plugins);return plot};$.plot.version="0.8.3";$.plot.plugins=[];$.fn.plot=function(data,options){return this.each(function(){$.plot(this,data,options)})};function floorInBase(n,base){return base*Math.floor(n/base)}})(jQuery);
+/* Javascript plotting library for jQuery, version 0.8.3.
+
+Copyright (c) 2007-2014 IOLA and Ole Laursen.
+Licensed under the MIT license.
+
+*/
+(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function($){var hasOwnProperty=Object.prototype.hasOwnProperty;if(!$.fn.detach){$.fn.detach=function(){return this.each(function(){if(this.parentNode){this.parentNode.removeChild(this)}})}}function Canvas(cls,container){var element=container.children("."+cls)[0];if(element==null){element=document.createElement("canvas");element.className=cls;$(element).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(container);if(!element.getContext){if(window.G_vmlCanvasManager){element=window.G_vmlCanvasManager.initElement(element)}else{throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.")}}}this.element=element;var context=this.context=element.getContext("2d");var devicePixelRatio=window.devicePixelRatio||1,backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingStorePixelRatio||context.msBackingStorePixelRatio||context.oBackingStorePixelRatio||context.backingStorePixelRatio||1;this.pixelRatio=devicePixelRatio/backingStoreRatio;this.resize(container.width(),container.height());this.textContainer=null;this.text={};this._textCache={}}Canvas.prototype.resize=function(width,height){if(width<=0||height<=0){throw new Error("Invalid dimensions for plot, width = "+width+", height = "+height)}var element=this.element,context=this.context,pixelRatio=this.pixelRatio;if(this.width!=width){element.width=width*pixelRatio;element.style.width=width+"px";this.width=width}if(this.height!=height){element.height=height*pixelRatio;element.style.height=height+"px";this.height=height}context.restore();context.save();context.scale(pixelRatio,pixelRatio)};Canvas.prototype.clear=function(){this.context.clearRect(0,0,this.width,this.height)};Canvas.prototype.render=function(){var cache=this._textCache;for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layer=this.getTextLayer(layerKey),layerCache=cache[layerKey];layer.hide();for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){if(position.active){if(!position.rendered){layer.append(position.element);position.rendered=true}}else{positions.splice(i--,1);if(position.rendered){position.element.detach()}}}if(positions.length==0){delete styleCache[key]}}}}}layer.show()}}};Canvas.prototype.getTextLayer=function(classes){var layer=this.text[classes];if(layer==null){if(this.textContainer==null){this.textContainer=$("<div class='flot-text'></div>").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)}layer=this.text[classes]=$("<div></div>").addClass(classes).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)}return layer};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px/"+font.lineHeight+"px "+font.family}else{textStyle=font}layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={}}styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={}}info=styleCache[text];if(info==null){var element=$("<div></div>").html(text).css({position:"absolute","max-width":width,top:-9999}).appendTo(this.getTextLayer(layer));if(typeof font==="object"){element.css({font:textStyle,color:font.color})}else if(typeof font==="string"){element.addClass(font)}info=styleCache[text]={width:element.outerWidth(true),height:element.outerHeight(true),element:element,positions:[]};element.detach()}return info};Canvas.prototype.addText=function(layer,x,y,text,font,angle,width,halign,valign){var info=this.getTextInfo(layer,text,font,angle,width),positions=info.positions;if(halign=="center"){x-=info.width/2}else if(halign=="right"){x-=info.width}if(valign=="middle"){y-=info.height/2}else if(valign=="bottom"){y-=info.height}for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=true;return}}position={active:true,rendered:false,element:positions.length?info.element.clone():info.element,x:x,y:y};positions.push(position);position.element.css({top:Math.round(y),left:Math.round(x),"text-align":halign})};Canvas.prototype.removeText=function(layer,x,y,text,font,angle){if(text==null){var layerCache=this._textCache[layer];if(layerCache!=null){for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){position.active=false}}}}}}}else{var positions=this.getTextInfo(layer,text,font,angle).positions;for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=false}}}};function Plot(placeholder,data_,options_,plugins){var series=[],options={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:.85,sorted:null},xaxis:{show:null,position:"bottom",mode:null,font:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null},yaxis:{autoscaleMargin:.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false,zero:true},shadowSize:3,highlightColor:null},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,margin:0,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},interaction:{redrawOverlayInterval:1e3/60},hooks:{}},surface=null,overlay=null,eventHolder=null,ctx=null,octx=null,xaxes=[],yaxes=[],plotOffset={left:0,right:0,top:0,bottom:0},plotWidth=0,plotHeight=0,hooks={processOptions:[],processRawData:[],processDatapoints:[],processOffset:[],drawBackground:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},plot=this;plot.setData=setData;plot.setupGrid=setupGrid;plot.draw=draw;plot.getPlaceholder=function(){return placeholder};plot.getCanvas=function(){return surface.element};plot.getPlotOffset=function(){return plotOffset};plot.width=function(){return plotWidth};plot.height=function(){return plotHeight};plot.offset=function(){var o=eventHolder.offset();o.left+=plotOffset.left;o.top+=plotOffset.top;return o};plot.getData=function(){return series};plot.getAxes=function(){var res={},i;$.each(xaxes.concat(yaxes),function(_,axis){if(axis)res[axis.direction+(axis.n!=1?axis.n:"")+"axis"]=axis});return res};plot.getXAxes=function(){return xaxes};plot.getYAxes=function(){return yaxes};plot.c2p=canvasToAxisCoords;plot.p2c=axisToCanvasCoords;plot.getOptions=function(){return options};plot.highlight=highlight;plot.unhighlight=unhighlight;plot.triggerRedrawOverlay=triggerRedrawOverlay;plot.pointOffset=function(point){return{left:parseInt(xaxes[axisNumber(point,"x")-1].p2c(+point.x)+plotOffset.left,10),top:parseInt(yaxes[axisNumber(point,"y")-1].p2c(+point.y)+plotOffset.top,10)}};plot.shutdown=shutdown;plot.destroy=function(){shutdown();placeholder.removeData("plot").empty();series=[];options=null;surface=null;overlay=null;eventHolder=null;ctx=null;octx=null;xaxes=[];yaxes=[];hooks=null;highlights=[];plot=null};plot.resize=function(){var width=placeholder.width(),height=placeholder.height();surface.resize(width,height);overlay.resize(width,height)};plot.hooks=hooks;initPlugins(plot);parseOptions(options_);setupCanvases();setData(data_);setupGrid();draw();bindEvents();function executeHooks(hook,args){args=[plot].concat(args);for(var i=0;i<hook.length;++i)hook[i].apply(this,args)}function initPlugins(){var classes={Canvas:Canvas};for(var i=0;i<plugins.length;++i){var p=plugins[i];p.init(plot,classes);if(p.options)$.extend(true,options,p.options)}}function parseOptions(opts){$.extend(true,options,opts);if(opts&&opts.colors){options.colors=opts.colors}if(options.xaxis.color==null)options.xaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.yaxis.color==null)options.yaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.xaxis.tickColor==null)options.xaxis.tickColor=options.grid.tickColor||options.xaxis.color;if(options.yaxis.tickColor==null)options.yaxis.tickColor=options.grid.tickColor||options.yaxis.color;if(options.grid.borderColor==null)options.grid.borderColor=options.grid.color;if(options.grid.tickColor==null)options.grid.tickColor=$.color.parse(options.grid.color).scale("a",.22).toString();var i,axisOptions,axisCount,fontSize=placeholder.css("font-size"),fontSizeDefault=fontSize?+fontSize.replace("px",""):13,fontDefaults={style:placeholder.css("font-style"),size:Math.round(.8*fontSizeDefault),variant:placeholder.css("font-variant"),weight:placeholder.css("font-weight"),family:placeholder.css("font-family")};axisCount=options.xaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.xaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.xaxis,axisOptions);options.xaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}axisCount=options.yaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.yaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.yaxis,axisOptions);options.yaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}if(options.xaxis.noTicks&&options.xaxis.ticks==null)options.xaxis.ticks=options.xaxis.noTicks;if(options.yaxis.noTicks&&options.yaxis.ticks==null)options.yaxis.ticks=options.yaxis.noTicks;if(options.x2axis){options.xaxes[1]=$.extend(true,{},options.xaxis,options.x2axis);options.xaxes[1].position="top";if(options.x2axis.min==null){options.xaxes[1].min=null}if(options.x2axis.max==null){options.xaxes[1].max=null}}if(options.y2axis){options.yaxes[1]=$.extend(true,{},options.yaxis,options.y2axis);options.yaxes[1].position="right";if(options.y2axis.min==null){options.yaxes[1].min=null}if(options.y2axis.max==null){options.yaxes[1].max=null}}if(options.grid.coloredAreas)options.grid.markings=options.grid.coloredAreas;if(options.grid.coloredAreasColor)options.grid.markingsColor=options.grid.coloredAreasColor;if(options.lines)$.extend(true,options.series.lines,options.lines);if(options.points)$.extend(true,options.series.points,options.points);if(options.bars)$.extend(true,options.series.bars,options.bars);if(options.shadowSize!=null)options.series.shadowSize=options.shadowSize;if(options.highlightColor!=null)options.series.highlightColor=options.highlightColor;for(i=0;i<options.xaxes.length;++i)getOrCreateAxis(xaxes,i+1).options=options.xaxes[i];for(i=0;i<options.yaxes.length;++i)getOrCreateAxis(yaxes,i+1).options=options.yaxes[i];for(var n in hooks)if(options.hooks[n]&&options.hooks[n].length)hooks[n]=hooks[n].concat(options.hooks[n]);executeHooks(hooks.processOptions,[options])}function setData(d){series=parseData(d);fillInSeriesOptions();processData()}function parseData(d){var res=[];for(var i=0;i<d.length;++i){var s=$.extend(true,{},options.series);if(d[i].data!=null){s.data=d[i].data;delete d[i].data;$.extend(true,s,d[i]);d[i].data=s.data}else s.data=d[i];res.push(s)}return res}function axisNumber(obj,coord){var a=obj[coord+"axis"];if(typeof a=="object")a=a.n;if(typeof a!="number")a=1;return a}function allAxes(){return $.grep(xaxes.concat(yaxes),function(a){return a})}function canvasToAxisCoords(pos){var res={},i,axis;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used)res["x"+axis.n]=axis.c2p(pos.left)}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used)res["y"+axis.n]=axis.c2p(pos.top)}if(res.x1!==undefined)res.x=res.x1;if(res.y1!==undefined)res.y=res.y1;return res}function axisToCanvasCoords(pos){var res={},i,axis,key;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used){key="x"+axis.n;if(pos[key]==null&&axis.n==1)key="x";if(pos[key]!=null){res.left=axis.p2c(pos[key]);break}}}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used){key="y"+axis.n;if(pos[key]==null&&axis.n==1)key="y";if(pos[key]!=null){res.top=axis.p2c(pos[key]);break}}}return res}function getOrCreateAxis(axes,number){if(!axes[number-1])axes[number-1]={n:number,direction:axes==xaxes?"x":"y",options:$.extend(true,{},axes==xaxes?options.xaxis:options.yaxis)};return axes[number-1]}function fillInSeriesOptions(){var neededColors=series.length,maxIndex=-1,i;for(i=0;i<series.length;++i){var sc=series[i].color;if(sc!=null){neededColors--;if(typeof sc=="number"&&sc>maxIndex){maxIndex=sc}}}if(neededColors<=maxIndex){neededColors=maxIndex+1}var c,colors=[],colorPool=options.colors,colorPoolSize=colorPool.length,variation=0;for(i=0;i<neededColors;i++){c=$.color.parse(colorPool[i%colorPoolSize]||"#666");if(i%colorPoolSize==0&&i){if(variation>=0){if(variation<.5){variation=-variation-.2}else variation=0}else variation=-variation}colors[i]=c.scale("rgb",1+variation)}var colori=0,s;for(i=0;i<series.length;++i){s=series[i];if(s.color==null){s.color=colors[colori].toString();++colori}else if(typeof s.color=="number")s.color=colors[s.color].toString();if(s.lines.show==null){var v,show=true;for(v in s)if(s[v]&&s[v].show){show=false;break}if(show)s.lines.show=true}if(s.lines.zero==null){s.lines.zero=!!s.lines.fill}s.xaxis=getOrCreateAxis(xaxes,axisNumber(s,"x"));s.yaxis=getOrCreateAxis(yaxes,axisNumber(s,"y"))}}function processData(){var topSentry=Number.POSITIVE_INFINITY,bottomSentry=Number.NEGATIVE_INFINITY,fakeInfinity=Number.MAX_VALUE,i,j,k,m,length,s,points,ps,x,y,axis,val,f,p,data,format;function updateAxis(axis,min,max){if(min<axis.datamin&&min!=-fakeInfinity)axis.datamin=min;if(max>axis.datamax&&max!=fakeInfinity)axis.datamax=max}$.each(allAxes(),function(_,axis){axis.datamin=topSentry;axis.datamax=bottomSentry;axis.used=false});for(i=0;i<series.length;++i){s=series[i];s.datapoints={points:[]};executeHooks(hooks.processRawData,[s,s.data,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];data=s.data;format=s.datapoints.format;if(!format){format=[];format.push({x:true,number:true,required:true});format.push({y:true,number:true,required:true});if(s.bars.show||s.lines.show&&s.lines.fill){var autoscale=!!(s.bars.show&&s.bars.zero||s.lines.show&&s.lines.zero);format.push({y:true,number:true,required:false,defaultValue:0,autoscale:autoscale});if(s.bars.horizontal){delete format[format.length-1].y;format[format.length-1].x=true}}s.datapoints.format=format}if(s.datapoints.pointsize!=null)continue;s.datapoints.pointsize=format.length;ps=s.datapoints.pointsize;points=s.datapoints.points;var insertSteps=s.lines.show&&s.lines.steps;s.xaxis.used=s.yaxis.used=true;for(j=k=0;j<data.length;++j,k+=ps){p=data[j];var nullify=p==null;if(!nullify){for(m=0;m<ps;++m){val=p[m];f=format[m];if(f){if(f.number&&val!=null){val=+val;if(isNaN(val))val=null;else if(val==Infinity)val=fakeInfinity;else if(val==-Infinity)val=-fakeInfinity}if(val==null){if(f.required)nullify=true;if(f.defaultValue!=null)val=f.defaultValue}}points[k+m]=val}}if(nullify){for(m=0;m<ps;++m){val=points[k+m];if(val!=null){f=format[m];if(f.autoscale!==false){if(f.x){updateAxis(s.xaxis,val,val)}if(f.y){updateAxis(s.yaxis,val,val)}}}points[k+m]=null}}else{if(insertSteps&&k>0&&points[k-ps]!=null&&points[k-ps]!=points[k]&&points[k-ps+1]!=points[k+1]){for(m=0;m<ps;++m)points[k+ps+m]=points[k+m];points[k+1]=points[k-ps+1];k+=ps}}}}for(i=0;i<series.length;++i){s=series[i];executeHooks(hooks.processDatapoints,[s,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];points=s.datapoints.points;ps=s.datapoints.pointsize;format=s.datapoints.format;var xmin=topSentry,ymin=topSentry,xmax=bottomSentry,ymax=bottomSentry;for(j=0;j<points.length;j+=ps){if(points[j]==null)continue;for(m=0;m<ps;++m){val=points[j+m];f=format[m];if(!f||f.autoscale===false||val==fakeInfinity||val==-fakeInfinity)continue;if(f.x){if(val<xmin)xmin=val;if(val>xmax)xmax=val}if(f.y){if(val<ymin)ymin=val;if(val>ymax)ymax=val}}}if(s.bars.show){var delta;switch(s.bars.align){case"left":delta=0;break;case"right":delta=-s.bars.barWidth;break;default:delta=-s.bars.barWidth/2}if(s.bars.horizontal){ymin+=delta;ymax+=delta+s.bars.barWidth}else{xmin+=delta;xmax+=delta+s.bars.barWidth}}updateAxis(s.xaxis,xmin,xmax);updateAxis(s.yaxis,ymin,ymax)}$.each(allAxes(),function(_,axis){if(axis.datamin==topSentry)axis.datamin=null;if(axis.datamax==bottomSentry)axis.datamax=null})}function setupCanvases(){placeholder.css("padding",0).children().filter(function(){return!$(this).hasClass("flot-overlay")&&!$(this).hasClass("flot-base")}).remove();if(placeholder.css("position")=="static")placeholder.css("position","relative");surface=new Canvas("flot-base",placeholder);overlay=new Canvas("flot-overlay",placeholder);ctx=surface.context;octx=overlay.context;eventHolder=$(overlay.element).unbind();var existing=placeholder.data("plot");if(existing){existing.shutdown();overlay.clear()}placeholder.data("plot",plot)}function bindEvents(){if(options.grid.hoverable){eventHolder.mousemove(onMouseMove);eventHolder.bind("mouseleave",onMouseLeave)}if(options.grid.clickable)eventHolder.click(onClick);executeHooks(hooks.bindEvents,[eventHolder])}function shutdown(){if(redrawTimeout)clearTimeout(redrawTimeout);eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mouseleave",onMouseLeave);eventHolder.unbind("click",onClick);executeHooks(hooks.shutdown,[eventHolder])}function setTransformationHelpers(axis){function identity(x){return x}var s,m,t=axis.options.transform||identity,it=axis.options.inverseTransform;if(axis.direction=="x"){s=axis.scale=plotWidth/Math.abs(t(axis.max)-t(axis.min));m=Math.min(t(axis.max),t(axis.min))}else{s=axis.scale=plotHeight/Math.abs(t(axis.max)-t(axis.min));s=-s;m=Math.max(t(axis.max),t(axis.min))}if(t==identity)axis.p2c=function(p){return(p-m)*s};else axis.p2c=function(p){return(t(p)-m)*s};if(!it)axis.c2p=function(c){return m+c/s};else axis.c2p=function(c){return it(m+c/s)}}function measureTickLabels(axis){var opts=axis.options,ticks=axis.ticks||[],labelWidth=opts.labelWidth||0,labelHeight=opts.labelHeight||0,maxWidth=labelWidth||(axis.direction=="x"?Math.floor(surface.width/(ticks.length||1)):null),legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=opts.font||"flot-tick-label tickLabel";for(var i=0;i<ticks.length;++i){var t=ticks[i];if(!t.label)continue;var info=surface.getTextInfo(layer,t.label,font,null,maxWidth);labelWidth=Math.max(labelWidth,info.width);labelHeight=Math.max(labelHeight,info.height)}axis.labelWidth=opts.labelWidth||labelWidth;axis.labelHeight=opts.labelHeight||labelHeight}function allocateAxisBoxFirstPhase(axis){var lw=axis.labelWidth,lh=axis.labelHeight,pos=axis.options.position,isXAxis=axis.direction==="x",tickLength=axis.options.tickLength,axisMargin=options.grid.axisMargin,padding=options.grid.labelMargin,innermost=true,outermost=true,first=true,found=false;$.each(isXAxis?xaxes:yaxes,function(i,a){if(a&&(a.show||a.reserveSpace)){if(a===axis){found=true}else if(a.options.position===pos){if(found){outermost=false}else{innermost=false}}if(!found){first=false}}});if(outermost){axisMargin=0}if(tickLength==null){tickLength=first?"full":5}if(!isNaN(+tickLength))padding+=+tickLength;if(isXAxis){lh+=padding;if(pos=="bottom"){plotOffset.bottom+=lh+axisMargin;axis.box={top:surface.height-plotOffset.bottom,height:lh}}else{axis.box={top:plotOffset.top+axisMargin,height:lh};plotOffset.top+=lh+axisMargin}}else{lw+=padding;if(pos=="left"){axis.box={left:plotOffset.left+axisMargin,width:lw};plotOffset.left+=lw+axisMargin}else{plotOffset.right+=lw+axisMargin;axis.box={left:surface.width-plotOffset.right,width:lw}}}axis.position=pos;axis.tickLength=tickLength;axis.box.padding=padding;axis.innermost=innermost}function allocateAxisBoxSecondPhase(axis){if(axis.direction=="x"){axis.box.left=plotOffset.left-axis.labelWidth/2;axis.box.width=surface.width-plotOffset.left-plotOffset.right+axis.labelWidth}else{axis.box.top=plotOffset.top-axis.labelHeight/2;axis.box.height=surface.height-plotOffset.bottom-plotOffset.top+axis.labelHeight}}function adjustLayoutForThingsStickingOut(){var minMargin=options.grid.minBorderMargin,axis,i;if(minMargin==null){minMargin=0;for(i=0;i<series.length;++i)minMargin=Math.max(minMargin,2*(series[i].points.radius+series[i].points.lineWidth/2))}var margins={left:minMargin,right:minMargin,top:minMargin,bottom:minMargin};$.each(allAxes(),function(_,axis){if(axis.reserveSpace&&axis.ticks&&axis.ticks.length){if(axis.direction==="x"){margins.left=Math.max(margins.left,axis.labelWidth/2);margins.right=Math.max(margins.right,axis.labelWidth/2)}else{margins.bottom=Math.max(margins.bottom,axis.labelHeight/2);margins.top=Math.max(margins.top,axis.labelHeight/2)}}});plotOffset.left=Math.ceil(Math.max(margins.left,plotOffset.left));plotOffset.right=Math.ceil(Math.max(margins.right,plotOffset.right));plotOffset.top=Math.ceil(Math.max(margins.top,plotOffset.top));plotOffset.bottom=Math.ceil(Math.max(margins.bottom,plotOffset.bottom))}function setupGrid(){var i,axes=allAxes(),showGrid=options.grid.show;for(var a in plotOffset){var margin=options.grid.margin||0;plotOffset[a]=typeof margin=="number"?margin:margin[a]||0}executeHooks(hooks.processOffset,[plotOffset]);for(var a in plotOffset){if(typeof options.grid.borderWidth=="object"){plotOffset[a]+=showGrid?options.grid.borderWidth[a]:0}else{plotOffset[a]+=showGrid?options.grid.borderWidth:0}}$.each(axes,function(_,axis){var axisOpts=axis.options;axis.show=axisOpts.show==null?axis.used:axisOpts.show;axis.reserveSpace=axisOpts.reserveSpace==null?axis.show:axisOpts.reserveSpace;setRange(axis)});if(showGrid){var allocatedAxes=$.grep(axes,function(axis){return axis.show||axis.reserveSpace});$.each(allocatedAxes,function(_,axis){setupTickGeneration(axis);setTicks(axis);snapRangeToTicks(axis,axis.ticks);measureTickLabels(axis)});for(i=allocatedAxes.length-1;i>=0;--i)allocateAxisBoxFirstPhase(allocatedAxes[i]);adjustLayoutForThingsStickingOut();$.each(allocatedAxes,function(_,axis){allocateAxisBoxSecondPhase(axis)})}plotWidth=surface.width-plotOffset.left-plotOffset.right;plotHeight=surface.height-plotOffset.bottom-plotOffset.top;$.each(axes,function(_,axis){setTransformationHelpers(axis)});if(showGrid){drawAxisLabels()}insertLegend()}function setRange(axis){var opts=axis.options,min=+(opts.min!=null?opts.min:axis.datamin),max=+(opts.max!=null?opts.max:axis.datamax),delta=max-min;if(delta==0){var widen=max==0?1:.01;if(opts.min==null)min-=widen;if(opts.max==null||opts.min!=null)max+=widen}else{var margin=opts.autoscaleMargin;if(margin!=null){if(opts.min==null){min-=delta*margin;if(min<0&&axis.datamin!=null&&axis.datamin>=0)min=0}if(opts.max==null){max+=delta*margin;if(max>0&&axis.datamax!=null&&axis.datamax<=0)max=0}}}axis.min=min;axis.max=max}function setupTickGeneration(axis){var opts=axis.options;var noTicks;if(typeof opts.ticks=="number"&&opts.ticks>0)noTicks=opts.ticks;else noTicks=.3*Math.sqrt(axis.direction=="x"?surface.width:surface.height);var delta=(axis.max-axis.min)/noTicks,dec=-Math.floor(Math.log(delta)/Math.LN10),maxDec=opts.tickDecimals;if(maxDec!=null&&dec>maxDec){dec=maxDec}var magn=Math.pow(10,-dec),norm=delta/magn,size;if(norm<1.5){size=1}else if(norm<3){size=2;if(norm>2.25&&(maxDec==null||dec+1<=maxDec)){size=2.5;++dec}}else if(norm<7.5){size=5}else{size=10}size*=magn;if(opts.minTickSize!=null&&size<opts.minTickSize){size=opts.minTickSize}axis.delta=delta;axis.tickDecimals=Math.max(0,maxDec!=null?maxDec:dec);axis.tickSize=opts.tickSize||size;if(opts.mode=="time"&&!axis.tickGenerator){throw new Error("Time mode requires the flot.time plugin.")}if(!axis.tickGenerator){axis.tickGenerator=function(axis){var ticks=[],start=floorInBase(axis.min,axis.tickSize),i=0,v=Number.NaN,prev;do{prev=v;v=start+i*axis.tickSize;ticks.push(v);++i}while(v<axis.max&&v!=prev);return ticks};axis.tickFormatter=function(value,axis){var factor=axis.tickDecimals?Math.pow(10,axis.tickDecimals):1;var formatted=""+Math.round(value*factor)/factor;if(axis.tickDecimals!=null){var decimal=formatted.indexOf(".");var precision=decimal==-1?0:formatted.length-decimal-1;if(precision<axis.tickDecimals){return(precision?formatted:formatted+".")+(""+factor).substr(1,axis.tickDecimals-precision)}}return formatted}}if($.isFunction(opts.tickFormatter))axis.tickFormatter=function(v,axis){return""+opts.tickFormatter(v,axis)};if(opts.alignTicksWithAxis!=null){var otherAxis=(axis.direction=="x"?xaxes:yaxes)[opts.alignTicksWithAxis-1];if(otherAxis&&otherAxis.used&&otherAxis!=axis){var niceTicks=axis.tickGenerator(axis);if(niceTicks.length>0){if(opts.min==null)axis.min=Math.min(axis.min,niceTicks[0]);if(opts.max==null&&niceTicks.length>1)axis.max=Math.max(axis.max,niceTicks[niceTicks.length-1])}axis.tickGenerator=function(axis){var ticks=[],v,i;for(i=0;i<otherAxis.ticks.length;++i){v=(otherAxis.ticks[i].v-otherAxis.min)/(otherAxis.max-otherAxis.min);v=axis.min+v*(axis.max-axis.min);ticks.push(v)}return ticks};if(!axis.mode&&opts.tickDecimals==null){var extraDec=Math.max(0,-Math.floor(Math.log(axis.delta)/Math.LN10)+1),ts=axis.tickGenerator(axis);if(!(ts.length>1&&/\..*0$/.test((ts[1]-ts[0]).toFixed(extraDec))))axis.tickDecimals=extraDec}}}}function setTicks(axis){var oticks=axis.options.ticks,ticks=[];if(oticks==null||typeof oticks=="number"&&oticks>0)ticks=axis.tickGenerator(axis);else if(oticks){if($.isFunction(oticks))ticks=oticks(axis);else ticks=oticks}var i,v;axis.ticks=[];for(i=0;i<ticks.length;++i){var label=null;var t=ticks[i];if(typeof t=="object"){v=+t[0];if(t.length>1)label=t[1]}else v=+t;if(label==null)label=axis.tickFormatter(v,axis);if(!isNaN(v))axis.ticks.push({v:v,label:label})}}function snapRangeToTicks(axis,ticks){if(axis.options.autoscaleMargin&&ticks.length>0){if(axis.options.min==null)axis.min=Math.min(axis.min,ticks[0].v);if(axis.options.max==null&&ticks.length>1)axis.max=Math.max(axis.max,ticks[ticks.length-1].v)}}function draw(){surface.clear();executeHooks(hooks.drawBackground,[ctx]);var grid=options.grid;if(grid.show&&grid.backgroundColor)drawBackground();if(grid.show&&!grid.aboveData){drawGrid()}for(var i=0;i<series.length;++i){executeHooks(hooks.drawSeries,[ctx,series[i]]);drawSeries(series[i])}executeHooks(hooks.draw,[ctx]);if(grid.show&&grid.aboveData){drawGrid()}surface.render();triggerRedrawOverlay()}function extractRange(ranges,coord){var axis,from,to,key,axes=allAxes();for(var i=0;i<axes.length;++i){axis=axes[i];if(axis.direction==coord){key=coord+axis.n+"axis";if(!ranges[key]&&axis.n==1)key=coord+"axis";if(ranges[key]){from=ranges[key].from;to=ranges[key].to;break}}}if(!ranges[key]){axis=coord=="x"?xaxes[0]:yaxes[0];from=ranges[coord+"1"];to=ranges[coord+"2"]}if(from!=null&&to!=null&&from>to){var tmp=from;from=to;to=tmp}return{from:from,to:to,axis:axis}}function drawBackground(){ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.fillStyle=getColorOrGradient(options.grid.backgroundColor,plotHeight,0,"rgba(255, 255, 255, 0)");ctx.fillRect(0,0,plotWidth,plotHeight);ctx.restore()}function drawGrid(){var i,axes,bw,bc;ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var markings=options.grid.markings;if(markings){if($.isFunction(markings)){axes=plot.getAxes();axes.xmin=axes.xaxis.min;axes.xmax=axes.xaxis.max;axes.ymin=axes.yaxis.min;axes.ymax=axes.yaxis.max;markings=markings(axes)}for(i=0;i<markings.length;++i){var m=markings[i],xrange=extractRange(m,"x"),yrange=extractRange(m,"y");if(xrange.from==null)xrange.from=xrange.axis.min;if(xrange.to==null)xrange.to=xrange.axis.max;
+if(yrange.from==null)yrange.from=yrange.axis.min;if(yrange.to==null)yrange.to=yrange.axis.max;if(xrange.to<xrange.axis.min||xrange.from>xrange.axis.max||yrange.to<yrange.axis.min||yrange.from>yrange.axis.max)continue;xrange.from=Math.max(xrange.from,xrange.axis.min);xrange.to=Math.min(xrange.to,xrange.axis.max);yrange.from=Math.max(yrange.from,yrange.axis.min);yrange.to=Math.min(yrange.to,yrange.axis.max);var xequal=xrange.from===xrange.to,yequal=yrange.from===yrange.to;if(xequal&&yequal){continue}xrange.from=Math.floor(xrange.axis.p2c(xrange.from));xrange.to=Math.floor(xrange.axis.p2c(xrange.to));yrange.from=Math.floor(yrange.axis.p2c(yrange.from));yrange.to=Math.floor(yrange.axis.p2c(yrange.to));if(xequal||yequal){var lineWidth=m.lineWidth||options.grid.markingsLineWidth,subPixel=lineWidth%2?.5:0;ctx.beginPath();ctx.strokeStyle=m.color||options.grid.markingsColor;ctx.lineWidth=lineWidth;if(xequal){ctx.moveTo(xrange.to+subPixel,yrange.from);ctx.lineTo(xrange.to+subPixel,yrange.to)}else{ctx.moveTo(xrange.from,yrange.to+subPixel);ctx.lineTo(xrange.to,yrange.to+subPixel)}ctx.stroke()}else{ctx.fillStyle=m.color||options.grid.markingsColor;ctx.fillRect(xrange.from,yrange.to,xrange.to-xrange.from,yrange.from-yrange.to)}}}axes=allAxes();bw=options.grid.borderWidth;for(var j=0;j<axes.length;++j){var axis=axes[j],box=axis.box,t=axis.tickLength,x,y,xoff,yoff;if(!axis.show||axis.ticks.length==0)continue;ctx.lineWidth=1;if(axis.direction=="x"){x=0;if(t=="full")y=axis.position=="top"?0:plotHeight;else y=box.top-plotOffset.top+(axis.position=="top"?box.height:0)}else{y=0;if(t=="full")x=axis.position=="left"?0:plotWidth;else x=box.left-plotOffset.left+(axis.position=="left"?box.width:0)}if(!axis.innermost){ctx.strokeStyle=axis.options.color;ctx.beginPath();xoff=yoff=0;if(axis.direction=="x")xoff=plotWidth+1;else yoff=plotHeight+1;if(ctx.lineWidth==1){if(axis.direction=="x"){y=Math.floor(y)+.5}else{x=Math.floor(x)+.5}}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff);ctx.stroke()}ctx.strokeStyle=axis.options.tickColor;ctx.beginPath();for(i=0;i<axis.ticks.length;++i){var v=axis.ticks[i].v;xoff=yoff=0;if(isNaN(v)||v<axis.min||v>axis.max||t=="full"&&(typeof bw=="object"&&bw[axis.position]>0||bw>0)&&(v==axis.min||v==axis.max))continue;if(axis.direction=="x"){x=axis.p2c(v);yoff=t=="full"?-plotHeight:t;if(axis.position=="top")yoff=-yoff}else{y=axis.p2c(v);xoff=t=="full"?-plotWidth:t;if(axis.position=="left")xoff=-xoff}if(ctx.lineWidth==1){if(axis.direction=="x")x=Math.floor(x)+.5;else y=Math.floor(y)+.5}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff)}ctx.stroke()}if(bw){bc=options.grid.borderColor;if(typeof bw=="object"||typeof bc=="object"){if(typeof bw!=="object"){bw={top:bw,right:bw,bottom:bw,left:bw}}if(typeof bc!=="object"){bc={top:bc,right:bc,bottom:bc,left:bc}}if(bw.top>0){ctx.strokeStyle=bc.top;ctx.lineWidth=bw.top;ctx.beginPath();ctx.moveTo(0-bw.left,0-bw.top/2);ctx.lineTo(plotWidth,0-bw.top/2);ctx.stroke()}if(bw.right>0){ctx.strokeStyle=bc.right;ctx.lineWidth=bw.right;ctx.beginPath();ctx.moveTo(plotWidth+bw.right/2,0-bw.top);ctx.lineTo(plotWidth+bw.right/2,plotHeight);ctx.stroke()}if(bw.bottom>0){ctx.strokeStyle=bc.bottom;ctx.lineWidth=bw.bottom;ctx.beginPath();ctx.moveTo(plotWidth+bw.right,plotHeight+bw.bottom/2);ctx.lineTo(0,plotHeight+bw.bottom/2);ctx.stroke()}if(bw.left>0){ctx.strokeStyle=bc.left;ctx.lineWidth=bw.left;ctx.beginPath();ctx.moveTo(0-bw.left/2,plotHeight+bw.bottom);ctx.lineTo(0-bw.left/2,0);ctx.stroke()}}else{ctx.lineWidth=bw;ctx.strokeStyle=options.grid.borderColor;ctx.strokeRect(-bw/2,-bw/2,plotWidth+bw,plotHeight+bw)}}ctx.restore()}function drawAxisLabels(){$.each(allAxes(),function(_,axis){var box=axis.box,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=axis.options.font||"flot-tick-label tickLabel",tick,x,y,halign,valign;surface.removeText(layer);if(!axis.show||axis.ticks.length==0)return;for(var i=0;i<axis.ticks.length;++i){tick=axis.ticks[i];if(!tick.label||tick.v<axis.min||tick.v>axis.max)continue;if(axis.direction=="x"){halign="center";x=plotOffset.left+axis.p2c(tick.v);if(axis.position=="bottom"){y=box.top+box.padding}else{y=box.top+box.height-box.padding;valign="bottom"}}else{valign="middle";y=plotOffset.top+axis.p2c(tick.v);if(axis.position=="left"){x=box.left+box.width-box.padding;halign="right"}else{x=box.left+box.padding}}surface.addText(layer,x,y,tick.label,font,null,null,halign,valign)}})}function drawSeries(series){if(series.lines.show)drawSeriesLines(series);if(series.bars.show)drawSeriesBars(series);if(series.points.show)drawSeriesPoints(series)}function drawSeriesLines(series){function plotLine(datapoints,xoffset,yoffset,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,prevx=null,prevy=null;ctx.beginPath();for(var i=ps;i<points.length;i+=ps){var x1=points[i-ps],y1=points[i-ps+1],x2=points[i],y2=points[i+1];if(x1==null||x2==null)continue;if(y1<=y2&&y1<axisy.min){if(y2<axisy.min)continue;x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min){if(y1<axisy.min)continue;x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max){if(y2>axisy.max)continue;x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max){if(y1>axisy.max)continue;x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(x1!=prevx||y1!=prevy)ctx.moveTo(axisx.p2c(x1)+xoffset,axisy.p2c(y1)+yoffset);prevx=x2;prevy=y2;ctx.lineTo(axisx.p2c(x2)+xoffset,axisy.p2c(y2)+yoffset)}ctx.stroke()}function plotLineArea(datapoints,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,bottom=Math.min(Math.max(0,axisy.min),axisy.max),i=0,top,areaOpen=false,ypos=1,segmentStart=0,segmentEnd=0;while(true){if(ps>0&&i>points.length+ps)break;i+=ps;var x1=points[i-ps],y1=points[i-ps+ypos],x2=points[i],y2=points[i+ypos];if(areaOpen){if(ps>0&&x1!=null&&x2==null){segmentEnd=i;ps=-ps;ypos=2;continue}if(ps<0&&i==segmentStart+ps){ctx.fill();areaOpen=false;ps=-ps;ypos=1;i=segmentStart=segmentEnd+ps;continue}}if(x1==null||x2==null)continue;if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(!areaOpen){ctx.beginPath();ctx.moveTo(axisx.p2c(x1),axisy.p2c(bottom));areaOpen=true}if(y1>=axisy.max&&y2>=axisy.max){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.max));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.max));continue}else if(y1<=axisy.min&&y2<=axisy.min){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.min));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.min));continue}var x1old=x1,x2old=x2;if(y1<=y2&&y1<axisy.min&&y2>=axisy.min){x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min&&y1>=axisy.min){x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max&&y2<=axisy.max){x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max&&y1<=axisy.max){x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1!=x1old){ctx.lineTo(axisx.p2c(x1old),axisy.p2c(y1))}ctx.lineTo(axisx.p2c(x1),axisy.p2c(y1));ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));if(x2!=x2old){ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));ctx.lineTo(axisx.p2c(x2old),axisy.p2c(y2))}}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineJoin="round";var lw=series.lines.lineWidth,sw=series.shadowSize;if(lw>0&&sw>0){ctx.lineWidth=sw;ctx.strokeStyle="rgba(0,0,0,0.1)";var angle=Math.PI/18;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/2),Math.cos(angle)*(lw/2+sw/2),series.xaxis,series.yaxis);ctx.lineWidth=sw/2;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/4),Math.cos(angle)*(lw/2+sw/4),series.xaxis,series.yaxis)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;var fillStyle=getFillStyle(series.lines,series.color,0,plotHeight);if(fillStyle){ctx.fillStyle=fillStyle;plotLineArea(series.datapoints,series.xaxis,series.yaxis)}if(lw>0)plotLine(series.datapoints,0,0,series.xaxis,series.yaxis);ctx.restore()}function drawSeriesPoints(series){function plotPoints(datapoints,radius,fillStyle,offset,shadow,axisx,axisy,symbol){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){var x=points[i],y=points[i+1];if(x==null||x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)continue;ctx.beginPath();x=axisx.p2c(x);y=axisy.p2c(y)+offset;if(symbol=="circle")ctx.arc(x,y,radius,0,shadow?Math.PI:Math.PI*2,false);else symbol(ctx,x,y,radius,shadow);ctx.closePath();if(fillStyle){ctx.fillStyle=fillStyle;ctx.fill()}ctx.stroke()}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var lw=series.points.lineWidth,sw=series.shadowSize,radius=series.points.radius,symbol=series.points.symbol;if(lw==0)lw=1e-4;if(lw>0&&sw>0){var w=sw/2;ctx.lineWidth=w;ctx.strokeStyle="rgba(0,0,0,0.1)";plotPoints(series.datapoints,radius,null,w+w/2,true,series.xaxis,series.yaxis,symbol);ctx.strokeStyle="rgba(0,0,0,0.2)";plotPoints(series.datapoints,radius,null,w/2,true,series.xaxis,series.yaxis,symbol)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;plotPoints(series.datapoints,radius,getFillStyle(series.points,series.color),0,false,series.xaxis,series.yaxis,symbol);ctx.restore()}function drawBar(x,y,b,barLeft,barRight,fillStyleCallback,axisx,axisy,c,horizontal,lineWidth){var left,right,bottom,top,drawLeft,drawRight,drawTop,drawBottom,tmp;if(horizontal){drawBottom=drawRight=drawTop=true;drawLeft=false;left=b;right=x;top=y+barLeft;bottom=y+barRight;if(right<left){tmp=right;right=left;left=tmp;drawLeft=true;drawRight=false}}else{drawLeft=drawRight=drawTop=true;drawBottom=false;left=x+barLeft;right=x+barRight;bottom=b;top=y;if(top<bottom){tmp=top;top=bottom;bottom=tmp;drawBottom=true;drawTop=false}}if(right<axisx.min||left>axisx.max||top<axisy.min||bottom>axisy.max)return;if(left<axisx.min){left=axisx.min;drawLeft=false}if(right>axisx.max){right=axisx.max;drawRight=false}if(bottom<axisy.min){bottom=axisy.min;drawBottom=false}if(top>axisy.max){top=axisy.max;drawTop=false}left=axisx.p2c(left);bottom=axisy.p2c(bottom);right=axisx.p2c(right);top=axisy.p2c(top);if(fillStyleCallback){c.fillStyle=fillStyleCallback(bottom,top);c.fillRect(left,top,right-left,bottom-top)}if(lineWidth>0&&(drawLeft||drawRight||drawTop||drawBottom)){c.beginPath();c.moveTo(left,bottom);if(drawLeft)c.lineTo(left,top);else c.moveTo(left,top);if(drawTop)c.lineTo(right,top);else c.moveTo(right,top);if(drawRight)c.lineTo(right,bottom);else c.moveTo(right,bottom);if(drawBottom)c.lineTo(left,bottom);else c.moveTo(left,bottom);c.stroke()}}function drawSeriesBars(series){function plotBars(datapoints,barLeft,barRight,fillStyleCallback,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){if(points[i]==null)continue;drawBar(points[i],points[i+1],points[i+2],barLeft,barRight,fillStyleCallback,axisx,axisy,ctx,series.bars.horizontal,series.bars.lineWidth)}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineWidth=series.bars.lineWidth;ctx.strokeStyle=series.color;var barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}var fillStyleCallback=series.bars.fill?function(bottom,top){return getFillStyle(series.bars,series.color,bottom,top)}:null;plotBars(series.datapoints,barLeft,barLeft+series.bars.barWidth,fillStyleCallback,series.xaxis,series.yaxis);ctx.restore()}function getFillStyle(filloptions,seriesColor,bottom,top){var fill=filloptions.fill;if(!fill)return null;if(filloptions.fillColor)return getColorOrGradient(filloptions.fillColor,bottom,top,seriesColor);var c=$.color.parse(seriesColor);c.a=typeof fill=="number"?fill:.4;c.normalize();return c.toString()}function insertLegend(){if(options.legend.container!=null){$(options.legend.container).html("")}else{placeholder.find(".legend").remove()}if(!options.legend.show){return}var fragments=[],entries=[],rowStarted=false,lf=options.legend.labelFormatter,s,label;for(var i=0;i<series.length;++i){s=series[i];if(s.label){label=lf?lf(s.label,s):s.label;if(label){entries.push({label:label,color:s.color})}}}if(options.legend.sorted){if($.isFunction(options.legend.sorted)){entries.sort(options.legend.sorted)}else if(options.legend.sorted=="reverse"){entries.reverse()}else{var ascending=options.legend.sorted!="descending";entries.sort(function(a,b){return a.label==b.label?0:a.label<b.label!=ascending?1:-1})}}for(var i=0;i<entries.length;++i){var entry=entries[i];if(i%options.legend.noColumns==0){if(rowStarted)fragments.push("</tr>");fragments.push("<tr>");rowStarted=true}fragments.push('<td class="legendColorBox"><div style="border:1px solid '+options.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+entry.color+';overflow:hidden"></div></div></td>'+'<td class="legendLabel">'+entry.label+"</td>")}if(rowStarted)fragments.push("</tr>");if(fragments.length==0)return;var table='<table style="font-size:smaller;color:'+options.grid.color+'">'+fragments.join("")+"</table>";if(options.legend.container!=null)$(options.legend.container).html(table);else{var pos="",p=options.legend.position,m=options.legend.margin;if(m[0]==null)m=[m,m];if(p.charAt(0)=="n")pos+="top:"+(m[1]+plotOffset.top)+"px;";else if(p.charAt(0)=="s")pos+="bottom:"+(m[1]+plotOffset.bottom)+"px;";if(p.charAt(1)=="e")pos+="right:"+(m[0]+plotOffset.right)+"px;";else if(p.charAt(1)=="w")pos+="left:"+(m[0]+plotOffset.left)+"px;";var legend=$('<div class="legend">'+table.replace('style="','style="position:absolute;'+pos+";")+"</div>").appendTo(placeholder);if(options.legend.backgroundOpacity!=0){var c=options.legend.backgroundColor;if(c==null){c=options.grid.backgroundColor;if(c&&typeof c=="string")c=$.color.parse(c);else c=$.color.extract(legend,"background-color");c.a=1;c=c.toString()}var div=legend.children();$('<div style="position:absolute;width:'+div.width()+"px;height:"+div.height()+"px;"+pos+"background-color:"+c+';"> </div>').prependTo(legend).css("opacity",options.legend.backgroundOpacity)}}}var highlights=[],redrawTimeout=null;function findNearbyItem(mouseX,mouseY,seriesFilter){var maxDistance=options.grid.mouseActiveRadius,smallestDistance=maxDistance*maxDistance+1,item=null,foundPoint=false,i,j,ps;for(i=series.length-1;i>=0;--i){if(!seriesFilter(series[i]))continue;var s=series[i],axisx=s.xaxis,axisy=s.yaxis,points=s.datapoints.points,mx=axisx.c2p(mouseX),my=axisy.c2p(mouseY),maxx=maxDistance/axisx.scale,maxy=maxDistance/axisy.scale;ps=s.datapoints.pointsize;if(axisx.options.inverseTransform)maxx=Number.MAX_VALUE;if(axisy.options.inverseTransform)maxy=Number.MAX_VALUE;if(s.lines.show||s.points.show){for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1];if(x==null)continue;if(x-mx>maxx||x-mx<-maxx||y-my>maxy||y-my<-maxy)continue;var dx=Math.abs(axisx.p2c(x)-mouseX),dy=Math.abs(axisy.p2c(y)-mouseY),dist=dx*dx+dy*dy;if(dist<smallestDistance){smallestDistance=dist;item=[i,j/ps]}}}if(s.bars.show&&!item){var barLeft,barRight;switch(s.bars.align){case"left":barLeft=0;break;case"right":barLeft=-s.bars.barWidth;break;default:barLeft=-s.bars.barWidth/2}barRight=barLeft+s.bars.barWidth;for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1],b=points[j+2];if(x==null)continue;if(series[i].bars.horizontal?mx<=Math.max(b,x)&&mx>=Math.min(b,x)&&my>=y+barLeft&&my<=y+barRight:mx>=x+barLeft&&mx<=x+barRight&&my>=Math.min(b,y)&&my<=Math.max(b,y))item=[i,j/ps]}}}if(item){i=item[0];j=item[1];ps=series[i].datapoints.pointsize;return{datapoint:series[i].datapoints.points.slice(j*ps,(j+1)*ps),dataIndex:j,series:series[i],seriesIndex:i}}return null}function onMouseMove(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return s["hoverable"]!=false})}function onMouseLeave(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return false})}function onClick(e){triggerClickHoverEvent("plotclick",e,function(s){return s["clickable"]!=false})}function triggerClickHoverEvent(eventname,event,seriesFilter){var offset=eventHolder.offset(),canvasX=event.pageX-offset.left-plotOffset.left,canvasY=event.pageY-offset.top-plotOffset.top,pos=canvasToAxisCoords({left:canvasX,top:canvasY});pos.pageX=event.pageX;pos.pageY=event.pageY;var item=findNearbyItem(canvasX,canvasY,seriesFilter);if(item){item.pageX=parseInt(item.series.xaxis.p2c(item.datapoint[0])+offset.left+plotOffset.left,10);item.pageY=parseInt(item.series.yaxis.p2c(item.datapoint[1])+offset.top+plotOffset.top,10)}if(options.grid.autoHighlight){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.auto==eventname&&!(item&&h.series==item.series&&h.point[0]==item.datapoint[0]&&h.point[1]==item.datapoint[1]))unhighlight(h.series,h.point)}if(item)highlight(item.series,item.datapoint,eventname)}placeholder.trigger(eventname,[pos,item])}function triggerRedrawOverlay(){var t=options.interaction.redrawOverlayInterval;if(t==-1){drawOverlay();return}if(!redrawTimeout)redrawTimeout=setTimeout(drawOverlay,t)}function drawOverlay(){redrawTimeout=null;octx.save();overlay.clear();octx.translate(plotOffset.left,plotOffset.top);var i,hi;for(i=0;i<highlights.length;++i){hi=highlights[i];if(hi.series.bars.show)drawBarHighlight(hi.series,hi.point);else drawPointHighlight(hi.series,hi.point)}octx.restore();executeHooks(hooks.drawOverlay,[octx])}function highlight(s,point,auto){if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i==-1){highlights.push({series:s,point:point,auto:auto});triggerRedrawOverlay()}else if(!auto)highlights[i].auto=false}function unhighlight(s,point){if(s==null&&point==null){highlights=[];triggerRedrawOverlay();return}if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i!=-1){highlights.splice(i,1);triggerRedrawOverlay()}}function indexOfHighlight(s,p){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.series==s&&h.point[0]==p[0]&&h.point[1]==p[1])return i}return-1}function drawPointHighlight(series,point){var x=point[0],y=point[1],axisx=series.xaxis,axisy=series.yaxis,highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString();if(x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)return;var pointRadius=series.points.radius+series.points.lineWidth/2;octx.lineWidth=pointRadius;octx.strokeStyle=highlightColor;var radius=1.5*pointRadius;x=axisx.p2c(x);y=axisy.p2c(y);octx.beginPath();if(series.points.symbol=="circle")octx.arc(x,y,radius,0,2*Math.PI,false);else series.points.symbol(octx,x,y,radius,false);octx.closePath();octx.stroke()}function drawBarHighlight(series,point){var highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString(),fillStyle=highlightColor,barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}octx.lineWidth=series.bars.lineWidth;octx.strokeStyle=highlightColor;drawBar(point[0],point[1],point[2]||0,barLeft,barLeft+series.bars.barWidth,function(){return fillStyle},series.xaxis,series.yaxis,octx,series.bars.horizontal,series.bars.lineWidth)}function getColorOrGradient(spec,bottom,top,defaultColor){if(typeof spec=="string")return spec;else{var gradient=ctx.createLinearGradient(0,top,0,bottom);for(var i=0,l=spec.colors.length;i<l;++i){var c=spec.colors[i];if(typeof c!="string"){var co=$.color.parse(defaultColor);if(c.brightness!=null)co=co.scale("rgb",c.brightness);if(c.opacity!=null)co.a*=c.opacity;c=co.toString()}gradient.addColorStop(i/(l-1),c)}return gradient}}}$.plot=function(placeholder,data,options){var plot=new Plot($(placeholder),data,options,$.plot.plugins);return plot};$.plot.version="0.8.3";$.plot.plugins=[];$.fn.plot=function(data,options){return this.each(function(){$.plot(this,data,options)})};function floorInBase(n,base){return base*Math.floor(n/base)}})(jQuery);
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.flot.navigate.min.js b/library/cpp/lwtrace/mon/static/js/jquery.flot.navigate.min.js
index af5ecd21e1..a7593fc8a7 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.flot.navigate.min.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.flot.navigate.min.js
@@ -1,7 +1,7 @@
-/* Javascript plotting library for jQuery, version 0.8.3.
-
-Copyright (c) 2007-2014 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-*/
-(function(a){function e(h){var k,j=this,l=h.data||{};if(l.elem)j=h.dragTarget=l.elem,h.dragProxy=d.proxy||j,h.cursorOffsetX=l.pageX-l.left,h.cursorOffsetY=l.pageY-l.top,h.offsetX=h.pageX-h.cursorOffsetX,h.offsetY=h.pageY-h.cursorOffsetY;else if(d.dragging||l.which>0&&h.which!=l.which||a(h.target).is(l.not))return;switch(h.type){case"mousedown":return a.extend(l,a(j).offset(),{elem:j,target:h.target,pageX:h.pageX,pageY:h.pageY}),b.add(document,"mousemove mouseup",e,l),i(j,!1),d.dragging=null,!1;case!d.dragging&&"mousemove":if(g(h.pageX-l.pageX)+g(h.pageY-l.pageY)<l.distance)break;h.target=l.target,k=f(h,"dragstart",j),k!==!1&&(d.dragging=j,d.proxy=h.dragProxy=a(k||j)[0]);case"mousemove":if(d.dragging){if(k=f(h,"drag",j),c.drop&&(c.drop.allowed=k!==!1,c.drop.handler(h)),k!==!1)break;h.type="mouseup"}case"mouseup":b.remove(document,"mousemove mouseup",e),d.dragging&&(c.drop&&c.drop.handler(h),f(h,"dragend",j)),i(j,!0),d.dragging=d.proxy=l.elem=!1}return!0}function f(b,c,d){b.type=c;var e=a.event.dispatch.call(d,b);return e===!1?!1:e||b.result}function g(a){return Math.pow(a,2)}function h(){return d.dragging===!1}function i(a,b){a&&(a.unselectable=b?"off":"on",a.onselectstart=function(){return b},a.style&&(a.style.MozUserSelect=b?"":"none"))}a.fn.drag=function(a,b,c){return b&&this.bind("dragstart",a),c&&this.bind("dragend",c),a?this.bind("drag",b?b:a):this.trigger("drag")};var b=a.event,c=b.special,d=c.drag={not:":input",distance:0,which:1,dragging:!1,setup:function(c){c=a.extend({distance:d.distance,which:d.which,not:d.not},c||{}),c.distance=g(c.distance),b.add(this,"mousedown",e,c),this.attachEvent&&this.attachEvent("ondragstart",h)},teardown:function(){b.remove(this,"mousedown",e),this===d.dragging&&(d.dragging=d.proxy=!1),i(this,!0),this.detachEvent&&this.detachEvent("ondragstart",h)}};c.dragstart=c.dragend={setup:function(){},teardown:function(){}}})(jQuery);(function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;void 0!==b.axis&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);void 0!==b.wheelDeltaY&&(g=b.wheelDeltaY/120);void 0!==b.wheelDeltaX&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,!1);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,!1);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);(function($){var options={xaxis:{zoomRange:null,panRange:null},zoom:{interactive:false,trigger:"dblclick",amount:1.5},pan:{interactive:false,cursor:"move",frameRate:20}};function init(plot){function onZoomClick(e,zoomOut){var c=plot.offset();c.left=e.pageX-c.left;c.top=e.pageY-c.top;if(zoomOut)plot.zoomOut({center:c});else plot.zoom({center:c})}function onMouseWheel(e,delta){e.preventDefault();onZoomClick(e,delta<0);return false}var prevCursor="default",prevPageX=0,prevPageY=0,panTimeout=null;function onDragStart(e){if(e.which!=1)return false;var c=plot.getPlaceholder().css("cursor");if(c)prevCursor=c;plot.getPlaceholder().css("cursor",plot.getOptions().pan.cursor);prevPageX=e.pageX;prevPageY=e.pageY}function onDrag(e){var frameRate=plot.getOptions().pan.frameRate;if(panTimeout||!frameRate)return;panTimeout=setTimeout(function(){plot.pan({left:prevPageX-e.pageX,top:prevPageY-e.pageY});prevPageX=e.pageX;prevPageY=e.pageY;panTimeout=null},1/frameRate*1e3)}function onDragEnd(e){if(panTimeout){clearTimeout(panTimeout);panTimeout=null}plot.getPlaceholder().css("cursor",prevCursor);plot.pan({left:prevPageX-e.pageX,top:prevPageY-e.pageY})}function bindEvents(plot,eventHolder){var o=plot.getOptions();if(o.zoom.interactive){eventHolder[o.zoom.trigger](onZoomClick);eventHolder.mousewheel(onMouseWheel)}if(o.pan.interactive){eventHolder.bind("dragstart",{distance:10},onDragStart);eventHolder.bind("drag",onDrag);eventHolder.bind("dragend",onDragEnd)}}plot.zoomOut=function(args){if(!args)args={};if(!args.amount)args.amount=plot.getOptions().zoom.amount;args.amount=1/args.amount;plot.zoom(args)};plot.zoom=function(args){if(!args)args={};var c=args.center,amount=args.amount||plot.getOptions().zoom.amount,w=plot.width(),h=plot.height();if(!c)c={left:w/2,top:h/2};var xf=c.left/w,yf=c.top/h,minmax={x:{min:c.left-xf*w/amount,max:c.left+(1-xf)*w/amount},y:{min:c.top-yf*h/amount,max:c.top+(1-yf)*h/amount}};$.each(plot.getAxes(),function(_,axis){var opts=axis.options,min=minmax[axis.direction].min,max=minmax[axis.direction].max,zr=opts.zoomRange,pr=opts.panRange;if(zr===false)return;min=axis.c2p(min);max=axis.c2p(max);if(min>max){var tmp=min;min=max;max=tmp}if(pr){if(pr[0]!=null&&min<pr[0]){min=pr[0]}if(pr[1]!=null&&max>pr[1]){max=pr[1]}}var range=max-min;if(zr&&(zr[0]!=null&&range<zr[0]&&amount>1||zr[1]!=null&&range>zr[1]&&amount<1))return;opts.min=min;opts.max=max});plot.setupGrid();plot.draw();if(!args.preventEvent)plot.getPlaceholder().trigger("plotzoom",[plot,args])};plot.pan=function(args){var delta={x:+args.left,y:+args.top};if(isNaN(delta.x))delta.x=0;if(isNaN(delta.y))delta.y=0;$.each(plot.getAxes(),function(_,axis){var opts=axis.options,min,max,d=delta[axis.direction];min=axis.c2p(axis.p2c(axis.min)+d),max=axis.c2p(axis.p2c(axis.max)+d);var pr=opts.panRange;if(pr===false)return;if(pr){if(pr[0]!=null&&pr[0]>min){d=pr[0]-min;min+=d;max+=d}if(pr[1]!=null&&pr[1]<max){d=pr[1]-max;min+=d;max+=d}}opts.min=min;opts.max=max});plot.setupGrid();plot.draw();if(!args.preventEvent)plot.getPlaceholder().trigger("plotpan",[plot,args])};function shutdown(plot,eventHolder){eventHolder.unbind(plot.getOptions().zoom.trigger,onZoomClick);eventHolder.unbind("mousewheel",onMouseWheel);eventHolder.unbind("dragstart",onDragStart);eventHolder.unbind("drag",onDrag);eventHolder.unbind("dragend",onDragEnd);if(panTimeout)clearTimeout(panTimeout)}plot.hooks.bindEvents.push(bindEvents);plot.hooks.shutdown.push(shutdown)}$.plot.plugins.push({init:init,options:options,name:"navigate",version:"1.3"})})(jQuery);
+/* Javascript plotting library for jQuery, version 0.8.3.
+
+Copyright (c) 2007-2014 IOLA and Ole Laursen.
+Licensed under the MIT license.
+
+*/
+(function(a){function e(h){var k,j=this,l=h.data||{};if(l.elem)j=h.dragTarget=l.elem,h.dragProxy=d.proxy||j,h.cursorOffsetX=l.pageX-l.left,h.cursorOffsetY=l.pageY-l.top,h.offsetX=h.pageX-h.cursorOffsetX,h.offsetY=h.pageY-h.cursorOffsetY;else if(d.dragging||l.which>0&&h.which!=l.which||a(h.target).is(l.not))return;switch(h.type){case"mousedown":return a.extend(l,a(j).offset(),{elem:j,target:h.target,pageX:h.pageX,pageY:h.pageY}),b.add(document,"mousemove mouseup",e,l),i(j,!1),d.dragging=null,!1;case!d.dragging&&"mousemove":if(g(h.pageX-l.pageX)+g(h.pageY-l.pageY)<l.distance)break;h.target=l.target,k=f(h,"dragstart",j),k!==!1&&(d.dragging=j,d.proxy=h.dragProxy=a(k||j)[0]);case"mousemove":if(d.dragging){if(k=f(h,"drag",j),c.drop&&(c.drop.allowed=k!==!1,c.drop.handler(h)),k!==!1)break;h.type="mouseup"}case"mouseup":b.remove(document,"mousemove mouseup",e),d.dragging&&(c.drop&&c.drop.handler(h),f(h,"dragend",j)),i(j,!0),d.dragging=d.proxy=l.elem=!1}return!0}function f(b,c,d){b.type=c;var e=a.event.dispatch.call(d,b);return e===!1?!1:e||b.result}function g(a){return Math.pow(a,2)}function h(){return d.dragging===!1}function i(a,b){a&&(a.unselectable=b?"off":"on",a.onselectstart=function(){return b},a.style&&(a.style.MozUserSelect=b?"":"none"))}a.fn.drag=function(a,b,c){return b&&this.bind("dragstart",a),c&&this.bind("dragend",c),a?this.bind("drag",b?b:a):this.trigger("drag")};var b=a.event,c=b.special,d=c.drag={not:":input",distance:0,which:1,dragging:!1,setup:function(c){c=a.extend({distance:d.distance,which:d.which,not:d.not},c||{}),c.distance=g(c.distance),b.add(this,"mousedown",e,c),this.attachEvent&&this.attachEvent("ondragstart",h)},teardown:function(){b.remove(this,"mousedown",e),this===d.dragging&&(d.dragging=d.proxy=!1),i(this,!0),this.detachEvent&&this.detachEvent("ondragstart",h)}};c.dragstart=c.dragend={setup:function(){},teardown:function(){}}})(jQuery);(function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;void 0!==b.axis&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);void 0!==b.wheelDeltaY&&(g=b.wheelDeltaY/120);void 0!==b.wheelDeltaX&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,!1);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,!1);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);(function($){var options={xaxis:{zoomRange:null,panRange:null},zoom:{interactive:false,trigger:"dblclick",amount:1.5},pan:{interactive:false,cursor:"move",frameRate:20}};function init(plot){function onZoomClick(e,zoomOut){var c=plot.offset();c.left=e.pageX-c.left;c.top=e.pageY-c.top;if(zoomOut)plot.zoomOut({center:c});else plot.zoom({center:c})}function onMouseWheel(e,delta){e.preventDefault();onZoomClick(e,delta<0);return false}var prevCursor="default",prevPageX=0,prevPageY=0,panTimeout=null;function onDragStart(e){if(e.which!=1)return false;var c=plot.getPlaceholder().css("cursor");if(c)prevCursor=c;plot.getPlaceholder().css("cursor",plot.getOptions().pan.cursor);prevPageX=e.pageX;prevPageY=e.pageY}function onDrag(e){var frameRate=plot.getOptions().pan.frameRate;if(panTimeout||!frameRate)return;panTimeout=setTimeout(function(){plot.pan({left:prevPageX-e.pageX,top:prevPageY-e.pageY});prevPageX=e.pageX;prevPageY=e.pageY;panTimeout=null},1/frameRate*1e3)}function onDragEnd(e){if(panTimeout){clearTimeout(panTimeout);panTimeout=null}plot.getPlaceholder().css("cursor",prevCursor);plot.pan({left:prevPageX-e.pageX,top:prevPageY-e.pageY})}function bindEvents(plot,eventHolder){var o=plot.getOptions();if(o.zoom.interactive){eventHolder[o.zoom.trigger](onZoomClick);eventHolder.mousewheel(onMouseWheel)}if(o.pan.interactive){eventHolder.bind("dragstart",{distance:10},onDragStart);eventHolder.bind("drag",onDrag);eventHolder.bind("dragend",onDragEnd)}}plot.zoomOut=function(args){if(!args)args={};if(!args.amount)args.amount=plot.getOptions().zoom.amount;args.amount=1/args.amount;plot.zoom(args)};plot.zoom=function(args){if(!args)args={};var c=args.center,amount=args.amount||plot.getOptions().zoom.amount,w=plot.width(),h=plot.height();if(!c)c={left:w/2,top:h/2};var xf=c.left/w,yf=c.top/h,minmax={x:{min:c.left-xf*w/amount,max:c.left+(1-xf)*w/amount},y:{min:c.top-yf*h/amount,max:c.top+(1-yf)*h/amount}};$.each(plot.getAxes(),function(_,axis){var opts=axis.options,min=minmax[axis.direction].min,max=minmax[axis.direction].max,zr=opts.zoomRange,pr=opts.panRange;if(zr===false)return;min=axis.c2p(min);max=axis.c2p(max);if(min>max){var tmp=min;min=max;max=tmp}if(pr){if(pr[0]!=null&&min<pr[0]){min=pr[0]}if(pr[1]!=null&&max>pr[1]){max=pr[1]}}var range=max-min;if(zr&&(zr[0]!=null&&range<zr[0]&&amount>1||zr[1]!=null&&range>zr[1]&&amount<1))return;opts.min=min;opts.max=max});plot.setupGrid();plot.draw();if(!args.preventEvent)plot.getPlaceholder().trigger("plotzoom",[plot,args])};plot.pan=function(args){var delta={x:+args.left,y:+args.top};if(isNaN(delta.x))delta.x=0;if(isNaN(delta.y))delta.y=0;$.each(plot.getAxes(),function(_,axis){var opts=axis.options,min,max,d=delta[axis.direction];min=axis.c2p(axis.p2c(axis.min)+d),max=axis.c2p(axis.p2c(axis.max)+d);var pr=opts.panRange;if(pr===false)return;if(pr){if(pr[0]!=null&&pr[0]>min){d=pr[0]-min;min+=d;max+=d}if(pr[1]!=null&&pr[1]<max){d=pr[1]-max;min+=d;max+=d}}opts.min=min;opts.max=max});plot.setupGrid();plot.draw();if(!args.preventEvent)plot.getPlaceholder().trigger("plotpan",[plot,args])};function shutdown(plot,eventHolder){eventHolder.unbind(plot.getOptions().zoom.trigger,onZoomClick);eventHolder.unbind("mousewheel",onMouseWheel);eventHolder.unbind("dragstart",onDragStart);eventHolder.unbind("drag",onDrag);eventHolder.unbind("dragend",onDragEnd);if(panTimeout)clearTimeout(panTimeout)}plot.hooks.bindEvents.push(bindEvents);plot.hooks.shutdown.push(shutdown)}$.plot.plugins.push({init:init,options:options,name:"navigate",version:"1.3"})})(jQuery);
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.flot.selection.min.js b/library/cpp/lwtrace/mon/static/js/jquery.flot.selection.min.js
index a0154fbc5b..da6185b1ef 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.flot.selection.min.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.flot.selection.min.js
@@ -1,7 +1,7 @@
-/* Javascript plotting library for jQuery, version 0.8.3.
-
-Copyright (c) 2007-2014 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-*/
-(function($){function init(plot){var selection={first:{x:-1,y:-1},second:{x:-1,y:-1},show:false,active:false};var savedhandlers={};var mouseUpHandler=null;function onMouseMove(e){if(selection.active){updateSelection(e);plot.getPlaceholder().trigger("plotselecting",[getSelection()])}}function onMouseDown(e){if(e.which!=1)return;document.body.focus();if(document.onselectstart!==undefined&&savedhandlers.onselectstart==null){savedhandlers.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!==undefined&&savedhandlers.ondrag==null){savedhandlers.ondrag=document.ondrag;document.ondrag=function(){return false}}setSelectionPos(selection.first,e);selection.active=true;mouseUpHandler=function(e){onMouseUp(e)};$(document).one("mouseup",mouseUpHandler)}function onMouseUp(e){mouseUpHandler=null;if(document.onselectstart!==undefined)document.onselectstart=savedhandlers.onselectstart;if(document.ondrag!==undefined)document.ondrag=savedhandlers.ondrag;selection.active=false;updateSelection(e);if(selectionIsSane())triggerSelectedEvent();else{plot.getPlaceholder().trigger("plotunselected",[]);plot.getPlaceholder().trigger("plotselecting",[null])}return false}function getSelection(){if(!selectionIsSane())return null;if(!selection.show)return null;var r={},c1=selection.first,c2=selection.second;$.each(plot.getAxes(),function(name,axis){if(axis.used){var p1=axis.c2p(c1[axis.direction]),p2=axis.c2p(c2[axis.direction]);r[name]={from:Math.min(p1,p2),to:Math.max(p1,p2)}}});return r}function triggerSelectedEvent(){var r=getSelection();plot.getPlaceholder().trigger("plotselected",[r]);if(r.xaxis&&r.yaxis)plot.getPlaceholder().trigger("selected",[{x1:r.xaxis.from,y1:r.yaxis.from,x2:r.xaxis.to,y2:r.yaxis.to}])}function clamp(min,value,max){return value<min?min:value>max?max:value}function setSelectionPos(pos,e){var o=plot.getOptions();var offset=plot.getPlaceholder().offset();var plotOffset=plot.getPlotOffset();pos.x=clamp(0,e.pageX-offset.left-plotOffset.left,plot.width());pos.y=clamp(0,e.pageY-offset.top-plotOffset.top,plot.height());if(o.selection.mode=="y")pos.x=pos==selection.first?0:plot.width();if(o.selection.mode=="x")pos.y=pos==selection.first?0:plot.height()}function updateSelection(pos){if(pos.pageX==null)return;setSelectionPos(selection.second,pos);if(selectionIsSane()){selection.show=true;plot.triggerRedrawOverlay()}else clearSelection(true)}function clearSelection(preventEvent){if(selection.show){selection.show=false;plot.triggerRedrawOverlay();if(!preventEvent)plot.getPlaceholder().trigger("plotunselected",[])}}function extractRange(ranges,coord){var axis,from,to,key,axes=plot.getAxes();for(var k in axes){axis=axes[k];if(axis.direction==coord){key=coord+axis.n+"axis";if(!ranges[key]&&axis.n==1)key=coord+"axis";if(ranges[key]){from=ranges[key].from;to=ranges[key].to;break}}}if(!ranges[key]){axis=coord=="x"?plot.getXAxes()[0]:plot.getYAxes()[0];from=ranges[coord+"1"];to=ranges[coord+"2"]}if(from!=null&&to!=null&&from>to){var tmp=from;from=to;to=tmp}return{from:from,to:to,axis:axis}}function setSelection(ranges,preventEvent){var axis,range,o=plot.getOptions();if(o.selection.mode=="y"){selection.first.x=0;selection.second.x=plot.width()}else{range=extractRange(ranges,"x");selection.first.x=range.axis.p2c(range.from);selection.second.x=range.axis.p2c(range.to)}if(o.selection.mode=="x"){selection.first.y=0;selection.second.y=plot.height()}else{range=extractRange(ranges,"y");selection.first.y=range.axis.p2c(range.from);selection.second.y=range.axis.p2c(range.to)}selection.show=true;plot.triggerRedrawOverlay();if(!preventEvent&&selectionIsSane())triggerSelectedEvent()}function selectionIsSane(){var minSize=plot.getOptions().selection.minSize;return Math.abs(selection.second.x-selection.first.x)>=minSize&&Math.abs(selection.second.y-selection.first.y)>=minSize}plot.clearSelection=clearSelection;plot.setSelection=setSelection;plot.getSelection=getSelection;plot.hooks.bindEvents.push(function(plot,eventHolder){var o=plot.getOptions();if(o.selection.mode!=null){eventHolder.mousemove(onMouseMove);eventHolder.mousedown(onMouseDown)}});plot.hooks.drawOverlay.push(function(plot,ctx){if(selection.show&&selectionIsSane()){var plotOffset=plot.getPlotOffset();var o=plot.getOptions();ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var c=$.color.parse(o.selection.color);ctx.strokeStyle=c.scale("a",.8).toString();ctx.lineWidth=1;ctx.lineJoin=o.selection.shape;ctx.fillStyle=c.scale("a",.4).toString();var x=Math.min(selection.first.x,selection.second.x)+.5,y=Math.min(selection.first.y,selection.second.y)+.5,w=Math.abs(selection.second.x-selection.first.x)-1,h=Math.abs(selection.second.y-selection.first.y)-1;ctx.fillRect(x,y,w,h);ctx.strokeRect(x,y,w,h);ctx.restore()}});plot.hooks.shutdown.push(function(plot,eventHolder){eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mousedown",onMouseDown);if(mouseUpHandler)$(document).unbind("mouseup",mouseUpHandler)})}$.plot.plugins.push({init:init,options:{selection:{mode:null,color:"#e8cfac",shape:"round",minSize:5}},name:"selection",version:"1.1"})})(jQuery); \ No newline at end of file
+/* Javascript plotting library for jQuery, version 0.8.3.
+
+Copyright (c) 2007-2014 IOLA and Ole Laursen.
+Licensed under the MIT license.
+
+*/
+(function($){function init(plot){var selection={first:{x:-1,y:-1},second:{x:-1,y:-1},show:false,active:false};var savedhandlers={};var mouseUpHandler=null;function onMouseMove(e){if(selection.active){updateSelection(e);plot.getPlaceholder().trigger("plotselecting",[getSelection()])}}function onMouseDown(e){if(e.which!=1)return;document.body.focus();if(document.onselectstart!==undefined&&savedhandlers.onselectstart==null){savedhandlers.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!==undefined&&savedhandlers.ondrag==null){savedhandlers.ondrag=document.ondrag;document.ondrag=function(){return false}}setSelectionPos(selection.first,e);selection.active=true;mouseUpHandler=function(e){onMouseUp(e)};$(document).one("mouseup",mouseUpHandler)}function onMouseUp(e){mouseUpHandler=null;if(document.onselectstart!==undefined)document.onselectstart=savedhandlers.onselectstart;if(document.ondrag!==undefined)document.ondrag=savedhandlers.ondrag;selection.active=false;updateSelection(e);if(selectionIsSane())triggerSelectedEvent();else{plot.getPlaceholder().trigger("plotunselected",[]);plot.getPlaceholder().trigger("plotselecting",[null])}return false}function getSelection(){if(!selectionIsSane())return null;if(!selection.show)return null;var r={},c1=selection.first,c2=selection.second;$.each(plot.getAxes(),function(name,axis){if(axis.used){var p1=axis.c2p(c1[axis.direction]),p2=axis.c2p(c2[axis.direction]);r[name]={from:Math.min(p1,p2),to:Math.max(p1,p2)}}});return r}function triggerSelectedEvent(){var r=getSelection();plot.getPlaceholder().trigger("plotselected",[r]);if(r.xaxis&&r.yaxis)plot.getPlaceholder().trigger("selected",[{x1:r.xaxis.from,y1:r.yaxis.from,x2:r.xaxis.to,y2:r.yaxis.to}])}function clamp(min,value,max){return value<min?min:value>max?max:value}function setSelectionPos(pos,e){var o=plot.getOptions();var offset=plot.getPlaceholder().offset();var plotOffset=plot.getPlotOffset();pos.x=clamp(0,e.pageX-offset.left-plotOffset.left,plot.width());pos.y=clamp(0,e.pageY-offset.top-plotOffset.top,plot.height());if(o.selection.mode=="y")pos.x=pos==selection.first?0:plot.width();if(o.selection.mode=="x")pos.y=pos==selection.first?0:plot.height()}function updateSelection(pos){if(pos.pageX==null)return;setSelectionPos(selection.second,pos);if(selectionIsSane()){selection.show=true;plot.triggerRedrawOverlay()}else clearSelection(true)}function clearSelection(preventEvent){if(selection.show){selection.show=false;plot.triggerRedrawOverlay();if(!preventEvent)plot.getPlaceholder().trigger("plotunselected",[])}}function extractRange(ranges,coord){var axis,from,to,key,axes=plot.getAxes();for(var k in axes){axis=axes[k];if(axis.direction==coord){key=coord+axis.n+"axis";if(!ranges[key]&&axis.n==1)key=coord+"axis";if(ranges[key]){from=ranges[key].from;to=ranges[key].to;break}}}if(!ranges[key]){axis=coord=="x"?plot.getXAxes()[0]:plot.getYAxes()[0];from=ranges[coord+"1"];to=ranges[coord+"2"]}if(from!=null&&to!=null&&from>to){var tmp=from;from=to;to=tmp}return{from:from,to:to,axis:axis}}function setSelection(ranges,preventEvent){var axis,range,o=plot.getOptions();if(o.selection.mode=="y"){selection.first.x=0;selection.second.x=plot.width()}else{range=extractRange(ranges,"x");selection.first.x=range.axis.p2c(range.from);selection.second.x=range.axis.p2c(range.to)}if(o.selection.mode=="x"){selection.first.y=0;selection.second.y=plot.height()}else{range=extractRange(ranges,"y");selection.first.y=range.axis.p2c(range.from);selection.second.y=range.axis.p2c(range.to)}selection.show=true;plot.triggerRedrawOverlay();if(!preventEvent&&selectionIsSane())triggerSelectedEvent()}function selectionIsSane(){var minSize=plot.getOptions().selection.minSize;return Math.abs(selection.second.x-selection.first.x)>=minSize&&Math.abs(selection.second.y-selection.first.y)>=minSize}plot.clearSelection=clearSelection;plot.setSelection=setSelection;plot.getSelection=getSelection;plot.hooks.bindEvents.push(function(plot,eventHolder){var o=plot.getOptions();if(o.selection.mode!=null){eventHolder.mousemove(onMouseMove);eventHolder.mousedown(onMouseDown)}});plot.hooks.drawOverlay.push(function(plot,ctx){if(selection.show&&selectionIsSane()){var plotOffset=plot.getPlotOffset();var o=plot.getOptions();ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var c=$.color.parse(o.selection.color);ctx.strokeStyle=c.scale("a",.8).toString();ctx.lineWidth=1;ctx.lineJoin=o.selection.shape;ctx.fillStyle=c.scale("a",.4).toString();var x=Math.min(selection.first.x,selection.second.x)+.5,y=Math.min(selection.first.y,selection.second.y)+.5,w=Math.abs(selection.second.x-selection.first.x)-1,h=Math.abs(selection.second.y-selection.first.y)-1;ctx.fillRect(x,y,w,h);ctx.strokeRect(x,y,w,h);ctx.restore()}});plot.hooks.shutdown.push(function(plot,eventHolder){eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mousedown",onMouseDown);if(mouseUpHandler)$(document).unbind("mouseup",mouseUpHandler)})}$.plot.plugins.push({init:init,options:{selection:{mode:null,color:"#e8cfac",shape:"round",minSize:5}},name:"selection",version:"1.1"})})(jQuery); \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.min.js b/library/cpp/lwtrace/mon/static/js/jquery.min.js
index ee48790811..c82a235fee 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.min.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.min.js
@@ -1,5 +1,5 @@
-(function(window,undefined){var rootjQuery,readyList,document=window.document,location=window.location,navigator=window.navigator,_jQuery=window.jQuery,_$=window.$,core_push=Array.prototype.push,core_slice=Array.prototype.slice,core_indexOf=Array.prototype.indexOf,core_toString=Object.prototype.toString,core_hasOwn=Object.prototype.hasOwnProperty,core_trim=String.prototype.trim,jQuery=function(selector,context){return new jQuery.fn.init(selector,context,rootjQuery)},core_pnum=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,core_rnotwhite=/\S/,core_rspace=/\s+/,rtrim=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,rquickExpr=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,rvalidchars=/^[\],:{}\s]*$/,rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g,rvalidescape=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,rvalidtokens=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,rmsPrefix=/^-ms-/,rdashAlpha=/-([\da-z])/gi,fcamelCase=function(all,letter){return(letter+"").toUpperCase()},DOMContentLoaded=function(){if(document.addEventListener){document.removeEventListener("DOMContentLoaded",DOMContentLoaded,false);jQuery.ready()}else if(document.readyState==="complete"){document.detachEvent("onreadystatechange",DOMContentLoaded);jQuery.ready()}},class2type={};jQuery.fn=jQuery.prototype={constructor:jQuery,init:function(selector,context,rootjQuery){var match,elem,ret,doc;if(!selector){return this}if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this}if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null]}else{match=rquickExpr.exec(selector)}if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;doc=context&&context.nodeType?context.ownerDocument||context:document;selector=jQuery.parseHTML(match[1],doc,true);if(rsingleTag.test(match[1])&&jQuery.isPlainObject(context)){this.attr.call(selector,context,true)}return jQuery.merge(this,selector)}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){if(elem.id!==match[2]){return rootjQuery.find(selector)}this.length=1;this[0]=elem}this.context=document;this.selector=selector;return this}}else if(!context||context.jquery){return(context||rootjQuery).find(selector)}else{return this.constructor(context).find(selector)}}else if(jQuery.isFunction(selector)){return rootjQuery.ready(selector)}if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context}return jQuery.makeArray(selector,this)},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return core_slice.call(this)},get:function(num){return num==null?this.toArray():num<0?this[this.length+num]:this[num]},pushStack:function(elems,name,selector){var ret=jQuery.merge(this.constructor(),elems);ret.prevObject=this;ret.context=this.context;if(name==="find"){ret.selector=this.selector+(this.selector?" ":"")+selector}else if(name){ret.selector=this.selector+"."+name+"("+selector+")"}return ret},each:function(callback,args){return jQuery.each(this,callback,args)},ready:function(fn){jQuery.ready.promise().done(fn);return this},eq:function(i){i=+i;return i===-1?this.slice(i):this.slice(i,i+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(core_slice.apply(this,arguments),"slice",core_slice.call(arguments).join(","))},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem)}))},end:function(){return this.prevObject||this.constructor(null)},push:core_push,sort:[].sort,splice:[].splice};jQuery.fn.init.prototype=jQuery.fn;jQuery.extend=jQuery.fn.extend=function(){var options,name,src,copy,copyIsArray,clone,target=arguments[0]||{},i=1,length=arguments.length,deep=false;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2}if(typeof target!=="object"&&!jQuery.isFunction(target)){target={}}if(length===i){target=this;--i}for(;i<length;i++){if((options=arguments[i])!=null){for(name in options){src=target[name];copy=options[name];if(target===copy){continue}if(deep&&copy&&(jQuery.isPlainObject(copy)||(copyIsArray=jQuery.isArray(copy)))){if(copyIsArray){copyIsArray=false;clone=src&&jQuery.isArray(src)?src:[]}else{clone=src&&jQuery.isPlainObject(src)?src:{}}target[name]=jQuery.extend(deep,clone,copy)}else if(copy!==undefined){target[name]=copy}}}}return target};jQuery.extend({noConflict:function(deep){if(window.$===jQuery){window.$=_$}if(deep&&window.jQuery===jQuery){window.jQuery=_jQuery}return jQuery},isReady:false,readyWait:1,holdReady:function(hold){if(hold){jQuery.readyWait++}else{jQuery.ready(true)}},ready:function(wait){if(wait===true?--jQuery.readyWait:jQuery.isReady){return}if(!document.body){return setTimeout(jQuery.ready,1)}jQuery.isReady=true;if(wait!==true&&--jQuery.readyWait>0){return}readyList.resolveWith(document,[jQuery]);if(jQuery.fn.trigger){jQuery(document).trigger("ready").off("ready")}},isFunction:function(obj){return jQuery.type(obj)==="function"},isArray:Array.isArray||function(obj){return jQuery.type(obj)==="array"},isWindow:function(obj){return obj!=null&&obj==obj.window},isNumeric:function(obj){return!isNaN(parseFloat(obj))&&isFinite(obj)},type:function(obj){return obj==null?String(obj):class2type[core_toString.call(obj)]||"object"},isPlainObject:function(obj){if(!obj||jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false}try{if(obj.constructor&&!core_hasOwn.call(obj,"constructor")&&!core_hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false}}catch(e){return false}var key;for(key in obj){}return key===undefined||core_hasOwn.call(obj,key)},isEmptyObject:function(obj){var name;for(name in obj){return false}return true},error:function(msg){throw new Error(msg)},parseHTML:function(data,context,scripts){var parsed;if(!data||typeof data!=="string"){return null}if(typeof context==="boolean"){scripts=context;context=0}context=context||document;if(parsed=rsingleTag.exec(data)){return[context.createElement(parsed[1])]}parsed=jQuery.buildFragment([data],context,scripts?null:[]);return jQuery.merge([],(parsed.cacheable?jQuery.clone(parsed.fragment):parsed.fragment).childNodes)},parseJSON:function(data){if(!data||typeof data!=="string"){return null}data=jQuery.trim(data);if(window.JSON&&window.JSON.parse){return window.JSON.parse(data)}if(rvalidchars.test(data.replace(rvalidescape,"@").replace(rvalidtokens,"]").replace(rvalidbraces,""))){return new Function("return "+data)()}jQuery.error("Invalid JSON: "+data)},parseXML:function(data){var xml,tmp;if(!data||typeof data!=="string"){return null}try{if(window.DOMParser){tmp=new DOMParser;xml=tmp.parseFromString(data,"text/xml")}else{xml=new ActiveXObject("Microsoft.XMLDOM");xml.async="false";xml.loadXML(data)}}catch(e){xml=undefined}if(!xml||!xml.documentElement||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data)}return xml},noop:function(){},globalEval:function(data){if(data&&core_rnotwhite.test(data)){(window.execScript||function(data){window["eval"].call(window,data)})(data)}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase)},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toLowerCase()===name.toLowerCase()},each:function(obj,callback,args){var name,i=0,length=obj.length,isObj=length===undefined||jQuery.isFunction(obj);if(args){if(isObj){for(name in obj){if(callback.apply(obj[name],args)===false){break}}}else{for(;i<length;){if(callback.apply(obj[i++],args)===false){break}}}}else{if(isObj){for(name in obj){if(callback.call(obj[name],name,obj[name])===false){break}}}else{for(;i<length;){if(callback.call(obj[i],i,obj[i++])===false){break}}}}return obj},trim:core_trim&&!core_trim.call(" ")?function(text){return text==null?"":core_trim.call(text)}:function(text){return text==null?"":(text+"").replace(rtrim,"")},makeArray:function(arr,results){var type,ret=results||[];if(arr!=null){type=jQuery.type(arr);if(arr.length==null||type==="string"||type==="function"||type==="regexp"||jQuery.isWindow(arr)){core_push.call(ret,arr)}else{jQuery.merge(ret,arr)}}return ret},inArray:function(elem,arr,i){var len;if(arr){if(core_indexOf){return core_indexOf.call(arr,elem,i)}len=arr.length;i=i?i<0?Math.max(0,len+i):i:0;for(;i<len;i++){if(i in arr&&arr[i]===elem){return i}}}return-1},merge:function(first,second){var l=second.length,i=first.length,j=0;if(typeof l==="number"){for(;j<l;j++){first[i++]=second[j]}}else{while(second[j]!==undefined){first[i++]=second[j++]}}first.length=i;return first},grep:function(elems,callback,inv){var retVal,ret=[],i=0,length=elems.length;inv=!!inv;for(;i<length;i++){retVal=!!callback(elems[i],i);if(inv!==retVal){ret.push(elems[i])}}return ret},map:function(elems,callback,arg){var value,key,ret=[],i=0,length=elems.length,isArray=elems instanceof jQuery||length!==undefined&&typeof length==="number"&&(length>0&&elems[0]&&elems[length-1]||length===0||jQuery.isArray(elems));if(isArray){for(;i<length;i++){value=callback(elems[i],i,arg);if(value!=null){ret[ret.length]=value}}}else{for(key in elems){value=callback(elems[key],key,arg);if(value!=null){ret[ret.length]=value}}}return ret.concat.apply([],ret)},guid:1,proxy:function(fn,context){var tmp,args,proxy;if(typeof context==="string"){tmp=fn[context];context=fn;fn=tmp}if(!jQuery.isFunction(fn)){return undefined}args=core_slice.call(arguments,2);proxy=function(){return fn.apply(context,args.concat(core_slice.call(arguments)))};proxy.guid=fn.guid=fn.guid||jQuery.guid++;return proxy},access:function(elems,fn,key,value,chainable,emptyGet,pass){var exec,bulk=key==null,i=0,length=elems.length;if(key&&typeof key==="object"){for(i in key){jQuery.access(elems,fn,i,key[i],1,emptyGet,value)}chainable=1}else if(value!==undefined){exec=pass===undefined&&jQuery.isFunction(value);if(bulk){if(exec){exec=fn;fn=function(elem,key,value){return exec.call(jQuery(elem),value)}}else{fn.call(elems,value);fn=null}}if(fn){for(;i<length;i++){fn(elems[i],key,exec?value.call(elems[i],i,fn(elems[i],key)):value,pass)}}chainable=1}return chainable?elems:bulk?fn.call(elems):length?fn(elems[0],key):emptyGet},now:function(){return(new Date).getTime()}});jQuery.ready.promise=function(obj){if(!readyList){readyList=jQuery.Deferred();if(document.readyState==="complete"){setTimeout(jQuery.ready,1)}else if(document.addEventListener){document.addEventListener("DOMContentLoaded",DOMContentLoaded,false);window.addEventListener("load",jQuery.ready,false)}else{document.attachEvent("onreadystatechange",DOMContentLoaded);window.attachEvent("onload",jQuery.ready);var top=false;try{top=window.frameElement==null&&document.documentElement}catch(e){}if(top&&top.doScroll){(function doScrollCheck(){if(!jQuery.isReady){try{top.doScroll("left")}catch(e){return setTimeout(doScrollCheck,50)}jQuery.ready()}})()}}}return readyList.promise(obj)};jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(i,name){class2type["[object "+name+"]"]=name.toLowerCase()});rootjQuery=jQuery(document);var optionsCache={};function createOptions(options){var object=optionsCache[options]={};jQuery.each(options.split(core_rspace),function(_,flag){object[flag]=true});return object}jQuery.Callbacks=function(options){options=typeof options==="string"?optionsCache[options]||createOptions(options):jQuery.extend({},options);var memory,fired,firing,firingStart,firingLength,firingIndex,list=[],stack=!options.once&&[],fire=function(data){memory=options.memory&&data;fired=true;firingIndex=firingStart||0;firingStart=0;firingLength=list.length;firing=true;for(;list&&firingIndex<firingLength;firingIndex++){if(list[firingIndex].apply(data[0],data[1])===false&&options.stopOnFalse){memory=false;break}}firing=false;if(list){if(stack){if(stack.length){fire(stack.shift())}}else if(memory){list=[]}else{self.disable()}}},self={add:function(){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg)}}else if(arg&&arg.length&&type!=="string"){add(arg)}})})(arguments);if(firing){firingLength=list.length}else if(memory){firingStart=start;fire(memory)}}return this},remove:function(){if(list){jQuery.each(arguments,function(_,arg){var index;while((index=jQuery.inArray(arg,list,index))>-1){list.splice(index,1);if(firing){if(index<=firingLength){firingLength--}if(index<=firingIndex){firingIndex--}}}})}return this},has:function(fn){return jQuery.inArray(fn,list)>-1},empty:function(){list=[];return this},disable:function(){list=stack=memory=undefined;return this},disabled:function(){return!list},lock:function(){stack=undefined;if(!memory){self.disable()}return this},locked:function(){return!stack},fireWith:function(context,args){args=args||[];args=[context,args.slice?args.slice():args];if(list&&(!fired||stack)){if(firing){stack.push(args)}else{fire(args)}}return this},fire:function(){self.fireWith(this,arguments);return this},fired:function(){return!!fired}};return self};jQuery.extend({Deferred:function(func){var tuples=[["resolve","done",jQuery.Callbacks("once memory"),"resolved"],["reject","fail",jQuery.Callbacks("once memory"),"rejected"],["notify","progress",jQuery.Callbacks("memory")]],state="pending",promise={state:function(){return state},always:function(){deferred.done(arguments).fail(arguments);return this},then:function(){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=fns[i];deferred[tuple[1]](jQuery.isFunction(fn)?function(){var returned=fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify)}else{newDefer[action+"With"](this===deferred?newDefer:this,[returned])}}:newDefer[action])});fns=null}).promise()},promise:function(obj){return obj!=null?jQuery.extend(obj,promise):promise}},deferred={};promise.pipe=promise.then;jQuery.each(tuples,function(i,tuple){var list=tuple[2],stateString=tuple[3];promise[tuple[1]]=list.add;if(stateString){list.add(function(){state=stateString},tuples[i^1][2].disable,tuples[2][2].lock)}deferred[tuple[0]]=list.fire;deferred[tuple[0]+"With"]=list.fireWith});promise.promise(deferred);if(func){func.call(deferred,deferred)}return deferred},when:function(subordinate){var i=0,resolveValues=core_slice.call(arguments),length=resolveValues.length,remaining=length!==1||subordinate&&jQuery.isFunction(subordinate.promise)?length:0,deferred=remaining===1?subordinate:jQuery.Deferred(),updateFunc=function(i,contexts,values){return function(value){contexts[i]=this;values[i]=arguments.length>1?core_slice.call(arguments):value;if(values===progressValues){deferred.notifyWith(contexts,values)}else if(!--remaining){deferred.resolveWith(contexts,values)}}},progressValues,progressContexts,resolveContexts;if(length>1){progressValues=new Array(length);progressContexts=new Array(length);resolveContexts=new Array(length);for(;i<length;i++){if(resolveValues[i]&&jQuery.isFunction(resolveValues[i].promise)){resolveValues[i].promise().done(updateFunc(i,resolveContexts,resolveValues)).fail(deferred.reject).progress(updateFunc(i,progressContexts,progressValues))}else{--remaining}}}if(!remaining){deferred.resolveWith(resolveContexts,resolveValues)}return deferred.promise()}});jQuery.support=function(){var support,all,a,select,opt,input,fragment,eventName,i,isSupported,clickFn,div=document.createElement("div");div.setAttribute("className","t");div.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";all=div.getElementsByTagName("*");a=div.getElementsByTagName("a")[0];if(!all||!a||!all.length){return{}}select=document.createElement("select");opt=select.appendChild(document.createElement("option"));input=div.getElementsByTagName("input")[0];a.style.cssText="top:1px;float:left;opacity:.5";support={leadingWhitespace:div.firstChild.nodeType===3,tbody:!div.getElementsByTagName("tbody").length,htmlSerialize:!!div.getElementsByTagName("link").length,style:/top/.test(a.getAttribute("style")),hrefNormalized:a.getAttribute("href")==="/a",opacity:/^0.5/.test(a.style.opacity),cssFloat:!!a.style.cssFloat,checkOn:input.value==="on",optSelected:opt.selected,getSetAttribute:div.className!=="t",enctype:!!document.createElement("form").enctype,html5Clone:document.createElement("nav").cloneNode(true).outerHTML!=="<:nav></:nav>",boxModel:document.compatMode==="CSS1Compat",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true,boxSizingReliable:true,pixelPosition:false};input.checked=true;support.noCloneChecked=input.cloneNode(true).checked;select.disabled=true;support.optDisabled=!opt.disabled;try{delete div.test}catch(e){support.deleteExpando=false}if(!div.addEventListener&&div.attachEvent&&div.fireEvent){div.attachEvent("onclick",clickFn=function(){support.noCloneEvent=false});div.cloneNode(true).fireEvent("onclick");div.detachEvent("onclick",clickFn)}input=document.createElement("input");input.value="t";input.setAttribute("type","radio");support.radioValue=input.value==="t";input.setAttribute("checked","checked");input.setAttribute("name","t");div.appendChild(input);fragment=document.createDocumentFragment();fragment.appendChild(div.lastChild);support.checkClone=fragment.cloneNode(true).cloneNode(true).lastChild.checked;support.appendChecked=input.checked;fragment.removeChild(input);fragment.appendChild(div);if(div.attachEvent){for(i in{submit:true,change:true,focusin:true}){eventName="on"+i;isSupported=eventName in div;if(!isSupported){div.setAttribute(eventName,"return;");isSupported=typeof div[eventName]==="function"}support[i+"Bubbles"]=isSupported}}jQuery(function(){var container,div,tds,marginDiv,divReset="padding:0;margin:0;border:0;display:block;overflow:hidden;",body=document.getElementsByTagName("body")[0];if(!body){return}container=document.createElement("div");container.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";body.insertBefore(container,body.firstChild);div=document.createElement("div");container.appendChild(div);div.innerHTML="<table><tr><td></td><td>t</td></tr></table>";tds=div.getElementsByTagName("td");tds[0].style.cssText="padding:0;margin:0;border:0;display:none";isSupported=tds[0].offsetHeight===0;tds[0].style.display="";tds[1].style.display="none";support.reliableHiddenOffsets=isSupported&&tds[0].offsetHeight===0;div.innerHTML="";div.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";support.boxSizing=div.offsetWidth===4;support.doesNotIncludeMarginInBodyOffset=body.offsetTop!==1;if(window.getComputedStyle){support.pixelPosition=(window.getComputedStyle(div,null)||{}).top!=="1%";support.boxSizingReliable=(window.getComputedStyle(div,null)||{width:"4px"}).width==="4px";marginDiv=document.createElement("div");marginDiv.style.cssText=div.style.cssText=divReset;marginDiv.style.marginRight=marginDiv.style.width="0";div.style.width="1px";div.appendChild(marginDiv);support.reliableMarginRight=!parseFloat((window.getComputedStyle(marginDiv,null)||{}).marginRight)}if(typeof div.style.zoom!=="undefined"){div.innerHTML="";div.style.cssText=divReset+"width:1px;padding:1px;display:inline;zoom:1";support.inlineBlockNeedsLayout=div.offsetWidth===3;div.style.display="block";div.style.overflow="visible";div.innerHTML="<div></div>";div.firstChild.style.width="5px";support.shrinkWrapBlocks=div.offsetWidth!==3;container.style.zoom=1}body.removeChild(container);container=div=tds=marginDiv=null});fragment.removeChild(div);all=a=select=opt=input=fragment=div=null;return support}();var rbrace=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,rmultiDash=/([A-Z])/g;jQuery.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(jQuery.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(elem){elem=elem.nodeType?jQuery.cache[elem[jQuery.expando]]:elem[jQuery.expando];return!!elem&&!isEmptyDataObject(elem)},data:function(elem,name,data,pvt){if(!jQuery.acceptData(elem)){return}var thisCache,ret,internalKey=jQuery.expando,getByName=typeof name==="string",isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[internalKey]:elem[internalKey]&&internalKey;if((!id||!cache[id]||!pvt&&!cache[id].data)&&getByName&&data===undefined){return}if(!id){if(isNode){elem[internalKey]=id=jQuery.deletedIds.pop()||jQuery.guid++}else{id=internalKey}}if(!cache[id]){cache[id]={};if(!isNode){cache[id].toJSON=jQuery.noop}}if(typeof name==="object"||typeof name==="function"){if(pvt){cache[id]=jQuery.extend(cache[id],name)}else{cache[id].data=jQuery.extend(cache[id].data,name)}}thisCache=cache[id];if(!pvt){if(!thisCache.data){thisCache.data={}}thisCache=thisCache.data}if(data!==undefined){thisCache[jQuery.camelCase(name)]=data}if(getByName){ret=thisCache[name];if(ret==null){ret=thisCache[jQuery.camelCase(name)]}}else{ret=thisCache}return ret},removeData:function(elem,name,pvt){if(!jQuery.acceptData(elem)){return}var thisCache,i,l,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[jQuery.expando]:jQuery.expando;if(!cache[id]){return}if(name){thisCache=pvt?cache[id]:cache[id].data;if(thisCache){if(!jQuery.isArray(name)){if(name in thisCache){name=[name]}else{name=jQuery.camelCase(name);if(name in thisCache){name=[name]}else{name=name.split(" ")}}}for(i=0,l=name.length;i<l;i++){delete thisCache[name[i]]}if(!(pvt?isEmptyDataObject:jQuery.isEmptyObject)(thisCache)){return}}}if(!pvt){delete cache[id].data;if(!isEmptyDataObject(cache[id])){return}}if(isNode){jQuery.cleanData([elem],true)}else if(jQuery.support.deleteExpando||cache!=cache.window){delete cache[id]}else{cache[id]=null}},_data:function(elem,name,data){return jQuery.data(elem,name,data,true)},acceptData:function(elem){var noData=elem.nodeName&&jQuery.noData[elem.nodeName.toLowerCase()];return!noData||noData!==true&&elem.getAttribute("classid")===noData}});jQuery.fn.extend({data:function(key,value){var parts,part,attr,name,l,elem=this[0],i=0,data=null;if(key===undefined){if(this.length){data=jQuery.data(elem);if(elem.nodeType===1&&!jQuery._data(elem,"parsedAttrs")){attr=elem.attributes;for(l=attr.length;i<l;i++){name=attr[i].name;if(!name.indexOf("data-")){name=jQuery.camelCase(name.substring(5));dataAttr(elem,name,data[name])}}jQuery._data(elem,"parsedAttrs",true)}}return data}if(typeof key==="object"){return this.each(function(){jQuery.data(this,key)})}parts=key.split(".",2);parts[1]=parts[1]?"."+parts[1]:"";part=parts[1]+"!";return jQuery.access(this,function(value){if(value===undefined){data=this.triggerHandler("getData"+part,[parts[0]]);if(data===undefined&&elem){data=jQuery.data(elem,key);data=dataAttr(elem,key,data)}return data===undefined&&parts[1]?this.data(parts[0]):data}parts[1]=value;this.each(function(){var self=jQuery(this);self.triggerHandler("setData"+part,parts);jQuery.data(this,key,value);self.triggerHandler("changeData"+part,parts)})},null,value,arguments.length>1,null,false)},removeData:function(key){return this.each(function(){jQuery.removeData(this,key)})}});function dataAttr(elem,key,data){if(data===undefined&&elem.nodeType===1){var name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:+data+""===data?+data:rbrace.test(data)?jQuery.parseJSON(data):data}catch(e){}jQuery.data(elem,key,data)}else{data=undefined}}return data}function isEmptyDataObject(obj){var name;for(name in obj){if(name==="data"&&jQuery.isEmptyObject(obj[name])){continue}if(name!=="toJSON"){return false}}return true}jQuery.extend({queue:function(elem,type,data){var queue;if(elem){type=(type||"fx")+"queue";queue=jQuery._data(elem,type);if(data){if(!queue||jQuery.isArray(data)){queue=jQuery._data(elem,type,jQuery.makeArray(data))}else{queue.push(data)}}return queue||[]}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),startLength=queue.length,fn=queue.shift(),hooks=jQuery._queueHooks(elem,type),next=function(){jQuery.dequeue(elem,type)};if(fn==="inprogress"){fn=queue.shift();startLength--}if(fn){if(type==="fx"){queue.unshift("inprogress")}delete hooks.stop;fn.call(elem,next,hooks)}if(!startLength&&hooks){hooks.empty.fire()}},_queueHooks:function(elem,type){var key=type+"queueHooks";return jQuery._data(elem,key)||jQuery._data(elem,key,{empty:jQuery.Callbacks("once memory").add(function(){jQuery.removeData(elem,type+"queue",true);jQuery.removeData(elem,key,true)})})}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--}if(arguments.length<setter){return jQuery.queue(this[0],type)}return data===undefined?this:this.each(function(){var queue=jQuery.queue(this,type,data);jQuery._queueHooks(this,type);if(type==="fx"&&queue[0]!=="inprogress"){jQuery.dequeue(this,type)}})},dequeue:function(type){return this.each(function(){jQuery.dequeue(this,type)})},delay:function(time,type){time=jQuery.fx?jQuery.fx.speeds[time]||time:time;type=type||"fx";return this.queue(type,function(next,hooks){var timeout=setTimeout(next,time);hooks.stop=function(){clearTimeout(timeout)}})},clearQueue:function(type){return this.queue(type||"fx",[])},promise:function(type,obj){var tmp,count=1,defer=jQuery.Deferred(),elements=this,i=this.length,resolve=function(){if(!--count){defer.resolveWith(elements,[elements])}};if(typeof type!=="string"){obj=type;type=undefined}type=type||"fx";while(i--){tmp=jQuery._data(elements[i],type+"queueHooks");if(tmp&&tmp.empty){count++;tmp.empty.add(resolve)}}resolve();return defer.promise(obj)}});var nodeHook,boolHook,fixSpecified,rclass=/[\t\r\n]/g,rreturn=/\r/g,rtype=/^(?:button|input)$/i,rfocusable=/^(?:button|input|object|select|textarea)$/i,rclickable=/^a(?:rea|)$/i,rboolean=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,getSetAttribute=jQuery.support.getSetAttribute;jQuery.fn.extend({attr:function(name,value){return jQuery.access(this,jQuery.attr,name,value,arguments.length>1)},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name)})},prop:function(name,value){return jQuery.access(this,jQuery.prop,name,value,arguments.length>1)},removeProp:function(name){name=jQuery.propFix[name]||name;return this.each(function(){try{this[name]=undefined;delete this[name]}catch(e){}})},addClass:function(value){var classNames,i,l,elem,setClass,c,cl;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className))})}if(value&&typeof value==="string"){classNames=value.split(core_rspace);for(i=0,l=this.length;i<l;i++){elem=this[i];if(elem.nodeType===1){if(!elem.className&&classNames.length===1){elem.className=value}else{setClass=" "+elem.className+" ";for(c=0,cl=classNames.length;c<cl;c++){if(setClass.indexOf(" "+classNames[c]+" ")<0){setClass+=classNames[c]+" "}}elem.className=jQuery.trim(setClass)}}}}return this},removeClass:function(value){var removes,className,elem,c,cl,i,l;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).removeClass(value.call(this,j,this.className))})}if(value&&typeof value==="string"||value===undefined){removes=(value||"").split(core_rspace);for(i=0,l=this.length;i<l;i++){elem=this[i];if(elem.nodeType===1&&elem.className){className=(" "+elem.className+" ").replace(rclass," ");for(c=0,cl=removes.length;c<cl;c++){while(className.indexOf(" "+removes[c]+" ")>=0){className=className.replace(" "+removes[c]+" "," ")}}elem.className=value?jQuery.trim(className):""}}}return this},toggleClass:function(value,stateVal){var type=typeof value,isBool=typeof stateVal==="boolean";if(jQuery.isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal)})}return this.each(function(){if(type==="string"){var className,i=0,self=jQuery(this),state=stateVal,classNames=value.split(core_rspace);while(className=classNames[i++]){state=isBool?state:!self.hasClass(className);self[state?"addClass":"removeClass"](className)}}else if(type==="undefined"||type==="boolean"){if(this.className){jQuery._data(this,"__className__",this.className)}this.className=this.className||value===false?"":jQuery._data(this,"__className__")||""}})},hasClass:function(selector){var className=" "+selector+" ",i=0,l=this.length;for(;i<l;i++){if(this[i].nodeType===1&&(" "+this[i].className+" ").replace(rclass," ").indexOf(className)>=0){return true}}return false},val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret}ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret}return}isFunction=jQuery.isFunction(value);return this.each(function(i){var val,self=jQuery(this);if(this.nodeType!==1){return}if(isFunction){val=value.call(this,i,self.val())}else{val=value}if(val==null){val=""}else if(typeof val==="number"){val+=""}else if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+""})}hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val}})}});jQuery.extend({valHooks:{option:{get:function(elem){var val=elem.attributes.value;return!val||val.specified?elem.value:elem.text}},select:{get:function(elem){var value,option,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one"||index<0,values=one?null:[],max=one?index+1:options.length,i=index<0?max:one?index:0;for(;i<max;i++){option=options[i];if((option.selected||i===index)&&(jQuery.support.optDisabled?!option.disabled:option.getAttribute("disabled")===null)&&(!option.parentNode.disabled||!jQuery.nodeName(option.parentNode,"optgroup"))){value=jQuery(option).val();if(one){return value}values.push(value)}}return values},set:function(elem,value){var values=jQuery.makeArray(value);jQuery(elem).find("option").each(function(){this.selected=jQuery.inArray(jQuery(this).val(),values)>=0});if(!values.length){elem.selectedIndex=-1}return values}}},attrFn:{},attr:function(elem,name,value,pass){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return}if(pass&&jQuery.isFunction(jQuery.fn[name])){return jQuery(elem)[name](value)}if(typeof elem.getAttribute==="undefined"){return jQuery.prop(elem,name,value)}notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(rboolean.test(name)?boolHook:nodeHook)}if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);return}else if(hooks&&"set"in hooks&&notxml&&(ret=hooks.set(elem,value,name))!==undefined){return ret}else{elem.setAttribute(name,value+"");return value}}else if(hooks&&"get"in hooks&&notxml&&(ret=hooks.get(elem,name))!==null){return ret}else{ret=elem.getAttribute(name);return ret===null?undefined:ret}},removeAttr:function(elem,value){var propName,attrNames,name,isBool,i=0;if(value&&elem.nodeType===1){attrNames=value.split(core_rspace);for(;i<attrNames.length;i++){name=attrNames[i];if(name){propName=jQuery.propFix[name]||name;isBool=rboolean.test(name);if(!isBool){jQuery.attr(elem,name,"")}elem.removeAttribute(getSetAttribute?name:propName);if(isBool&&propName in elem){elem[propName]=false}}}}},attrHooks:{type:{set:function(elem,value){if(rtype.test(elem.nodeName)&&elem.parentNode){jQuery.error("type property can't be changed")
-}else if(!jQuery.support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val}return value}}},value:{get:function(elem,name){if(nodeHook&&jQuery.nodeName(elem,"button")){return nodeHook.get(elem,name)}return name in elem?elem.value:null},set:function(elem,value,name){if(nodeHook&&jQuery.nodeName(elem,"button")){return nodeHook.set(elem,value,name)}elem.value=value}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return}notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name]}if(value!==undefined){if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret}else{return elem[name]=value}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret}else{return elem[name]}}},propHooks:{tabIndex:{get:function(elem){var attributeNode=elem.getAttributeNode("tabindex");return attributeNode&&attributeNode.specified?parseInt(attributeNode.value,10):rfocusable.test(elem.nodeName)||rclickable.test(elem.nodeName)&&elem.href?0:undefined}}}});boolHook={get:function(elem,name){var attrNode,property=jQuery.prop(elem,name);return property===true||typeof property!=="boolean"&&(attrNode=elem.getAttributeNode(name))&&attrNode.nodeValue!==false?name.toLowerCase():undefined},set:function(elem,value,name){var propName;if(value===false){jQuery.removeAttr(elem,name)}else{propName=jQuery.propFix[name]||name;if(propName in elem){elem[propName]=true}elem.setAttribute(name,name.toLowerCase())}return name}};if(!getSetAttribute){fixSpecified={name:true,id:true,coords:true};nodeHook=jQuery.valHooks.button={get:function(elem,name){var ret;ret=elem.getAttributeNode(name);return ret&&(fixSpecified[name]?ret.value!=="":ret.specified)?ret.value:undefined},set:function(elem,value,name){var ret=elem.getAttributeNode(name);if(!ret){ret=document.createAttribute(name);elem.setAttributeNode(ret)}return ret.value=value+""}};jQuery.each(["width","height"],function(i,name){jQuery.attrHooks[name]=jQuery.extend(jQuery.attrHooks[name],{set:function(elem,value){if(value===""){elem.setAttribute(name,"auto");return value}}})});jQuery.attrHooks.contenteditable={get:nodeHook.get,set:function(elem,value,name){if(value===""){value="false"}nodeHook.set(elem,value,name)}}}if(!jQuery.support.hrefNormalized){jQuery.each(["href","src","width","height"],function(i,name){jQuery.attrHooks[name]=jQuery.extend(jQuery.attrHooks[name],{get:function(elem){var ret=elem.getAttribute(name,2);return ret===null?undefined:ret}})})}if(!jQuery.support.style){jQuery.attrHooks.style={get:function(elem){return elem.style.cssText.toLowerCase()||undefined},set:function(elem,value){return elem.style.cssText=value+""}}}if(!jQuery.support.optSelected){jQuery.propHooks.selected=jQuery.extend(jQuery.propHooks.selected,{get:function(elem){var parent=elem.parentNode;if(parent){parent.selectedIndex;if(parent.parentNode){parent.parentNode.selectedIndex}}return null}})}if(!jQuery.support.enctype){jQuery.propFix.enctype="encoding"}if(!jQuery.support.checkOn){jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={get:function(elem){return elem.getAttribute("value")===null?"on":elem.value}}})}jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]=jQuery.extend(jQuery.valHooks[this],{set:function(elem,value){if(jQuery.isArray(value)){return elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0}}})});var rformElems=/^(?:textarea|input|select)$/i,rtypenamespace=/^([^\.]*|)(?:\.(.+)|)$/,rhoverHack=/(?:^|\s)hover(\.\S+|)\b/,rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,hoverHack=function(events){return jQuery.event.special.hover?events:events.replace(rhoverHack,"mouseenter$1 mouseleave$1")};jQuery.event={add:function(elem,types,handler,data,selector){var elemData,eventHandle,events,t,tns,type,namespaces,handleObj,handleObjIn,handlers,special;if(elem.nodeType===3||elem.nodeType===8||!types||!handler||!(elemData=jQuery._data(elem))){return}if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector}if(!handler.guid){handler.guid=jQuery.guid++}events=elemData.events;if(!events){elemData.events=events={}}eventHandle=elemData.handle;if(!eventHandle){elemData.handle=eventHandle=function(e){return typeof jQuery!=="undefined"&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined};eventHandle.elem=elem}types=jQuery.trim(hoverHack(types)).split(" ");for(t=0;t<types.length;t++){tns=rtypenamespace.exec(types[t])||[];type=tns[1];namespaces=(tns[2]||"").split(".").sort();special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:tns[1],data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);handlers=events[type];if(!handlers){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle,false)}else if(elem.attachEvent){elem.attachEvent("on"+type,eventHandle)}}}if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid}}if(selector){handlers.splice(handlers.delegateCount++,0,handleObj)}else{handlers.push(handleObj)}jQuery.event.global[type]=true}elem=null},global:{},remove:function(elem,types,handler,selector,mappedTypes){var t,tns,type,origType,namespaces,origCount,j,events,special,eventType,handleObj,elemData=jQuery.hasData(elem)&&jQuery._data(elem);if(!elemData||!(events=elemData.events)){return}types=jQuery.trim(hoverHack(types||"")).split(" ");for(t=0;t<types.length;t++){tns=rtypenamespace.exec(types[t])||[];type=origType=tns[1];namespaces=tns[2];if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true)}continue}special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;eventType=events[type]||[];origCount=eventType.length;namespaces=namespaces?new RegExp("(^|\\.)"+namespaces.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(j=0;j<eventType.length;j++){handleObj=eventType[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!namespaces||namespaces.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){eventType.splice(j--,1);if(handleObj.selector){eventType.delegateCount--}if(special.remove){special.remove.call(elem,handleObj)}}}if(eventType.length===0&&origCount!==eventType.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle)}delete events[type]}}if(jQuery.isEmptyObject(events)){delete elemData.handle;jQuery.removeData(elem,"events",true)}},customEvent:{getData:true,setData:true,changeData:true},trigger:function(event,data,elem,onlyHandlers){if(elem&&(elem.nodeType===3||elem.nodeType===8)){return}var cache,exclusive,i,cur,old,ontype,special,handle,eventPath,bubbleType,type=event.type||event,namespaces=[];if(rfocusMorph.test(type+jQuery.event.triggered)){return}if(type.indexOf("!")>=0){type=type.slice(0,-1);exclusive=true}if(type.indexOf(".")>=0){namespaces=type.split(".");type=namespaces.shift();namespaces.sort()}if((!elem||jQuery.event.customEvent[type])&&!jQuery.event.global[type]){return}event=typeof event==="object"?event[jQuery.expando]?event:new jQuery.Event(type,event):new jQuery.Event(type);event.type=type;event.isTrigger=true;event.exclusive=exclusive;event.namespace=namespaces.join(".");event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;ontype=type.indexOf(":")<0?"on"+type:"";if(!elem){cache=jQuery.cache;for(i in cache){if(cache[i].events&&cache[i].events[type]){jQuery.event.trigger(event,data,cache[i].handle.elem,true)}}return}event.result=undefined;if(!event.target){event.target=elem}data=data!=null?jQuery.makeArray(data):[];data.unshift(event);special=jQuery.event.special[type]||{};if(special.trigger&&special.trigger.apply(elem,data)===false){return}eventPath=[[elem,special.bindType||type]];if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;cur=rfocusMorph.test(bubbleType+type)?elem:elem.parentNode;for(old=elem;cur;cur=cur.parentNode){eventPath.push([cur,bubbleType]);old=cur}if(old===(elem.ownerDocument||document)){eventPath.push([old.defaultView||old.parentWindow||window,bubbleType])}}for(i=0;i<eventPath.length&&!event.isPropagationStopped();i++){cur=eventPath[i][0];event.type=eventPath[i][1];handle=(jQuery._data(cur,"events")||{})[event.type]&&jQuery._data(cur,"handle");if(handle){handle.apply(cur,data)}handle=ontype&&cur[ontype];if(handle&&jQuery.acceptData(cur)&&handle.apply&&handle.apply(cur,data)===false){event.preventDefault()}}event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(elem.ownerDocument,data)===false)&&!(type==="click"&&jQuery.nodeName(elem,"a"))&&jQuery.acceptData(elem)){if(ontype&&elem[type]&&(type!=="focus"&&type!=="blur"||event.target.offsetWidth!==0)&&!jQuery.isWindow(elem)){old=elem[ontype];if(old){elem[ontype]=null}jQuery.event.triggered=type;elem[type]();jQuery.event.triggered=undefined;if(old){elem[ontype]=old}}}}return event.result},dispatch:function(event){event=jQuery.event.fix(event||window.event);var i,j,cur,ret,selMatch,matched,matches,handleObj,sel,related,handlers=(jQuery._data(this,"events")||{})[event.type]||[],delegateCount=handlers.delegateCount,args=core_slice.call(arguments),run_all=!event.exclusive&&!event.namespace,special=jQuery.event.special[event.type]||{},handlerQueue=[];args[0]=event;event.delegateTarget=this;if(special.preDispatch&&special.preDispatch.call(this,event)===false){return}if(delegateCount&&!(event.button&&event.type==="click")){for(cur=event.target;cur!=this;cur=cur.parentNode||this){if(cur.disabled!==true||event.type!=="click"){selMatch={};matches=[];for(i=0;i<delegateCount;i++){handleObj=handlers[i];sel=handleObj.selector;if(selMatch[sel]===undefined){selMatch[sel]=handleObj.needsContext?jQuery(sel,this).index(cur)>=0:jQuery.find(sel,this,null,[cur]).length}if(selMatch[sel]){matches.push(handleObj)}}if(matches.length){handlerQueue.push({elem:cur,matches:matches})}}}}if(handlers.length>delegateCount){handlerQueue.push({elem:this,matches:handlers.slice(delegateCount)})}for(i=0;i<handlerQueue.length&&!event.isPropagationStopped();i++){matched=handlerQueue[i];event.currentTarget=matched.elem;for(j=0;j<matched.matches.length&&!event.isImmediatePropagationStopped();j++){handleObj=matched.matches[j];if(run_all||!event.namespace&&!handleObj.namespace||event.namespace_re&&event.namespace_re.test(handleObj.namespace)){event.data=handleObj.data;event.handleObj=handleObj;ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args);if(ret!==undefined){event.result=ret;if(ret===false){event.preventDefault();event.stopPropagation()}}}}}if(special.postDispatch){special.postDispatch.call(this,event)}return event.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(event,original){if(event.which==null){event.which=original.charCode!=null?original.charCode:original.keyCode}return event}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(event,original){var eventDoc,doc,body,button=original.button,fromElement=original.fromElement;if(event.pageX==null&&original.clientX!=null){eventDoc=event.target.ownerDocument||document;doc=eventDoc.documentElement;body=eventDoc.body;event.pageX=original.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);event.pageY=original.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0)}if(!event.relatedTarget&&fromElement){event.relatedTarget=fromElement===event.target?original.toElement:fromElement}if(!event.which&&button!==undefined){event.which=button&1?1:button&2?3:button&4?2:0}return event}},fix:function(event){if(event[jQuery.expando]){return event}var i,prop,originalEvent=event,fixHook=jQuery.event.fixHooks[event.type]||{},copy=fixHook.props?this.props.concat(fixHook.props):this.props;event=jQuery.Event(originalEvent);for(i=copy.length;i;){prop=copy[--i];event[prop]=originalEvent[prop]}if(!event.target){event.target=originalEvent.srcElement||document}if(event.target.nodeType===3){event.target=event.target.parentNode}event.metaKey=!!event.metaKey;return fixHook.filter?fixHook.filter(event,originalEvent):event},special:{load:{noBubble:true},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(data,namespaces,eventHandle){if(jQuery.isWindow(this)){this.onbeforeunload=eventHandle}},teardown:function(namespaces,eventHandle){if(this.onbeforeunload===eventHandle){this.onbeforeunload=null}}}},simulate:function(type,elem,event,bubble){var e=jQuery.extend(new jQuery.Event,event,{type:type,isSimulated:true,originalEvent:{}});if(bubble){jQuery.event.trigger(e,null,elem)}else{jQuery.event.dispatch.call(elem,e)}if(e.isDefaultPrevented()){event.preventDefault()}}};jQuery.event.handle=jQuery.event.dispatch;jQuery.removeEvent=document.removeEventListener?function(elem,type,handle){if(elem.removeEventListener){elem.removeEventListener(type,handle,false)}}:function(elem,type,handle){var name="on"+type;if(elem.detachEvent){if(typeof elem[name]==="undefined"){elem[name]=null}elem.detachEvent(name,handle)}};jQuery.Event=function(src,props){if(!(this instanceof jQuery.Event)){return new jQuery.Event(src,props)}if(src&&src.type){this.originalEvent=src;this.type=src.type;this.isDefaultPrevented=src.defaultPrevented||src.returnValue===false||src.getPreventDefault&&src.getPreventDefault()?returnTrue:returnFalse}else{this.type=src}if(props){jQuery.extend(this,props)}this.timeStamp=src&&src.timeStamp||jQuery.now();this[jQuery.expando]=true};function returnFalse(){return false}function returnTrue(){return true}jQuery.Event.prototype={preventDefault:function(){this.isDefaultPrevented=returnTrue;var e=this.originalEvent;if(!e){return}if(e.preventDefault){e.preventDefault()}else{e.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=returnTrue;var e=this.originalEvent;if(!e){return}if(e.stopPropagation){e.stopPropagation()}e.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation()},isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse};jQuery.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(orig,fix){jQuery.event.special[orig]={delegateType:fix,bindType:fix,handle:function(event){var ret,target=this,related=event.relatedTarget,handleObj=event.handleObj,selector=handleObj.selector;if(!related||related!==target&&!jQuery.contains(target,related)){event.type=handleObj.origType;ret=handleObj.handler.apply(this,arguments);event.type=fix}return ret}}});if(!jQuery.support.submitBubbles){jQuery.event.special.submit={setup:function(){if(jQuery.nodeName(this,"form")){return false}jQuery.event.add(this,"click._submit keypress._submit",function(e){var elem=e.target,form=jQuery.nodeName(elem,"input")||jQuery.nodeName(elem,"button")?elem.form:undefined;if(form&&!jQuery._data(form,"_submit_attached")){jQuery.event.add(form,"submit._submit",function(event){event._submit_bubble=true});jQuery._data(form,"_submit_attached",true)}})},postDispatch:function(event){if(event._submit_bubble){delete event._submit_bubble;if(this.parentNode&&!event.isTrigger){jQuery.event.simulate("submit",this.parentNode,event,true)}}},teardown:function(){if(jQuery.nodeName(this,"form")){return false}jQuery.event.remove(this,"._submit")}}}if(!jQuery.support.changeBubbles){jQuery.event.special.change={setup:function(){if(rformElems.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio"){jQuery.event.add(this,"propertychange._change",function(event){if(event.originalEvent.propertyName==="checked"){this._just_changed=true}});jQuery.event.add(this,"click._change",function(event){if(this._just_changed&&!event.isTrigger){this._just_changed=false}jQuery.event.simulate("change",this,event,true)})}return false}jQuery.event.add(this,"beforeactivate._change",function(e){var elem=e.target;if(rformElems.test(elem.nodeName)&&!jQuery._data(elem,"_change_attached")){jQuery.event.add(elem,"change._change",function(event){if(this.parentNode&&!event.isSimulated&&!event.isTrigger){jQuery.event.simulate("change",this.parentNode,event,true)}});jQuery._data(elem,"_change_attached",true)}})},handle:function(event){var elem=event.target;if(this!==elem||event.isSimulated||event.isTrigger||elem.type!=="radio"&&elem.type!=="checkbox"){return event.handleObj.handler.apply(this,arguments)}},teardown:function(){jQuery.event.remove(this,"._change");return!rformElems.test(this.nodeName)}}}if(!jQuery.support.focusinBubbles){jQuery.each({focus:"focusin",blur:"focusout"},function(orig,fix){var attaches=0,handler=function(event){jQuery.event.simulate(fix,event.target,jQuery.event.fix(event),true)};jQuery.event.special[fix]={setup:function(){if(attaches++===0){document.addEventListener(orig,handler,true)}},teardown:function(){if(--attaches===0){document.removeEventListener(orig,handler,true)}}}})}jQuery.fn.extend({on:function(types,selector,data,fn,one){var origFn,type;if(typeof types==="object"){if(typeof selector!=="string"){data=data||selector;selector=undefined}for(type in types){this.on(type,selector,data,types[type],one)}return this}if(data==null&&fn==null){fn=selector;data=selector=undefined}else if(fn==null){if(typeof selector==="string"){fn=data;data=undefined}else{fn=data;data=selector;selector=undefined}}if(fn===false){fn=returnFalse}else if(!fn){return this}if(one===1){origFn=fn;fn=function(event){jQuery().off(event);return origFn.apply(this,arguments)};fn.guid=origFn.guid||(origFn.guid=jQuery.guid++)}return this.each(function(){jQuery.event.add(this,types,fn,data,selector)})},one:function(types,selector,data,fn){return this.on(types,selector,data,fn,1)},off:function(types,selector,fn){var handleObj,type;if(types&&types.preventDefault&&types.handleObj){handleObj=types.handleObj;jQuery(types.delegateTarget).off(handleObj.namespace?handleObj.origType+"."+handleObj.namespace:handleObj.origType,handleObj.selector,handleObj.handler);return this}if(typeof types==="object"){for(type in types){this.off(type,selector,types[type])}return this}if(selector===false||typeof selector==="function"){fn=selector;selector=undefined}if(fn===false){fn=returnFalse}return this.each(function(){jQuery.event.remove(this,types,fn,selector)})},bind:function(types,data,fn){return this.on(types,null,data,fn)},unbind:function(types,fn){return this.off(types,null,fn)},live:function(types,data,fn){jQuery(this.context).on(types,this.selector,data,fn);return this},die:function(types,fn){jQuery(this.context).off(types,this.selector||"**",fn);return this},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn)},undelegate:function(selector,types,fn){return arguments.length===1?this.off(selector,"**"):this.off(types,selector||"**",fn)},trigger:function(type,data){return this.each(function(){jQuery.event.trigger(type,data,this)})},triggerHandler:function(type,data){if(this[0]){return jQuery.event.trigger(type,data,this[0],true)}},toggle:function(fn){var args=arguments,guid=fn.guid||jQuery.guid++,i=0,toggler=function(event){var lastToggle=(jQuery._data(this,"lastToggle"+fn.guid)||0)%i;jQuery._data(this,"lastToggle"+fn.guid,lastToggle+1);event.preventDefault();return args[lastToggle].apply(this,arguments)||false};toggler.guid=guid;while(i<args.length){args[i++].guid=guid}return this.click(toggler)},hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver)}});jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick "+"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+"change select submit keydown keypress keyup error contextmenu").split(" "),function(i,name){jQuery.fn[name]=function(data,fn){if(fn==null){fn=data;data=null}return arguments.length>0?this.on(name,null,data,fn):this.trigger(name)};if(rkeyEvent.test(name)){jQuery.event.fixHooks[name]=jQuery.event.keyHooks}if(rmouseEvent.test(name)){jQuery.event.fixHooks[name]=jQuery.event.mouseHooks}});(function(window,undefined){var cachedruns,assertGetIdNotName,Expr,getText,isXML,contains,compile,sortOrder,hasDuplicate,outermostContext,baseHasDuplicate=true,strundefined="undefined",expando=("sizcache"+Math.random()).replace(".",""),Token=String,document=window.document,docElem=document.documentElement,dirruns=0,done=0,pop=[].pop,push=[].push,slice=[].slice,indexOf=[].indexOf||function(elem){var i=0,len=this.length;for(;i<len;i++){if(this[i]===elem){return i}}return-1},markFunction=function(fn,value){fn[expando]=value==null||value;return fn},createCache=function(){var cache={},keys=[];return markFunction(function(key,value){if(keys.push(key)>Expr.cacheLength){delete cache[keys.shift()]}return cache[key+" "]=value},cache)},classCache=createCache(),tokenCache=createCache(),compilerCache=createCache(),whitespace="[\\x20\\t\\r\\n\\f]",characterEncoding="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",identifier=characterEncoding.replace("w","w#"),operators="([*^$|!~]?=)",attributes="\\["+whitespace+"*("+characterEncoding+")"+whitespace+"*(?:"+operators+whitespace+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+identifier+")|)|)"+whitespace+"*\\]",pseudos=":("+characterEncoding+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+attributes+")|[^:]|\\\\.)*|.*))\\)|)",pos=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+whitespace+"*((?:-\\d)?\\d*)"+whitespace+"*\\)|)(?=[^-]|$)",rtrim=new RegExp("^"+whitespace+"+|((?:^|[^\\\\])(?:\\\\.)*)"+whitespace+"+$","g"),rcomma=new RegExp("^"+whitespace+"*,"+whitespace+"*"),rcombinators=new RegExp("^"+whitespace+"*([\\x20\\t\\r\\n\\f>+~])"+whitespace+"*"),rpseudo=new RegExp(pseudos),rquickExpr=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,rnot=/^:not/,rsibling=/[\x20\t\r\n\f]*[+~]/,rendsWithNot=/:not\($/,rheader=/h\d/i,rinputs=/input|select|textarea|button/i,rbackslash=/\\(?!\\)/g,matchExpr={ID:new RegExp("^#("+characterEncoding+")"),CLASS:new RegExp("^\\.("+characterEncoding+")"),NAME:new RegExp("^\\[name=['\"]?("+characterEncoding+")['\"]?\\]"),TAG:new RegExp("^("+characterEncoding.replace("w","w*")+")"),ATTR:new RegExp("^"+attributes),PSEUDO:new RegExp("^"+pseudos),POS:new RegExp(pos,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+whitespace+"*(even|odd|(([+-]|)(\\d*)n|)"+whitespace+"*(?:([+-]|)"+whitespace+"*(\\d+)|))"+whitespace+"*\\)|)","i"),needsContext:new RegExp("^"+whitespace+"*[>+~]|"+pos,"i")},assert=function(fn){var div=document.createElement("div");try{return fn(div)}catch(e){return false}finally{div=null}},assertTagNameNoComments=assert(function(div){div.appendChild(document.createComment(""));return!div.getElementsByTagName("*").length}),assertHrefNotNormalized=assert(function(div){div.innerHTML="<a href='#'></a>";return div.firstChild&&typeof div.firstChild.getAttribute!==strundefined&&div.firstChild.getAttribute("href")==="#"}),assertAttributes=assert(function(div){div.innerHTML="<select></select>";var type=typeof div.lastChild.getAttribute("multiple");return type!=="boolean"&&type!=="string"}),assertUsableClassName=assert(function(div){div.innerHTML="<div class='hidden e'></div><div class='hidden'></div>";if(!div.getElementsByClassName||!div.getElementsByClassName("e").length){return false}div.lastChild.className="e";return div.getElementsByClassName("e").length===2}),assertUsableName=assert(function(div){div.id=expando+0;div.innerHTML="<a name='"+expando+"'></a><div name='"+expando+"'></div>";docElem.insertBefore(div,docElem.firstChild);var pass=document.getElementsByName&&document.getElementsByName(expando).length===2+document.getElementsByName(expando+0).length;assertGetIdNotName=!document.getElementById(expando);docElem.removeChild(div);return pass});try{slice.call(docElem.childNodes,0)[0].nodeType}catch(e){slice=function(i){var elem,results=[];for(;elem=this[i];i++){results.push(elem)}return results}}function Sizzle(selector,context,results,seed){results=results||[];context=context||document;var match,elem,xml,m,nodeType=context.nodeType;if(!selector||typeof selector!=="string"){return results}if(nodeType!==1&&nodeType!==9){return[]}xml=isXML(context);if(!xml&&!seed){if(match=rquickExpr.exec(selector)){if(m=match[1]){if(nodeType===9){elem=context.getElementById(m);if(elem&&elem.parentNode){if(elem.id===m){results.push(elem);return results}}else{return results}}else{if(context.ownerDocument&&(elem=context.ownerDocument.getElementById(m))&&contains(context,elem)&&elem.id===m){results.push(elem);return results}}}else if(match[2]){push.apply(results,slice.call(context.getElementsByTagName(selector),0));return results}else if((m=match[3])&&assertUsableClassName&&context.getElementsByClassName){push.apply(results,slice.call(context.getElementsByClassName(m),0));return results}}}return select(selector.replace(rtrim,"$1"),context,results,seed,xml)}Sizzle.matches=function(expr,elements){return Sizzle(expr,null,null,elements)};Sizzle.matchesSelector=function(elem,expr){return Sizzle(expr,null,null,[elem]).length>0};function createInputPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type===type}}function createButtonPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&elem.type===type}}function createPositionalPseudo(fn){return markFunction(function(argument){argument=+argument;return markFunction(function(seed,matches){var j,matchIndexes=fn([],seed.length,argument),i=matchIndexes.length;while(i--){if(seed[j=matchIndexes[i]]){seed[j]=!(matches[j]=seed[j])}}})})}getText=Sizzle.getText=function(elem){var node,ret="",i=0,nodeType=elem.nodeType;if(nodeType){if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem)}}}else if(nodeType===3||nodeType===4){return elem.nodeValue}}else{for(;node=elem[i];i++){ret+=getText(node)}}return ret};isXML=Sizzle.isXML=function(elem){var documentElement=elem&&(elem.ownerDocument||elem).documentElement;return documentElement?documentElement.nodeName!=="HTML":false};contains=Sizzle.contains=docElem.contains?function(a,b){var adown=a.nodeType===9?a.documentElement:a,bup=b&&b.parentNode;return a===bup||!!(bup&&bup.nodeType===1&&adown.contains&&adown.contains(bup))}:docElem.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode){if(b===a){return true}}return false};Sizzle.attr=function(elem,name){var val,xml=isXML(elem);if(!xml){name=name.toLowerCase()}if(val=Expr.attrHandle[name]){return val(elem)}if(xml||assertAttributes){return elem.getAttribute(name)}val=elem.getAttributeNode(name);return val?typeof elem[name]==="boolean"?elem[name]?name:null:val.specified?val.value:null:null};Expr=Sizzle.selectors={cacheLength:50,createPseudo:markFunction,match:matchExpr,attrHandle:assertHrefNotNormalized?{}:{href:function(elem){return elem.getAttribute("href",2)},type:function(elem){return elem.getAttribute("type")}},find:{ID:assertGetIdNotName?function(id,context,xml){if(typeof context.getElementById!==strundefined&&!xml){var m=context.getElementById(id);return m&&m.parentNode?[m]:[]}}:function(id,context,xml){if(typeof context.getElementById!==strundefined&&!xml){var m=context.getElementById(id);return m?m.id===id||typeof m.getAttributeNode!==strundefined&&m.getAttributeNode("id").value===id?[m]:undefined:[]}},TAG:assertTagNameNoComments?function(tag,context){if(typeof context.getElementsByTagName!==strundefined){return context.getElementsByTagName(tag)}}:function(tag,context){var results=context.getElementsByTagName(tag);if(tag==="*"){var elem,tmp=[],i=0;for(;elem=results[i];i++){if(elem.nodeType===1){tmp.push(elem)}}return tmp}return results},NAME:assertUsableName&&function(tag,context){if(typeof context.getElementsByName!==strundefined){return context.getElementsByName(name)}},CLASS:assertUsableClassName&&function(className,context,xml){if(typeof context.getElementsByClassName!==strundefined&&!xml){return context.getElementsByClassName(className)}}},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(match){match[1]=match[1].replace(rbackslash,"");match[3]=(match[4]||match[5]||"").replace(rbackslash,"");if(match[2]==="~="){match[3]=" "+match[3]+" "}return match.slice(0,4)},CHILD:function(match){match[1]=match[1].toLowerCase();if(match[1]==="nth"){if(!match[2]){Sizzle.error(match[0])}match[3]=+(match[3]?match[4]+(match[5]||1):2*(match[2]==="even"||match[2]==="odd"));match[4]=+(match[6]+match[7]||match[2]==="odd")}else if(match[2]){Sizzle.error(match[0])}return match},PSEUDO:function(match){var unquoted,excess;if(matchExpr["CHILD"].test(match[0])){return null}if(match[3]){match[2]=match[3]}else if(unquoted=match[4]){if(rpseudo.test(unquoted)&&(excess=tokenize(unquoted,true))&&(excess=unquoted.indexOf(")",unquoted.length-excess)-unquoted.length)){unquoted=unquoted.slice(0,excess);match[0]=match[0].slice(0,excess)}match[2]=unquoted}return match.slice(0,3)}},filter:{ID:assertGetIdNotName?function(id){id=id.replace(rbackslash,"");return function(elem){return elem.getAttribute("id")===id}}:function(id){id=id.replace(rbackslash,"");return function(elem){var node=typeof elem.getAttributeNode!==strundefined&&elem.getAttributeNode("id");return node&&node.value===id}},TAG:function(nodeName){if(nodeName==="*"){return function(){return true}}nodeName=nodeName.replace(rbackslash,"").toLowerCase();return function(elem){return elem.nodeName&&elem.nodeName.toLowerCase()===nodeName}},CLASS:function(className){var pattern=classCache[expando][className+" "];return pattern||(pattern=new RegExp("(^|"+whitespace+")"+className+"("+whitespace+"|$)"))&&classCache(className,function(elem){return pattern.test(elem.className||typeof elem.getAttribute!==strundefined&&elem.getAttribute("class")||"")})},ATTR:function(name,operator,check){return function(elem,context){var result=Sizzle.attr(elem,name);if(result==null){return operator==="!="}if(!operator){return true}result+="";return operator==="="?result===check:operator==="!="?result!==check:operator==="^="?check&&result.indexOf(check)===0:operator==="*="?check&&result.indexOf(check)>-1:operator==="$="?check&&result.substr(result.length-check.length)===check:operator==="~="?(" "+result+" ").indexOf(check)>-1:operator==="|="?result===check||result.substr(0,check.length+1)===check+"-":false}},CHILD:function(type,argument,first,last){if(type==="nth"){return function(elem){var node,diff,parent=elem.parentNode;if(first===1&&last===0){return true}if(parent){diff=0;for(node=parent.firstChild;node;node=node.nextSibling){if(node.nodeType===1){diff++;
-if(elem===node){break}}}}diff-=last;return diff===first||diff%first===0&&diff/first>=0}}return function(elem){var node=elem;switch(type){case"only":case"first":while(node=node.previousSibling){if(node.nodeType===1){return false}}if(type==="first"){return true}node=elem;case"last":while(node=node.nextSibling){if(node.nodeType===1){return false}}return true}}},PSEUDO:function(pseudo,argument){var args,fn=Expr.pseudos[pseudo]||Expr.setFilters[pseudo.toLowerCase()]||Sizzle.error("unsupported pseudo: "+pseudo);if(fn[expando]){return fn(argument)}if(fn.length>1){args=[pseudo,pseudo,"",argument];return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase())?markFunction(function(seed,matches){var idx,matched=fn(seed,argument),i=matched.length;while(i--){idx=indexOf.call(seed,matched[i]);seed[idx]=!(matches[idx]=matched[i])}}):function(elem){return fn(elem,0,args)}}return fn}},pseudos:{not:markFunction(function(selector){var input=[],results=[],matcher=compile(selector.replace(rtrim,"$1"));return matcher[expando]?markFunction(function(seed,matches,context,xml){var elem,unmatched=matcher(seed,null,xml,[]),i=seed.length;while(i--){if(elem=unmatched[i]){seed[i]=!(matches[i]=elem)}}}):function(elem,context,xml){input[0]=elem;matcher(input,null,xml,results);return!results.pop()}}),has:markFunction(function(selector){return function(elem){return Sizzle(selector,elem).length>0}}),contains:markFunction(function(text){return function(elem){return(elem.textContent||elem.innerText||getText(elem)).indexOf(text)>-1}}),enabled:function(elem){return elem.disabled===false},disabled:function(elem){return elem.disabled===true},checked:function(elem){var nodeName=elem.nodeName.toLowerCase();return nodeName==="input"&&!!elem.checked||nodeName==="option"&&!!elem.selected},selected:function(elem){if(elem.parentNode){elem.parentNode.selectedIndex}return elem.selected===true},parent:function(elem){return!Expr.pseudos["empty"](elem)},empty:function(elem){var nodeType;elem=elem.firstChild;while(elem){if(elem.nodeName>"@"||(nodeType=elem.nodeType)===3||nodeType===4){return false}elem=elem.nextSibling}return true},header:function(elem){return rheader.test(elem.nodeName)},text:function(elem){var type,attr;return elem.nodeName.toLowerCase()==="input"&&(type=elem.type)==="text"&&((attr=elem.getAttribute("type"))==null||attr.toLowerCase()===type)},radio:createInputPseudo("radio"),checkbox:createInputPseudo("checkbox"),file:createInputPseudo("file"),password:createInputPseudo("password"),image:createInputPseudo("image"),submit:createButtonPseudo("submit"),reset:createButtonPseudo("reset"),button:function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type==="button"||name==="button"},input:function(elem){return rinputs.test(elem.nodeName)},focus:function(elem){var doc=elem.ownerDocument;return elem===doc.activeElement&&(!doc.hasFocus||doc.hasFocus())&&!!(elem.type||elem.href||~elem.tabIndex)},active:function(elem){return elem===elem.ownerDocument.activeElement},first:createPositionalPseudo(function(){return[0]}),last:createPositionalPseudo(function(matchIndexes,length){return[length-1]}),eq:createPositionalPseudo(function(matchIndexes,length,argument){return[argument<0?argument+length:argument]}),even:createPositionalPseudo(function(matchIndexes,length){for(var i=0;i<length;i+=2){matchIndexes.push(i)}return matchIndexes}),odd:createPositionalPseudo(function(matchIndexes,length){for(var i=1;i<length;i+=2){matchIndexes.push(i)}return matchIndexes}),lt:createPositionalPseudo(function(matchIndexes,length,argument){for(var i=argument<0?argument+length:argument;--i>=0;){matchIndexes.push(i)}return matchIndexes}),gt:createPositionalPseudo(function(matchIndexes,length,argument){for(var i=argument<0?argument+length:argument;++i<length;){matchIndexes.push(i)}return matchIndexes})}};function siblingCheck(a,b,ret){if(a===b){return ret}var cur=a.nextSibling;while(cur){if(cur===b){return-1}cur=cur.nextSibling}return 1}sortOrder=docElem.compareDocumentPosition?function(a,b){if(a===b){hasDuplicate=true;return 0}return(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b){hasDuplicate=true;return 0}else if(a.sourceIndex&&b.sourceIndex){return a.sourceIndex-b.sourceIndex}var al,bl,ap=[],bp=[],aup=a.parentNode,bup=b.parentNode,cur=aup;if(aup===bup){return siblingCheck(a,b)}else if(!aup){return-1}else if(!bup){return 1}while(cur){ap.unshift(cur);cur=cur.parentNode}cur=bup;while(cur){bp.unshift(cur);cur=cur.parentNode}al=ap.length;bl=bp.length;for(var i=0;i<al&&i<bl;i++){if(ap[i]!==bp[i]){return siblingCheck(ap[i],bp[i])}}return i===al?siblingCheck(a,bp[i],-1):siblingCheck(ap[i],b,1)};[0,0].sort(sortOrder);baseHasDuplicate=!hasDuplicate;Sizzle.uniqueSort=function(results){var elem,duplicates=[],i=1,j=0;hasDuplicate=baseHasDuplicate;results.sort(sortOrder);if(hasDuplicate){for(;elem=results[i];i++){if(elem===results[i-1]){j=duplicates.push(i)}}while(j--){results.splice(duplicates[j],1)}}return results};Sizzle.error=function(msg){throw new Error("Syntax error, unrecognized expression: "+msg)};function tokenize(selector,parseOnly){var matched,match,tokens,type,soFar,groups,preFilters,cached=tokenCache[expando][selector+" "];if(cached){return parseOnly?0:cached.slice(0)}soFar=selector;groups=[];preFilters=Expr.preFilter;while(soFar){if(!matched||(match=rcomma.exec(soFar))){if(match){soFar=soFar.slice(match[0].length)||soFar}groups.push(tokens=[])}matched=false;if(match=rcombinators.exec(soFar)){tokens.push(matched=new Token(match.shift()));soFar=soFar.slice(matched.length);matched.type=match[0].replace(rtrim," ")}for(type in Expr.filter){if((match=matchExpr[type].exec(soFar))&&(!preFilters[type]||(match=preFilters[type](match)))){tokens.push(matched=new Token(match.shift()));soFar=soFar.slice(matched.length);matched.type=type;matched.matches=match}}if(!matched){break}}return parseOnly?soFar.length:soFar?Sizzle.error(selector):tokenCache(selector,groups).slice(0)}function addCombinator(matcher,combinator,base){var dir=combinator.dir,checkNonElements=base&&combinator.dir==="parentNode",doneName=done++;return combinator.first?function(elem,context,xml){while(elem=elem[dir]){if(checkNonElements||elem.nodeType===1){return matcher(elem,context,xml)}}}:function(elem,context,xml){if(!xml){var cache,dirkey=dirruns+" "+doneName+" ",cachedkey=dirkey+cachedruns;while(elem=elem[dir]){if(checkNonElements||elem.nodeType===1){if((cache=elem[expando])===cachedkey){return elem.sizset}else if(typeof cache==="string"&&cache.indexOf(dirkey)===0){if(elem.sizset){return elem}}else{elem[expando]=cachedkey;if(matcher(elem,context,xml)){elem.sizset=true;return elem}elem.sizset=false}}}}else{while(elem=elem[dir]){if(checkNonElements||elem.nodeType===1){if(matcher(elem,context,xml)){return elem}}}}}}function elementMatcher(matchers){return matchers.length>1?function(elem,context,xml){var i=matchers.length;while(i--){if(!matchers[i](elem,context,xml)){return false}}return true}:matchers[0]}function condense(unmatched,map,filter,context,xml){var elem,newUnmatched=[],i=0,len=unmatched.length,mapped=map!=null;for(;i<len;i++){if(elem=unmatched[i]){if(!filter||filter(elem,context,xml)){newUnmatched.push(elem);if(mapped){map.push(i)}}}}return newUnmatched}function setMatcher(preFilter,selector,matcher,postFilter,postFinder,postSelector){if(postFilter&&!postFilter[expando]){postFilter=setMatcher(postFilter)}if(postFinder&&!postFinder[expando]){postFinder=setMatcher(postFinder,postSelector)}return markFunction(function(seed,results,context,xml){var temp,i,elem,preMap=[],postMap=[],preexisting=results.length,elems=seed||multipleContexts(selector||"*",context.nodeType?[context]:context,[]),matcherIn=preFilter&&(seed||!selector)?condense(elems,preMap,preFilter,context,xml):elems,matcherOut=matcher?postFinder||(seed?preFilter:preexisting||postFilter)?[]:results:matcherIn;if(matcher){matcher(matcherIn,matcherOut,context,xml)}if(postFilter){temp=condense(matcherOut,postMap);postFilter(temp,[],context,xml);i=temp.length;while(i--){if(elem=temp[i]){matcherOut[postMap[i]]=!(matcherIn[postMap[i]]=elem)}}}if(seed){if(postFinder||preFilter){if(postFinder){temp=[];i=matcherOut.length;while(i--){if(elem=matcherOut[i]){temp.push(matcherIn[i]=elem)}}postFinder(null,matcherOut=[],temp,xml)}i=matcherOut.length;while(i--){if((elem=matcherOut[i])&&(temp=postFinder?indexOf.call(seed,elem):preMap[i])>-1){seed[temp]=!(results[temp]=elem)}}}}else{matcherOut=condense(matcherOut===results?matcherOut.splice(preexisting,matcherOut.length):matcherOut);if(postFinder){postFinder(null,results,matcherOut,xml)}else{push.apply(results,matcherOut)}}})}function matcherFromTokens(tokens){var checkContext,matcher,j,len=tokens.length,leadingRelative=Expr.relative[tokens[0].type],implicitRelative=leadingRelative||Expr.relative[" "],i=leadingRelative?1:0,matchContext=addCombinator(function(elem){return elem===checkContext},implicitRelative,true),matchAnyContext=addCombinator(function(elem){return indexOf.call(checkContext,elem)>-1},implicitRelative,true),matchers=[function(elem,context,xml){return!leadingRelative&&(xml||context!==outermostContext)||((checkContext=context).nodeType?matchContext(elem,context,xml):matchAnyContext(elem,context,xml))}];for(;i<len;i++){if(matcher=Expr.relative[tokens[i].type]){matchers=[addCombinator(elementMatcher(matchers),matcher)]}else{matcher=Expr.filter[tokens[i].type].apply(null,tokens[i].matches);if(matcher[expando]){j=++i;for(;j<len;j++){if(Expr.relative[tokens[j].type]){break}}return setMatcher(i>1&&elementMatcher(matchers),i>1&&tokens.slice(0,i-1).join("").replace(rtrim,"$1"),matcher,i<j&&matcherFromTokens(tokens.slice(i,j)),j<len&&matcherFromTokens(tokens=tokens.slice(j)),j<len&&tokens.join(""))}matchers.push(matcher)}}return elementMatcher(matchers)}function matcherFromGroupMatchers(elementMatchers,setMatchers){var bySet=setMatchers.length>0,byElement=elementMatchers.length>0,superMatcher=function(seed,context,xml,results,expandContext){var elem,j,matcher,setMatched=[],matchedCount=0,i="0",unmatched=seed&&[],outermost=expandContext!=null,contextBackup=outermostContext,elems=seed||byElement&&Expr.find["TAG"]("*",expandContext&&context.parentNode||context),dirrunsUnique=dirruns+=contextBackup==null?1:Math.E;if(outermost){outermostContext=context!==document&&context;cachedruns=superMatcher.el}for(;(elem=elems[i])!=null;i++){if(byElement&&elem){for(j=0;matcher=elementMatchers[j];j++){if(matcher(elem,context,xml)){results.push(elem);break}}if(outermost){dirruns=dirrunsUnique;cachedruns=++superMatcher.el}}if(bySet){if(elem=!matcher&&elem){matchedCount--}if(seed){unmatched.push(elem)}}}matchedCount+=i;if(bySet&&i!==matchedCount){for(j=0;matcher=setMatchers[j];j++){matcher(unmatched,setMatched,context,xml)}if(seed){if(matchedCount>0){while(i--){if(!(unmatched[i]||setMatched[i])){setMatched[i]=pop.call(results)}}}setMatched=condense(setMatched)}push.apply(results,setMatched);if(outermost&&!seed&&setMatched.length>0&&matchedCount+setMatchers.length>1){Sizzle.uniqueSort(results)}}if(outermost){dirruns=dirrunsUnique;outermostContext=contextBackup}return unmatched};superMatcher.el=0;return bySet?markFunction(superMatcher):superMatcher}compile=Sizzle.compile=function(selector,group){var i,setMatchers=[],elementMatchers=[],cached=compilerCache[expando][selector+" "];if(!cached){if(!group){group=tokenize(selector)}i=group.length;while(i--){cached=matcherFromTokens(group[i]);if(cached[expando]){setMatchers.push(cached)}else{elementMatchers.push(cached)}}cached=compilerCache(selector,matcherFromGroupMatchers(elementMatchers,setMatchers))}return cached};function multipleContexts(selector,contexts,results){var i=0,len=contexts.length;for(;i<len;i++){Sizzle(selector,contexts[i],results)}return results}function select(selector,context,results,seed,xml){var i,tokens,token,type,find,match=tokenize(selector),j=match.length;if(!seed){if(match.length===1){tokens=match[0]=match[0].slice(0);if(tokens.length>2&&(token=tokens[0]).type==="ID"&&context.nodeType===9&&!xml&&Expr.relative[tokens[1].type]){context=Expr.find["ID"](token.matches[0].replace(rbackslash,""),context,xml)[0];if(!context){return results}selector=selector.slice(tokens.shift().length)}for(i=matchExpr["POS"].test(selector)?-1:tokens.length-1;i>=0;i--){token=tokens[i];if(Expr.relative[type=token.type]){break}if(find=Expr.find[type]){if(seed=find(token.matches[0].replace(rbackslash,""),rsibling.test(tokens[0].type)&&context.parentNode||context,xml)){tokens.splice(i,1);selector=seed.length&&tokens.join("");if(!selector){push.apply(results,slice.call(seed,0));return results}break}}}}}compile(selector,match)(seed,context,xml,results,rsibling.test(selector));return results}if(document.querySelectorAll){(function(){var disconnectedMatch,oldSelect=select,rescape=/'|\\/g,rattributeQuotes=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,rbuggyQSA=[":focus"],rbuggyMatches=[":active"],matches=docElem.matchesSelector||docElem.mozMatchesSelector||docElem.webkitMatchesSelector||docElem.oMatchesSelector||docElem.msMatchesSelector;assert(function(div){div.innerHTML="<select><option selected=''></option></select>";if(!div.querySelectorAll("[selected]").length){rbuggyQSA.push("\\["+whitespace+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)")}if(!div.querySelectorAll(":checked").length){rbuggyQSA.push(":checked")}});assert(function(div){div.innerHTML="<p test=''></p>";if(div.querySelectorAll("[test^='']").length){rbuggyQSA.push("[*^$]="+whitespace+"*(?:\"\"|'')")}div.innerHTML="<input type='hidden'/>";if(!div.querySelectorAll(":enabled").length){rbuggyQSA.push(":enabled",":disabled")}});rbuggyQSA=new RegExp(rbuggyQSA.join("|"));select=function(selector,context,results,seed,xml){if(!seed&&!xml&&!rbuggyQSA.test(selector)){var groups,i,old=true,nid=expando,newContext=context,newSelector=context.nodeType===9&&selector;if(context.nodeType===1&&context.nodeName.toLowerCase()!=="object"){groups=tokenize(selector);if(old=context.getAttribute("id")){nid=old.replace(rescape,"\\$&")}else{context.setAttribute("id",nid)}nid="[id='"+nid+"'] ";i=groups.length;while(i--){groups[i]=nid+groups[i].join("")}newContext=rsibling.test(selector)&&context.parentNode||context;newSelector=groups.join(",")}if(newSelector){try{push.apply(results,slice.call(newContext.querySelectorAll(newSelector),0));return results}catch(qsaError){}finally{if(!old){context.removeAttribute("id")}}}}return oldSelect(selector,context,results,seed,xml)};if(matches){assert(function(div){disconnectedMatch=matches.call(div,"div");try{matches.call(div,"[test!='']:sizzle");rbuggyMatches.push("!=",pseudos)}catch(e){}});rbuggyMatches=new RegExp(rbuggyMatches.join("|"));Sizzle.matchesSelector=function(elem,expr){expr=expr.replace(rattributeQuotes,"='$1']");if(!isXML(elem)&&!rbuggyMatches.test(expr)&&!rbuggyQSA.test(expr)){try{var ret=matches.call(elem,expr);if(ret||disconnectedMatch||elem.document&&elem.document.nodeType!==11){return ret}}catch(e){}}return Sizzle(expr,null,null,[elem]).length>0}}})()}Expr.pseudos["nth"]=Expr.pseudos["eq"];function setFilters(){}Expr.filters=setFilters.prototype=Expr.pseudos;Expr.setFilters=new setFilters;Sizzle.attr=jQuery.attr;jQuery.find=Sizzle;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.pseudos;jQuery.unique=Sizzle.uniqueSort;jQuery.text=Sizzle.getText;jQuery.isXMLDoc=Sizzle.isXML;jQuery.contains=Sizzle.contains})(window);var runtil=/Until$/,rparentsprev=/^(?:parents|prev(?:Until|All))/,isSimple=/^.[^:#\[\.,]*$/,rneedsContext=jQuery.expr.match.needsContext,guaranteedUnique={children:true,contents:true,next:true,prev:true};jQuery.fn.extend({find:function(selector){var i,l,length,n,r,ret,self=this;if(typeof selector!=="string"){return jQuery(selector).filter(function(){for(i=0,l=self.length;i<l;i++){if(jQuery.contains(self[i],this)){return true}}})}ret=this.pushStack("","find",selector);for(i=0,l=this.length;i<l;i++){length=ret.length;jQuery.find(selector,this[i],ret);if(i>0){for(n=length;n<ret.length;n++){for(r=0;r<length;r++){if(ret[r]===ret[n]){ret.splice(n--,1);break}}}}}return ret},has:function(target){var i,targets=jQuery(target,this),len=targets.length;return this.filter(function(){for(i=0;i<len;i++){if(jQuery.contains(this,targets[i])){return true}}})},not:function(selector){return this.pushStack(winnow(this,selector,false),"not",selector)},filter:function(selector){return this.pushStack(winnow(this,selector,true),"filter",selector)},is:function(selector){return!!selector&&(typeof selector==="string"?rneedsContext.test(selector)?jQuery(selector,this.context).index(this[0])>=0:jQuery.filter(selector,this).length>0:this.filter(selector).length>0)},closest:function(selectors,context){var cur,i=0,l=this.length,ret=[],pos=rneedsContext.test(selectors)||typeof selectors!=="string"?jQuery(selectors,context||this.context):0;for(;i<l;i++){cur=this[i];while(cur&&cur.ownerDocument&&cur!==context&&cur.nodeType!==11){if(pos?pos.index(cur)>-1:jQuery.find.matchesSelector(cur,selectors)){ret.push(cur);break}cur=cur.parentNode}}ret=ret.length>1?jQuery.unique(ret):ret;return this.pushStack(ret,"closest",selectors)},index:function(elem){if(!elem){return this[0]&&this[0].parentNode?this.prevAll().length:-1}if(typeof elem==="string"){return jQuery.inArray(this[0],jQuery(elem))}return jQuery.inArray(elem.jquery?elem[0]:elem,this)},add:function(selector,context){var set=typeof selector==="string"?jQuery(selector,context):jQuery.makeArray(selector&&selector.nodeType?[selector]:selector),all=jQuery.merge(this.get(),set);return this.pushStack(isDisconnected(set[0])||isDisconnected(all[0])?all:jQuery.unique(all))},addBack:function(selector){return this.add(selector==null?this.prevObject:this.prevObject.filter(selector))}});jQuery.fn.andSelf=jQuery.fn.addBack;function isDisconnected(node){return!node||!node.parentNode||node.parentNode.nodeType===11}function sibling(cur,dir){do{cur=cur[dir]}while(cur&&cur.nodeType!==1);return cur}jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null},parents:function(elem){return jQuery.dir(elem,"parentNode")},parentsUntil:function(elem,i,until){return jQuery.dir(elem,"parentNode",until)},next:function(elem){return sibling(elem,"nextSibling")},prev:function(elem){return sibling(elem,"previousSibling")},nextAll:function(elem){return jQuery.dir(elem,"nextSibling")},prevAll:function(elem){return jQuery.dir(elem,"previousSibling")},nextUntil:function(elem,i,until){return jQuery.dir(elem,"nextSibling",until)},prevUntil:function(elem,i,until){return jQuery.dir(elem,"previousSibling",until)},siblings:function(elem){return jQuery.sibling((elem.parentNode||{}).firstChild,elem)},children:function(elem){return jQuery.sibling(elem.firstChild)},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.merge([],elem.childNodes)}},function(name,fn){jQuery.fn[name]=function(until,selector){var ret=jQuery.map(this,fn,until);if(!runtil.test(name)){selector=until}if(selector&&typeof selector==="string"){ret=jQuery.filter(selector,ret)}ret=this.length>1&&!guaranteedUnique[name]?jQuery.unique(ret):ret;if(this.length>1&&rparentsprev.test(name)){ret=ret.reverse()}return this.pushStack(ret,name,core_slice.call(arguments).join(","))}});jQuery.extend({filter:function(expr,elems,not){if(not){expr=":not("+expr+")"}return elems.length===1?jQuery.find.matchesSelector(elems[0],expr)?[elems[0]]:[]:jQuery.find.matches(expr,elems)},dir:function(elem,dir,until){var matched=[],cur=elem[dir];while(cur&&cur.nodeType!==9&&(until===undefined||cur.nodeType!==1||!jQuery(cur).is(until))){if(cur.nodeType===1){matched.push(cur)}cur=cur[dir]}return matched},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){r.push(n)}}return r}});function winnow(elements,qualifier,keep){qualifier=qualifier||0;if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){var retVal=!!qualifier.call(elem,i,elem);return retVal===keep})}else if(qualifier.nodeType){return jQuery.grep(elements,function(elem,i){return elem===qualifier===keep})}else if(typeof qualifier==="string"){var filtered=jQuery.grep(elements,function(elem){return elem.nodeType===1});if(isSimple.test(qualifier)){return jQuery.filter(qualifier,filtered,!keep)}else{qualifier=jQuery.filter(qualifier,filtered)}}return jQuery.grep(elements,function(elem,i){return jQuery.inArray(elem,qualifier)>=0===keep})}function createSafeFragment(document){var list=nodeNames.split("|"),safeFrag=document.createDocumentFragment();if(safeFrag.createElement){while(list.length){safeFrag.createElement(list.pop())}}return safeFrag}var nodeNames="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|"+"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",rinlinejQuery=/ jQuery\d+="(?:null|\d+)"/g,rleadingWhitespace=/^\s+/,rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,rtagName=/<([\w:]+)/,rtbody=/<tbody/i,rhtml=/<|&#?\w+;/,rnoInnerhtml=/<(?:script|style|link)/i,rnocache=/<(?:script|object|embed|option|style)/i,rnoshimcache=new RegExp("<(?:"+nodeNames+")[\\s/>]","i"),rcheckableType=/^(?:checkbox|radio)$/,rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/\/(java|ecma)script/i,rcleanScript=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,wrapMap={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},safeFragment=createSafeFragment(document),fragmentDiv=safeFragment.appendChild(document.createElement("div"));wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;if(!jQuery.support.htmlSerialize){wrapMap._default=[1,"X<div>","</div>"]}jQuery.fn.extend({text:function(value){return jQuery.access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value))},null,value,arguments.length)},wrapAll:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapAll(html.call(this,i))})}if(this[0]){var wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0])}wrap.map(function(){var elem=this;while(elem.firstChild&&elem.firstChild.nodeType===1){elem=elem.firstChild}return elem}).append(this)}return this},wrapInner:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i))})}return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html)}else{self.append(html)}})},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html)})},unwrap:function(){return this.parent().each(function(){if(!jQuery.nodeName(this,"body")){jQuery(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType===1||this.nodeType===11){this.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType===1||this.nodeType===11){this.insertBefore(elem,this.firstChild)}})},before:function(){if(!isDisconnected(this[0])){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this)})}if(arguments.length){var set=jQuery.clean(arguments);return this.pushStack(jQuery.merge(set,this),"before",this.selector)}},after:function(){if(!isDisconnected(this[0])){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this.nextSibling)})}if(arguments.length){var set=jQuery.clean(arguments);return this.pushStack(jQuery.merge(this,set),"after",this.selector)}},remove:function(selector,keepData){var elem,i=0;for(;(elem=this[i])!=null;i++){if(!selector||jQuery.filter(selector,[elem]).length){if(!keepData&&elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"));jQuery.cleanData([elem])}if(elem.parentNode){elem.parentNode.removeChild(elem)}}}return this},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"))}while(elem.firstChild){elem.removeChild(elem.firstChild)}}return this},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents)})},html:function(value){return jQuery.access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined){return elem.nodeType===1?elem.innerHTML.replace(rinlinejQuery,""):undefined}if(typeof value==="string"&&!rnoInnerhtml.test(value)&&(jQuery.support.htmlSerialize||!rnoshimcache.test(value))&&(jQuery.support.leadingWhitespace||!rleadingWhitespace.test(value))&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1></$2>");try{for(;i<l;i++){elem=this[i]||{};if(elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"));elem.innerHTML=value}}elem=0}catch(e){}}if(elem){this.empty().append(value)}},null,value,arguments.length)},replaceWith:function(value){if(!isDisconnected(this[0])){if(jQuery.isFunction(value)){return this.each(function(i){var self=jQuery(this),old=self.html();self.replaceWith(value.call(this,i,old))})}if(typeof value!=="string"){value=jQuery(value).detach()}return this.each(function(){var next=this.nextSibling,parent=this.parentNode;jQuery(this).remove();if(next){jQuery(next).before(value)}else{jQuery(parent).append(value)}})}return this.length?this.pushStack(jQuery(jQuery.isFunction(value)?value():value),"replaceWith",value):this},detach:function(selector){return this.remove(selector,true)},domManip:function(args,table,callback){args=[].concat.apply([],args);var results,first,fragment,iNoClone,i=0,value=args[0],scripts=[],l=this.length;if(!jQuery.support.checkClone&&l>1&&typeof value==="string"&&rchecked.test(value)){return this.each(function(){jQuery(this).domManip(args,table,callback)})}if(jQuery.isFunction(value)){return this.each(function(i){var self=jQuery(this);args[0]=value.call(this,i,table?self.html():undefined);self.domManip(args,table,callback)})}if(this[0]){results=jQuery.buildFragment(args,this,scripts);fragment=results.fragment;first=fragment.firstChild;if(fragment.childNodes.length===1){fragment=first}if(first){table=table&&jQuery.nodeName(first,"tr");for(iNoClone=results.cacheable||l-1;i<l;i++){callback.call(table&&jQuery.nodeName(this[i],"table")?findOrAppend(this[i],"tbody"):this[i],i===iNoClone?fragment:jQuery.clone(fragment,true,true))}}fragment=first=null;if(scripts.length){jQuery.each(scripts,function(i,elem){if(elem.src){if(jQuery.ajax){jQuery.ajax({url:elem.src,type:"GET",dataType:"script",async:false,global:false,"throws":true})}else{jQuery.error("no ajax")}}else{jQuery.globalEval((elem.text||elem.textContent||elem.innerHTML||"").replace(rcleanScript,""))}if(elem.parentNode){elem.parentNode.removeChild(elem)}})}}return this}});function findOrAppend(elem,tag){return elem.getElementsByTagName(tag)[0]||elem.appendChild(elem.ownerDocument.createElement(tag))}function cloneCopyEvent(src,dest){if(dest.nodeType!==1||!jQuery.hasData(src)){return}var type,i,l,oldData=jQuery._data(src),curData=jQuery._data(dest,oldData),events=oldData.events;if(events){delete curData.handle;curData.events={};for(type in events){for(i=0,l=events[type].length;i<l;i++){jQuery.event.add(dest,type,events[type][i])}}}if(curData.data){curData.data=jQuery.extend({},curData.data)}}function cloneFixAttributes(src,dest){var nodeName;if(dest.nodeType!==1){return}if(dest.clearAttributes){dest.clearAttributes()}if(dest.mergeAttributes){dest.mergeAttributes(src)}nodeName=dest.nodeName.toLowerCase();if(nodeName==="object"){if(dest.parentNode){dest.outerHTML=src.outerHTML}if(jQuery.support.html5Clone&&(src.innerHTML&&!jQuery.trim(dest.innerHTML))){dest.innerHTML=src.innerHTML}}else if(nodeName==="input"&&rcheckableType.test(src.type)){dest.defaultChecked=dest.checked=src.checked;if(dest.value!==src.value){dest.value=src.value}}else if(nodeName==="option"){dest.selected=src.defaultSelected}else if(nodeName==="input"||nodeName==="textarea"){dest.defaultValue=src.defaultValue}else if(nodeName==="script"&&dest.text!==src.text){dest.text=src.text}dest.removeAttribute(jQuery.expando)}jQuery.buildFragment=function(args,context,scripts){var fragment,cacheable,cachehit,first=args[0];context=context||document;context=!context.nodeType&&context[0]||context;context=context.ownerDocument||context;if(args.length===1&&typeof first==="string"&&first.length<512&&context===document&&first.charAt(0)==="<"&&!rnocache.test(first)&&(jQuery.support.checkClone||!rchecked.test(first))&&(jQuery.support.html5Clone||!rnoshimcache.test(first))){cacheable=true;fragment=jQuery.fragments[first];cachehit=fragment!==undefined}if(!fragment){fragment=context.createDocumentFragment();jQuery.clean(args,context,fragment,scripts);if(cacheable){jQuery.fragments[first]=cachehit&&fragment}}return{fragment:fragment,cacheable:cacheable}};jQuery.fragments={};jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(selector){var elems,i=0,ret=[],insert=jQuery(selector),l=insert.length,parent=this.length===1&&this[0].parentNode;if((parent==null||parent&&parent.nodeType===11&&parent.childNodes.length===1)&&l===1){insert[original](this[0]);return this}else{for(;i<l;i++){elems=(i>0?this.clone(true):this).get();jQuery(insert[i])[original](elems);ret=ret.concat(elems)}return this.pushStack(ret,name,insert.selector)}}});function getAll(elem){if(typeof elem.getElementsByTagName!=="undefined"){return elem.getElementsByTagName("*")}else if(typeof elem.querySelectorAll!=="undefined"){return elem.querySelectorAll("*")}else{return[]}}function fixDefaultChecked(elem){if(rcheckableType.test(elem.type)){elem.defaultChecked=elem.checked}}jQuery.extend({clone:function(elem,dataAndEvents,deepDataAndEvents){var srcElements,destElements,i,clone;if(jQuery.support.html5Clone||jQuery.isXMLDoc(elem)||!rnoshimcache.test("<"+elem.nodeName+">")){clone=elem.cloneNode(true)}else{fragmentDiv.innerHTML=elem.outerHTML;fragmentDiv.removeChild(clone=fragmentDiv.firstChild)}if((!jQuery.support.noCloneEvent||!jQuery.support.noCloneChecked)&&(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){cloneFixAttributes(elem,clone);srcElements=getAll(elem);destElements=getAll(clone);for(i=0;srcElements[i];++i){if(destElements[i]){cloneFixAttributes(srcElements[i],destElements[i])}}}if(dataAndEvents){cloneCopyEvent(elem,clone);if(deepDataAndEvents){srcElements=getAll(elem);destElements=getAll(clone);for(i=0;srcElements[i];++i){cloneCopyEvent(srcElements[i],destElements[i])}}}srcElements=destElements=null;return clone},clean:function(elems,context,fragment,scripts){var i,j,elem,tag,wrap,depth,div,hasBody,tbody,len,handleScript,jsTags,safe=context===document&&safeFragment,ret=[];if(!context||typeof context.createDocumentFragment==="undefined"){context=document}for(i=0;(elem=elems[i])!=null;i++){if(typeof elem==="number"){elem+=""}if(!elem){continue}if(typeof elem==="string"){if(!rhtml.test(elem)){elem=context.createTextNode(elem)}else{safe=safe||createSafeFragment(context);div=context.createElement("div");safe.appendChild(div);elem=elem.replace(rxhtmlTag,"<$1></$2>");tag=(rtagName.exec(elem)||["",""])[1].toLowerCase();wrap=wrapMap[tag]||wrapMap._default;depth=wrap[0];div.innerHTML=wrap[1]+elem+wrap[2];while(depth--){div=div.lastChild
-}if(!jQuery.support.tbody){hasBody=rtbody.test(elem);tbody=tag==="table"&&!hasBody?div.firstChild&&div.firstChild.childNodes:wrap[1]==="<table>"&&!hasBody?div.childNodes:[];for(j=tbody.length-1;j>=0;--j){if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length){tbody[j].parentNode.removeChild(tbody[j])}}}if(!jQuery.support.leadingWhitespace&&rleadingWhitespace.test(elem)){div.insertBefore(context.createTextNode(rleadingWhitespace.exec(elem)[0]),div.firstChild)}elem=div.childNodes;div.parentNode.removeChild(div)}}if(elem.nodeType){ret.push(elem)}else{jQuery.merge(ret,elem)}}if(div){elem=div=safe=null}if(!jQuery.support.appendChecked){for(i=0;(elem=ret[i])!=null;i++){if(jQuery.nodeName(elem,"input")){fixDefaultChecked(elem)}else if(typeof elem.getElementsByTagName!=="undefined"){jQuery.grep(elem.getElementsByTagName("input"),fixDefaultChecked)}}}if(fragment){handleScript=function(elem){if(!elem.type||rscriptType.test(elem.type)){return scripts?scripts.push(elem.parentNode?elem.parentNode.removeChild(elem):elem):fragment.appendChild(elem)}};for(i=0;(elem=ret[i])!=null;i++){if(!(jQuery.nodeName(elem,"script")&&handleScript(elem))){fragment.appendChild(elem);if(typeof elem.getElementsByTagName!=="undefined"){jsTags=jQuery.grep(jQuery.merge([],elem.getElementsByTagName("script")),handleScript);ret.splice.apply(ret,[i+1,0].concat(jsTags));i+=jsTags.length}}}}return ret},cleanData:function(elems,acceptData){var data,id,elem,type,i=0,internalKey=jQuery.expando,cache=jQuery.cache,deleteExpando=jQuery.support.deleteExpando,special=jQuery.event.special;for(;(elem=elems[i])!=null;i++){if(acceptData||jQuery.acceptData(elem)){id=elem[internalKey];data=id&&cache[id];if(data){if(data.events){for(type in data.events){if(special[type]){jQuery.event.remove(elem,type)}else{jQuery.removeEvent(elem,type,data.handle)}}}if(cache[id]){delete cache[id];if(deleteExpando){delete elem[internalKey]}else if(elem.removeAttribute){elem.removeAttribute(internalKey)}else{elem[internalKey]=null}jQuery.deletedIds.push(id)}}}}}});(function(){var matched,browser;jQuery.uaMatch=function(ua){ua=ua.toLowerCase();var match=/(chrome)[ \/]([\w.]+)/.exec(ua)||/(webkit)[ \/]([\w.]+)/.exec(ua)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua)||/(msie) ([\w.]+)/.exec(ua)||ua.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)||[];return{browser:match[1]||"",version:match[2]||"0"}};matched=jQuery.uaMatch(navigator.userAgent);browser={};if(matched.browser){browser[matched.browser]=true;browser.version=matched.version}if(browser.chrome){browser.webkit=true}else if(browser.webkit){browser.safari=true}jQuery.browser=browser;jQuery.sub=function(){function jQuerySub(selector,context){return new jQuerySub.fn.init(selector,context)}jQuery.extend(true,jQuerySub,this);jQuerySub.superclass=this;jQuerySub.fn=jQuerySub.prototype=this();jQuerySub.fn.constructor=jQuerySub;jQuerySub.sub=this.sub;jQuerySub.fn.init=function init(selector,context){if(context&&context instanceof jQuery&&!(context instanceof jQuerySub)){context=jQuerySub(context)}return jQuery.fn.init.call(this,selector,context,rootjQuerySub)};jQuerySub.fn.init.prototype=jQuerySub.fn;var rootjQuerySub=jQuerySub(document);return jQuerySub}})();var curCSS,iframe,iframeDoc,ralpha=/alpha\([^)]*\)/i,ropacity=/opacity=([^)]*)/,rposition=/^(top|right|bottom|left)$/,rdisplayswap=/^(none|table(?!-c[ea]).+)/,rmargin=/^margin/,rnumsplit=new RegExp("^("+core_pnum+")(.*)$","i"),rnumnonpx=new RegExp("^("+core_pnum+")(?!px)[a-z%]+$","i"),rrelNum=new RegExp("^([-+])=("+core_pnum+")","i"),elemdisplay={BODY:"block"},cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:0,fontWeight:400},cssExpand=["Top","Right","Bottom","Left"],cssPrefixes=["Webkit","O","Moz","ms"],eventsToggle=jQuery.fn.toggle;function vendorPropName(style,name){if(name in style){return name}var capName=name.charAt(0).toUpperCase()+name.slice(1),origName=name,i=cssPrefixes.length;while(i--){name=cssPrefixes[i]+capName;if(name in style){return name}}return origName}function isHidden(elem,el){elem=el||elem;return jQuery.css(elem,"display")==="none"||!jQuery.contains(elem.ownerDocument,elem)}function showHide(elements,show){var elem,display,values=[],index=0,length=elements.length;for(;index<length;index++){elem=elements[index];if(!elem.style){continue}values[index]=jQuery._data(elem,"olddisplay");if(show){if(!values[index]&&elem.style.display==="none"){elem.style.display=""}if(elem.style.display===""&&isHidden(elem)){values[index]=jQuery._data(elem,"olddisplay",css_defaultDisplay(elem.nodeName))}}else{display=curCSS(elem,"display");if(!values[index]&&display!=="none"){jQuery._data(elem,"olddisplay",display)}}}for(index=0;index<length;index++){elem=elements[index];if(!elem.style){continue}if(!show||elem.style.display==="none"||elem.style.display===""){elem.style.display=show?values[index]||"":"none"}}return elements}jQuery.fn.extend({css:function(name,value){return jQuery.access(this,function(elem,name,value){return value!==undefined?jQuery.style(elem,name,value):jQuery.css(elem,name)},name,value,arguments.length>1)},show:function(){return showHide(this,true)},hide:function(){return showHide(this)},toggle:function(state,fn2){var bool=typeof state==="boolean";if(jQuery.isFunction(state)&&jQuery.isFunction(fn2)){return eventsToggle.apply(this,arguments)}return this.each(function(){if(bool?state:isHidden(this)){jQuery(this).show()}else{jQuery(this).hide()}})}});jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return ret===""?"1":ret}}}},cssNumber:{fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":jQuery.support.cssFloat?"cssFloat":"styleFloat"},style:function(elem,name,value,extra){if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){return}var ret,type,hooks,origName=jQuery.camelCase(name),style=elem.style;name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(value!==undefined){type=typeof value;if(type==="string"&&(ret=rrelNum.exec(value))){value=(ret[1]+1)*ret[2]+parseFloat(jQuery.css(elem,name));type="number"}if(value==null||type==="number"&&isNaN(value)){return}if(type==="number"&&!jQuery.cssNumber[origName]){value+="px"}if(!hooks||!("set"in hooks)||(value=hooks.set(elem,value,extra))!==undefined){try{style[name]=value}catch(e){}}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){return ret}return style[name]}},css:function(elem,name,numeric,extra){var val,num,hooks,origName=jQuery.camelCase(name);name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(elem.style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(hooks&&"get"in hooks){val=hooks.get(elem,true,extra)}if(val===undefined){val=curCSS(elem,name)}if(val==="normal"&&name in cssNormalTransform){val=cssNormalTransform[name]}if(numeric||extra!==undefined){num=parseFloat(val);return numeric||jQuery.isNumeric(num)?num||0:val}return val},swap:function(elem,options,callback){var ret,name,old={};for(name in options){old[name]=elem.style[name];elem.style[name]=options[name]}ret=callback.call(elem);for(name in options){elem.style[name]=old[name]}return ret}});if(window.getComputedStyle){curCSS=function(elem,name){var ret,width,minWidth,maxWidth,computed=window.getComputedStyle(elem,null),style=elem.style;if(computed){ret=computed.getPropertyValue(name)||computed[name];if(ret===""&&!jQuery.contains(elem.ownerDocument,elem)){ret=jQuery.style(elem,name)}if(rnumnonpx.test(ret)&&rmargin.test(name)){width=style.width;minWidth=style.minWidth;maxWidth=style.maxWidth;style.minWidth=style.maxWidth=style.width=ret;ret=computed.width;style.width=width;style.minWidth=minWidth;style.maxWidth=maxWidth}}return ret}}else if(document.documentElement.currentStyle){curCSS=function(elem,name){var left,rsLeft,ret=elem.currentStyle&&elem.currentStyle[name],style=elem.style;if(ret==null&&style&&style[name]){ret=style[name]}if(rnumnonpx.test(ret)&&!rposition.test(name)){left=style.left;rsLeft=elem.runtimeStyle&&elem.runtimeStyle.left;if(rsLeft){elem.runtimeStyle.left=elem.currentStyle.left}style.left=name==="fontSize"?"1em":ret;ret=style.pixelLeft+"px";style.left=left;if(rsLeft){elem.runtimeStyle.left=rsLeft}}return ret===""?"auto":ret}}function setPositiveNumber(elem,value,subtract){var matches=rnumsplit.exec(value);return matches?Math.max(0,matches[1]-(subtract||0))+(matches[2]||"px"):value}function augmentWidthOrHeight(elem,name,extra,isBorderBox){var i=extra===(isBorderBox?"border":"content")?4:name==="width"?1:0,val=0;for(;i<4;i+=2){if(extra==="margin"){val+=jQuery.css(elem,extra+cssExpand[i],true)}if(isBorderBox){if(extra==="content"){val-=parseFloat(curCSS(elem,"padding"+cssExpand[i]))||0}if(extra!=="margin"){val-=parseFloat(curCSS(elem,"border"+cssExpand[i]+"Width"))||0}}else{val+=parseFloat(curCSS(elem,"padding"+cssExpand[i]))||0;if(extra!=="padding"){val+=parseFloat(curCSS(elem,"border"+cssExpand[i]+"Width"))||0}}}return val}function getWidthOrHeight(elem,name,extra){var val=name==="width"?elem.offsetWidth:elem.offsetHeight,valueIsBorderBox=true,isBorderBox=jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing")==="border-box";if(val<=0||val==null){val=curCSS(elem,name);if(val<0||val==null){val=elem.style[name]}if(rnumnonpx.test(val)){return val}valueIsBorderBox=isBorderBox&&(jQuery.support.boxSizingReliable||val===elem.style[name]);val=parseFloat(val)||0}return val+augmentWidthOrHeight(elem,name,extra||(isBorderBox?"border":"content"),valueIsBorderBox)+"px"}function css_defaultDisplay(nodeName){if(elemdisplay[nodeName]){return elemdisplay[nodeName]}var elem=jQuery("<"+nodeName+">").appendTo(document.body),display=elem.css("display");elem.remove();if(display==="none"||display===""){iframe=document.body.appendChild(iframe||jQuery.extend(document.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!iframeDoc||!iframe.createElement){iframeDoc=(iframe.contentWindow||iframe.contentDocument).document;iframeDoc.write("<!doctype html><html><body>");iframeDoc.close()}elem=iframeDoc.body.appendChild(iframeDoc.createElement(nodeName));display=curCSS(elem,"display");document.body.removeChild(iframe)}elemdisplay[nodeName]=display;return display}jQuery.each(["height","width"],function(i,name){jQuery.cssHooks[name]={get:function(elem,computed,extra){if(computed){if(elem.offsetWidth===0&&rdisplayswap.test(curCSS(elem,"display"))){return jQuery.swap(elem,cssShow,function(){return getWidthOrHeight(elem,name,extra)})}else{return getWidthOrHeight(elem,name,extra)}}},set:function(elem,value,extra){return setPositiveNumber(elem,value,extra?augmentWidthOrHeight(elem,name,extra,jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing")==="border-box"):0)}}});if(!jQuery.support.opacity){jQuery.cssHooks.opacity={get:function(elem,computed){return ropacity.test((computed&&elem.currentStyle?elem.currentStyle.filter:elem.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":computed?"1":""},set:function(elem,value){var style=elem.style,currentStyle=elem.currentStyle,opacity=jQuery.isNumeric(value)?"alpha(opacity="+value*100+")":"",filter=currentStyle&&currentStyle.filter||style.filter||"";style.zoom=1;if(value>=1&&jQuery.trim(filter.replace(ralpha,""))===""&&style.removeAttribute){style.removeAttribute("filter");if(currentStyle&&!currentStyle.filter){return}}style.filter=ralpha.test(filter)?filter.replace(ralpha,opacity):filter+" "+opacity}}}jQuery(function(){if(!jQuery.support.reliableMarginRight){jQuery.cssHooks.marginRight={get:function(elem,computed){return jQuery.swap(elem,{display:"inline-block"},function(){if(computed){return curCSS(elem,"marginRight")}})}}}if(!jQuery.support.pixelPosition&&jQuery.fn.position){jQuery.each(["top","left"],function(i,prop){jQuery.cssHooks[prop]={get:function(elem,computed){if(computed){var ret=curCSS(elem,prop);return rnumnonpx.test(ret)?jQuery(elem).position()[prop]+"px":ret}}}})}});if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.hidden=function(elem){return elem.offsetWidth===0&&elem.offsetHeight===0||!jQuery.support.reliableHiddenOffsets&&(elem.style&&elem.style.display||curCSS(elem,"display"))==="none"};jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem)}}jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i,parts=typeof value==="string"?value.split(" "):[value],expanded={};for(i=0;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0]}return expanded}};if(!rmargin.test(prefix)){jQuery.cssHooks[prefix+suffix].set=setPositiveNumber}});var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rinput=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,rselectTextarea=/^(?:select|textarea)/i;jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?jQuery.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||rselectTextarea.test(this.nodeName)||rinput.test(this.type))}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:jQuery.isArray(val)?jQuery.map(val,function(val,i){return{name:elem.name,value:val.replace(rCRLF,"\r\n")}}):{name:elem.name,value:val.replace(rCRLF,"\r\n")}}).get()}});jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():value==null?"":value;s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value)};if(traditional===undefined){traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional}if(jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a)){jQuery.each(a,function(){add(this.name,this.value)})}else{for(prefix in a){buildParams(prefix,a[prefix],traditional,add)}}return s.join("&").replace(r20,"+")};function buildParams(prefix,obj,traditional,add){var name;if(jQuery.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v)}else{buildParams(prefix+"["+(typeof v==="object"?i:"")+"]",v,traditional,add)}})}else if(!traditional&&jQuery.type(obj)==="object"){for(name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add)}}else{add(prefix,obj)}}var ajaxLocParts,ajaxLocation,rhash=/#.*$/,rheaders=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,rlocalProtocol=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rquery=/\?/,rscript=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,rts=/([?&])_=[^&]*/,rurl=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,_load=jQuery.fn.load,prefilters={},transports={},allTypes=["*/"]+["*"];try{ajaxLocation=location.href}catch(e){ajaxLocation=document.createElement("a");ajaxLocation.href="";ajaxLocation=ajaxLocation.href}ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*"}var dataType,list,placeBefore,dataTypes=dataTypeExpression.toLowerCase().split(core_rspace),i=0,length=dataTypes.length;if(jQuery.isFunction(func)){for(;i<length;i++){dataType=dataTypes[i];placeBefore=/^\+/.test(dataType);if(placeBefore){dataType=dataType.substr(1)||"*"}list=structure[dataType]=structure[dataType]||[];list[placeBefore?"unshift":"push"](func)}}}}function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,dataType,inspected){dataType=dataType||options.dataTypes[0];inspected=inspected||{};inspected[dataType]=true;var selection,list=structure[dataType],i=0,length=list?list.length:0,executeOnly=structure===prefilters;for(;i<length&&(executeOnly||!selection);i++){selection=list[i](options,originalOptions,jqXHR);if(typeof selection==="string"){if(!executeOnly||inspected[selection]){selection=undefined}else{options.dataTypes.unshift(selection);selection=inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,selection,inspected)}}}if((executeOnly||!selection)&&!inspected["*"]){selection=inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,"*",inspected)}return selection}function ajaxExtend(target,src){var key,deep,flatOptions=jQuery.ajaxSettings.flatOptions||{};for(key in src){if(src[key]!==undefined){(flatOptions[key]?target:deep||(deep={}))[key]=src[key]}}if(deep){jQuery.extend(true,target,deep)}}jQuery.fn.load=function(url,params,callback){if(typeof url!=="string"&&_load){return _load.apply(this,arguments)}if(!this.length){return this}var selector,type,response,self=this,off=url.indexOf(" ");if(off>=0){selector=url.slice(off,url.length);url=url.slice(0,off)}if(jQuery.isFunction(params)){callback=params;params=undefined}else if(params&&typeof params==="object"){type="POST"}jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(jqXHR,status){if(callback){self.each(callback,response||[jqXHR.responseText,status,jqXHR])}}}).done(function(responseText){response=arguments;self.html(selector?jQuery("<div>").append(responseText.replace(rscript,"")).find(selector):responseText)});return this};jQuery.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(i,o){jQuery.fn[o]=function(f){return this.on(o,f)}});jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){if(jQuery.isFunction(data)){type=type||callback;callback=data;data=undefined}return jQuery.ajax({type:method,url:url,data:data,success:callback,dataType:type})}});jQuery.extend({getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script")},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},ajaxSetup:function(target,settings){if(settings){ajaxExtend(target,jQuery.ajaxSettings)}else{settings=target;target=jQuery.ajaxSettings}ajaxExtend(target,settings);return target},ajaxSettings:{url:ajaxLocation,isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":allTypes},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":window.String,"text html":true,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined}options=options||{};var ifModifiedKey,responseHeadersString,responseHeaders,transport,timeoutTimer,parts,fireGlobals,i,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=callbackContext!==s&&(callbackContext.nodeType||callbackContext instanceof jQuery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,setRequestHeader:function(name,value){if(!state){var lname=name.toLowerCase();name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;requestHeaders[name]=value}return this},getAllResponseHeaders:function(){return state===2?responseHeadersString:null},getResponseHeader:function(key){var match;if(state===2){if(!responseHeaders){responseHeaders={};while(match=rheaders.exec(responseHeadersString)){responseHeaders[match[1].toLowerCase()]=match[2]}}match=responseHeaders[key.toLowerCase()]}return match===undefined?null:match},overrideMimeType:function(type){if(!state){s.mimeType=type}return this},abort:function(statusText){statusText=statusText||strAbort;if(transport){transport.abort(statusText)}done(0,statusText);return this}};function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;if(state===2){return}state=2;if(timeoutTimer){clearTimeout(timeoutTimer)}transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;if(responses){response=ajaxHandleResponses(s,jqXHR,responses)}if(status>=200&&status<300||status===304){if(s.ifModified){modified=jqXHR.getResponseHeader("Last-Modified");if(modified){jQuery.lastModified[ifModifiedKey]=modified}modified=jqXHR.getResponseHeader("Etag");if(modified){jQuery.etag[ifModifiedKey]=modified}}if(status===304){statusText="notmodified";isSuccess=true}else{isSuccess=ajaxConvert(s,response);statusText=isSuccess.state;success=isSuccess.data;error=isSuccess.error;isSuccess=!error}}else{error=statusText;if(!statusText||status){statusText="error";if(status<0){status=0}}}jqXHR.status=status;jqXHR.statusText=(nativeStatusText||statusText)+"";if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR])}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error])}jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger("ajax"+(isSuccess?"Success":"Error"),[jqXHR,s,isSuccess?success:error])}completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!--jQuery.active){jQuery.event.trigger("ajaxStop")}}}deferred.promise(jqXHR);jqXHR.success=jqXHR.done;jqXHR.error=jqXHR.fail;jqXHR.complete=completeDeferred.add;jqXHR.statusCode=function(map){if(map){var tmp;if(state<2){for(tmp in map){statusCode[tmp]=[statusCode[tmp],map[tmp]]}}else{tmp=map[jqXHR.status];jqXHR.always(tmp)}}return this};s.url=((url||s.url)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().split(core_rspace);if(s.crossDomain==null){parts=rurl.exec(s.url.toLowerCase());s.crossDomain=!!(parts&&(parts[1]!==ajaxLocParts[1]||parts[2]!==ajaxLocParts[2]||(parts[3]||(parts[1]==="http:"?80:443))!=(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?80:443))))}if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional)}inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(state===2){return jqXHR}fireGlobals=s.global;s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart")}if(!s.hasContent){if(s.data){s.url+=(rquery.test(s.url)?"&":"?")+s.data;delete s.data}ifModifiedKey=s.url;if(s.cache===false){var ts=jQuery.now(),ret=s.url.replace(rts,"$1_="+ts);s.url=ret+(ret===s.url?(rquery.test(s.url)?"&":"?")+"_="+ts:"")}}if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType)}if(s.ifModified){ifModifiedKey=ifModifiedKey||s.url;if(jQuery.lastModified[ifModifiedKey]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[ifModifiedKey])}if(jQuery.etag[ifModifiedKey]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[ifModifiedKey])}}jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i])}if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){return jqXHR.abort()}strAbort="abort";for(i in{success:1,error:1,complete:1}){jqXHR[i](s[i])}transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport")}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s])}if(s.async&&s.timeout>0){timeoutTimer=setTimeout(function(){jqXHR.abort("timeout")},s.timeout)}try{state=1;transport.send(requestHeaders,done)}catch(e){if(state<2){done(-1,e)}else{throw e}}}return jqXHR},active:0,lastModified:{},etag:{}});function ajaxHandleResponses(s,jqXHR,responses){var ct,type,finalDataType,firstDataType,contents=s.contents,dataTypes=s.dataTypes,responseFields=s.responseFields;for(type in responseFields){if(type in responses){jqXHR[responseFields[type]]=responses[type]}}while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("content-type")}}if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break}}}if(dataTypes[0]in responses){finalDataType=dataTypes[0]}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break}if(!firstDataType){firstDataType=type}}finalDataType=finalDataType||firstDataType}if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType)}return responses[finalDataType]}}function ajaxConvert(s,response){var conv,conv2,current,tmp,dataTypes=s.dataTypes.slice(),prev=dataTypes[0],converters={},i=0;if(s.dataFilter){response=s.dataFilter(response,s.dataType)}if(dataTypes[1]){for(conv in s.converters){converters[conv.toLowerCase()]=s.converters[conv]}}for(;current=dataTypes[++i];){if(current!=="*"){if(prev!=="*"&&prev!==current){conv=converters[prev+" "+current]||converters["* "+current];if(!conv){for(conv2 in converters){tmp=conv2.split(" ");if(tmp[1]===current){conv=converters[prev+" "+tmp[0]]||converters["* "+tmp[0]];if(conv){if(conv===true){conv=converters[conv2]}else if(converters[conv2]!==true){current=tmp[0];dataTypes.splice(i--,0,current)}break}}}}if(conv!==true){if(conv&&s["throws"]){response=conv(response)}else{try{response=conv(response)}catch(e){return{state:"parsererror",error:conv?e:"No conversion from "+prev+" to "+current}}}}}prev=current}}return{state:"success",data:response}}var oldCallbacks=[],rquestion=/\?/,rjsonp=/(=)\?(?=&|$)|\?\?/,nonce=jQuery.now();jQuery.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var callback=oldCallbacks.pop()||jQuery.expando+"_"+nonce++;this[callback]=true;return callback}});jQuery.ajaxPrefilter("json jsonp",function(s,originalSettings,jqXHR){var callbackName,overwritten,responseContainer,data=s.data,url=s.url,hasCallback=s.jsonp!==false,replaceInUrl=hasCallback&&rjsonp.test(url),replaceInData=hasCallback&&!replaceInUrl&&typeof data==="string"&&!(s.contentType||"").indexOf("application/x-www-form-urlencoded")&&rjsonp.test(data);if(s.dataTypes[0]==="jsonp"||replaceInUrl||replaceInData){callbackName=s.jsonpCallback=jQuery.isFunction(s.jsonpCallback)?s.jsonpCallback():s.jsonpCallback;overwritten=window[callbackName];if(replaceInUrl){s.url=url.replace(rjsonp,"$1"+callbackName)}else if(replaceInData){s.data=data.replace(rjsonp,"$1"+callbackName)}else if(hasCallback){s.url+=(rquestion.test(url)?"&":"?")+s.jsonp+"="+callbackName}s.converters["script json"]=function(){if(!responseContainer){jQuery.error(callbackName+" was not called")}return responseContainer[0]};s.dataTypes[0]="json";window[callbackName]=function(){responseContainer=arguments};jqXHR.always(function(){window[callbackName]=overwritten;if(s[callbackName]){s.jsonpCallback=originalSettings.jsonpCallback;oldCallbacks.push(callbackName)}if(responseContainer&&jQuery.isFunction(overwritten)){overwritten(responseContainer[0])}responseContainer=overwritten=undefined});return"script"}});jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(text){jQuery.globalEval(text);return text}}});jQuery.ajaxPrefilter("script",function(s){if(s.cache===undefined){s.cache=false}if(s.crossDomain){s.type="GET";s.global=false}});jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,head=document.head||document.getElementsByTagName("head")[0]||document.documentElement;return{send:function(_,callback){script=document.createElement("script");script.async="async";if(s.scriptCharset){script.charset=s.scriptCharset}script.src=s.url;script.onload=script.onreadystatechange=function(_,isAbort){if(isAbort||!script.readyState||/loaded|complete/.test(script.readyState)){script.onload=script.onreadystatechange=null;if(head&&script.parentNode){head.removeChild(script)}script=undefined;if(!isAbort){callback(200,"success")}}};head.insertBefore(script,head.firstChild)},abort:function(){if(script){script.onload(0,1)}}}}});var xhrCallbacks,xhrOnUnloadAbort=window.ActiveXObject?function(){for(var key in xhrCallbacks){xhrCallbacks[key](0,1)}}:false,xhrId=0;function createStandardXHR(){try{return new window.XMLHttpRequest}catch(e){}}function createActiveXHR(){try{return new window.ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}jQuery.ajaxSettings.xhr=window.ActiveXObject?function(){return!this.isLocal&&createStandardXHR()||createActiveXHR()}:createStandardXHR;(function(xhr){jQuery.extend(jQuery.support,{ajax:!!xhr,cors:!!xhr&&"withCredentials"in xhr})})(jQuery.ajaxSettings.xhr());if(jQuery.support.ajax){jQuery.ajaxTransport(function(s){if(!s.crossDomain||jQuery.support.cors){var callback;return{send:function(headers,complete){var handle,i,xhr=s.xhr();if(s.username){xhr.open(s.type,s.url,s.async,s.username,s.password)}else{xhr.open(s.type,s.url,s.async)}if(s.xhrFields){for(i in s.xhrFields){xhr[i]=s.xhrFields[i]}}if(s.mimeType&&xhr.overrideMimeType){xhr.overrideMimeType(s.mimeType)}if(!s.crossDomain&&!headers["X-Requested-With"]){headers["X-Requested-With"]="XMLHttpRequest"}try{for(i in headers){xhr.setRequestHeader(i,headers[i])}}catch(_){}xhr.send(s.hasContent&&s.data||null);callback=function(_,isAbort){var status,statusText,responseHeaders,responses,xml;try{if(callback&&(isAbort||xhr.readyState===4)){callback=undefined;if(handle){xhr.onreadystatechange=jQuery.noop;if(xhrOnUnloadAbort){delete xhrCallbacks[handle]}}if(isAbort){if(xhr.readyState!==4){xhr.abort()}}else{status=xhr.status;responseHeaders=xhr.getAllResponseHeaders();responses={};xml=xhr.responseXML;if(xml&&xml.documentElement){responses.xml=xml}try{responses.text=xhr.responseText}catch(e){}try{statusText=xhr.statusText}catch(e){statusText=""}if(!status&&s.isLocal&&!s.crossDomain){status=responses.text?200:404}else if(status===1223){status=204}}}}catch(firefoxAccessException){if(!isAbort){complete(-1,firefoxAccessException)}}if(responses){complete(status,statusText,responses,responseHeaders)}};if(!s.async){callback()}else if(xhr.readyState===4){setTimeout(callback,0)}else{handle=++xhrId;if(xhrOnUnloadAbort){if(!xhrCallbacks){xhrCallbacks={};jQuery(window).unload(xhrOnUnloadAbort)}xhrCallbacks[handle]=callback}xhr.onreadystatechange=callback}},abort:function(){if(callback){callback(0,1)}}}}})}var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rfxnum=new RegExp("^(?:([-+])=|)("+core_pnum+")([a-z%]*)$","i"),rrun=/queueHooks$/,animationPrefilters=[defaultPrefilter],tweeners={"*":[function(prop,value){var end,unit,tween=this.createTween(prop,value),parts=rfxnum.exec(value),target=tween.cur(),start=+target||0,scale=1,maxIterations=20;if(parts){end=+parts[2];unit=parts[3]||(jQuery.cssNumber[prop]?"":"px");if(unit!=="px"&&start){start=jQuery.css(tween.elem,prop,true)||end||1;do{scale=scale||".5";start=start/scale;jQuery.style(tween.elem,prop,start+unit)}while(scale!==(scale=tween.cur()/target)&&scale!==1&&--maxIterations)}tween.unit=unit;tween.start=start;tween.end=parts[1]?start+(parts[1]+1)*end:end}return tween}]};function createFxNow(){setTimeout(function(){fxNow=undefined},0);return fxNow=jQuery.now()}function createTweens(animation,props){jQuery.each(props,function(prop,value){var collection=(tweeners[prop]||[]).concat(tweeners["*"]),index=0,length=collection.length;for(;index<length;index++){if(collection[index].call(animation,prop,value)){return}}})}function Animation(elem,properties,options){var result,index=0,tweenerIndex=0,length=animationPrefilters.length,deferred=jQuery.Deferred().always(function(){delete tick.elem}),tick=function(){var currentTime=fxNow||createFxNow(),remaining=Math.max(0,animation.startTime+animation.duration-currentTime),temp=remaining/animation.duration||0,percent=1-temp,index=0,length=animation.tweens.length;
-for(;index<length;index++){animation.tweens[index].run(percent)}deferred.notifyWith(elem,[animation,percent,remaining]);if(percent<1&&length){return remaining}else{deferred.resolveWith(elem,[animation]);return false}},animation=deferred.promise({elem:elem,props:jQuery.extend({},properties),opts:jQuery.extend(true,{specialEasing:{}},options),originalProperties:properties,originalOptions:options,startTime:fxNow||createFxNow(),duration:options.duration,tweens:[],createTween:function(prop,end,easing){var tween=jQuery.Tween(elem,animation.opts,prop,end,animation.opts.specialEasing[prop]||animation.opts.easing);animation.tweens.push(tween);return tween},stop:function(gotoEnd){var index=0,length=gotoEnd?animation.tweens.length:0;for(;index<length;index++){animation.tweens[index].run(1)}if(gotoEnd){deferred.resolveWith(elem,[animation,gotoEnd])}else{deferred.rejectWith(elem,[animation,gotoEnd])}return this}}),props=animation.props;propFilter(props,animation.opts.specialEasing);for(;index<length;index++){result=animationPrefilters[index].call(animation,elem,props,animation.opts);if(result){return result}}createTweens(animation,props);if(jQuery.isFunction(animation.opts.start)){animation.opts.start.call(elem,animation)}jQuery.fx.timer(jQuery.extend(tick,{anim:animation,queue:animation.opts.queue,elem:elem}));return animation.progress(animation.opts.progress).done(animation.opts.done,animation.opts.complete).fail(animation.opts.fail).always(animation.opts.always)}function propFilter(props,specialEasing){var index,name,easing,value,hooks;for(index in props){name=jQuery.camelCase(index);easing=specialEasing[name];value=props[index];if(jQuery.isArray(value)){easing=value[1];value=props[index]=value[0]}if(index!==name){props[name]=value;delete props[index]}hooks=jQuery.cssHooks[name];if(hooks&&"expand"in hooks){value=hooks.expand(value);delete props[name];for(index in value){if(!(index in props)){props[index]=value[index];specialEasing[index]=easing}}}else{specialEasing[name]=easing}}}jQuery.Animation=jQuery.extend(Animation,{tweener:function(props,callback){if(jQuery.isFunction(props)){callback=props;props=["*"]}else{props=props.split(" ")}var prop,index=0,length=props.length;for(;index<length;index++){prop=props[index];tweeners[prop]=tweeners[prop]||[];tweeners[prop].unshift(callback)}},prefilter:function(callback,prepend){if(prepend){animationPrefilters.unshift(callback)}else{animationPrefilters.push(callback)}}});function defaultPrefilter(elem,props,opts){var index,prop,value,length,dataShow,toggle,tween,hooks,oldfire,anim=this,style=elem.style,orig={},handled=[],hidden=elem.nodeType&&isHidden(elem);if(!opts.queue){hooks=jQuery._queueHooks(elem,"fx");if(hooks.unqueued==null){hooks.unqueued=0;oldfire=hooks.empty.fire;hooks.empty.fire=function(){if(!hooks.unqueued){oldfire()}}}hooks.unqueued++;anim.always(function(){anim.always(function(){hooks.unqueued--;if(!jQuery.queue(elem,"fx").length){hooks.empty.fire()}})})}if(elem.nodeType===1&&("height"in props||"width"in props)){opts.overflow=[style.overflow,style.overflowX,style.overflowY];if(jQuery.css(elem,"display")==="inline"&&jQuery.css(elem,"float")==="none"){if(!jQuery.support.inlineBlockNeedsLayout||css_defaultDisplay(elem.nodeName)==="inline"){style.display="inline-block"}else{style.zoom=1}}}if(opts.overflow){style.overflow="hidden";if(!jQuery.support.shrinkWrapBlocks){anim.done(function(){style.overflow=opts.overflow[0];style.overflowX=opts.overflow[1];style.overflowY=opts.overflow[2]})}}for(index in props){value=props[index];if(rfxtypes.exec(value)){delete props[index];toggle=toggle||value==="toggle";if(value===(hidden?"hide":"show")){continue}handled.push(index)}}length=handled.length;if(length){dataShow=jQuery._data(elem,"fxshow")||jQuery._data(elem,"fxshow",{});if("hidden"in dataShow){hidden=dataShow.hidden}if(toggle){dataShow.hidden=!hidden}if(hidden){jQuery(elem).show()}else{anim.done(function(){jQuery(elem).hide()})}anim.done(function(){var prop;jQuery.removeData(elem,"fxshow",true);for(prop in orig){jQuery.style(elem,prop,orig[prop])}});for(index=0;index<length;index++){prop=handled[index];tween=anim.createTween(prop,hidden?dataShow[prop]:0);orig[prop]=dataShow[prop]||jQuery.style(elem,prop);if(!(prop in dataShow)){dataShow[prop]=tween.start;if(hidden){tween.end=tween.start;tween.start=prop==="width"||prop==="height"?1:0}}}}}function Tween(elem,options,prop,end,easing){return new Tween.prototype.init(elem,options,prop,end,easing)}jQuery.Tween=Tween;Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem;this.prop=prop;this.easing=easing||"swing";this.options=options;this.start=this.now=this.cur();this.end=end;this.unit=unit||(jQuery.cssNumber[prop]?"":"px")},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this)},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];if(this.options.duration){this.pos=eased=jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration)}else{this.pos=eased=percent}this.now=(this.end-this.start)*eased+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this)}if(hooks&&hooks.set){hooks.set(this)}else{Tween.propHooks._default.set(this)}return this}};Tween.prototype.init.prototype=Tween.prototype;Tween.propHooks={_default:{get:function(tween){var result;if(tween.elem[tween.prop]!=null&&(!tween.elem.style||tween.elem.style[tween.prop]==null)){return tween.elem[tween.prop]}result=jQuery.css(tween.elem,tween.prop,false,"");return!result||result==="auto"?0:result},set:function(tween){if(jQuery.fx.step[tween.prop]){jQuery.fx.step[tween.prop](tween)}else if(tween.elem.style&&(tween.elem.style[jQuery.cssProps[tween.prop]]!=null||jQuery.cssHooks[tween.prop])){jQuery.style(tween.elem,tween.prop,tween.now+tween.unit)}else{tween.elem[tween.prop]=tween.now}}}};Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){if(tween.elem.nodeType&&tween.elem.parentNode){tween.elem[tween.prop]=tween.now}}};jQuery.each(["toggle","show","hide"],function(i,name){var cssFn=jQuery.fn[name];jQuery.fn[name]=function(speed,easing,callback){return speed==null||typeof speed==="boolean"||!i&&jQuery.isFunction(speed)&&jQuery.isFunction(easing)?cssFn.apply(this,arguments):this.animate(genFx(name,true),speed,easing,callback)}});jQuery.fn.extend({fadeTo:function(speed,to,easing,callback){return this.filter(isHidden).css("opacity",0).show().end().animate({opacity:to},speed,easing,callback)},animate:function(prop,speed,easing,callback){var empty=jQuery.isEmptyObject(prop),optall=jQuery.speed(speed,easing,callback),doAnimation=function(){var anim=Animation(this,jQuery.extend({},prop),optall);if(empty){anim.stop(true)}};return empty||optall.queue===false?this.each(doAnimation):this.queue(optall.queue,doAnimation)},stop:function(type,clearQueue,gotoEnd){var stopQueue=function(hooks){var stop=hooks.stop;delete hooks.stop;stop(gotoEnd)};if(typeof type!=="string"){gotoEnd=clearQueue;clearQueue=type;type=undefined}if(clearQueue&&type!==false){this.queue(type||"fx",[])}return this.each(function(){var dequeue=true,index=type!=null&&type+"queueHooks",timers=jQuery.timers,data=jQuery._data(this);if(index){if(data[index]&&data[index].stop){stopQueue(data[index])}}else{for(index in data){if(data[index]&&data[index].stop&&rrun.test(index)){stopQueue(data[index])}}}for(index=timers.length;index--;){if(timers[index].elem===this&&(type==null||timers[index].queue===type)){timers[index].anim.stop(gotoEnd);dequeue=false;timers.splice(index,1)}}if(dequeue||!gotoEnd){jQuery.dequeue(this,type)}})}});function genFx(type,includeWidth){var which,attrs={height:type},i=0;includeWidth=includeWidth?1:0;for(;i<4;i+=2-includeWidth){which=cssExpand[i];attrs["margin"+which]=attrs["padding"+which]=type}if(includeWidth){attrs.opacity=attrs.width=type}return attrs}jQuery.each({slideDown:genFx("show"),slideUp:genFx("hide"),slideToggle:genFx("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(name,props){jQuery.fn[name]=function(speed,easing,callback){return this.animate(props,speed,easing,callback)}});jQuery.speed=function(speed,easing,fn){var opt=speed&&typeof speed==="object"?jQuery.extend({},speed):{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&!jQuery.isFunction(easing)&&easing};opt.duration=jQuery.fx.off?0:typeof opt.duration==="number"?opt.duration:opt.duration in jQuery.fx.speeds?jQuery.fx.speeds[opt.duration]:jQuery.fx.speeds._default;if(opt.queue==null||opt.queue===true){opt.queue="fx"}opt.old=opt.complete;opt.complete=function(){if(jQuery.isFunction(opt.old)){opt.old.call(this)}if(opt.queue){jQuery.dequeue(this,opt.queue)}};return opt};jQuery.easing={linear:function(p){return p},swing:function(p){return.5-Math.cos(p*Math.PI)/2}};jQuery.timers=[];jQuery.fx=Tween.prototype.init;jQuery.fx.tick=function(){var timer,timers=jQuery.timers,i=0;fxNow=jQuery.now();for(;i<timers.length;i++){timer=timers[i];if(!timer()&&timers[i]===timer){timers.splice(i--,1)}}if(!timers.length){jQuery.fx.stop()}fxNow=undefined};jQuery.fx.timer=function(timer){if(timer()&&jQuery.timers.push(timer)&&!timerId){timerId=setInterval(jQuery.fx.tick,jQuery.fx.interval)}};jQuery.fx.interval=13;jQuery.fx.stop=function(){clearInterval(timerId);timerId=null};jQuery.fx.speeds={slow:600,fast:200,_default:400};jQuery.fx.step={};if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.animated=function(elem){return jQuery.grep(jQuery.timers,function(fn){return elem===fn.elem}).length}}var rroot=/^(?:body|html)$/i;jQuery.fn.offset=function(options){if(arguments.length){return options===undefined?this:this.each(function(i){jQuery.offset.setOffset(this,options,i)})}var docElem,body,win,clientTop,clientLeft,scrollTop,scrollLeft,box={top:0,left:0},elem=this[0],doc=elem&&elem.ownerDocument;if(!doc){return}if((body=doc.body)===elem){return jQuery.offset.bodyOffset(elem)}docElem=doc.documentElement;if(!jQuery.contains(docElem,elem)){return box}if(typeof elem.getBoundingClientRect!=="undefined"){box=elem.getBoundingClientRect()}win=getWindow(doc);clientTop=docElem.clientTop||body.clientTop||0;clientLeft=docElem.clientLeft||body.clientLeft||0;scrollTop=win.pageYOffset||docElem.scrollTop;scrollLeft=win.pageXOffset||docElem.scrollLeft;return{top:box.top+scrollTop-clientTop,left:box.left+scrollLeft-clientLeft}};jQuery.offset={bodyOffset:function(body){var top=body.offsetTop,left=body.offsetLeft;if(jQuery.support.doesNotIncludeMarginInBodyOffset){top+=parseFloat(jQuery.css(body,"marginTop"))||0;left+=parseFloat(jQuery.css(body,"marginLeft"))||0}return{top:top,left:left}},setOffset:function(elem,options,i){var position=jQuery.css(elem,"position");if(position==="static"){elem.style.position="relative"}var curElem=jQuery(elem),curOffset=curElem.offset(),curCSSTop=jQuery.css(elem,"top"),curCSSLeft=jQuery.css(elem,"left"),calculatePosition=(position==="absolute"||position==="fixed")&&jQuery.inArray("auto",[curCSSTop,curCSSLeft])>-1,props={},curPosition={},curTop,curLeft;if(calculatePosition){curPosition=curElem.position();curTop=curPosition.top;curLeft=curPosition.left}else{curTop=parseFloat(curCSSTop)||0;curLeft=parseFloat(curCSSLeft)||0}if(jQuery.isFunction(options)){options=options.call(elem,i,curOffset)}if(options.top!=null){props.top=options.top-curOffset.top+curTop}if(options.left!=null){props.left=options.left-curOffset.left+curLeft}if("using"in options){options.using.call(elem,props)}else{curElem.css(props)}}};jQuery.fn.extend({position:function(){if(!this[0]){return}var elem=this[0],offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=rroot.test(offsetParent[0].nodeName)?{top:0,left:0}:offsetParent.offset();offset.top-=parseFloat(jQuery.css(elem,"marginTop"))||0;offset.left-=parseFloat(jQuery.css(elem,"marginLeft"))||0;parentOffset.top+=parseFloat(jQuery.css(offsetParent[0],"borderTopWidth"))||0;parentOffset.left+=parseFloat(jQuery.css(offsetParent[0],"borderLeftWidth"))||0;return{top:offset.top-parentOffset.top,left:offset.left-parentOffset.left}},offsetParent:function(){return this.map(function(){var offsetParent=this.offsetParent||document.body;while(offsetParent&&(!rroot.test(offsetParent.nodeName)&&jQuery.css(offsetParent,"position")==="static")){offsetParent=offsetParent.offsetParent}return offsetParent||document.body})}});jQuery.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(method,prop){var top=/Y/.test(prop);jQuery.fn[method]=function(val){return jQuery.access(this,function(elem,method,val){var win=getWindow(elem);if(val===undefined){return win?prop in win?win[prop]:win.document.documentElement[method]:elem[method]}if(win){win.scrollTo(!top?val:jQuery(win).scrollLeft(),top?val:jQuery(win).scrollTop())}else{elem[method]=val}},method,val,arguments.length,null)}});function getWindow(elem){return jQuery.isWindow(elem)?elem:elem.nodeType===9?elem.defaultView||elem.parentWindow:false}jQuery.each({Height:"height",Width:"width"},function(name,type){jQuery.each({padding:"inner"+name,content:type,"":"outer"+name},function(defaultExtra,funcName){jQuery.fn[funcName]=function(margin,value){var chainable=arguments.length&&(defaultExtra||typeof margin!=="boolean"),extra=defaultExtra||(margin===true||value===true?"margin":"border");return jQuery.access(this,function(elem,type,value){var doc;if(jQuery.isWindow(elem)){return elem.document.documentElement["client"+name]}if(elem.nodeType===9){doc=elem.documentElement;return Math.max(elem.body["scroll"+name],doc["scroll"+name],elem.body["offset"+name],doc["offset"+name],doc["client"+name])}return value===undefined?jQuery.css(elem,type,value,extra):jQuery.style(elem,type,value,extra)},type,chainable?margin:undefined,chainable,null)}})});window.jQuery=window.$=jQuery;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return jQuery})}})(window); \ No newline at end of file
+(function(window,undefined){var rootjQuery,readyList,document=window.document,location=window.location,navigator=window.navigator,_jQuery=window.jQuery,_$=window.$,core_push=Array.prototype.push,core_slice=Array.prototype.slice,core_indexOf=Array.prototype.indexOf,core_toString=Object.prototype.toString,core_hasOwn=Object.prototype.hasOwnProperty,core_trim=String.prototype.trim,jQuery=function(selector,context){return new jQuery.fn.init(selector,context,rootjQuery)},core_pnum=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,core_rnotwhite=/\S/,core_rspace=/\s+/,rtrim=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,rquickExpr=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,rvalidchars=/^[\],:{}\s]*$/,rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g,rvalidescape=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,rvalidtokens=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,rmsPrefix=/^-ms-/,rdashAlpha=/-([\da-z])/gi,fcamelCase=function(all,letter){return(letter+"").toUpperCase()},DOMContentLoaded=function(){if(document.addEventListener){document.removeEventListener("DOMContentLoaded",DOMContentLoaded,false);jQuery.ready()}else if(document.readyState==="complete"){document.detachEvent("onreadystatechange",DOMContentLoaded);jQuery.ready()}},class2type={};jQuery.fn=jQuery.prototype={constructor:jQuery,init:function(selector,context,rootjQuery){var match,elem,ret,doc;if(!selector){return this}if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this}if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null]}else{match=rquickExpr.exec(selector)}if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;doc=context&&context.nodeType?context.ownerDocument||context:document;selector=jQuery.parseHTML(match[1],doc,true);if(rsingleTag.test(match[1])&&jQuery.isPlainObject(context)){this.attr.call(selector,context,true)}return jQuery.merge(this,selector)}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){if(elem.id!==match[2]){return rootjQuery.find(selector)}this.length=1;this[0]=elem}this.context=document;this.selector=selector;return this}}else if(!context||context.jquery){return(context||rootjQuery).find(selector)}else{return this.constructor(context).find(selector)}}else if(jQuery.isFunction(selector)){return rootjQuery.ready(selector)}if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context}return jQuery.makeArray(selector,this)},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return core_slice.call(this)},get:function(num){return num==null?this.toArray():num<0?this[this.length+num]:this[num]},pushStack:function(elems,name,selector){var ret=jQuery.merge(this.constructor(),elems);ret.prevObject=this;ret.context=this.context;if(name==="find"){ret.selector=this.selector+(this.selector?" ":"")+selector}else if(name){ret.selector=this.selector+"."+name+"("+selector+")"}return ret},each:function(callback,args){return jQuery.each(this,callback,args)},ready:function(fn){jQuery.ready.promise().done(fn);return this},eq:function(i){i=+i;return i===-1?this.slice(i):this.slice(i,i+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(core_slice.apply(this,arguments),"slice",core_slice.call(arguments).join(","))},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem)}))},end:function(){return this.prevObject||this.constructor(null)},push:core_push,sort:[].sort,splice:[].splice};jQuery.fn.init.prototype=jQuery.fn;jQuery.extend=jQuery.fn.extend=function(){var options,name,src,copy,copyIsArray,clone,target=arguments[0]||{},i=1,length=arguments.length,deep=false;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2}if(typeof target!=="object"&&!jQuery.isFunction(target)){target={}}if(length===i){target=this;--i}for(;i<length;i++){if((options=arguments[i])!=null){for(name in options){src=target[name];copy=options[name];if(target===copy){continue}if(deep&&copy&&(jQuery.isPlainObject(copy)||(copyIsArray=jQuery.isArray(copy)))){if(copyIsArray){copyIsArray=false;clone=src&&jQuery.isArray(src)?src:[]}else{clone=src&&jQuery.isPlainObject(src)?src:{}}target[name]=jQuery.extend(deep,clone,copy)}else if(copy!==undefined){target[name]=copy}}}}return target};jQuery.extend({noConflict:function(deep){if(window.$===jQuery){window.$=_$}if(deep&&window.jQuery===jQuery){window.jQuery=_jQuery}return jQuery},isReady:false,readyWait:1,holdReady:function(hold){if(hold){jQuery.readyWait++}else{jQuery.ready(true)}},ready:function(wait){if(wait===true?--jQuery.readyWait:jQuery.isReady){return}if(!document.body){return setTimeout(jQuery.ready,1)}jQuery.isReady=true;if(wait!==true&&--jQuery.readyWait>0){return}readyList.resolveWith(document,[jQuery]);if(jQuery.fn.trigger){jQuery(document).trigger("ready").off("ready")}},isFunction:function(obj){return jQuery.type(obj)==="function"},isArray:Array.isArray||function(obj){return jQuery.type(obj)==="array"},isWindow:function(obj){return obj!=null&&obj==obj.window},isNumeric:function(obj){return!isNaN(parseFloat(obj))&&isFinite(obj)},type:function(obj){return obj==null?String(obj):class2type[core_toString.call(obj)]||"object"},isPlainObject:function(obj){if(!obj||jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false}try{if(obj.constructor&&!core_hasOwn.call(obj,"constructor")&&!core_hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false}}catch(e){return false}var key;for(key in obj){}return key===undefined||core_hasOwn.call(obj,key)},isEmptyObject:function(obj){var name;for(name in obj){return false}return true},error:function(msg){throw new Error(msg)},parseHTML:function(data,context,scripts){var parsed;if(!data||typeof data!=="string"){return null}if(typeof context==="boolean"){scripts=context;context=0}context=context||document;if(parsed=rsingleTag.exec(data)){return[context.createElement(parsed[1])]}parsed=jQuery.buildFragment([data],context,scripts?null:[]);return jQuery.merge([],(parsed.cacheable?jQuery.clone(parsed.fragment):parsed.fragment).childNodes)},parseJSON:function(data){if(!data||typeof data!=="string"){return null}data=jQuery.trim(data);if(window.JSON&&window.JSON.parse){return window.JSON.parse(data)}if(rvalidchars.test(data.replace(rvalidescape,"@").replace(rvalidtokens,"]").replace(rvalidbraces,""))){return new Function("return "+data)()}jQuery.error("Invalid JSON: "+data)},parseXML:function(data){var xml,tmp;if(!data||typeof data!=="string"){return null}try{if(window.DOMParser){tmp=new DOMParser;xml=tmp.parseFromString(data,"text/xml")}else{xml=new ActiveXObject("Microsoft.XMLDOM");xml.async="false";xml.loadXML(data)}}catch(e){xml=undefined}if(!xml||!xml.documentElement||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data)}return xml},noop:function(){},globalEval:function(data){if(data&&core_rnotwhite.test(data)){(window.execScript||function(data){window["eval"].call(window,data)})(data)}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase)},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toLowerCase()===name.toLowerCase()},each:function(obj,callback,args){var name,i=0,length=obj.length,isObj=length===undefined||jQuery.isFunction(obj);if(args){if(isObj){for(name in obj){if(callback.apply(obj[name],args)===false){break}}}else{for(;i<length;){if(callback.apply(obj[i++],args)===false){break}}}}else{if(isObj){for(name in obj){if(callback.call(obj[name],name,obj[name])===false){break}}}else{for(;i<length;){if(callback.call(obj[i],i,obj[i++])===false){break}}}}return obj},trim:core_trim&&!core_trim.call(" ")?function(text){return text==null?"":core_trim.call(text)}:function(text){return text==null?"":(text+"").replace(rtrim,"")},makeArray:function(arr,results){var type,ret=results||[];if(arr!=null){type=jQuery.type(arr);if(arr.length==null||type==="string"||type==="function"||type==="regexp"||jQuery.isWindow(arr)){core_push.call(ret,arr)}else{jQuery.merge(ret,arr)}}return ret},inArray:function(elem,arr,i){var len;if(arr){if(core_indexOf){return core_indexOf.call(arr,elem,i)}len=arr.length;i=i?i<0?Math.max(0,len+i):i:0;for(;i<len;i++){if(i in arr&&arr[i]===elem){return i}}}return-1},merge:function(first,second){var l=second.length,i=first.length,j=0;if(typeof l==="number"){for(;j<l;j++){first[i++]=second[j]}}else{while(second[j]!==undefined){first[i++]=second[j++]}}first.length=i;return first},grep:function(elems,callback,inv){var retVal,ret=[],i=0,length=elems.length;inv=!!inv;for(;i<length;i++){retVal=!!callback(elems[i],i);if(inv!==retVal){ret.push(elems[i])}}return ret},map:function(elems,callback,arg){var value,key,ret=[],i=0,length=elems.length,isArray=elems instanceof jQuery||length!==undefined&&typeof length==="number"&&(length>0&&elems[0]&&elems[length-1]||length===0||jQuery.isArray(elems));if(isArray){for(;i<length;i++){value=callback(elems[i],i,arg);if(value!=null){ret[ret.length]=value}}}else{for(key in elems){value=callback(elems[key],key,arg);if(value!=null){ret[ret.length]=value}}}return ret.concat.apply([],ret)},guid:1,proxy:function(fn,context){var tmp,args,proxy;if(typeof context==="string"){tmp=fn[context];context=fn;fn=tmp}if(!jQuery.isFunction(fn)){return undefined}args=core_slice.call(arguments,2);proxy=function(){return fn.apply(context,args.concat(core_slice.call(arguments)))};proxy.guid=fn.guid=fn.guid||jQuery.guid++;return proxy},access:function(elems,fn,key,value,chainable,emptyGet,pass){var exec,bulk=key==null,i=0,length=elems.length;if(key&&typeof key==="object"){for(i in key){jQuery.access(elems,fn,i,key[i],1,emptyGet,value)}chainable=1}else if(value!==undefined){exec=pass===undefined&&jQuery.isFunction(value);if(bulk){if(exec){exec=fn;fn=function(elem,key,value){return exec.call(jQuery(elem),value)}}else{fn.call(elems,value);fn=null}}if(fn){for(;i<length;i++){fn(elems[i],key,exec?value.call(elems[i],i,fn(elems[i],key)):value,pass)}}chainable=1}return chainable?elems:bulk?fn.call(elems):length?fn(elems[0],key):emptyGet},now:function(){return(new Date).getTime()}});jQuery.ready.promise=function(obj){if(!readyList){readyList=jQuery.Deferred();if(document.readyState==="complete"){setTimeout(jQuery.ready,1)}else if(document.addEventListener){document.addEventListener("DOMContentLoaded",DOMContentLoaded,false);window.addEventListener("load",jQuery.ready,false)}else{document.attachEvent("onreadystatechange",DOMContentLoaded);window.attachEvent("onload",jQuery.ready);var top=false;try{top=window.frameElement==null&&document.documentElement}catch(e){}if(top&&top.doScroll){(function doScrollCheck(){if(!jQuery.isReady){try{top.doScroll("left")}catch(e){return setTimeout(doScrollCheck,50)}jQuery.ready()}})()}}}return readyList.promise(obj)};jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(i,name){class2type["[object "+name+"]"]=name.toLowerCase()});rootjQuery=jQuery(document);var optionsCache={};function createOptions(options){var object=optionsCache[options]={};jQuery.each(options.split(core_rspace),function(_,flag){object[flag]=true});return object}jQuery.Callbacks=function(options){options=typeof options==="string"?optionsCache[options]||createOptions(options):jQuery.extend({},options);var memory,fired,firing,firingStart,firingLength,firingIndex,list=[],stack=!options.once&&[],fire=function(data){memory=options.memory&&data;fired=true;firingIndex=firingStart||0;firingStart=0;firingLength=list.length;firing=true;for(;list&&firingIndex<firingLength;firingIndex++){if(list[firingIndex].apply(data[0],data[1])===false&&options.stopOnFalse){memory=false;break}}firing=false;if(list){if(stack){if(stack.length){fire(stack.shift())}}else if(memory){list=[]}else{self.disable()}}},self={add:function(){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg)}}else if(arg&&arg.length&&type!=="string"){add(arg)}})})(arguments);if(firing){firingLength=list.length}else if(memory){firingStart=start;fire(memory)}}return this},remove:function(){if(list){jQuery.each(arguments,function(_,arg){var index;while((index=jQuery.inArray(arg,list,index))>-1){list.splice(index,1);if(firing){if(index<=firingLength){firingLength--}if(index<=firingIndex){firingIndex--}}}})}return this},has:function(fn){return jQuery.inArray(fn,list)>-1},empty:function(){list=[];return this},disable:function(){list=stack=memory=undefined;return this},disabled:function(){return!list},lock:function(){stack=undefined;if(!memory){self.disable()}return this},locked:function(){return!stack},fireWith:function(context,args){args=args||[];args=[context,args.slice?args.slice():args];if(list&&(!fired||stack)){if(firing){stack.push(args)}else{fire(args)}}return this},fire:function(){self.fireWith(this,arguments);return this},fired:function(){return!!fired}};return self};jQuery.extend({Deferred:function(func){var tuples=[["resolve","done",jQuery.Callbacks("once memory"),"resolved"],["reject","fail",jQuery.Callbacks("once memory"),"rejected"],["notify","progress",jQuery.Callbacks("memory")]],state="pending",promise={state:function(){return state},always:function(){deferred.done(arguments).fail(arguments);return this},then:function(){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=fns[i];deferred[tuple[1]](jQuery.isFunction(fn)?function(){var returned=fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify)}else{newDefer[action+"With"](this===deferred?newDefer:this,[returned])}}:newDefer[action])});fns=null}).promise()},promise:function(obj){return obj!=null?jQuery.extend(obj,promise):promise}},deferred={};promise.pipe=promise.then;jQuery.each(tuples,function(i,tuple){var list=tuple[2],stateString=tuple[3];promise[tuple[1]]=list.add;if(stateString){list.add(function(){state=stateString},tuples[i^1][2].disable,tuples[2][2].lock)}deferred[tuple[0]]=list.fire;deferred[tuple[0]+"With"]=list.fireWith});promise.promise(deferred);if(func){func.call(deferred,deferred)}return deferred},when:function(subordinate){var i=0,resolveValues=core_slice.call(arguments),length=resolveValues.length,remaining=length!==1||subordinate&&jQuery.isFunction(subordinate.promise)?length:0,deferred=remaining===1?subordinate:jQuery.Deferred(),updateFunc=function(i,contexts,values){return function(value){contexts[i]=this;values[i]=arguments.length>1?core_slice.call(arguments):value;if(values===progressValues){deferred.notifyWith(contexts,values)}else if(!--remaining){deferred.resolveWith(contexts,values)}}},progressValues,progressContexts,resolveContexts;if(length>1){progressValues=new Array(length);progressContexts=new Array(length);resolveContexts=new Array(length);for(;i<length;i++){if(resolveValues[i]&&jQuery.isFunction(resolveValues[i].promise)){resolveValues[i].promise().done(updateFunc(i,resolveContexts,resolveValues)).fail(deferred.reject).progress(updateFunc(i,progressContexts,progressValues))}else{--remaining}}}if(!remaining){deferred.resolveWith(resolveContexts,resolveValues)}return deferred.promise()}});jQuery.support=function(){var support,all,a,select,opt,input,fragment,eventName,i,isSupported,clickFn,div=document.createElement("div");div.setAttribute("className","t");div.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";all=div.getElementsByTagName("*");a=div.getElementsByTagName("a")[0];if(!all||!a||!all.length){return{}}select=document.createElement("select");opt=select.appendChild(document.createElement("option"));input=div.getElementsByTagName("input")[0];a.style.cssText="top:1px;float:left;opacity:.5";support={leadingWhitespace:div.firstChild.nodeType===3,tbody:!div.getElementsByTagName("tbody").length,htmlSerialize:!!div.getElementsByTagName("link").length,style:/top/.test(a.getAttribute("style")),hrefNormalized:a.getAttribute("href")==="/a",opacity:/^0.5/.test(a.style.opacity),cssFloat:!!a.style.cssFloat,checkOn:input.value==="on",optSelected:opt.selected,getSetAttribute:div.className!=="t",enctype:!!document.createElement("form").enctype,html5Clone:document.createElement("nav").cloneNode(true).outerHTML!=="<:nav></:nav>",boxModel:document.compatMode==="CSS1Compat",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true,boxSizingReliable:true,pixelPosition:false};input.checked=true;support.noCloneChecked=input.cloneNode(true).checked;select.disabled=true;support.optDisabled=!opt.disabled;try{delete div.test}catch(e){support.deleteExpando=false}if(!div.addEventListener&&div.attachEvent&&div.fireEvent){div.attachEvent("onclick",clickFn=function(){support.noCloneEvent=false});div.cloneNode(true).fireEvent("onclick");div.detachEvent("onclick",clickFn)}input=document.createElement("input");input.value="t";input.setAttribute("type","radio");support.radioValue=input.value==="t";input.setAttribute("checked","checked");input.setAttribute("name","t");div.appendChild(input);fragment=document.createDocumentFragment();fragment.appendChild(div.lastChild);support.checkClone=fragment.cloneNode(true).cloneNode(true).lastChild.checked;support.appendChecked=input.checked;fragment.removeChild(input);fragment.appendChild(div);if(div.attachEvent){for(i in{submit:true,change:true,focusin:true}){eventName="on"+i;isSupported=eventName in div;if(!isSupported){div.setAttribute(eventName,"return;");isSupported=typeof div[eventName]==="function"}support[i+"Bubbles"]=isSupported}}jQuery(function(){var container,div,tds,marginDiv,divReset="padding:0;margin:0;border:0;display:block;overflow:hidden;",body=document.getElementsByTagName("body")[0];if(!body){return}container=document.createElement("div");container.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";body.insertBefore(container,body.firstChild);div=document.createElement("div");container.appendChild(div);div.innerHTML="<table><tr><td></td><td>t</td></tr></table>";tds=div.getElementsByTagName("td");tds[0].style.cssText="padding:0;margin:0;border:0;display:none";isSupported=tds[0].offsetHeight===0;tds[0].style.display="";tds[1].style.display="none";support.reliableHiddenOffsets=isSupported&&tds[0].offsetHeight===0;div.innerHTML="";div.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";support.boxSizing=div.offsetWidth===4;support.doesNotIncludeMarginInBodyOffset=body.offsetTop!==1;if(window.getComputedStyle){support.pixelPosition=(window.getComputedStyle(div,null)||{}).top!=="1%";support.boxSizingReliable=(window.getComputedStyle(div,null)||{width:"4px"}).width==="4px";marginDiv=document.createElement("div");marginDiv.style.cssText=div.style.cssText=divReset;marginDiv.style.marginRight=marginDiv.style.width="0";div.style.width="1px";div.appendChild(marginDiv);support.reliableMarginRight=!parseFloat((window.getComputedStyle(marginDiv,null)||{}).marginRight)}if(typeof div.style.zoom!=="undefined"){div.innerHTML="";div.style.cssText=divReset+"width:1px;padding:1px;display:inline;zoom:1";support.inlineBlockNeedsLayout=div.offsetWidth===3;div.style.display="block";div.style.overflow="visible";div.innerHTML="<div></div>";div.firstChild.style.width="5px";support.shrinkWrapBlocks=div.offsetWidth!==3;container.style.zoom=1}body.removeChild(container);container=div=tds=marginDiv=null});fragment.removeChild(div);all=a=select=opt=input=fragment=div=null;return support}();var rbrace=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,rmultiDash=/([A-Z])/g;jQuery.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(jQuery.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(elem){elem=elem.nodeType?jQuery.cache[elem[jQuery.expando]]:elem[jQuery.expando];return!!elem&&!isEmptyDataObject(elem)},data:function(elem,name,data,pvt){if(!jQuery.acceptData(elem)){return}var thisCache,ret,internalKey=jQuery.expando,getByName=typeof name==="string",isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[internalKey]:elem[internalKey]&&internalKey;if((!id||!cache[id]||!pvt&&!cache[id].data)&&getByName&&data===undefined){return}if(!id){if(isNode){elem[internalKey]=id=jQuery.deletedIds.pop()||jQuery.guid++}else{id=internalKey}}if(!cache[id]){cache[id]={};if(!isNode){cache[id].toJSON=jQuery.noop}}if(typeof name==="object"||typeof name==="function"){if(pvt){cache[id]=jQuery.extend(cache[id],name)}else{cache[id].data=jQuery.extend(cache[id].data,name)}}thisCache=cache[id];if(!pvt){if(!thisCache.data){thisCache.data={}}thisCache=thisCache.data}if(data!==undefined){thisCache[jQuery.camelCase(name)]=data}if(getByName){ret=thisCache[name];if(ret==null){ret=thisCache[jQuery.camelCase(name)]}}else{ret=thisCache}return ret},removeData:function(elem,name,pvt){if(!jQuery.acceptData(elem)){return}var thisCache,i,l,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[jQuery.expando]:jQuery.expando;if(!cache[id]){return}if(name){thisCache=pvt?cache[id]:cache[id].data;if(thisCache){if(!jQuery.isArray(name)){if(name in thisCache){name=[name]}else{name=jQuery.camelCase(name);if(name in thisCache){name=[name]}else{name=name.split(" ")}}}for(i=0,l=name.length;i<l;i++){delete thisCache[name[i]]}if(!(pvt?isEmptyDataObject:jQuery.isEmptyObject)(thisCache)){return}}}if(!pvt){delete cache[id].data;if(!isEmptyDataObject(cache[id])){return}}if(isNode){jQuery.cleanData([elem],true)}else if(jQuery.support.deleteExpando||cache!=cache.window){delete cache[id]}else{cache[id]=null}},_data:function(elem,name,data){return jQuery.data(elem,name,data,true)},acceptData:function(elem){var noData=elem.nodeName&&jQuery.noData[elem.nodeName.toLowerCase()];return!noData||noData!==true&&elem.getAttribute("classid")===noData}});jQuery.fn.extend({data:function(key,value){var parts,part,attr,name,l,elem=this[0],i=0,data=null;if(key===undefined){if(this.length){data=jQuery.data(elem);if(elem.nodeType===1&&!jQuery._data(elem,"parsedAttrs")){attr=elem.attributes;for(l=attr.length;i<l;i++){name=attr[i].name;if(!name.indexOf("data-")){name=jQuery.camelCase(name.substring(5));dataAttr(elem,name,data[name])}}jQuery._data(elem,"parsedAttrs",true)}}return data}if(typeof key==="object"){return this.each(function(){jQuery.data(this,key)})}parts=key.split(".",2);parts[1]=parts[1]?"."+parts[1]:"";part=parts[1]+"!";return jQuery.access(this,function(value){if(value===undefined){data=this.triggerHandler("getData"+part,[parts[0]]);if(data===undefined&&elem){data=jQuery.data(elem,key);data=dataAttr(elem,key,data)}return data===undefined&&parts[1]?this.data(parts[0]):data}parts[1]=value;this.each(function(){var self=jQuery(this);self.triggerHandler("setData"+part,parts);jQuery.data(this,key,value);self.triggerHandler("changeData"+part,parts)})},null,value,arguments.length>1,null,false)},removeData:function(key){return this.each(function(){jQuery.removeData(this,key)})}});function dataAttr(elem,key,data){if(data===undefined&&elem.nodeType===1){var name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:+data+""===data?+data:rbrace.test(data)?jQuery.parseJSON(data):data}catch(e){}jQuery.data(elem,key,data)}else{data=undefined}}return data}function isEmptyDataObject(obj){var name;for(name in obj){if(name==="data"&&jQuery.isEmptyObject(obj[name])){continue}if(name!=="toJSON"){return false}}return true}jQuery.extend({queue:function(elem,type,data){var queue;if(elem){type=(type||"fx")+"queue";queue=jQuery._data(elem,type);if(data){if(!queue||jQuery.isArray(data)){queue=jQuery._data(elem,type,jQuery.makeArray(data))}else{queue.push(data)}}return queue||[]}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),startLength=queue.length,fn=queue.shift(),hooks=jQuery._queueHooks(elem,type),next=function(){jQuery.dequeue(elem,type)};if(fn==="inprogress"){fn=queue.shift();startLength--}if(fn){if(type==="fx"){queue.unshift("inprogress")}delete hooks.stop;fn.call(elem,next,hooks)}if(!startLength&&hooks){hooks.empty.fire()}},_queueHooks:function(elem,type){var key=type+"queueHooks";return jQuery._data(elem,key)||jQuery._data(elem,key,{empty:jQuery.Callbacks("once memory").add(function(){jQuery.removeData(elem,type+"queue",true);jQuery.removeData(elem,key,true)})})}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--}if(arguments.length<setter){return jQuery.queue(this[0],type)}return data===undefined?this:this.each(function(){var queue=jQuery.queue(this,type,data);jQuery._queueHooks(this,type);if(type==="fx"&&queue[0]!=="inprogress"){jQuery.dequeue(this,type)}})},dequeue:function(type){return this.each(function(){jQuery.dequeue(this,type)})},delay:function(time,type){time=jQuery.fx?jQuery.fx.speeds[time]||time:time;type=type||"fx";return this.queue(type,function(next,hooks){var timeout=setTimeout(next,time);hooks.stop=function(){clearTimeout(timeout)}})},clearQueue:function(type){return this.queue(type||"fx",[])},promise:function(type,obj){var tmp,count=1,defer=jQuery.Deferred(),elements=this,i=this.length,resolve=function(){if(!--count){defer.resolveWith(elements,[elements])}};if(typeof type!=="string"){obj=type;type=undefined}type=type||"fx";while(i--){tmp=jQuery._data(elements[i],type+"queueHooks");if(tmp&&tmp.empty){count++;tmp.empty.add(resolve)}}resolve();return defer.promise(obj)}});var nodeHook,boolHook,fixSpecified,rclass=/[\t\r\n]/g,rreturn=/\r/g,rtype=/^(?:button|input)$/i,rfocusable=/^(?:button|input|object|select|textarea)$/i,rclickable=/^a(?:rea|)$/i,rboolean=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,getSetAttribute=jQuery.support.getSetAttribute;jQuery.fn.extend({attr:function(name,value){return jQuery.access(this,jQuery.attr,name,value,arguments.length>1)},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name)})},prop:function(name,value){return jQuery.access(this,jQuery.prop,name,value,arguments.length>1)},removeProp:function(name){name=jQuery.propFix[name]||name;return this.each(function(){try{this[name]=undefined;delete this[name]}catch(e){}})},addClass:function(value){var classNames,i,l,elem,setClass,c,cl;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className))})}if(value&&typeof value==="string"){classNames=value.split(core_rspace);for(i=0,l=this.length;i<l;i++){elem=this[i];if(elem.nodeType===1){if(!elem.className&&classNames.length===1){elem.className=value}else{setClass=" "+elem.className+" ";for(c=0,cl=classNames.length;c<cl;c++){if(setClass.indexOf(" "+classNames[c]+" ")<0){setClass+=classNames[c]+" "}}elem.className=jQuery.trim(setClass)}}}}return this},removeClass:function(value){var removes,className,elem,c,cl,i,l;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).removeClass(value.call(this,j,this.className))})}if(value&&typeof value==="string"||value===undefined){removes=(value||"").split(core_rspace);for(i=0,l=this.length;i<l;i++){elem=this[i];if(elem.nodeType===1&&elem.className){className=(" "+elem.className+" ").replace(rclass," ");for(c=0,cl=removes.length;c<cl;c++){while(className.indexOf(" "+removes[c]+" ")>=0){className=className.replace(" "+removes[c]+" "," ")}}elem.className=value?jQuery.trim(className):""}}}return this},toggleClass:function(value,stateVal){var type=typeof value,isBool=typeof stateVal==="boolean";if(jQuery.isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal)})}return this.each(function(){if(type==="string"){var className,i=0,self=jQuery(this),state=stateVal,classNames=value.split(core_rspace);while(className=classNames[i++]){state=isBool?state:!self.hasClass(className);self[state?"addClass":"removeClass"](className)}}else if(type==="undefined"||type==="boolean"){if(this.className){jQuery._data(this,"__className__",this.className)}this.className=this.className||value===false?"":jQuery._data(this,"__className__")||""}})},hasClass:function(selector){var className=" "+selector+" ",i=0,l=this.length;for(;i<l;i++){if(this[i].nodeType===1&&(" "+this[i].className+" ").replace(rclass," ").indexOf(className)>=0){return true}}return false},val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret}ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret}return}isFunction=jQuery.isFunction(value);return this.each(function(i){var val,self=jQuery(this);if(this.nodeType!==1){return}if(isFunction){val=value.call(this,i,self.val())}else{val=value}if(val==null){val=""}else if(typeof val==="number"){val+=""}else if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+""})}hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val}})}});jQuery.extend({valHooks:{option:{get:function(elem){var val=elem.attributes.value;return!val||val.specified?elem.value:elem.text}},select:{get:function(elem){var value,option,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one"||index<0,values=one?null:[],max=one?index+1:options.length,i=index<0?max:one?index:0;for(;i<max;i++){option=options[i];if((option.selected||i===index)&&(jQuery.support.optDisabled?!option.disabled:option.getAttribute("disabled")===null)&&(!option.parentNode.disabled||!jQuery.nodeName(option.parentNode,"optgroup"))){value=jQuery(option).val();if(one){return value}values.push(value)}}return values},set:function(elem,value){var values=jQuery.makeArray(value);jQuery(elem).find("option").each(function(){this.selected=jQuery.inArray(jQuery(this).val(),values)>=0});if(!values.length){elem.selectedIndex=-1}return values}}},attrFn:{},attr:function(elem,name,value,pass){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return}if(pass&&jQuery.isFunction(jQuery.fn[name])){return jQuery(elem)[name](value)}if(typeof elem.getAttribute==="undefined"){return jQuery.prop(elem,name,value)}notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(rboolean.test(name)?boolHook:nodeHook)}if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);return}else if(hooks&&"set"in hooks&&notxml&&(ret=hooks.set(elem,value,name))!==undefined){return ret}else{elem.setAttribute(name,value+"");return value}}else if(hooks&&"get"in hooks&&notxml&&(ret=hooks.get(elem,name))!==null){return ret}else{ret=elem.getAttribute(name);return ret===null?undefined:ret}},removeAttr:function(elem,value){var propName,attrNames,name,isBool,i=0;if(value&&elem.nodeType===1){attrNames=value.split(core_rspace);for(;i<attrNames.length;i++){name=attrNames[i];if(name){propName=jQuery.propFix[name]||name;isBool=rboolean.test(name);if(!isBool){jQuery.attr(elem,name,"")}elem.removeAttribute(getSetAttribute?name:propName);if(isBool&&propName in elem){elem[propName]=false}}}}},attrHooks:{type:{set:function(elem,value){if(rtype.test(elem.nodeName)&&elem.parentNode){jQuery.error("type property can't be changed")
+}else if(!jQuery.support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val}return value}}},value:{get:function(elem,name){if(nodeHook&&jQuery.nodeName(elem,"button")){return nodeHook.get(elem,name)}return name in elem?elem.value:null},set:function(elem,value,name){if(nodeHook&&jQuery.nodeName(elem,"button")){return nodeHook.set(elem,value,name)}elem.value=value}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return}notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name]}if(value!==undefined){if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret}else{return elem[name]=value}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret}else{return elem[name]}}},propHooks:{tabIndex:{get:function(elem){var attributeNode=elem.getAttributeNode("tabindex");return attributeNode&&attributeNode.specified?parseInt(attributeNode.value,10):rfocusable.test(elem.nodeName)||rclickable.test(elem.nodeName)&&elem.href?0:undefined}}}});boolHook={get:function(elem,name){var attrNode,property=jQuery.prop(elem,name);return property===true||typeof property!=="boolean"&&(attrNode=elem.getAttributeNode(name))&&attrNode.nodeValue!==false?name.toLowerCase():undefined},set:function(elem,value,name){var propName;if(value===false){jQuery.removeAttr(elem,name)}else{propName=jQuery.propFix[name]||name;if(propName in elem){elem[propName]=true}elem.setAttribute(name,name.toLowerCase())}return name}};if(!getSetAttribute){fixSpecified={name:true,id:true,coords:true};nodeHook=jQuery.valHooks.button={get:function(elem,name){var ret;ret=elem.getAttributeNode(name);return ret&&(fixSpecified[name]?ret.value!=="":ret.specified)?ret.value:undefined},set:function(elem,value,name){var ret=elem.getAttributeNode(name);if(!ret){ret=document.createAttribute(name);elem.setAttributeNode(ret)}return ret.value=value+""}};jQuery.each(["width","height"],function(i,name){jQuery.attrHooks[name]=jQuery.extend(jQuery.attrHooks[name],{set:function(elem,value){if(value===""){elem.setAttribute(name,"auto");return value}}})});jQuery.attrHooks.contenteditable={get:nodeHook.get,set:function(elem,value,name){if(value===""){value="false"}nodeHook.set(elem,value,name)}}}if(!jQuery.support.hrefNormalized){jQuery.each(["href","src","width","height"],function(i,name){jQuery.attrHooks[name]=jQuery.extend(jQuery.attrHooks[name],{get:function(elem){var ret=elem.getAttribute(name,2);return ret===null?undefined:ret}})})}if(!jQuery.support.style){jQuery.attrHooks.style={get:function(elem){return elem.style.cssText.toLowerCase()||undefined},set:function(elem,value){return elem.style.cssText=value+""}}}if(!jQuery.support.optSelected){jQuery.propHooks.selected=jQuery.extend(jQuery.propHooks.selected,{get:function(elem){var parent=elem.parentNode;if(parent){parent.selectedIndex;if(parent.parentNode){parent.parentNode.selectedIndex}}return null}})}if(!jQuery.support.enctype){jQuery.propFix.enctype="encoding"}if(!jQuery.support.checkOn){jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={get:function(elem){return elem.getAttribute("value")===null?"on":elem.value}}})}jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]=jQuery.extend(jQuery.valHooks[this],{set:function(elem,value){if(jQuery.isArray(value)){return elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0}}})});var rformElems=/^(?:textarea|input|select)$/i,rtypenamespace=/^([^\.]*|)(?:\.(.+)|)$/,rhoverHack=/(?:^|\s)hover(\.\S+|)\b/,rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,hoverHack=function(events){return jQuery.event.special.hover?events:events.replace(rhoverHack,"mouseenter$1 mouseleave$1")};jQuery.event={add:function(elem,types,handler,data,selector){var elemData,eventHandle,events,t,tns,type,namespaces,handleObj,handleObjIn,handlers,special;if(elem.nodeType===3||elem.nodeType===8||!types||!handler||!(elemData=jQuery._data(elem))){return}if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector}if(!handler.guid){handler.guid=jQuery.guid++}events=elemData.events;if(!events){elemData.events=events={}}eventHandle=elemData.handle;if(!eventHandle){elemData.handle=eventHandle=function(e){return typeof jQuery!=="undefined"&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined};eventHandle.elem=elem}types=jQuery.trim(hoverHack(types)).split(" ");for(t=0;t<types.length;t++){tns=rtypenamespace.exec(types[t])||[];type=tns[1];namespaces=(tns[2]||"").split(".").sort();special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:tns[1],data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);handlers=events[type];if(!handlers){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle,false)}else if(elem.attachEvent){elem.attachEvent("on"+type,eventHandle)}}}if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid}}if(selector){handlers.splice(handlers.delegateCount++,0,handleObj)}else{handlers.push(handleObj)}jQuery.event.global[type]=true}elem=null},global:{},remove:function(elem,types,handler,selector,mappedTypes){var t,tns,type,origType,namespaces,origCount,j,events,special,eventType,handleObj,elemData=jQuery.hasData(elem)&&jQuery._data(elem);if(!elemData||!(events=elemData.events)){return}types=jQuery.trim(hoverHack(types||"")).split(" ");for(t=0;t<types.length;t++){tns=rtypenamespace.exec(types[t])||[];type=origType=tns[1];namespaces=tns[2];if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true)}continue}special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;eventType=events[type]||[];origCount=eventType.length;namespaces=namespaces?new RegExp("(^|\\.)"+namespaces.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(j=0;j<eventType.length;j++){handleObj=eventType[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!namespaces||namespaces.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){eventType.splice(j--,1);if(handleObj.selector){eventType.delegateCount--}if(special.remove){special.remove.call(elem,handleObj)}}}if(eventType.length===0&&origCount!==eventType.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle)}delete events[type]}}if(jQuery.isEmptyObject(events)){delete elemData.handle;jQuery.removeData(elem,"events",true)}},customEvent:{getData:true,setData:true,changeData:true},trigger:function(event,data,elem,onlyHandlers){if(elem&&(elem.nodeType===3||elem.nodeType===8)){return}var cache,exclusive,i,cur,old,ontype,special,handle,eventPath,bubbleType,type=event.type||event,namespaces=[];if(rfocusMorph.test(type+jQuery.event.triggered)){return}if(type.indexOf("!")>=0){type=type.slice(0,-1);exclusive=true}if(type.indexOf(".")>=0){namespaces=type.split(".");type=namespaces.shift();namespaces.sort()}if((!elem||jQuery.event.customEvent[type])&&!jQuery.event.global[type]){return}event=typeof event==="object"?event[jQuery.expando]?event:new jQuery.Event(type,event):new jQuery.Event(type);event.type=type;event.isTrigger=true;event.exclusive=exclusive;event.namespace=namespaces.join(".");event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;ontype=type.indexOf(":")<0?"on"+type:"";if(!elem){cache=jQuery.cache;for(i in cache){if(cache[i].events&&cache[i].events[type]){jQuery.event.trigger(event,data,cache[i].handle.elem,true)}}return}event.result=undefined;if(!event.target){event.target=elem}data=data!=null?jQuery.makeArray(data):[];data.unshift(event);special=jQuery.event.special[type]||{};if(special.trigger&&special.trigger.apply(elem,data)===false){return}eventPath=[[elem,special.bindType||type]];if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;cur=rfocusMorph.test(bubbleType+type)?elem:elem.parentNode;for(old=elem;cur;cur=cur.parentNode){eventPath.push([cur,bubbleType]);old=cur}if(old===(elem.ownerDocument||document)){eventPath.push([old.defaultView||old.parentWindow||window,bubbleType])}}for(i=0;i<eventPath.length&&!event.isPropagationStopped();i++){cur=eventPath[i][0];event.type=eventPath[i][1];handle=(jQuery._data(cur,"events")||{})[event.type]&&jQuery._data(cur,"handle");if(handle){handle.apply(cur,data)}handle=ontype&&cur[ontype];if(handle&&jQuery.acceptData(cur)&&handle.apply&&handle.apply(cur,data)===false){event.preventDefault()}}event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(elem.ownerDocument,data)===false)&&!(type==="click"&&jQuery.nodeName(elem,"a"))&&jQuery.acceptData(elem)){if(ontype&&elem[type]&&(type!=="focus"&&type!=="blur"||event.target.offsetWidth!==0)&&!jQuery.isWindow(elem)){old=elem[ontype];if(old){elem[ontype]=null}jQuery.event.triggered=type;elem[type]();jQuery.event.triggered=undefined;if(old){elem[ontype]=old}}}}return event.result},dispatch:function(event){event=jQuery.event.fix(event||window.event);var i,j,cur,ret,selMatch,matched,matches,handleObj,sel,related,handlers=(jQuery._data(this,"events")||{})[event.type]||[],delegateCount=handlers.delegateCount,args=core_slice.call(arguments),run_all=!event.exclusive&&!event.namespace,special=jQuery.event.special[event.type]||{},handlerQueue=[];args[0]=event;event.delegateTarget=this;if(special.preDispatch&&special.preDispatch.call(this,event)===false){return}if(delegateCount&&!(event.button&&event.type==="click")){for(cur=event.target;cur!=this;cur=cur.parentNode||this){if(cur.disabled!==true||event.type!=="click"){selMatch={};matches=[];for(i=0;i<delegateCount;i++){handleObj=handlers[i];sel=handleObj.selector;if(selMatch[sel]===undefined){selMatch[sel]=handleObj.needsContext?jQuery(sel,this).index(cur)>=0:jQuery.find(sel,this,null,[cur]).length}if(selMatch[sel]){matches.push(handleObj)}}if(matches.length){handlerQueue.push({elem:cur,matches:matches})}}}}if(handlers.length>delegateCount){handlerQueue.push({elem:this,matches:handlers.slice(delegateCount)})}for(i=0;i<handlerQueue.length&&!event.isPropagationStopped();i++){matched=handlerQueue[i];event.currentTarget=matched.elem;for(j=0;j<matched.matches.length&&!event.isImmediatePropagationStopped();j++){handleObj=matched.matches[j];if(run_all||!event.namespace&&!handleObj.namespace||event.namespace_re&&event.namespace_re.test(handleObj.namespace)){event.data=handleObj.data;event.handleObj=handleObj;ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args);if(ret!==undefined){event.result=ret;if(ret===false){event.preventDefault();event.stopPropagation()}}}}}if(special.postDispatch){special.postDispatch.call(this,event)}return event.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(event,original){if(event.which==null){event.which=original.charCode!=null?original.charCode:original.keyCode}return event}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(event,original){var eventDoc,doc,body,button=original.button,fromElement=original.fromElement;if(event.pageX==null&&original.clientX!=null){eventDoc=event.target.ownerDocument||document;doc=eventDoc.documentElement;body=eventDoc.body;event.pageX=original.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);event.pageY=original.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0)}if(!event.relatedTarget&&fromElement){event.relatedTarget=fromElement===event.target?original.toElement:fromElement}if(!event.which&&button!==undefined){event.which=button&1?1:button&2?3:button&4?2:0}return event}},fix:function(event){if(event[jQuery.expando]){return event}var i,prop,originalEvent=event,fixHook=jQuery.event.fixHooks[event.type]||{},copy=fixHook.props?this.props.concat(fixHook.props):this.props;event=jQuery.Event(originalEvent);for(i=copy.length;i;){prop=copy[--i];event[prop]=originalEvent[prop]}if(!event.target){event.target=originalEvent.srcElement||document}if(event.target.nodeType===3){event.target=event.target.parentNode}event.metaKey=!!event.metaKey;return fixHook.filter?fixHook.filter(event,originalEvent):event},special:{load:{noBubble:true},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(data,namespaces,eventHandle){if(jQuery.isWindow(this)){this.onbeforeunload=eventHandle}},teardown:function(namespaces,eventHandle){if(this.onbeforeunload===eventHandle){this.onbeforeunload=null}}}},simulate:function(type,elem,event,bubble){var e=jQuery.extend(new jQuery.Event,event,{type:type,isSimulated:true,originalEvent:{}});if(bubble){jQuery.event.trigger(e,null,elem)}else{jQuery.event.dispatch.call(elem,e)}if(e.isDefaultPrevented()){event.preventDefault()}}};jQuery.event.handle=jQuery.event.dispatch;jQuery.removeEvent=document.removeEventListener?function(elem,type,handle){if(elem.removeEventListener){elem.removeEventListener(type,handle,false)}}:function(elem,type,handle){var name="on"+type;if(elem.detachEvent){if(typeof elem[name]==="undefined"){elem[name]=null}elem.detachEvent(name,handle)}};jQuery.Event=function(src,props){if(!(this instanceof jQuery.Event)){return new jQuery.Event(src,props)}if(src&&src.type){this.originalEvent=src;this.type=src.type;this.isDefaultPrevented=src.defaultPrevented||src.returnValue===false||src.getPreventDefault&&src.getPreventDefault()?returnTrue:returnFalse}else{this.type=src}if(props){jQuery.extend(this,props)}this.timeStamp=src&&src.timeStamp||jQuery.now();this[jQuery.expando]=true};function returnFalse(){return false}function returnTrue(){return true}jQuery.Event.prototype={preventDefault:function(){this.isDefaultPrevented=returnTrue;var e=this.originalEvent;if(!e){return}if(e.preventDefault){e.preventDefault()}else{e.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=returnTrue;var e=this.originalEvent;if(!e){return}if(e.stopPropagation){e.stopPropagation()}e.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation()},isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse};jQuery.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(orig,fix){jQuery.event.special[orig]={delegateType:fix,bindType:fix,handle:function(event){var ret,target=this,related=event.relatedTarget,handleObj=event.handleObj,selector=handleObj.selector;if(!related||related!==target&&!jQuery.contains(target,related)){event.type=handleObj.origType;ret=handleObj.handler.apply(this,arguments);event.type=fix}return ret}}});if(!jQuery.support.submitBubbles){jQuery.event.special.submit={setup:function(){if(jQuery.nodeName(this,"form")){return false}jQuery.event.add(this,"click._submit keypress._submit",function(e){var elem=e.target,form=jQuery.nodeName(elem,"input")||jQuery.nodeName(elem,"button")?elem.form:undefined;if(form&&!jQuery._data(form,"_submit_attached")){jQuery.event.add(form,"submit._submit",function(event){event._submit_bubble=true});jQuery._data(form,"_submit_attached",true)}})},postDispatch:function(event){if(event._submit_bubble){delete event._submit_bubble;if(this.parentNode&&!event.isTrigger){jQuery.event.simulate("submit",this.parentNode,event,true)}}},teardown:function(){if(jQuery.nodeName(this,"form")){return false}jQuery.event.remove(this,"._submit")}}}if(!jQuery.support.changeBubbles){jQuery.event.special.change={setup:function(){if(rformElems.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio"){jQuery.event.add(this,"propertychange._change",function(event){if(event.originalEvent.propertyName==="checked"){this._just_changed=true}});jQuery.event.add(this,"click._change",function(event){if(this._just_changed&&!event.isTrigger){this._just_changed=false}jQuery.event.simulate("change",this,event,true)})}return false}jQuery.event.add(this,"beforeactivate._change",function(e){var elem=e.target;if(rformElems.test(elem.nodeName)&&!jQuery._data(elem,"_change_attached")){jQuery.event.add(elem,"change._change",function(event){if(this.parentNode&&!event.isSimulated&&!event.isTrigger){jQuery.event.simulate("change",this.parentNode,event,true)}});jQuery._data(elem,"_change_attached",true)}})},handle:function(event){var elem=event.target;if(this!==elem||event.isSimulated||event.isTrigger||elem.type!=="radio"&&elem.type!=="checkbox"){return event.handleObj.handler.apply(this,arguments)}},teardown:function(){jQuery.event.remove(this,"._change");return!rformElems.test(this.nodeName)}}}if(!jQuery.support.focusinBubbles){jQuery.each({focus:"focusin",blur:"focusout"},function(orig,fix){var attaches=0,handler=function(event){jQuery.event.simulate(fix,event.target,jQuery.event.fix(event),true)};jQuery.event.special[fix]={setup:function(){if(attaches++===0){document.addEventListener(orig,handler,true)}},teardown:function(){if(--attaches===0){document.removeEventListener(orig,handler,true)}}}})}jQuery.fn.extend({on:function(types,selector,data,fn,one){var origFn,type;if(typeof types==="object"){if(typeof selector!=="string"){data=data||selector;selector=undefined}for(type in types){this.on(type,selector,data,types[type],one)}return this}if(data==null&&fn==null){fn=selector;data=selector=undefined}else if(fn==null){if(typeof selector==="string"){fn=data;data=undefined}else{fn=data;data=selector;selector=undefined}}if(fn===false){fn=returnFalse}else if(!fn){return this}if(one===1){origFn=fn;fn=function(event){jQuery().off(event);return origFn.apply(this,arguments)};fn.guid=origFn.guid||(origFn.guid=jQuery.guid++)}return this.each(function(){jQuery.event.add(this,types,fn,data,selector)})},one:function(types,selector,data,fn){return this.on(types,selector,data,fn,1)},off:function(types,selector,fn){var handleObj,type;if(types&&types.preventDefault&&types.handleObj){handleObj=types.handleObj;jQuery(types.delegateTarget).off(handleObj.namespace?handleObj.origType+"."+handleObj.namespace:handleObj.origType,handleObj.selector,handleObj.handler);return this}if(typeof types==="object"){for(type in types){this.off(type,selector,types[type])}return this}if(selector===false||typeof selector==="function"){fn=selector;selector=undefined}if(fn===false){fn=returnFalse}return this.each(function(){jQuery.event.remove(this,types,fn,selector)})},bind:function(types,data,fn){return this.on(types,null,data,fn)},unbind:function(types,fn){return this.off(types,null,fn)},live:function(types,data,fn){jQuery(this.context).on(types,this.selector,data,fn);return this},die:function(types,fn){jQuery(this.context).off(types,this.selector||"**",fn);return this},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn)},undelegate:function(selector,types,fn){return arguments.length===1?this.off(selector,"**"):this.off(types,selector||"**",fn)},trigger:function(type,data){return this.each(function(){jQuery.event.trigger(type,data,this)})},triggerHandler:function(type,data){if(this[0]){return jQuery.event.trigger(type,data,this[0],true)}},toggle:function(fn){var args=arguments,guid=fn.guid||jQuery.guid++,i=0,toggler=function(event){var lastToggle=(jQuery._data(this,"lastToggle"+fn.guid)||0)%i;jQuery._data(this,"lastToggle"+fn.guid,lastToggle+1);event.preventDefault();return args[lastToggle].apply(this,arguments)||false};toggler.guid=guid;while(i<args.length){args[i++].guid=guid}return this.click(toggler)},hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver)}});jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick "+"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+"change select submit keydown keypress keyup error contextmenu").split(" "),function(i,name){jQuery.fn[name]=function(data,fn){if(fn==null){fn=data;data=null}return arguments.length>0?this.on(name,null,data,fn):this.trigger(name)};if(rkeyEvent.test(name)){jQuery.event.fixHooks[name]=jQuery.event.keyHooks}if(rmouseEvent.test(name)){jQuery.event.fixHooks[name]=jQuery.event.mouseHooks}});(function(window,undefined){var cachedruns,assertGetIdNotName,Expr,getText,isXML,contains,compile,sortOrder,hasDuplicate,outermostContext,baseHasDuplicate=true,strundefined="undefined",expando=("sizcache"+Math.random()).replace(".",""),Token=String,document=window.document,docElem=document.documentElement,dirruns=0,done=0,pop=[].pop,push=[].push,slice=[].slice,indexOf=[].indexOf||function(elem){var i=0,len=this.length;for(;i<len;i++){if(this[i]===elem){return i}}return-1},markFunction=function(fn,value){fn[expando]=value==null||value;return fn},createCache=function(){var cache={},keys=[];return markFunction(function(key,value){if(keys.push(key)>Expr.cacheLength){delete cache[keys.shift()]}return cache[key+" "]=value},cache)},classCache=createCache(),tokenCache=createCache(),compilerCache=createCache(),whitespace="[\\x20\\t\\r\\n\\f]",characterEncoding="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",identifier=characterEncoding.replace("w","w#"),operators="([*^$|!~]?=)",attributes="\\["+whitespace+"*("+characterEncoding+")"+whitespace+"*(?:"+operators+whitespace+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+identifier+")|)|)"+whitespace+"*\\]",pseudos=":("+characterEncoding+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+attributes+")|[^:]|\\\\.)*|.*))\\)|)",pos=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+whitespace+"*((?:-\\d)?\\d*)"+whitespace+"*\\)|)(?=[^-]|$)",rtrim=new RegExp("^"+whitespace+"+|((?:^|[^\\\\])(?:\\\\.)*)"+whitespace+"+$","g"),rcomma=new RegExp("^"+whitespace+"*,"+whitespace+"*"),rcombinators=new RegExp("^"+whitespace+"*([\\x20\\t\\r\\n\\f>+~])"+whitespace+"*"),rpseudo=new RegExp(pseudos),rquickExpr=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,rnot=/^:not/,rsibling=/[\x20\t\r\n\f]*[+~]/,rendsWithNot=/:not\($/,rheader=/h\d/i,rinputs=/input|select|textarea|button/i,rbackslash=/\\(?!\\)/g,matchExpr={ID:new RegExp("^#("+characterEncoding+")"),CLASS:new RegExp("^\\.("+characterEncoding+")"),NAME:new RegExp("^\\[name=['\"]?("+characterEncoding+")['\"]?\\]"),TAG:new RegExp("^("+characterEncoding.replace("w","w*")+")"),ATTR:new RegExp("^"+attributes),PSEUDO:new RegExp("^"+pseudos),POS:new RegExp(pos,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+whitespace+"*(even|odd|(([+-]|)(\\d*)n|)"+whitespace+"*(?:([+-]|)"+whitespace+"*(\\d+)|))"+whitespace+"*\\)|)","i"),needsContext:new RegExp("^"+whitespace+"*[>+~]|"+pos,"i")},assert=function(fn){var div=document.createElement("div");try{return fn(div)}catch(e){return false}finally{div=null}},assertTagNameNoComments=assert(function(div){div.appendChild(document.createComment(""));return!div.getElementsByTagName("*").length}),assertHrefNotNormalized=assert(function(div){div.innerHTML="<a href='#'></a>";return div.firstChild&&typeof div.firstChild.getAttribute!==strundefined&&div.firstChild.getAttribute("href")==="#"}),assertAttributes=assert(function(div){div.innerHTML="<select></select>";var type=typeof div.lastChild.getAttribute("multiple");return type!=="boolean"&&type!=="string"}),assertUsableClassName=assert(function(div){div.innerHTML="<div class='hidden e'></div><div class='hidden'></div>";if(!div.getElementsByClassName||!div.getElementsByClassName("e").length){return false}div.lastChild.className="e";return div.getElementsByClassName("e").length===2}),assertUsableName=assert(function(div){div.id=expando+0;div.innerHTML="<a name='"+expando+"'></a><div name='"+expando+"'></div>";docElem.insertBefore(div,docElem.firstChild);var pass=document.getElementsByName&&document.getElementsByName(expando).length===2+document.getElementsByName(expando+0).length;assertGetIdNotName=!document.getElementById(expando);docElem.removeChild(div);return pass});try{slice.call(docElem.childNodes,0)[0].nodeType}catch(e){slice=function(i){var elem,results=[];for(;elem=this[i];i++){results.push(elem)}return results}}function Sizzle(selector,context,results,seed){results=results||[];context=context||document;var match,elem,xml,m,nodeType=context.nodeType;if(!selector||typeof selector!=="string"){return results}if(nodeType!==1&&nodeType!==9){return[]}xml=isXML(context);if(!xml&&!seed){if(match=rquickExpr.exec(selector)){if(m=match[1]){if(nodeType===9){elem=context.getElementById(m);if(elem&&elem.parentNode){if(elem.id===m){results.push(elem);return results}}else{return results}}else{if(context.ownerDocument&&(elem=context.ownerDocument.getElementById(m))&&contains(context,elem)&&elem.id===m){results.push(elem);return results}}}else if(match[2]){push.apply(results,slice.call(context.getElementsByTagName(selector),0));return results}else if((m=match[3])&&assertUsableClassName&&context.getElementsByClassName){push.apply(results,slice.call(context.getElementsByClassName(m),0));return results}}}return select(selector.replace(rtrim,"$1"),context,results,seed,xml)}Sizzle.matches=function(expr,elements){return Sizzle(expr,null,null,elements)};Sizzle.matchesSelector=function(elem,expr){return Sizzle(expr,null,null,[elem]).length>0};function createInputPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type===type}}function createButtonPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&elem.type===type}}function createPositionalPseudo(fn){return markFunction(function(argument){argument=+argument;return markFunction(function(seed,matches){var j,matchIndexes=fn([],seed.length,argument),i=matchIndexes.length;while(i--){if(seed[j=matchIndexes[i]]){seed[j]=!(matches[j]=seed[j])}}})})}getText=Sizzle.getText=function(elem){var node,ret="",i=0,nodeType=elem.nodeType;if(nodeType){if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem)}}}else if(nodeType===3||nodeType===4){return elem.nodeValue}}else{for(;node=elem[i];i++){ret+=getText(node)}}return ret};isXML=Sizzle.isXML=function(elem){var documentElement=elem&&(elem.ownerDocument||elem).documentElement;return documentElement?documentElement.nodeName!=="HTML":false};contains=Sizzle.contains=docElem.contains?function(a,b){var adown=a.nodeType===9?a.documentElement:a,bup=b&&b.parentNode;return a===bup||!!(bup&&bup.nodeType===1&&adown.contains&&adown.contains(bup))}:docElem.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode){if(b===a){return true}}return false};Sizzle.attr=function(elem,name){var val,xml=isXML(elem);if(!xml){name=name.toLowerCase()}if(val=Expr.attrHandle[name]){return val(elem)}if(xml||assertAttributes){return elem.getAttribute(name)}val=elem.getAttributeNode(name);return val?typeof elem[name]==="boolean"?elem[name]?name:null:val.specified?val.value:null:null};Expr=Sizzle.selectors={cacheLength:50,createPseudo:markFunction,match:matchExpr,attrHandle:assertHrefNotNormalized?{}:{href:function(elem){return elem.getAttribute("href",2)},type:function(elem){return elem.getAttribute("type")}},find:{ID:assertGetIdNotName?function(id,context,xml){if(typeof context.getElementById!==strundefined&&!xml){var m=context.getElementById(id);return m&&m.parentNode?[m]:[]}}:function(id,context,xml){if(typeof context.getElementById!==strundefined&&!xml){var m=context.getElementById(id);return m?m.id===id||typeof m.getAttributeNode!==strundefined&&m.getAttributeNode("id").value===id?[m]:undefined:[]}},TAG:assertTagNameNoComments?function(tag,context){if(typeof context.getElementsByTagName!==strundefined){return context.getElementsByTagName(tag)}}:function(tag,context){var results=context.getElementsByTagName(tag);if(tag==="*"){var elem,tmp=[],i=0;for(;elem=results[i];i++){if(elem.nodeType===1){tmp.push(elem)}}return tmp}return results},NAME:assertUsableName&&function(tag,context){if(typeof context.getElementsByName!==strundefined){return context.getElementsByName(name)}},CLASS:assertUsableClassName&&function(className,context,xml){if(typeof context.getElementsByClassName!==strundefined&&!xml){return context.getElementsByClassName(className)}}},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(match){match[1]=match[1].replace(rbackslash,"");match[3]=(match[4]||match[5]||"").replace(rbackslash,"");if(match[2]==="~="){match[3]=" "+match[3]+" "}return match.slice(0,4)},CHILD:function(match){match[1]=match[1].toLowerCase();if(match[1]==="nth"){if(!match[2]){Sizzle.error(match[0])}match[3]=+(match[3]?match[4]+(match[5]||1):2*(match[2]==="even"||match[2]==="odd"));match[4]=+(match[6]+match[7]||match[2]==="odd")}else if(match[2]){Sizzle.error(match[0])}return match},PSEUDO:function(match){var unquoted,excess;if(matchExpr["CHILD"].test(match[0])){return null}if(match[3]){match[2]=match[3]}else if(unquoted=match[4]){if(rpseudo.test(unquoted)&&(excess=tokenize(unquoted,true))&&(excess=unquoted.indexOf(")",unquoted.length-excess)-unquoted.length)){unquoted=unquoted.slice(0,excess);match[0]=match[0].slice(0,excess)}match[2]=unquoted}return match.slice(0,3)}},filter:{ID:assertGetIdNotName?function(id){id=id.replace(rbackslash,"");return function(elem){return elem.getAttribute("id")===id}}:function(id){id=id.replace(rbackslash,"");return function(elem){var node=typeof elem.getAttributeNode!==strundefined&&elem.getAttributeNode("id");return node&&node.value===id}},TAG:function(nodeName){if(nodeName==="*"){return function(){return true}}nodeName=nodeName.replace(rbackslash,"").toLowerCase();return function(elem){return elem.nodeName&&elem.nodeName.toLowerCase()===nodeName}},CLASS:function(className){var pattern=classCache[expando][className+" "];return pattern||(pattern=new RegExp("(^|"+whitespace+")"+className+"("+whitespace+"|$)"))&&classCache(className,function(elem){return pattern.test(elem.className||typeof elem.getAttribute!==strundefined&&elem.getAttribute("class")||"")})},ATTR:function(name,operator,check){return function(elem,context){var result=Sizzle.attr(elem,name);if(result==null){return operator==="!="}if(!operator){return true}result+="";return operator==="="?result===check:operator==="!="?result!==check:operator==="^="?check&&result.indexOf(check)===0:operator==="*="?check&&result.indexOf(check)>-1:operator==="$="?check&&result.substr(result.length-check.length)===check:operator==="~="?(" "+result+" ").indexOf(check)>-1:operator==="|="?result===check||result.substr(0,check.length+1)===check+"-":false}},CHILD:function(type,argument,first,last){if(type==="nth"){return function(elem){var node,diff,parent=elem.parentNode;if(first===1&&last===0){return true}if(parent){diff=0;for(node=parent.firstChild;node;node=node.nextSibling){if(node.nodeType===1){diff++;
+if(elem===node){break}}}}diff-=last;return diff===first||diff%first===0&&diff/first>=0}}return function(elem){var node=elem;switch(type){case"only":case"first":while(node=node.previousSibling){if(node.nodeType===1){return false}}if(type==="first"){return true}node=elem;case"last":while(node=node.nextSibling){if(node.nodeType===1){return false}}return true}}},PSEUDO:function(pseudo,argument){var args,fn=Expr.pseudos[pseudo]||Expr.setFilters[pseudo.toLowerCase()]||Sizzle.error("unsupported pseudo: "+pseudo);if(fn[expando]){return fn(argument)}if(fn.length>1){args=[pseudo,pseudo,"",argument];return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase())?markFunction(function(seed,matches){var idx,matched=fn(seed,argument),i=matched.length;while(i--){idx=indexOf.call(seed,matched[i]);seed[idx]=!(matches[idx]=matched[i])}}):function(elem){return fn(elem,0,args)}}return fn}},pseudos:{not:markFunction(function(selector){var input=[],results=[],matcher=compile(selector.replace(rtrim,"$1"));return matcher[expando]?markFunction(function(seed,matches,context,xml){var elem,unmatched=matcher(seed,null,xml,[]),i=seed.length;while(i--){if(elem=unmatched[i]){seed[i]=!(matches[i]=elem)}}}):function(elem,context,xml){input[0]=elem;matcher(input,null,xml,results);return!results.pop()}}),has:markFunction(function(selector){return function(elem){return Sizzle(selector,elem).length>0}}),contains:markFunction(function(text){return function(elem){return(elem.textContent||elem.innerText||getText(elem)).indexOf(text)>-1}}),enabled:function(elem){return elem.disabled===false},disabled:function(elem){return elem.disabled===true},checked:function(elem){var nodeName=elem.nodeName.toLowerCase();return nodeName==="input"&&!!elem.checked||nodeName==="option"&&!!elem.selected},selected:function(elem){if(elem.parentNode){elem.parentNode.selectedIndex}return elem.selected===true},parent:function(elem){return!Expr.pseudos["empty"](elem)},empty:function(elem){var nodeType;elem=elem.firstChild;while(elem){if(elem.nodeName>"@"||(nodeType=elem.nodeType)===3||nodeType===4){return false}elem=elem.nextSibling}return true},header:function(elem){return rheader.test(elem.nodeName)},text:function(elem){var type,attr;return elem.nodeName.toLowerCase()==="input"&&(type=elem.type)==="text"&&((attr=elem.getAttribute("type"))==null||attr.toLowerCase()===type)},radio:createInputPseudo("radio"),checkbox:createInputPseudo("checkbox"),file:createInputPseudo("file"),password:createInputPseudo("password"),image:createInputPseudo("image"),submit:createButtonPseudo("submit"),reset:createButtonPseudo("reset"),button:function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type==="button"||name==="button"},input:function(elem){return rinputs.test(elem.nodeName)},focus:function(elem){var doc=elem.ownerDocument;return elem===doc.activeElement&&(!doc.hasFocus||doc.hasFocus())&&!!(elem.type||elem.href||~elem.tabIndex)},active:function(elem){return elem===elem.ownerDocument.activeElement},first:createPositionalPseudo(function(){return[0]}),last:createPositionalPseudo(function(matchIndexes,length){return[length-1]}),eq:createPositionalPseudo(function(matchIndexes,length,argument){return[argument<0?argument+length:argument]}),even:createPositionalPseudo(function(matchIndexes,length){for(var i=0;i<length;i+=2){matchIndexes.push(i)}return matchIndexes}),odd:createPositionalPseudo(function(matchIndexes,length){for(var i=1;i<length;i+=2){matchIndexes.push(i)}return matchIndexes}),lt:createPositionalPseudo(function(matchIndexes,length,argument){for(var i=argument<0?argument+length:argument;--i>=0;){matchIndexes.push(i)}return matchIndexes}),gt:createPositionalPseudo(function(matchIndexes,length,argument){for(var i=argument<0?argument+length:argument;++i<length;){matchIndexes.push(i)}return matchIndexes})}};function siblingCheck(a,b,ret){if(a===b){return ret}var cur=a.nextSibling;while(cur){if(cur===b){return-1}cur=cur.nextSibling}return 1}sortOrder=docElem.compareDocumentPosition?function(a,b){if(a===b){hasDuplicate=true;return 0}return(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b){hasDuplicate=true;return 0}else if(a.sourceIndex&&b.sourceIndex){return a.sourceIndex-b.sourceIndex}var al,bl,ap=[],bp=[],aup=a.parentNode,bup=b.parentNode,cur=aup;if(aup===bup){return siblingCheck(a,b)}else if(!aup){return-1}else if(!bup){return 1}while(cur){ap.unshift(cur);cur=cur.parentNode}cur=bup;while(cur){bp.unshift(cur);cur=cur.parentNode}al=ap.length;bl=bp.length;for(var i=0;i<al&&i<bl;i++){if(ap[i]!==bp[i]){return siblingCheck(ap[i],bp[i])}}return i===al?siblingCheck(a,bp[i],-1):siblingCheck(ap[i],b,1)};[0,0].sort(sortOrder);baseHasDuplicate=!hasDuplicate;Sizzle.uniqueSort=function(results){var elem,duplicates=[],i=1,j=0;hasDuplicate=baseHasDuplicate;results.sort(sortOrder);if(hasDuplicate){for(;elem=results[i];i++){if(elem===results[i-1]){j=duplicates.push(i)}}while(j--){results.splice(duplicates[j],1)}}return results};Sizzle.error=function(msg){throw new Error("Syntax error, unrecognized expression: "+msg)};function tokenize(selector,parseOnly){var matched,match,tokens,type,soFar,groups,preFilters,cached=tokenCache[expando][selector+" "];if(cached){return parseOnly?0:cached.slice(0)}soFar=selector;groups=[];preFilters=Expr.preFilter;while(soFar){if(!matched||(match=rcomma.exec(soFar))){if(match){soFar=soFar.slice(match[0].length)||soFar}groups.push(tokens=[])}matched=false;if(match=rcombinators.exec(soFar)){tokens.push(matched=new Token(match.shift()));soFar=soFar.slice(matched.length);matched.type=match[0].replace(rtrim," ")}for(type in Expr.filter){if((match=matchExpr[type].exec(soFar))&&(!preFilters[type]||(match=preFilters[type](match)))){tokens.push(matched=new Token(match.shift()));soFar=soFar.slice(matched.length);matched.type=type;matched.matches=match}}if(!matched){break}}return parseOnly?soFar.length:soFar?Sizzle.error(selector):tokenCache(selector,groups).slice(0)}function addCombinator(matcher,combinator,base){var dir=combinator.dir,checkNonElements=base&&combinator.dir==="parentNode",doneName=done++;return combinator.first?function(elem,context,xml){while(elem=elem[dir]){if(checkNonElements||elem.nodeType===1){return matcher(elem,context,xml)}}}:function(elem,context,xml){if(!xml){var cache,dirkey=dirruns+" "+doneName+" ",cachedkey=dirkey+cachedruns;while(elem=elem[dir]){if(checkNonElements||elem.nodeType===1){if((cache=elem[expando])===cachedkey){return elem.sizset}else if(typeof cache==="string"&&cache.indexOf(dirkey)===0){if(elem.sizset){return elem}}else{elem[expando]=cachedkey;if(matcher(elem,context,xml)){elem.sizset=true;return elem}elem.sizset=false}}}}else{while(elem=elem[dir]){if(checkNonElements||elem.nodeType===1){if(matcher(elem,context,xml)){return elem}}}}}}function elementMatcher(matchers){return matchers.length>1?function(elem,context,xml){var i=matchers.length;while(i--){if(!matchers[i](elem,context,xml)){return false}}return true}:matchers[0]}function condense(unmatched,map,filter,context,xml){var elem,newUnmatched=[],i=0,len=unmatched.length,mapped=map!=null;for(;i<len;i++){if(elem=unmatched[i]){if(!filter||filter(elem,context,xml)){newUnmatched.push(elem);if(mapped){map.push(i)}}}}return newUnmatched}function setMatcher(preFilter,selector,matcher,postFilter,postFinder,postSelector){if(postFilter&&!postFilter[expando]){postFilter=setMatcher(postFilter)}if(postFinder&&!postFinder[expando]){postFinder=setMatcher(postFinder,postSelector)}return markFunction(function(seed,results,context,xml){var temp,i,elem,preMap=[],postMap=[],preexisting=results.length,elems=seed||multipleContexts(selector||"*",context.nodeType?[context]:context,[]),matcherIn=preFilter&&(seed||!selector)?condense(elems,preMap,preFilter,context,xml):elems,matcherOut=matcher?postFinder||(seed?preFilter:preexisting||postFilter)?[]:results:matcherIn;if(matcher){matcher(matcherIn,matcherOut,context,xml)}if(postFilter){temp=condense(matcherOut,postMap);postFilter(temp,[],context,xml);i=temp.length;while(i--){if(elem=temp[i]){matcherOut[postMap[i]]=!(matcherIn[postMap[i]]=elem)}}}if(seed){if(postFinder||preFilter){if(postFinder){temp=[];i=matcherOut.length;while(i--){if(elem=matcherOut[i]){temp.push(matcherIn[i]=elem)}}postFinder(null,matcherOut=[],temp,xml)}i=matcherOut.length;while(i--){if((elem=matcherOut[i])&&(temp=postFinder?indexOf.call(seed,elem):preMap[i])>-1){seed[temp]=!(results[temp]=elem)}}}}else{matcherOut=condense(matcherOut===results?matcherOut.splice(preexisting,matcherOut.length):matcherOut);if(postFinder){postFinder(null,results,matcherOut,xml)}else{push.apply(results,matcherOut)}}})}function matcherFromTokens(tokens){var checkContext,matcher,j,len=tokens.length,leadingRelative=Expr.relative[tokens[0].type],implicitRelative=leadingRelative||Expr.relative[" "],i=leadingRelative?1:0,matchContext=addCombinator(function(elem){return elem===checkContext},implicitRelative,true),matchAnyContext=addCombinator(function(elem){return indexOf.call(checkContext,elem)>-1},implicitRelative,true),matchers=[function(elem,context,xml){return!leadingRelative&&(xml||context!==outermostContext)||((checkContext=context).nodeType?matchContext(elem,context,xml):matchAnyContext(elem,context,xml))}];for(;i<len;i++){if(matcher=Expr.relative[tokens[i].type]){matchers=[addCombinator(elementMatcher(matchers),matcher)]}else{matcher=Expr.filter[tokens[i].type].apply(null,tokens[i].matches);if(matcher[expando]){j=++i;for(;j<len;j++){if(Expr.relative[tokens[j].type]){break}}return setMatcher(i>1&&elementMatcher(matchers),i>1&&tokens.slice(0,i-1).join("").replace(rtrim,"$1"),matcher,i<j&&matcherFromTokens(tokens.slice(i,j)),j<len&&matcherFromTokens(tokens=tokens.slice(j)),j<len&&tokens.join(""))}matchers.push(matcher)}}return elementMatcher(matchers)}function matcherFromGroupMatchers(elementMatchers,setMatchers){var bySet=setMatchers.length>0,byElement=elementMatchers.length>0,superMatcher=function(seed,context,xml,results,expandContext){var elem,j,matcher,setMatched=[],matchedCount=0,i="0",unmatched=seed&&[],outermost=expandContext!=null,contextBackup=outermostContext,elems=seed||byElement&&Expr.find["TAG"]("*",expandContext&&context.parentNode||context),dirrunsUnique=dirruns+=contextBackup==null?1:Math.E;if(outermost){outermostContext=context!==document&&context;cachedruns=superMatcher.el}for(;(elem=elems[i])!=null;i++){if(byElement&&elem){for(j=0;matcher=elementMatchers[j];j++){if(matcher(elem,context,xml)){results.push(elem);break}}if(outermost){dirruns=dirrunsUnique;cachedruns=++superMatcher.el}}if(bySet){if(elem=!matcher&&elem){matchedCount--}if(seed){unmatched.push(elem)}}}matchedCount+=i;if(bySet&&i!==matchedCount){for(j=0;matcher=setMatchers[j];j++){matcher(unmatched,setMatched,context,xml)}if(seed){if(matchedCount>0){while(i--){if(!(unmatched[i]||setMatched[i])){setMatched[i]=pop.call(results)}}}setMatched=condense(setMatched)}push.apply(results,setMatched);if(outermost&&!seed&&setMatched.length>0&&matchedCount+setMatchers.length>1){Sizzle.uniqueSort(results)}}if(outermost){dirruns=dirrunsUnique;outermostContext=contextBackup}return unmatched};superMatcher.el=0;return bySet?markFunction(superMatcher):superMatcher}compile=Sizzle.compile=function(selector,group){var i,setMatchers=[],elementMatchers=[],cached=compilerCache[expando][selector+" "];if(!cached){if(!group){group=tokenize(selector)}i=group.length;while(i--){cached=matcherFromTokens(group[i]);if(cached[expando]){setMatchers.push(cached)}else{elementMatchers.push(cached)}}cached=compilerCache(selector,matcherFromGroupMatchers(elementMatchers,setMatchers))}return cached};function multipleContexts(selector,contexts,results){var i=0,len=contexts.length;for(;i<len;i++){Sizzle(selector,contexts[i],results)}return results}function select(selector,context,results,seed,xml){var i,tokens,token,type,find,match=tokenize(selector),j=match.length;if(!seed){if(match.length===1){tokens=match[0]=match[0].slice(0);if(tokens.length>2&&(token=tokens[0]).type==="ID"&&context.nodeType===9&&!xml&&Expr.relative[tokens[1].type]){context=Expr.find["ID"](token.matches[0].replace(rbackslash,""),context,xml)[0];if(!context){return results}selector=selector.slice(tokens.shift().length)}for(i=matchExpr["POS"].test(selector)?-1:tokens.length-1;i>=0;i--){token=tokens[i];if(Expr.relative[type=token.type]){break}if(find=Expr.find[type]){if(seed=find(token.matches[0].replace(rbackslash,""),rsibling.test(tokens[0].type)&&context.parentNode||context,xml)){tokens.splice(i,1);selector=seed.length&&tokens.join("");if(!selector){push.apply(results,slice.call(seed,0));return results}break}}}}}compile(selector,match)(seed,context,xml,results,rsibling.test(selector));return results}if(document.querySelectorAll){(function(){var disconnectedMatch,oldSelect=select,rescape=/'|\\/g,rattributeQuotes=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,rbuggyQSA=[":focus"],rbuggyMatches=[":active"],matches=docElem.matchesSelector||docElem.mozMatchesSelector||docElem.webkitMatchesSelector||docElem.oMatchesSelector||docElem.msMatchesSelector;assert(function(div){div.innerHTML="<select><option selected=''></option></select>";if(!div.querySelectorAll("[selected]").length){rbuggyQSA.push("\\["+whitespace+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)")}if(!div.querySelectorAll(":checked").length){rbuggyQSA.push(":checked")}});assert(function(div){div.innerHTML="<p test=''></p>";if(div.querySelectorAll("[test^='']").length){rbuggyQSA.push("[*^$]="+whitespace+"*(?:\"\"|'')")}div.innerHTML="<input type='hidden'/>";if(!div.querySelectorAll(":enabled").length){rbuggyQSA.push(":enabled",":disabled")}});rbuggyQSA=new RegExp(rbuggyQSA.join("|"));select=function(selector,context,results,seed,xml){if(!seed&&!xml&&!rbuggyQSA.test(selector)){var groups,i,old=true,nid=expando,newContext=context,newSelector=context.nodeType===9&&selector;if(context.nodeType===1&&context.nodeName.toLowerCase()!=="object"){groups=tokenize(selector);if(old=context.getAttribute("id")){nid=old.replace(rescape,"\\$&")}else{context.setAttribute("id",nid)}nid="[id='"+nid+"'] ";i=groups.length;while(i--){groups[i]=nid+groups[i].join("")}newContext=rsibling.test(selector)&&context.parentNode||context;newSelector=groups.join(",")}if(newSelector){try{push.apply(results,slice.call(newContext.querySelectorAll(newSelector),0));return results}catch(qsaError){}finally{if(!old){context.removeAttribute("id")}}}}return oldSelect(selector,context,results,seed,xml)};if(matches){assert(function(div){disconnectedMatch=matches.call(div,"div");try{matches.call(div,"[test!='']:sizzle");rbuggyMatches.push("!=",pseudos)}catch(e){}});rbuggyMatches=new RegExp(rbuggyMatches.join("|"));Sizzle.matchesSelector=function(elem,expr){expr=expr.replace(rattributeQuotes,"='$1']");if(!isXML(elem)&&!rbuggyMatches.test(expr)&&!rbuggyQSA.test(expr)){try{var ret=matches.call(elem,expr);if(ret||disconnectedMatch||elem.document&&elem.document.nodeType!==11){return ret}}catch(e){}}return Sizzle(expr,null,null,[elem]).length>0}}})()}Expr.pseudos["nth"]=Expr.pseudos["eq"];function setFilters(){}Expr.filters=setFilters.prototype=Expr.pseudos;Expr.setFilters=new setFilters;Sizzle.attr=jQuery.attr;jQuery.find=Sizzle;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.pseudos;jQuery.unique=Sizzle.uniqueSort;jQuery.text=Sizzle.getText;jQuery.isXMLDoc=Sizzle.isXML;jQuery.contains=Sizzle.contains})(window);var runtil=/Until$/,rparentsprev=/^(?:parents|prev(?:Until|All))/,isSimple=/^.[^:#\[\.,]*$/,rneedsContext=jQuery.expr.match.needsContext,guaranteedUnique={children:true,contents:true,next:true,prev:true};jQuery.fn.extend({find:function(selector){var i,l,length,n,r,ret,self=this;if(typeof selector!=="string"){return jQuery(selector).filter(function(){for(i=0,l=self.length;i<l;i++){if(jQuery.contains(self[i],this)){return true}}})}ret=this.pushStack("","find",selector);for(i=0,l=this.length;i<l;i++){length=ret.length;jQuery.find(selector,this[i],ret);if(i>0){for(n=length;n<ret.length;n++){for(r=0;r<length;r++){if(ret[r]===ret[n]){ret.splice(n--,1);break}}}}}return ret},has:function(target){var i,targets=jQuery(target,this),len=targets.length;return this.filter(function(){for(i=0;i<len;i++){if(jQuery.contains(this,targets[i])){return true}}})},not:function(selector){return this.pushStack(winnow(this,selector,false),"not",selector)},filter:function(selector){return this.pushStack(winnow(this,selector,true),"filter",selector)},is:function(selector){return!!selector&&(typeof selector==="string"?rneedsContext.test(selector)?jQuery(selector,this.context).index(this[0])>=0:jQuery.filter(selector,this).length>0:this.filter(selector).length>0)},closest:function(selectors,context){var cur,i=0,l=this.length,ret=[],pos=rneedsContext.test(selectors)||typeof selectors!=="string"?jQuery(selectors,context||this.context):0;for(;i<l;i++){cur=this[i];while(cur&&cur.ownerDocument&&cur!==context&&cur.nodeType!==11){if(pos?pos.index(cur)>-1:jQuery.find.matchesSelector(cur,selectors)){ret.push(cur);break}cur=cur.parentNode}}ret=ret.length>1?jQuery.unique(ret):ret;return this.pushStack(ret,"closest",selectors)},index:function(elem){if(!elem){return this[0]&&this[0].parentNode?this.prevAll().length:-1}if(typeof elem==="string"){return jQuery.inArray(this[0],jQuery(elem))}return jQuery.inArray(elem.jquery?elem[0]:elem,this)},add:function(selector,context){var set=typeof selector==="string"?jQuery(selector,context):jQuery.makeArray(selector&&selector.nodeType?[selector]:selector),all=jQuery.merge(this.get(),set);return this.pushStack(isDisconnected(set[0])||isDisconnected(all[0])?all:jQuery.unique(all))},addBack:function(selector){return this.add(selector==null?this.prevObject:this.prevObject.filter(selector))}});jQuery.fn.andSelf=jQuery.fn.addBack;function isDisconnected(node){return!node||!node.parentNode||node.parentNode.nodeType===11}function sibling(cur,dir){do{cur=cur[dir]}while(cur&&cur.nodeType!==1);return cur}jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null},parents:function(elem){return jQuery.dir(elem,"parentNode")},parentsUntil:function(elem,i,until){return jQuery.dir(elem,"parentNode",until)},next:function(elem){return sibling(elem,"nextSibling")},prev:function(elem){return sibling(elem,"previousSibling")},nextAll:function(elem){return jQuery.dir(elem,"nextSibling")},prevAll:function(elem){return jQuery.dir(elem,"previousSibling")},nextUntil:function(elem,i,until){return jQuery.dir(elem,"nextSibling",until)},prevUntil:function(elem,i,until){return jQuery.dir(elem,"previousSibling",until)},siblings:function(elem){return jQuery.sibling((elem.parentNode||{}).firstChild,elem)},children:function(elem){return jQuery.sibling(elem.firstChild)},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.merge([],elem.childNodes)}},function(name,fn){jQuery.fn[name]=function(until,selector){var ret=jQuery.map(this,fn,until);if(!runtil.test(name)){selector=until}if(selector&&typeof selector==="string"){ret=jQuery.filter(selector,ret)}ret=this.length>1&&!guaranteedUnique[name]?jQuery.unique(ret):ret;if(this.length>1&&rparentsprev.test(name)){ret=ret.reverse()}return this.pushStack(ret,name,core_slice.call(arguments).join(","))}});jQuery.extend({filter:function(expr,elems,not){if(not){expr=":not("+expr+")"}return elems.length===1?jQuery.find.matchesSelector(elems[0],expr)?[elems[0]]:[]:jQuery.find.matches(expr,elems)},dir:function(elem,dir,until){var matched=[],cur=elem[dir];while(cur&&cur.nodeType!==9&&(until===undefined||cur.nodeType!==1||!jQuery(cur).is(until))){if(cur.nodeType===1){matched.push(cur)}cur=cur[dir]}return matched},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){r.push(n)}}return r}});function winnow(elements,qualifier,keep){qualifier=qualifier||0;if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){var retVal=!!qualifier.call(elem,i,elem);return retVal===keep})}else if(qualifier.nodeType){return jQuery.grep(elements,function(elem,i){return elem===qualifier===keep})}else if(typeof qualifier==="string"){var filtered=jQuery.grep(elements,function(elem){return elem.nodeType===1});if(isSimple.test(qualifier)){return jQuery.filter(qualifier,filtered,!keep)}else{qualifier=jQuery.filter(qualifier,filtered)}}return jQuery.grep(elements,function(elem,i){return jQuery.inArray(elem,qualifier)>=0===keep})}function createSafeFragment(document){var list=nodeNames.split("|"),safeFrag=document.createDocumentFragment();if(safeFrag.createElement){while(list.length){safeFrag.createElement(list.pop())}}return safeFrag}var nodeNames="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|"+"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",rinlinejQuery=/ jQuery\d+="(?:null|\d+)"/g,rleadingWhitespace=/^\s+/,rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,rtagName=/<([\w:]+)/,rtbody=/<tbody/i,rhtml=/<|&#?\w+;/,rnoInnerhtml=/<(?:script|style|link)/i,rnocache=/<(?:script|object|embed|option|style)/i,rnoshimcache=new RegExp("<(?:"+nodeNames+")[\\s/>]","i"),rcheckableType=/^(?:checkbox|radio)$/,rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/\/(java|ecma)script/i,rcleanScript=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,wrapMap={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},safeFragment=createSafeFragment(document),fragmentDiv=safeFragment.appendChild(document.createElement("div"));wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;if(!jQuery.support.htmlSerialize){wrapMap._default=[1,"X<div>","</div>"]}jQuery.fn.extend({text:function(value){return jQuery.access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value))},null,value,arguments.length)},wrapAll:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapAll(html.call(this,i))})}if(this[0]){var wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0])}wrap.map(function(){var elem=this;while(elem.firstChild&&elem.firstChild.nodeType===1){elem=elem.firstChild}return elem}).append(this)}return this},wrapInner:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i))})}return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html)}else{self.append(html)}})},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html)})},unwrap:function(){return this.parent().each(function(){if(!jQuery.nodeName(this,"body")){jQuery(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType===1||this.nodeType===11){this.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType===1||this.nodeType===11){this.insertBefore(elem,this.firstChild)}})},before:function(){if(!isDisconnected(this[0])){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this)})}if(arguments.length){var set=jQuery.clean(arguments);return this.pushStack(jQuery.merge(set,this),"before",this.selector)}},after:function(){if(!isDisconnected(this[0])){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this.nextSibling)})}if(arguments.length){var set=jQuery.clean(arguments);return this.pushStack(jQuery.merge(this,set),"after",this.selector)}},remove:function(selector,keepData){var elem,i=0;for(;(elem=this[i])!=null;i++){if(!selector||jQuery.filter(selector,[elem]).length){if(!keepData&&elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"));jQuery.cleanData([elem])}if(elem.parentNode){elem.parentNode.removeChild(elem)}}}return this},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"))}while(elem.firstChild){elem.removeChild(elem.firstChild)}}return this},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents)})},html:function(value){return jQuery.access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined){return elem.nodeType===1?elem.innerHTML.replace(rinlinejQuery,""):undefined}if(typeof value==="string"&&!rnoInnerhtml.test(value)&&(jQuery.support.htmlSerialize||!rnoshimcache.test(value))&&(jQuery.support.leadingWhitespace||!rleadingWhitespace.test(value))&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1></$2>");try{for(;i<l;i++){elem=this[i]||{};if(elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"));elem.innerHTML=value}}elem=0}catch(e){}}if(elem){this.empty().append(value)}},null,value,arguments.length)},replaceWith:function(value){if(!isDisconnected(this[0])){if(jQuery.isFunction(value)){return this.each(function(i){var self=jQuery(this),old=self.html();self.replaceWith(value.call(this,i,old))})}if(typeof value!=="string"){value=jQuery(value).detach()}return this.each(function(){var next=this.nextSibling,parent=this.parentNode;jQuery(this).remove();if(next){jQuery(next).before(value)}else{jQuery(parent).append(value)}})}return this.length?this.pushStack(jQuery(jQuery.isFunction(value)?value():value),"replaceWith",value):this},detach:function(selector){return this.remove(selector,true)},domManip:function(args,table,callback){args=[].concat.apply([],args);var results,first,fragment,iNoClone,i=0,value=args[0],scripts=[],l=this.length;if(!jQuery.support.checkClone&&l>1&&typeof value==="string"&&rchecked.test(value)){return this.each(function(){jQuery(this).domManip(args,table,callback)})}if(jQuery.isFunction(value)){return this.each(function(i){var self=jQuery(this);args[0]=value.call(this,i,table?self.html():undefined);self.domManip(args,table,callback)})}if(this[0]){results=jQuery.buildFragment(args,this,scripts);fragment=results.fragment;first=fragment.firstChild;if(fragment.childNodes.length===1){fragment=first}if(first){table=table&&jQuery.nodeName(first,"tr");for(iNoClone=results.cacheable||l-1;i<l;i++){callback.call(table&&jQuery.nodeName(this[i],"table")?findOrAppend(this[i],"tbody"):this[i],i===iNoClone?fragment:jQuery.clone(fragment,true,true))}}fragment=first=null;if(scripts.length){jQuery.each(scripts,function(i,elem){if(elem.src){if(jQuery.ajax){jQuery.ajax({url:elem.src,type:"GET",dataType:"script",async:false,global:false,"throws":true})}else{jQuery.error("no ajax")}}else{jQuery.globalEval((elem.text||elem.textContent||elem.innerHTML||"").replace(rcleanScript,""))}if(elem.parentNode){elem.parentNode.removeChild(elem)}})}}return this}});function findOrAppend(elem,tag){return elem.getElementsByTagName(tag)[0]||elem.appendChild(elem.ownerDocument.createElement(tag))}function cloneCopyEvent(src,dest){if(dest.nodeType!==1||!jQuery.hasData(src)){return}var type,i,l,oldData=jQuery._data(src),curData=jQuery._data(dest,oldData),events=oldData.events;if(events){delete curData.handle;curData.events={};for(type in events){for(i=0,l=events[type].length;i<l;i++){jQuery.event.add(dest,type,events[type][i])}}}if(curData.data){curData.data=jQuery.extend({},curData.data)}}function cloneFixAttributes(src,dest){var nodeName;if(dest.nodeType!==1){return}if(dest.clearAttributes){dest.clearAttributes()}if(dest.mergeAttributes){dest.mergeAttributes(src)}nodeName=dest.nodeName.toLowerCase();if(nodeName==="object"){if(dest.parentNode){dest.outerHTML=src.outerHTML}if(jQuery.support.html5Clone&&(src.innerHTML&&!jQuery.trim(dest.innerHTML))){dest.innerHTML=src.innerHTML}}else if(nodeName==="input"&&rcheckableType.test(src.type)){dest.defaultChecked=dest.checked=src.checked;if(dest.value!==src.value){dest.value=src.value}}else if(nodeName==="option"){dest.selected=src.defaultSelected}else if(nodeName==="input"||nodeName==="textarea"){dest.defaultValue=src.defaultValue}else if(nodeName==="script"&&dest.text!==src.text){dest.text=src.text}dest.removeAttribute(jQuery.expando)}jQuery.buildFragment=function(args,context,scripts){var fragment,cacheable,cachehit,first=args[0];context=context||document;context=!context.nodeType&&context[0]||context;context=context.ownerDocument||context;if(args.length===1&&typeof first==="string"&&first.length<512&&context===document&&first.charAt(0)==="<"&&!rnocache.test(first)&&(jQuery.support.checkClone||!rchecked.test(first))&&(jQuery.support.html5Clone||!rnoshimcache.test(first))){cacheable=true;fragment=jQuery.fragments[first];cachehit=fragment!==undefined}if(!fragment){fragment=context.createDocumentFragment();jQuery.clean(args,context,fragment,scripts);if(cacheable){jQuery.fragments[first]=cachehit&&fragment}}return{fragment:fragment,cacheable:cacheable}};jQuery.fragments={};jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(selector){var elems,i=0,ret=[],insert=jQuery(selector),l=insert.length,parent=this.length===1&&this[0].parentNode;if((parent==null||parent&&parent.nodeType===11&&parent.childNodes.length===1)&&l===1){insert[original](this[0]);return this}else{for(;i<l;i++){elems=(i>0?this.clone(true):this).get();jQuery(insert[i])[original](elems);ret=ret.concat(elems)}return this.pushStack(ret,name,insert.selector)}}});function getAll(elem){if(typeof elem.getElementsByTagName!=="undefined"){return elem.getElementsByTagName("*")}else if(typeof elem.querySelectorAll!=="undefined"){return elem.querySelectorAll("*")}else{return[]}}function fixDefaultChecked(elem){if(rcheckableType.test(elem.type)){elem.defaultChecked=elem.checked}}jQuery.extend({clone:function(elem,dataAndEvents,deepDataAndEvents){var srcElements,destElements,i,clone;if(jQuery.support.html5Clone||jQuery.isXMLDoc(elem)||!rnoshimcache.test("<"+elem.nodeName+">")){clone=elem.cloneNode(true)}else{fragmentDiv.innerHTML=elem.outerHTML;fragmentDiv.removeChild(clone=fragmentDiv.firstChild)}if((!jQuery.support.noCloneEvent||!jQuery.support.noCloneChecked)&&(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){cloneFixAttributes(elem,clone);srcElements=getAll(elem);destElements=getAll(clone);for(i=0;srcElements[i];++i){if(destElements[i]){cloneFixAttributes(srcElements[i],destElements[i])}}}if(dataAndEvents){cloneCopyEvent(elem,clone);if(deepDataAndEvents){srcElements=getAll(elem);destElements=getAll(clone);for(i=0;srcElements[i];++i){cloneCopyEvent(srcElements[i],destElements[i])}}}srcElements=destElements=null;return clone},clean:function(elems,context,fragment,scripts){var i,j,elem,tag,wrap,depth,div,hasBody,tbody,len,handleScript,jsTags,safe=context===document&&safeFragment,ret=[];if(!context||typeof context.createDocumentFragment==="undefined"){context=document}for(i=0;(elem=elems[i])!=null;i++){if(typeof elem==="number"){elem+=""}if(!elem){continue}if(typeof elem==="string"){if(!rhtml.test(elem)){elem=context.createTextNode(elem)}else{safe=safe||createSafeFragment(context);div=context.createElement("div");safe.appendChild(div);elem=elem.replace(rxhtmlTag,"<$1></$2>");tag=(rtagName.exec(elem)||["",""])[1].toLowerCase();wrap=wrapMap[tag]||wrapMap._default;depth=wrap[0];div.innerHTML=wrap[1]+elem+wrap[2];while(depth--){div=div.lastChild
+}if(!jQuery.support.tbody){hasBody=rtbody.test(elem);tbody=tag==="table"&&!hasBody?div.firstChild&&div.firstChild.childNodes:wrap[1]==="<table>"&&!hasBody?div.childNodes:[];for(j=tbody.length-1;j>=0;--j){if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length){tbody[j].parentNode.removeChild(tbody[j])}}}if(!jQuery.support.leadingWhitespace&&rleadingWhitespace.test(elem)){div.insertBefore(context.createTextNode(rleadingWhitespace.exec(elem)[0]),div.firstChild)}elem=div.childNodes;div.parentNode.removeChild(div)}}if(elem.nodeType){ret.push(elem)}else{jQuery.merge(ret,elem)}}if(div){elem=div=safe=null}if(!jQuery.support.appendChecked){for(i=0;(elem=ret[i])!=null;i++){if(jQuery.nodeName(elem,"input")){fixDefaultChecked(elem)}else if(typeof elem.getElementsByTagName!=="undefined"){jQuery.grep(elem.getElementsByTagName("input"),fixDefaultChecked)}}}if(fragment){handleScript=function(elem){if(!elem.type||rscriptType.test(elem.type)){return scripts?scripts.push(elem.parentNode?elem.parentNode.removeChild(elem):elem):fragment.appendChild(elem)}};for(i=0;(elem=ret[i])!=null;i++){if(!(jQuery.nodeName(elem,"script")&&handleScript(elem))){fragment.appendChild(elem);if(typeof elem.getElementsByTagName!=="undefined"){jsTags=jQuery.grep(jQuery.merge([],elem.getElementsByTagName("script")),handleScript);ret.splice.apply(ret,[i+1,0].concat(jsTags));i+=jsTags.length}}}}return ret},cleanData:function(elems,acceptData){var data,id,elem,type,i=0,internalKey=jQuery.expando,cache=jQuery.cache,deleteExpando=jQuery.support.deleteExpando,special=jQuery.event.special;for(;(elem=elems[i])!=null;i++){if(acceptData||jQuery.acceptData(elem)){id=elem[internalKey];data=id&&cache[id];if(data){if(data.events){for(type in data.events){if(special[type]){jQuery.event.remove(elem,type)}else{jQuery.removeEvent(elem,type,data.handle)}}}if(cache[id]){delete cache[id];if(deleteExpando){delete elem[internalKey]}else if(elem.removeAttribute){elem.removeAttribute(internalKey)}else{elem[internalKey]=null}jQuery.deletedIds.push(id)}}}}}});(function(){var matched,browser;jQuery.uaMatch=function(ua){ua=ua.toLowerCase();var match=/(chrome)[ \/]([\w.]+)/.exec(ua)||/(webkit)[ \/]([\w.]+)/.exec(ua)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua)||/(msie) ([\w.]+)/.exec(ua)||ua.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)||[];return{browser:match[1]||"",version:match[2]||"0"}};matched=jQuery.uaMatch(navigator.userAgent);browser={};if(matched.browser){browser[matched.browser]=true;browser.version=matched.version}if(browser.chrome){browser.webkit=true}else if(browser.webkit){browser.safari=true}jQuery.browser=browser;jQuery.sub=function(){function jQuerySub(selector,context){return new jQuerySub.fn.init(selector,context)}jQuery.extend(true,jQuerySub,this);jQuerySub.superclass=this;jQuerySub.fn=jQuerySub.prototype=this();jQuerySub.fn.constructor=jQuerySub;jQuerySub.sub=this.sub;jQuerySub.fn.init=function init(selector,context){if(context&&context instanceof jQuery&&!(context instanceof jQuerySub)){context=jQuerySub(context)}return jQuery.fn.init.call(this,selector,context,rootjQuerySub)};jQuerySub.fn.init.prototype=jQuerySub.fn;var rootjQuerySub=jQuerySub(document);return jQuerySub}})();var curCSS,iframe,iframeDoc,ralpha=/alpha\([^)]*\)/i,ropacity=/opacity=([^)]*)/,rposition=/^(top|right|bottom|left)$/,rdisplayswap=/^(none|table(?!-c[ea]).+)/,rmargin=/^margin/,rnumsplit=new RegExp("^("+core_pnum+")(.*)$","i"),rnumnonpx=new RegExp("^("+core_pnum+")(?!px)[a-z%]+$","i"),rrelNum=new RegExp("^([-+])=("+core_pnum+")","i"),elemdisplay={BODY:"block"},cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:0,fontWeight:400},cssExpand=["Top","Right","Bottom","Left"],cssPrefixes=["Webkit","O","Moz","ms"],eventsToggle=jQuery.fn.toggle;function vendorPropName(style,name){if(name in style){return name}var capName=name.charAt(0).toUpperCase()+name.slice(1),origName=name,i=cssPrefixes.length;while(i--){name=cssPrefixes[i]+capName;if(name in style){return name}}return origName}function isHidden(elem,el){elem=el||elem;return jQuery.css(elem,"display")==="none"||!jQuery.contains(elem.ownerDocument,elem)}function showHide(elements,show){var elem,display,values=[],index=0,length=elements.length;for(;index<length;index++){elem=elements[index];if(!elem.style){continue}values[index]=jQuery._data(elem,"olddisplay");if(show){if(!values[index]&&elem.style.display==="none"){elem.style.display=""}if(elem.style.display===""&&isHidden(elem)){values[index]=jQuery._data(elem,"olddisplay",css_defaultDisplay(elem.nodeName))}}else{display=curCSS(elem,"display");if(!values[index]&&display!=="none"){jQuery._data(elem,"olddisplay",display)}}}for(index=0;index<length;index++){elem=elements[index];if(!elem.style){continue}if(!show||elem.style.display==="none"||elem.style.display===""){elem.style.display=show?values[index]||"":"none"}}return elements}jQuery.fn.extend({css:function(name,value){return jQuery.access(this,function(elem,name,value){return value!==undefined?jQuery.style(elem,name,value):jQuery.css(elem,name)},name,value,arguments.length>1)},show:function(){return showHide(this,true)},hide:function(){return showHide(this)},toggle:function(state,fn2){var bool=typeof state==="boolean";if(jQuery.isFunction(state)&&jQuery.isFunction(fn2)){return eventsToggle.apply(this,arguments)}return this.each(function(){if(bool?state:isHidden(this)){jQuery(this).show()}else{jQuery(this).hide()}})}});jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return ret===""?"1":ret}}}},cssNumber:{fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":jQuery.support.cssFloat?"cssFloat":"styleFloat"},style:function(elem,name,value,extra){if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){return}var ret,type,hooks,origName=jQuery.camelCase(name),style=elem.style;name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(value!==undefined){type=typeof value;if(type==="string"&&(ret=rrelNum.exec(value))){value=(ret[1]+1)*ret[2]+parseFloat(jQuery.css(elem,name));type="number"}if(value==null||type==="number"&&isNaN(value)){return}if(type==="number"&&!jQuery.cssNumber[origName]){value+="px"}if(!hooks||!("set"in hooks)||(value=hooks.set(elem,value,extra))!==undefined){try{style[name]=value}catch(e){}}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){return ret}return style[name]}},css:function(elem,name,numeric,extra){var val,num,hooks,origName=jQuery.camelCase(name);name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(elem.style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(hooks&&"get"in hooks){val=hooks.get(elem,true,extra)}if(val===undefined){val=curCSS(elem,name)}if(val==="normal"&&name in cssNormalTransform){val=cssNormalTransform[name]}if(numeric||extra!==undefined){num=parseFloat(val);return numeric||jQuery.isNumeric(num)?num||0:val}return val},swap:function(elem,options,callback){var ret,name,old={};for(name in options){old[name]=elem.style[name];elem.style[name]=options[name]}ret=callback.call(elem);for(name in options){elem.style[name]=old[name]}return ret}});if(window.getComputedStyle){curCSS=function(elem,name){var ret,width,minWidth,maxWidth,computed=window.getComputedStyle(elem,null),style=elem.style;if(computed){ret=computed.getPropertyValue(name)||computed[name];if(ret===""&&!jQuery.contains(elem.ownerDocument,elem)){ret=jQuery.style(elem,name)}if(rnumnonpx.test(ret)&&rmargin.test(name)){width=style.width;minWidth=style.minWidth;maxWidth=style.maxWidth;style.minWidth=style.maxWidth=style.width=ret;ret=computed.width;style.width=width;style.minWidth=minWidth;style.maxWidth=maxWidth}}return ret}}else if(document.documentElement.currentStyle){curCSS=function(elem,name){var left,rsLeft,ret=elem.currentStyle&&elem.currentStyle[name],style=elem.style;if(ret==null&&style&&style[name]){ret=style[name]}if(rnumnonpx.test(ret)&&!rposition.test(name)){left=style.left;rsLeft=elem.runtimeStyle&&elem.runtimeStyle.left;if(rsLeft){elem.runtimeStyle.left=elem.currentStyle.left}style.left=name==="fontSize"?"1em":ret;ret=style.pixelLeft+"px";style.left=left;if(rsLeft){elem.runtimeStyle.left=rsLeft}}return ret===""?"auto":ret}}function setPositiveNumber(elem,value,subtract){var matches=rnumsplit.exec(value);return matches?Math.max(0,matches[1]-(subtract||0))+(matches[2]||"px"):value}function augmentWidthOrHeight(elem,name,extra,isBorderBox){var i=extra===(isBorderBox?"border":"content")?4:name==="width"?1:0,val=0;for(;i<4;i+=2){if(extra==="margin"){val+=jQuery.css(elem,extra+cssExpand[i],true)}if(isBorderBox){if(extra==="content"){val-=parseFloat(curCSS(elem,"padding"+cssExpand[i]))||0}if(extra!=="margin"){val-=parseFloat(curCSS(elem,"border"+cssExpand[i]+"Width"))||0}}else{val+=parseFloat(curCSS(elem,"padding"+cssExpand[i]))||0;if(extra!=="padding"){val+=parseFloat(curCSS(elem,"border"+cssExpand[i]+"Width"))||0}}}return val}function getWidthOrHeight(elem,name,extra){var val=name==="width"?elem.offsetWidth:elem.offsetHeight,valueIsBorderBox=true,isBorderBox=jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing")==="border-box";if(val<=0||val==null){val=curCSS(elem,name);if(val<0||val==null){val=elem.style[name]}if(rnumnonpx.test(val)){return val}valueIsBorderBox=isBorderBox&&(jQuery.support.boxSizingReliable||val===elem.style[name]);val=parseFloat(val)||0}return val+augmentWidthOrHeight(elem,name,extra||(isBorderBox?"border":"content"),valueIsBorderBox)+"px"}function css_defaultDisplay(nodeName){if(elemdisplay[nodeName]){return elemdisplay[nodeName]}var elem=jQuery("<"+nodeName+">").appendTo(document.body),display=elem.css("display");elem.remove();if(display==="none"||display===""){iframe=document.body.appendChild(iframe||jQuery.extend(document.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!iframeDoc||!iframe.createElement){iframeDoc=(iframe.contentWindow||iframe.contentDocument).document;iframeDoc.write("<!doctype html><html><body>");iframeDoc.close()}elem=iframeDoc.body.appendChild(iframeDoc.createElement(nodeName));display=curCSS(elem,"display");document.body.removeChild(iframe)}elemdisplay[nodeName]=display;return display}jQuery.each(["height","width"],function(i,name){jQuery.cssHooks[name]={get:function(elem,computed,extra){if(computed){if(elem.offsetWidth===0&&rdisplayswap.test(curCSS(elem,"display"))){return jQuery.swap(elem,cssShow,function(){return getWidthOrHeight(elem,name,extra)})}else{return getWidthOrHeight(elem,name,extra)}}},set:function(elem,value,extra){return setPositiveNumber(elem,value,extra?augmentWidthOrHeight(elem,name,extra,jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing")==="border-box"):0)}}});if(!jQuery.support.opacity){jQuery.cssHooks.opacity={get:function(elem,computed){return ropacity.test((computed&&elem.currentStyle?elem.currentStyle.filter:elem.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":computed?"1":""},set:function(elem,value){var style=elem.style,currentStyle=elem.currentStyle,opacity=jQuery.isNumeric(value)?"alpha(opacity="+value*100+")":"",filter=currentStyle&&currentStyle.filter||style.filter||"";style.zoom=1;if(value>=1&&jQuery.trim(filter.replace(ralpha,""))===""&&style.removeAttribute){style.removeAttribute("filter");if(currentStyle&&!currentStyle.filter){return}}style.filter=ralpha.test(filter)?filter.replace(ralpha,opacity):filter+" "+opacity}}}jQuery(function(){if(!jQuery.support.reliableMarginRight){jQuery.cssHooks.marginRight={get:function(elem,computed){return jQuery.swap(elem,{display:"inline-block"},function(){if(computed){return curCSS(elem,"marginRight")}})}}}if(!jQuery.support.pixelPosition&&jQuery.fn.position){jQuery.each(["top","left"],function(i,prop){jQuery.cssHooks[prop]={get:function(elem,computed){if(computed){var ret=curCSS(elem,prop);return rnumnonpx.test(ret)?jQuery(elem).position()[prop]+"px":ret}}}})}});if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.hidden=function(elem){return elem.offsetWidth===0&&elem.offsetHeight===0||!jQuery.support.reliableHiddenOffsets&&(elem.style&&elem.style.display||curCSS(elem,"display"))==="none"};jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem)}}jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i,parts=typeof value==="string"?value.split(" "):[value],expanded={};for(i=0;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0]}return expanded}};if(!rmargin.test(prefix)){jQuery.cssHooks[prefix+suffix].set=setPositiveNumber}});var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rinput=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,rselectTextarea=/^(?:select|textarea)/i;jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?jQuery.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||rselectTextarea.test(this.nodeName)||rinput.test(this.type))}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:jQuery.isArray(val)?jQuery.map(val,function(val,i){return{name:elem.name,value:val.replace(rCRLF,"\r\n")}}):{name:elem.name,value:val.replace(rCRLF,"\r\n")}}).get()}});jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():value==null?"":value;s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value)};if(traditional===undefined){traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional}if(jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a)){jQuery.each(a,function(){add(this.name,this.value)})}else{for(prefix in a){buildParams(prefix,a[prefix],traditional,add)}}return s.join("&").replace(r20,"+")};function buildParams(prefix,obj,traditional,add){var name;if(jQuery.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v)}else{buildParams(prefix+"["+(typeof v==="object"?i:"")+"]",v,traditional,add)}})}else if(!traditional&&jQuery.type(obj)==="object"){for(name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add)}}else{add(prefix,obj)}}var ajaxLocParts,ajaxLocation,rhash=/#.*$/,rheaders=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,rlocalProtocol=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rquery=/\?/,rscript=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,rts=/([?&])_=[^&]*/,rurl=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,_load=jQuery.fn.load,prefilters={},transports={},allTypes=["*/"]+["*"];try{ajaxLocation=location.href}catch(e){ajaxLocation=document.createElement("a");ajaxLocation.href="";ajaxLocation=ajaxLocation.href}ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*"}var dataType,list,placeBefore,dataTypes=dataTypeExpression.toLowerCase().split(core_rspace),i=0,length=dataTypes.length;if(jQuery.isFunction(func)){for(;i<length;i++){dataType=dataTypes[i];placeBefore=/^\+/.test(dataType);if(placeBefore){dataType=dataType.substr(1)||"*"}list=structure[dataType]=structure[dataType]||[];list[placeBefore?"unshift":"push"](func)}}}}function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,dataType,inspected){dataType=dataType||options.dataTypes[0];inspected=inspected||{};inspected[dataType]=true;var selection,list=structure[dataType],i=0,length=list?list.length:0,executeOnly=structure===prefilters;for(;i<length&&(executeOnly||!selection);i++){selection=list[i](options,originalOptions,jqXHR);if(typeof selection==="string"){if(!executeOnly||inspected[selection]){selection=undefined}else{options.dataTypes.unshift(selection);selection=inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,selection,inspected)}}}if((executeOnly||!selection)&&!inspected["*"]){selection=inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,"*",inspected)}return selection}function ajaxExtend(target,src){var key,deep,flatOptions=jQuery.ajaxSettings.flatOptions||{};for(key in src){if(src[key]!==undefined){(flatOptions[key]?target:deep||(deep={}))[key]=src[key]}}if(deep){jQuery.extend(true,target,deep)}}jQuery.fn.load=function(url,params,callback){if(typeof url!=="string"&&_load){return _load.apply(this,arguments)}if(!this.length){return this}var selector,type,response,self=this,off=url.indexOf(" ");if(off>=0){selector=url.slice(off,url.length);url=url.slice(0,off)}if(jQuery.isFunction(params)){callback=params;params=undefined}else if(params&&typeof params==="object"){type="POST"}jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(jqXHR,status){if(callback){self.each(callback,response||[jqXHR.responseText,status,jqXHR])}}}).done(function(responseText){response=arguments;self.html(selector?jQuery("<div>").append(responseText.replace(rscript,"")).find(selector):responseText)});return this};jQuery.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(i,o){jQuery.fn[o]=function(f){return this.on(o,f)}});jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){if(jQuery.isFunction(data)){type=type||callback;callback=data;data=undefined}return jQuery.ajax({type:method,url:url,data:data,success:callback,dataType:type})}});jQuery.extend({getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script")},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},ajaxSetup:function(target,settings){if(settings){ajaxExtend(target,jQuery.ajaxSettings)}else{settings=target;target=jQuery.ajaxSettings}ajaxExtend(target,settings);return target},ajaxSettings:{url:ajaxLocation,isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":allTypes},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":window.String,"text html":true,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined}options=options||{};var ifModifiedKey,responseHeadersString,responseHeaders,transport,timeoutTimer,parts,fireGlobals,i,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=callbackContext!==s&&(callbackContext.nodeType||callbackContext instanceof jQuery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,setRequestHeader:function(name,value){if(!state){var lname=name.toLowerCase();name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;requestHeaders[name]=value}return this},getAllResponseHeaders:function(){return state===2?responseHeadersString:null},getResponseHeader:function(key){var match;if(state===2){if(!responseHeaders){responseHeaders={};while(match=rheaders.exec(responseHeadersString)){responseHeaders[match[1].toLowerCase()]=match[2]}}match=responseHeaders[key.toLowerCase()]}return match===undefined?null:match},overrideMimeType:function(type){if(!state){s.mimeType=type}return this},abort:function(statusText){statusText=statusText||strAbort;if(transport){transport.abort(statusText)}done(0,statusText);return this}};function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;if(state===2){return}state=2;if(timeoutTimer){clearTimeout(timeoutTimer)}transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;if(responses){response=ajaxHandleResponses(s,jqXHR,responses)}if(status>=200&&status<300||status===304){if(s.ifModified){modified=jqXHR.getResponseHeader("Last-Modified");if(modified){jQuery.lastModified[ifModifiedKey]=modified}modified=jqXHR.getResponseHeader("Etag");if(modified){jQuery.etag[ifModifiedKey]=modified}}if(status===304){statusText="notmodified";isSuccess=true}else{isSuccess=ajaxConvert(s,response);statusText=isSuccess.state;success=isSuccess.data;error=isSuccess.error;isSuccess=!error}}else{error=statusText;if(!statusText||status){statusText="error";if(status<0){status=0}}}jqXHR.status=status;jqXHR.statusText=(nativeStatusText||statusText)+"";if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR])}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error])}jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger("ajax"+(isSuccess?"Success":"Error"),[jqXHR,s,isSuccess?success:error])}completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!--jQuery.active){jQuery.event.trigger("ajaxStop")}}}deferred.promise(jqXHR);jqXHR.success=jqXHR.done;jqXHR.error=jqXHR.fail;jqXHR.complete=completeDeferred.add;jqXHR.statusCode=function(map){if(map){var tmp;if(state<2){for(tmp in map){statusCode[tmp]=[statusCode[tmp],map[tmp]]}}else{tmp=map[jqXHR.status];jqXHR.always(tmp)}}return this};s.url=((url||s.url)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().split(core_rspace);if(s.crossDomain==null){parts=rurl.exec(s.url.toLowerCase());s.crossDomain=!!(parts&&(parts[1]!==ajaxLocParts[1]||parts[2]!==ajaxLocParts[2]||(parts[3]||(parts[1]==="http:"?80:443))!=(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?80:443))))}if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional)}inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(state===2){return jqXHR}fireGlobals=s.global;s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart")}if(!s.hasContent){if(s.data){s.url+=(rquery.test(s.url)?"&":"?")+s.data;delete s.data}ifModifiedKey=s.url;if(s.cache===false){var ts=jQuery.now(),ret=s.url.replace(rts,"$1_="+ts);s.url=ret+(ret===s.url?(rquery.test(s.url)?"&":"?")+"_="+ts:"")}}if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType)}if(s.ifModified){ifModifiedKey=ifModifiedKey||s.url;if(jQuery.lastModified[ifModifiedKey]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[ifModifiedKey])}if(jQuery.etag[ifModifiedKey]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[ifModifiedKey])}}jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i])}if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){return jqXHR.abort()}strAbort="abort";for(i in{success:1,error:1,complete:1}){jqXHR[i](s[i])}transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport")}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s])}if(s.async&&s.timeout>0){timeoutTimer=setTimeout(function(){jqXHR.abort("timeout")},s.timeout)}try{state=1;transport.send(requestHeaders,done)}catch(e){if(state<2){done(-1,e)}else{throw e}}}return jqXHR},active:0,lastModified:{},etag:{}});function ajaxHandleResponses(s,jqXHR,responses){var ct,type,finalDataType,firstDataType,contents=s.contents,dataTypes=s.dataTypes,responseFields=s.responseFields;for(type in responseFields){if(type in responses){jqXHR[responseFields[type]]=responses[type]}}while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("content-type")}}if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break}}}if(dataTypes[0]in responses){finalDataType=dataTypes[0]}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break}if(!firstDataType){firstDataType=type}}finalDataType=finalDataType||firstDataType}if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType)}return responses[finalDataType]}}function ajaxConvert(s,response){var conv,conv2,current,tmp,dataTypes=s.dataTypes.slice(),prev=dataTypes[0],converters={},i=0;if(s.dataFilter){response=s.dataFilter(response,s.dataType)}if(dataTypes[1]){for(conv in s.converters){converters[conv.toLowerCase()]=s.converters[conv]}}for(;current=dataTypes[++i];){if(current!=="*"){if(prev!=="*"&&prev!==current){conv=converters[prev+" "+current]||converters["* "+current];if(!conv){for(conv2 in converters){tmp=conv2.split(" ");if(tmp[1]===current){conv=converters[prev+" "+tmp[0]]||converters["* "+tmp[0]];if(conv){if(conv===true){conv=converters[conv2]}else if(converters[conv2]!==true){current=tmp[0];dataTypes.splice(i--,0,current)}break}}}}if(conv!==true){if(conv&&s["throws"]){response=conv(response)}else{try{response=conv(response)}catch(e){return{state:"parsererror",error:conv?e:"No conversion from "+prev+" to "+current}}}}}prev=current}}return{state:"success",data:response}}var oldCallbacks=[],rquestion=/\?/,rjsonp=/(=)\?(?=&|$)|\?\?/,nonce=jQuery.now();jQuery.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var callback=oldCallbacks.pop()||jQuery.expando+"_"+nonce++;this[callback]=true;return callback}});jQuery.ajaxPrefilter("json jsonp",function(s,originalSettings,jqXHR){var callbackName,overwritten,responseContainer,data=s.data,url=s.url,hasCallback=s.jsonp!==false,replaceInUrl=hasCallback&&rjsonp.test(url),replaceInData=hasCallback&&!replaceInUrl&&typeof data==="string"&&!(s.contentType||"").indexOf("application/x-www-form-urlencoded")&&rjsonp.test(data);if(s.dataTypes[0]==="jsonp"||replaceInUrl||replaceInData){callbackName=s.jsonpCallback=jQuery.isFunction(s.jsonpCallback)?s.jsonpCallback():s.jsonpCallback;overwritten=window[callbackName];if(replaceInUrl){s.url=url.replace(rjsonp,"$1"+callbackName)}else if(replaceInData){s.data=data.replace(rjsonp,"$1"+callbackName)}else if(hasCallback){s.url+=(rquestion.test(url)?"&":"?")+s.jsonp+"="+callbackName}s.converters["script json"]=function(){if(!responseContainer){jQuery.error(callbackName+" was not called")}return responseContainer[0]};s.dataTypes[0]="json";window[callbackName]=function(){responseContainer=arguments};jqXHR.always(function(){window[callbackName]=overwritten;if(s[callbackName]){s.jsonpCallback=originalSettings.jsonpCallback;oldCallbacks.push(callbackName)}if(responseContainer&&jQuery.isFunction(overwritten)){overwritten(responseContainer[0])}responseContainer=overwritten=undefined});return"script"}});jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(text){jQuery.globalEval(text);return text}}});jQuery.ajaxPrefilter("script",function(s){if(s.cache===undefined){s.cache=false}if(s.crossDomain){s.type="GET";s.global=false}});jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,head=document.head||document.getElementsByTagName("head")[0]||document.documentElement;return{send:function(_,callback){script=document.createElement("script");script.async="async";if(s.scriptCharset){script.charset=s.scriptCharset}script.src=s.url;script.onload=script.onreadystatechange=function(_,isAbort){if(isAbort||!script.readyState||/loaded|complete/.test(script.readyState)){script.onload=script.onreadystatechange=null;if(head&&script.parentNode){head.removeChild(script)}script=undefined;if(!isAbort){callback(200,"success")}}};head.insertBefore(script,head.firstChild)},abort:function(){if(script){script.onload(0,1)}}}}});var xhrCallbacks,xhrOnUnloadAbort=window.ActiveXObject?function(){for(var key in xhrCallbacks){xhrCallbacks[key](0,1)}}:false,xhrId=0;function createStandardXHR(){try{return new window.XMLHttpRequest}catch(e){}}function createActiveXHR(){try{return new window.ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}jQuery.ajaxSettings.xhr=window.ActiveXObject?function(){return!this.isLocal&&createStandardXHR()||createActiveXHR()}:createStandardXHR;(function(xhr){jQuery.extend(jQuery.support,{ajax:!!xhr,cors:!!xhr&&"withCredentials"in xhr})})(jQuery.ajaxSettings.xhr());if(jQuery.support.ajax){jQuery.ajaxTransport(function(s){if(!s.crossDomain||jQuery.support.cors){var callback;return{send:function(headers,complete){var handle,i,xhr=s.xhr();if(s.username){xhr.open(s.type,s.url,s.async,s.username,s.password)}else{xhr.open(s.type,s.url,s.async)}if(s.xhrFields){for(i in s.xhrFields){xhr[i]=s.xhrFields[i]}}if(s.mimeType&&xhr.overrideMimeType){xhr.overrideMimeType(s.mimeType)}if(!s.crossDomain&&!headers["X-Requested-With"]){headers["X-Requested-With"]="XMLHttpRequest"}try{for(i in headers){xhr.setRequestHeader(i,headers[i])}}catch(_){}xhr.send(s.hasContent&&s.data||null);callback=function(_,isAbort){var status,statusText,responseHeaders,responses,xml;try{if(callback&&(isAbort||xhr.readyState===4)){callback=undefined;if(handle){xhr.onreadystatechange=jQuery.noop;if(xhrOnUnloadAbort){delete xhrCallbacks[handle]}}if(isAbort){if(xhr.readyState!==4){xhr.abort()}}else{status=xhr.status;responseHeaders=xhr.getAllResponseHeaders();responses={};xml=xhr.responseXML;if(xml&&xml.documentElement){responses.xml=xml}try{responses.text=xhr.responseText}catch(e){}try{statusText=xhr.statusText}catch(e){statusText=""}if(!status&&s.isLocal&&!s.crossDomain){status=responses.text?200:404}else if(status===1223){status=204}}}}catch(firefoxAccessException){if(!isAbort){complete(-1,firefoxAccessException)}}if(responses){complete(status,statusText,responses,responseHeaders)}};if(!s.async){callback()}else if(xhr.readyState===4){setTimeout(callback,0)}else{handle=++xhrId;if(xhrOnUnloadAbort){if(!xhrCallbacks){xhrCallbacks={};jQuery(window).unload(xhrOnUnloadAbort)}xhrCallbacks[handle]=callback}xhr.onreadystatechange=callback}},abort:function(){if(callback){callback(0,1)}}}}})}var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rfxnum=new RegExp("^(?:([-+])=|)("+core_pnum+")([a-z%]*)$","i"),rrun=/queueHooks$/,animationPrefilters=[defaultPrefilter],tweeners={"*":[function(prop,value){var end,unit,tween=this.createTween(prop,value),parts=rfxnum.exec(value),target=tween.cur(),start=+target||0,scale=1,maxIterations=20;if(parts){end=+parts[2];unit=parts[3]||(jQuery.cssNumber[prop]?"":"px");if(unit!=="px"&&start){start=jQuery.css(tween.elem,prop,true)||end||1;do{scale=scale||".5";start=start/scale;jQuery.style(tween.elem,prop,start+unit)}while(scale!==(scale=tween.cur()/target)&&scale!==1&&--maxIterations)}tween.unit=unit;tween.start=start;tween.end=parts[1]?start+(parts[1]+1)*end:end}return tween}]};function createFxNow(){setTimeout(function(){fxNow=undefined},0);return fxNow=jQuery.now()}function createTweens(animation,props){jQuery.each(props,function(prop,value){var collection=(tweeners[prop]||[]).concat(tweeners["*"]),index=0,length=collection.length;for(;index<length;index++){if(collection[index].call(animation,prop,value)){return}}})}function Animation(elem,properties,options){var result,index=0,tweenerIndex=0,length=animationPrefilters.length,deferred=jQuery.Deferred().always(function(){delete tick.elem}),tick=function(){var currentTime=fxNow||createFxNow(),remaining=Math.max(0,animation.startTime+animation.duration-currentTime),temp=remaining/animation.duration||0,percent=1-temp,index=0,length=animation.tweens.length;
+for(;index<length;index++){animation.tweens[index].run(percent)}deferred.notifyWith(elem,[animation,percent,remaining]);if(percent<1&&length){return remaining}else{deferred.resolveWith(elem,[animation]);return false}},animation=deferred.promise({elem:elem,props:jQuery.extend({},properties),opts:jQuery.extend(true,{specialEasing:{}},options),originalProperties:properties,originalOptions:options,startTime:fxNow||createFxNow(),duration:options.duration,tweens:[],createTween:function(prop,end,easing){var tween=jQuery.Tween(elem,animation.opts,prop,end,animation.opts.specialEasing[prop]||animation.opts.easing);animation.tweens.push(tween);return tween},stop:function(gotoEnd){var index=0,length=gotoEnd?animation.tweens.length:0;for(;index<length;index++){animation.tweens[index].run(1)}if(gotoEnd){deferred.resolveWith(elem,[animation,gotoEnd])}else{deferred.rejectWith(elem,[animation,gotoEnd])}return this}}),props=animation.props;propFilter(props,animation.opts.specialEasing);for(;index<length;index++){result=animationPrefilters[index].call(animation,elem,props,animation.opts);if(result){return result}}createTweens(animation,props);if(jQuery.isFunction(animation.opts.start)){animation.opts.start.call(elem,animation)}jQuery.fx.timer(jQuery.extend(tick,{anim:animation,queue:animation.opts.queue,elem:elem}));return animation.progress(animation.opts.progress).done(animation.opts.done,animation.opts.complete).fail(animation.opts.fail).always(animation.opts.always)}function propFilter(props,specialEasing){var index,name,easing,value,hooks;for(index in props){name=jQuery.camelCase(index);easing=specialEasing[name];value=props[index];if(jQuery.isArray(value)){easing=value[1];value=props[index]=value[0]}if(index!==name){props[name]=value;delete props[index]}hooks=jQuery.cssHooks[name];if(hooks&&"expand"in hooks){value=hooks.expand(value);delete props[name];for(index in value){if(!(index in props)){props[index]=value[index];specialEasing[index]=easing}}}else{specialEasing[name]=easing}}}jQuery.Animation=jQuery.extend(Animation,{tweener:function(props,callback){if(jQuery.isFunction(props)){callback=props;props=["*"]}else{props=props.split(" ")}var prop,index=0,length=props.length;for(;index<length;index++){prop=props[index];tweeners[prop]=tweeners[prop]||[];tweeners[prop].unshift(callback)}},prefilter:function(callback,prepend){if(prepend){animationPrefilters.unshift(callback)}else{animationPrefilters.push(callback)}}});function defaultPrefilter(elem,props,opts){var index,prop,value,length,dataShow,toggle,tween,hooks,oldfire,anim=this,style=elem.style,orig={},handled=[],hidden=elem.nodeType&&isHidden(elem);if(!opts.queue){hooks=jQuery._queueHooks(elem,"fx");if(hooks.unqueued==null){hooks.unqueued=0;oldfire=hooks.empty.fire;hooks.empty.fire=function(){if(!hooks.unqueued){oldfire()}}}hooks.unqueued++;anim.always(function(){anim.always(function(){hooks.unqueued--;if(!jQuery.queue(elem,"fx").length){hooks.empty.fire()}})})}if(elem.nodeType===1&&("height"in props||"width"in props)){opts.overflow=[style.overflow,style.overflowX,style.overflowY];if(jQuery.css(elem,"display")==="inline"&&jQuery.css(elem,"float")==="none"){if(!jQuery.support.inlineBlockNeedsLayout||css_defaultDisplay(elem.nodeName)==="inline"){style.display="inline-block"}else{style.zoom=1}}}if(opts.overflow){style.overflow="hidden";if(!jQuery.support.shrinkWrapBlocks){anim.done(function(){style.overflow=opts.overflow[0];style.overflowX=opts.overflow[1];style.overflowY=opts.overflow[2]})}}for(index in props){value=props[index];if(rfxtypes.exec(value)){delete props[index];toggle=toggle||value==="toggle";if(value===(hidden?"hide":"show")){continue}handled.push(index)}}length=handled.length;if(length){dataShow=jQuery._data(elem,"fxshow")||jQuery._data(elem,"fxshow",{});if("hidden"in dataShow){hidden=dataShow.hidden}if(toggle){dataShow.hidden=!hidden}if(hidden){jQuery(elem).show()}else{anim.done(function(){jQuery(elem).hide()})}anim.done(function(){var prop;jQuery.removeData(elem,"fxshow",true);for(prop in orig){jQuery.style(elem,prop,orig[prop])}});for(index=0;index<length;index++){prop=handled[index];tween=anim.createTween(prop,hidden?dataShow[prop]:0);orig[prop]=dataShow[prop]||jQuery.style(elem,prop);if(!(prop in dataShow)){dataShow[prop]=tween.start;if(hidden){tween.end=tween.start;tween.start=prop==="width"||prop==="height"?1:0}}}}}function Tween(elem,options,prop,end,easing){return new Tween.prototype.init(elem,options,prop,end,easing)}jQuery.Tween=Tween;Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem;this.prop=prop;this.easing=easing||"swing";this.options=options;this.start=this.now=this.cur();this.end=end;this.unit=unit||(jQuery.cssNumber[prop]?"":"px")},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this)},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];if(this.options.duration){this.pos=eased=jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration)}else{this.pos=eased=percent}this.now=(this.end-this.start)*eased+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this)}if(hooks&&hooks.set){hooks.set(this)}else{Tween.propHooks._default.set(this)}return this}};Tween.prototype.init.prototype=Tween.prototype;Tween.propHooks={_default:{get:function(tween){var result;if(tween.elem[tween.prop]!=null&&(!tween.elem.style||tween.elem.style[tween.prop]==null)){return tween.elem[tween.prop]}result=jQuery.css(tween.elem,tween.prop,false,"");return!result||result==="auto"?0:result},set:function(tween){if(jQuery.fx.step[tween.prop]){jQuery.fx.step[tween.prop](tween)}else if(tween.elem.style&&(tween.elem.style[jQuery.cssProps[tween.prop]]!=null||jQuery.cssHooks[tween.prop])){jQuery.style(tween.elem,tween.prop,tween.now+tween.unit)}else{tween.elem[tween.prop]=tween.now}}}};Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){if(tween.elem.nodeType&&tween.elem.parentNode){tween.elem[tween.prop]=tween.now}}};jQuery.each(["toggle","show","hide"],function(i,name){var cssFn=jQuery.fn[name];jQuery.fn[name]=function(speed,easing,callback){return speed==null||typeof speed==="boolean"||!i&&jQuery.isFunction(speed)&&jQuery.isFunction(easing)?cssFn.apply(this,arguments):this.animate(genFx(name,true),speed,easing,callback)}});jQuery.fn.extend({fadeTo:function(speed,to,easing,callback){return this.filter(isHidden).css("opacity",0).show().end().animate({opacity:to},speed,easing,callback)},animate:function(prop,speed,easing,callback){var empty=jQuery.isEmptyObject(prop),optall=jQuery.speed(speed,easing,callback),doAnimation=function(){var anim=Animation(this,jQuery.extend({},prop),optall);if(empty){anim.stop(true)}};return empty||optall.queue===false?this.each(doAnimation):this.queue(optall.queue,doAnimation)},stop:function(type,clearQueue,gotoEnd){var stopQueue=function(hooks){var stop=hooks.stop;delete hooks.stop;stop(gotoEnd)};if(typeof type!=="string"){gotoEnd=clearQueue;clearQueue=type;type=undefined}if(clearQueue&&type!==false){this.queue(type||"fx",[])}return this.each(function(){var dequeue=true,index=type!=null&&type+"queueHooks",timers=jQuery.timers,data=jQuery._data(this);if(index){if(data[index]&&data[index].stop){stopQueue(data[index])}}else{for(index in data){if(data[index]&&data[index].stop&&rrun.test(index)){stopQueue(data[index])}}}for(index=timers.length;index--;){if(timers[index].elem===this&&(type==null||timers[index].queue===type)){timers[index].anim.stop(gotoEnd);dequeue=false;timers.splice(index,1)}}if(dequeue||!gotoEnd){jQuery.dequeue(this,type)}})}});function genFx(type,includeWidth){var which,attrs={height:type},i=0;includeWidth=includeWidth?1:0;for(;i<4;i+=2-includeWidth){which=cssExpand[i];attrs["margin"+which]=attrs["padding"+which]=type}if(includeWidth){attrs.opacity=attrs.width=type}return attrs}jQuery.each({slideDown:genFx("show"),slideUp:genFx("hide"),slideToggle:genFx("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(name,props){jQuery.fn[name]=function(speed,easing,callback){return this.animate(props,speed,easing,callback)}});jQuery.speed=function(speed,easing,fn){var opt=speed&&typeof speed==="object"?jQuery.extend({},speed):{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&!jQuery.isFunction(easing)&&easing};opt.duration=jQuery.fx.off?0:typeof opt.duration==="number"?opt.duration:opt.duration in jQuery.fx.speeds?jQuery.fx.speeds[opt.duration]:jQuery.fx.speeds._default;if(opt.queue==null||opt.queue===true){opt.queue="fx"}opt.old=opt.complete;opt.complete=function(){if(jQuery.isFunction(opt.old)){opt.old.call(this)}if(opt.queue){jQuery.dequeue(this,opt.queue)}};return opt};jQuery.easing={linear:function(p){return p},swing:function(p){return.5-Math.cos(p*Math.PI)/2}};jQuery.timers=[];jQuery.fx=Tween.prototype.init;jQuery.fx.tick=function(){var timer,timers=jQuery.timers,i=0;fxNow=jQuery.now();for(;i<timers.length;i++){timer=timers[i];if(!timer()&&timers[i]===timer){timers.splice(i--,1)}}if(!timers.length){jQuery.fx.stop()}fxNow=undefined};jQuery.fx.timer=function(timer){if(timer()&&jQuery.timers.push(timer)&&!timerId){timerId=setInterval(jQuery.fx.tick,jQuery.fx.interval)}};jQuery.fx.interval=13;jQuery.fx.stop=function(){clearInterval(timerId);timerId=null};jQuery.fx.speeds={slow:600,fast:200,_default:400};jQuery.fx.step={};if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.animated=function(elem){return jQuery.grep(jQuery.timers,function(fn){return elem===fn.elem}).length}}var rroot=/^(?:body|html)$/i;jQuery.fn.offset=function(options){if(arguments.length){return options===undefined?this:this.each(function(i){jQuery.offset.setOffset(this,options,i)})}var docElem,body,win,clientTop,clientLeft,scrollTop,scrollLeft,box={top:0,left:0},elem=this[0],doc=elem&&elem.ownerDocument;if(!doc){return}if((body=doc.body)===elem){return jQuery.offset.bodyOffset(elem)}docElem=doc.documentElement;if(!jQuery.contains(docElem,elem)){return box}if(typeof elem.getBoundingClientRect!=="undefined"){box=elem.getBoundingClientRect()}win=getWindow(doc);clientTop=docElem.clientTop||body.clientTop||0;clientLeft=docElem.clientLeft||body.clientLeft||0;scrollTop=win.pageYOffset||docElem.scrollTop;scrollLeft=win.pageXOffset||docElem.scrollLeft;return{top:box.top+scrollTop-clientTop,left:box.left+scrollLeft-clientLeft}};jQuery.offset={bodyOffset:function(body){var top=body.offsetTop,left=body.offsetLeft;if(jQuery.support.doesNotIncludeMarginInBodyOffset){top+=parseFloat(jQuery.css(body,"marginTop"))||0;left+=parseFloat(jQuery.css(body,"marginLeft"))||0}return{top:top,left:left}},setOffset:function(elem,options,i){var position=jQuery.css(elem,"position");if(position==="static"){elem.style.position="relative"}var curElem=jQuery(elem),curOffset=curElem.offset(),curCSSTop=jQuery.css(elem,"top"),curCSSLeft=jQuery.css(elem,"left"),calculatePosition=(position==="absolute"||position==="fixed")&&jQuery.inArray("auto",[curCSSTop,curCSSLeft])>-1,props={},curPosition={},curTop,curLeft;if(calculatePosition){curPosition=curElem.position();curTop=curPosition.top;curLeft=curPosition.left}else{curTop=parseFloat(curCSSTop)||0;curLeft=parseFloat(curCSSLeft)||0}if(jQuery.isFunction(options)){options=options.call(elem,i,curOffset)}if(options.top!=null){props.top=options.top-curOffset.top+curTop}if(options.left!=null){props.left=options.left-curOffset.left+curLeft}if("using"in options){options.using.call(elem,props)}else{curElem.css(props)}}};jQuery.fn.extend({position:function(){if(!this[0]){return}var elem=this[0],offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=rroot.test(offsetParent[0].nodeName)?{top:0,left:0}:offsetParent.offset();offset.top-=parseFloat(jQuery.css(elem,"marginTop"))||0;offset.left-=parseFloat(jQuery.css(elem,"marginLeft"))||0;parentOffset.top+=parseFloat(jQuery.css(offsetParent[0],"borderTopWidth"))||0;parentOffset.left+=parseFloat(jQuery.css(offsetParent[0],"borderLeftWidth"))||0;return{top:offset.top-parentOffset.top,left:offset.left-parentOffset.left}},offsetParent:function(){return this.map(function(){var offsetParent=this.offsetParent||document.body;while(offsetParent&&(!rroot.test(offsetParent.nodeName)&&jQuery.css(offsetParent,"position")==="static")){offsetParent=offsetParent.offsetParent}return offsetParent||document.body})}});jQuery.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(method,prop){var top=/Y/.test(prop);jQuery.fn[method]=function(val){return jQuery.access(this,function(elem,method,val){var win=getWindow(elem);if(val===undefined){return win?prop in win?win[prop]:win.document.documentElement[method]:elem[method]}if(win){win.scrollTo(!top?val:jQuery(win).scrollLeft(),top?val:jQuery(win).scrollTop())}else{elem[method]=val}},method,val,arguments.length,null)}});function getWindow(elem){return jQuery.isWindow(elem)?elem:elem.nodeType===9?elem.defaultView||elem.parentWindow:false}jQuery.each({Height:"height",Width:"width"},function(name,type){jQuery.each({padding:"inner"+name,content:type,"":"outer"+name},function(defaultExtra,funcName){jQuery.fn[funcName]=function(margin,value){var chainable=arguments.length&&(defaultExtra||typeof margin!=="boolean"),extra=defaultExtra||(margin===true||value===true?"margin":"border");return jQuery.access(this,function(elem,type,value){var doc;if(jQuery.isWindow(elem)){return elem.document.documentElement["client"+name]}if(elem.nodeType===9){doc=elem.documentElement;return Math.max(elem.body["scroll"+name],doc["scroll"+name],elem.body["offset"+name],doc["offset"+name],doc["client"+name])}return value===undefined?jQuery.css(elem,type,value,extra):jQuery.style(elem,type,value,extra)},type,chainable?margin:undefined,chainable,null)}})});window.jQuery=window.$=jQuery;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return jQuery})}})(window); \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js b/library/cpp/lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js
index ac4a835205..8346d9d2f1 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js
@@ -1,4 +1,4 @@
-$.extend($.fn.treegrid.defaults, {
- expanderExpandedClass: 'glyphicon glyphicon-chevron-down',
- expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'
-});
+$.extend($.fn.treegrid.defaults, {
+ expanderExpandedClass: 'glyphicon glyphicon-chevron-down',
+ expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'
+});
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.treegrid.min.js b/library/cpp/lwtrace/mon/static/js/jquery.treegrid.min.js
index 7b7566f323..345038c5ed 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.treegrid.min.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.treegrid.min.js
@@ -1,2 +1,2 @@
-/*! jquery-treegrid 0.3.0 */
-!function(a){var b={initTree:function(b){var c=a.extend({},this.treegrid.defaults,b);return this.each(function(){var b=a(this);b.treegrid("setTreeContainer",a(this)),b.treegrid("setSettings",c),c.getRootNodes.apply(this,[a(this)]).treegrid("initNode",c),b.treegrid("getRootNodes").treegrid("render")})},initNode:function(b){return this.each(function(){var c=a(this);c.treegrid("setTreeContainer",b.getTreeGridContainer.apply(this)),c.treegrid("getChildNodes").treegrid("initNode",b),c.treegrid("initExpander").treegrid("initIndent").treegrid("initEvents").treegrid("initState").treegrid("initChangeEvent").treegrid("initSettingsEvents")})},initChangeEvent:function(){var b=a(this);return b.on("change",function(){var b=a(this);b.treegrid("render"),b.treegrid("getSetting","saveState")&&b.treegrid("saveState")}),b},initEvents:function(){var b=a(this);return b.on("collapse",function(){var b=a(this);b.removeClass("treegrid-expanded"),b.addClass("treegrid-collapsed")}),b.on("expand",function(){var b=a(this);b.removeClass("treegrid-collapsed"),b.addClass("treegrid-expanded")}),b},initSettingsEvents:function(){var b=a(this);return b.on("change",function(){var b=a(this);"function"==typeof b.treegrid("getSetting","onChange")&&b.treegrid("getSetting","onChange").apply(b)}),b.on("collapse",function(){var b=a(this);"function"==typeof b.treegrid("getSetting","onCollapse")&&b.treegrid("getSetting","onCollapse").apply(b)}),b.on("expand",function(){var b=a(this);"function"==typeof b.treegrid("getSetting","onExpand")&&b.treegrid("getSetting","onExpand").apply(b)}),b},initExpander:function(){var b=a(this),c=b.find("td").get(b.treegrid("getSetting","treeColumn")),d=b.treegrid("getSetting","expanderTemplate"),e=b.treegrid("getSetting","getExpander").apply(this);return e&&e.remove(),a(d).prependTo(c).click(function(){a(a(this).closest("tr")).treegrid("toggle")}),b},initIndent:function(){var b=a(this);b.find(".treegrid-indent").remove();for(var c=b.treegrid("getSetting","indentTemplate"),d=b.find(".treegrid-expander"),e=b.treegrid("getDepth"),f=0;e>f;f++)a(c).insertBefore(d);return b},initState:function(){var b=a(this);return b.treegrid(b.treegrid("getSetting","saveState")&&!b.treegrid("isFirstInit")?"restoreState":"expanded"===b.treegrid("getSetting","initialState")?"expand":"collapse"),b},isFirstInit:function(){var b=a(this).treegrid("getTreeContainer");return void 0===b.data("first_init")&&b.data("first_init",void 0===a.cookie(b.treegrid("getSetting","saveStateName"))),b.data("first_init")},saveState:function(){var b=a(this);if("cookie"===b.treegrid("getSetting","saveStateMethod")){var c=a.cookie(b.treegrid("getSetting","saveStateName"))||"",d=""===c?[]:c.split(","),e=b.treegrid("getNodeId");b.treegrid("isExpanded")?-1===a.inArray(e,d)&&d.push(e):b.treegrid("isCollapsed")&&-1!==a.inArray(e,d)&&d.splice(a.inArray(e,d),1),a.cookie(b.treegrid("getSetting","saveStateName"),d.join(","))}return b},restoreState:function(){var b=a(this);if("cookie"===b.treegrid("getSetting","saveStateMethod")){var c=a.cookie(b.treegrid("getSetting","saveStateName")).split(",");b.treegrid(-1!==a.inArray(b.treegrid("getNodeId"),c)?"expand":"collapse")}return b},getSetting:function(b){return a(this).treegrid("getTreeContainer")?a(this).treegrid("getTreeContainer").data("settings")[b]:null},setSettings:function(b){a(this).treegrid("getTreeContainer").data("settings",b)},getTreeContainer:function(){return a(this).data("treegrid")},setTreeContainer:function(b){return a(this).data("treegrid",b)},getRootNodes:function(){return a(this).treegrid("getSetting","getRootNodes").apply(this,[a(this).treegrid("getTreeContainer")])},getAllNodes:function(){return a(this).treegrid("getSetting","getAllNodes").apply(this,[a(this).treegrid("getTreeContainer")])},isNode:function(){return null!==a(this).treegrid("getNodeId")},getNodeId:function(){return null===a(this).treegrid("getSetting","getNodeId")?null:a(this).treegrid("getSetting","getNodeId").apply(this)},getParentNodeId:function(){return a(this).treegrid("getSetting","getParentNodeId").apply(this)},getParentNode:function(){return null===a(this).treegrid("getParentNodeId")?null:a(this).treegrid("getSetting","getNodeById").apply(this,[a(this).treegrid("getParentNodeId"),a(this).treegrid("getTreeContainer")])},getChildNodes:function(){return a(this).treegrid("getSetting","getChildNodes").apply(this,[a(this).treegrid("getNodeId"),a(this).treegrid("getTreeContainer")])},getDepth:function(){return null===a(this).treegrid("getParentNode")?0:a(this).treegrid("getParentNode").treegrid("getDepth")+1},isRoot:function(){return 0===a(this).treegrid("getDepth")},isLeaf:function(){return 0===a(this).treegrid("getChildNodes").length},isLast:function(){if(a(this).treegrid("isNode")){var b=a(this).treegrid("getParentNode");if(null===b){if(a(this).treegrid("getNodeId")===a(this).treegrid("getRootNodes").last().treegrid("getNodeId"))return!0}else if(a(this).treegrid("getNodeId")===b.treegrid("getChildNodes").last().treegrid("getNodeId"))return!0}return!1},isFirst:function(){if(a(this).treegrid("isNode")){var b=a(this).treegrid("getParentNode");if(null===b){if(a(this).treegrid("getNodeId")===a(this).treegrid("getRootNodes").first().treegrid("getNodeId"))return!0}else if(a(this).treegrid("getNodeId")===b.treegrid("getChildNodes").first().treegrid("getNodeId"))return!0}return!1},isExpanded:function(){return a(this).hasClass("treegrid-expanded")},isCollapsed:function(){return a(this).hasClass("treegrid-collapsed")},isOneOfParentsCollapsed:function(){var b=a(this);return b.treegrid("isRoot")?!1:b.treegrid("getParentNode").treegrid("isCollapsed")?!0:b.treegrid("getParentNode").treegrid("isOneOfParentsCollapsed")},expand:function(){return this.treegrid("isLeaf")||this.treegrid("isExpanded")?this:(this.trigger("expand"),this.trigger("change"),this)},expandAll:function(){var b=a(this);return b.treegrid("getRootNodes").treegrid("expandRecursive"),b},expandRecursive:function(){return a(this).each(function(){var b=a(this);b.treegrid("expand"),b.treegrid("isLeaf")||b.treegrid("getChildNodes").treegrid("expandRecursive")})},collapse:function(){return a(this).each(function(){var b=a(this);b.treegrid("isLeaf")||b.treegrid("isCollapsed")||(b.trigger("collapse"),b.trigger("change"))})},collapseAll:function(){var b=a(this);return b.treegrid("getRootNodes").treegrid("collapseRecursive"),b},collapseRecursive:function(){return a(this).each(function(){var b=a(this);b.treegrid("collapse"),b.treegrid("isLeaf")||b.treegrid("getChildNodes").treegrid("collapseRecursive")})},toggle:function(){var b=a(this);return b.treegrid(b.treegrid("isExpanded")?"collapse":"expand"),b},render:function(){return a(this).each(function(){var b=a(this);b.treegrid("isOneOfParentsCollapsed")?b.hide():b.show(),b.treegrid("isLeaf")||(b.treegrid("renderExpander"),b.treegrid("getChildNodes").treegrid("render"))})},renderExpander:function(){return a(this).each(function(){var b=a(this),c=b.treegrid("getSetting","getExpander").apply(this);c?b.treegrid("isCollapsed")?(c.removeClass(b.treegrid("getSetting","expanderExpandedClass")),c.addClass(b.treegrid("getSetting","expanderCollapsedClass"))):(c.removeClass(b.treegrid("getSetting","expanderCollapsedClass")),c.addClass(b.treegrid("getSetting","expanderExpandedClass"))):(b.treegrid("initExpander"),b.treegrid("renderExpander"))})}};a.fn.treegrid=function(c){return b[c]?b[c].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof c&&c?void a.error("Method with name "+c+" does not exists for jQuery.treegrid"):b.initTree.apply(this,arguments)},a.fn.treegrid.defaults={initialState:"expanded",saveState:!1,saveStateMethod:"cookie",saveStateName:"tree-grid-state",expanderTemplate:'<span class="treegrid-expander"></span>',indentTemplate:'<span class="treegrid-indent"></span>',expanderExpandedClass:"treegrid-expander-expanded",expanderCollapsedClass:"treegrid-expander-collapsed",treeColumn:0,getExpander:function(){return a(this).find(".treegrid-expander")},getNodeId:function(){var b=/treegrid-([A-Za-z0-9_-]+)/;return b.test(a(this).attr("class"))?b.exec(a(this).attr("class"))[1]:null},getParentNodeId:function(){var b=/treegrid-parent-([A-Za-z0-9_-]+)/;return b.test(a(this).attr("class"))?b.exec(a(this).attr("class"))[1]:null},getNodeById:function(a,b){var c="treegrid-"+a;return b.find("tr."+c)},getChildNodes:function(a,b){var c="treegrid-parent-"+a;return b.find("tr."+c)},getTreeGridContainer:function(){return a(this).closest("table")},getRootNodes:function(b){var c=a.grep(b.find("tr"),function(b){var c=a(b).attr("class"),d=/treegrid-([A-Za-z0-9_-]+)/,e=/treegrid-parent-([A-Za-z0-9_-]+)/;return d.test(c)&&!e.test(c)});return a(c)},getAllNodes:function(b){var c=a.grep(b.find("tr"),function(b){var c=a(b).attr("class"),d=/treegrid-([A-Za-z0-9_-]+)/;return d.test(c)});return a(c)},onCollapse:null,onExpand:null,onChange:null}}(jQuery); \ No newline at end of file
+/*! jquery-treegrid 0.3.0 */
+!function(a){var b={initTree:function(b){var c=a.extend({},this.treegrid.defaults,b);return this.each(function(){var b=a(this);b.treegrid("setTreeContainer",a(this)),b.treegrid("setSettings",c),c.getRootNodes.apply(this,[a(this)]).treegrid("initNode",c),b.treegrid("getRootNodes").treegrid("render")})},initNode:function(b){return this.each(function(){var c=a(this);c.treegrid("setTreeContainer",b.getTreeGridContainer.apply(this)),c.treegrid("getChildNodes").treegrid("initNode",b),c.treegrid("initExpander").treegrid("initIndent").treegrid("initEvents").treegrid("initState").treegrid("initChangeEvent").treegrid("initSettingsEvents")})},initChangeEvent:function(){var b=a(this);return b.on("change",function(){var b=a(this);b.treegrid("render"),b.treegrid("getSetting","saveState")&&b.treegrid("saveState")}),b},initEvents:function(){var b=a(this);return b.on("collapse",function(){var b=a(this);b.removeClass("treegrid-expanded"),b.addClass("treegrid-collapsed")}),b.on("expand",function(){var b=a(this);b.removeClass("treegrid-collapsed"),b.addClass("treegrid-expanded")}),b},initSettingsEvents:function(){var b=a(this);return b.on("change",function(){var b=a(this);"function"==typeof b.treegrid("getSetting","onChange")&&b.treegrid("getSetting","onChange").apply(b)}),b.on("collapse",function(){var b=a(this);"function"==typeof b.treegrid("getSetting","onCollapse")&&b.treegrid("getSetting","onCollapse").apply(b)}),b.on("expand",function(){var b=a(this);"function"==typeof b.treegrid("getSetting","onExpand")&&b.treegrid("getSetting","onExpand").apply(b)}),b},initExpander:function(){var b=a(this),c=b.find("td").get(b.treegrid("getSetting","treeColumn")),d=b.treegrid("getSetting","expanderTemplate"),e=b.treegrid("getSetting","getExpander").apply(this);return e&&e.remove(),a(d).prependTo(c).click(function(){a(a(this).closest("tr")).treegrid("toggle")}),b},initIndent:function(){var b=a(this);b.find(".treegrid-indent").remove();for(var c=b.treegrid("getSetting","indentTemplate"),d=b.find(".treegrid-expander"),e=b.treegrid("getDepth"),f=0;e>f;f++)a(c).insertBefore(d);return b},initState:function(){var b=a(this);return b.treegrid(b.treegrid("getSetting","saveState")&&!b.treegrid("isFirstInit")?"restoreState":"expanded"===b.treegrid("getSetting","initialState")?"expand":"collapse"),b},isFirstInit:function(){var b=a(this).treegrid("getTreeContainer");return void 0===b.data("first_init")&&b.data("first_init",void 0===a.cookie(b.treegrid("getSetting","saveStateName"))),b.data("first_init")},saveState:function(){var b=a(this);if("cookie"===b.treegrid("getSetting","saveStateMethod")){var c=a.cookie(b.treegrid("getSetting","saveStateName"))||"",d=""===c?[]:c.split(","),e=b.treegrid("getNodeId");b.treegrid("isExpanded")?-1===a.inArray(e,d)&&d.push(e):b.treegrid("isCollapsed")&&-1!==a.inArray(e,d)&&d.splice(a.inArray(e,d),1),a.cookie(b.treegrid("getSetting","saveStateName"),d.join(","))}return b},restoreState:function(){var b=a(this);if("cookie"===b.treegrid("getSetting","saveStateMethod")){var c=a.cookie(b.treegrid("getSetting","saveStateName")).split(",");b.treegrid(-1!==a.inArray(b.treegrid("getNodeId"),c)?"expand":"collapse")}return b},getSetting:function(b){return a(this).treegrid("getTreeContainer")?a(this).treegrid("getTreeContainer").data("settings")[b]:null},setSettings:function(b){a(this).treegrid("getTreeContainer").data("settings",b)},getTreeContainer:function(){return a(this).data("treegrid")},setTreeContainer:function(b){return a(this).data("treegrid",b)},getRootNodes:function(){return a(this).treegrid("getSetting","getRootNodes").apply(this,[a(this).treegrid("getTreeContainer")])},getAllNodes:function(){return a(this).treegrid("getSetting","getAllNodes").apply(this,[a(this).treegrid("getTreeContainer")])},isNode:function(){return null!==a(this).treegrid("getNodeId")},getNodeId:function(){return null===a(this).treegrid("getSetting","getNodeId")?null:a(this).treegrid("getSetting","getNodeId").apply(this)},getParentNodeId:function(){return a(this).treegrid("getSetting","getParentNodeId").apply(this)},getParentNode:function(){return null===a(this).treegrid("getParentNodeId")?null:a(this).treegrid("getSetting","getNodeById").apply(this,[a(this).treegrid("getParentNodeId"),a(this).treegrid("getTreeContainer")])},getChildNodes:function(){return a(this).treegrid("getSetting","getChildNodes").apply(this,[a(this).treegrid("getNodeId"),a(this).treegrid("getTreeContainer")])},getDepth:function(){return null===a(this).treegrid("getParentNode")?0:a(this).treegrid("getParentNode").treegrid("getDepth")+1},isRoot:function(){return 0===a(this).treegrid("getDepth")},isLeaf:function(){return 0===a(this).treegrid("getChildNodes").length},isLast:function(){if(a(this).treegrid("isNode")){var b=a(this).treegrid("getParentNode");if(null===b){if(a(this).treegrid("getNodeId")===a(this).treegrid("getRootNodes").last().treegrid("getNodeId"))return!0}else if(a(this).treegrid("getNodeId")===b.treegrid("getChildNodes").last().treegrid("getNodeId"))return!0}return!1},isFirst:function(){if(a(this).treegrid("isNode")){var b=a(this).treegrid("getParentNode");if(null===b){if(a(this).treegrid("getNodeId")===a(this).treegrid("getRootNodes").first().treegrid("getNodeId"))return!0}else if(a(this).treegrid("getNodeId")===b.treegrid("getChildNodes").first().treegrid("getNodeId"))return!0}return!1},isExpanded:function(){return a(this).hasClass("treegrid-expanded")},isCollapsed:function(){return a(this).hasClass("treegrid-collapsed")},isOneOfParentsCollapsed:function(){var b=a(this);return b.treegrid("isRoot")?!1:b.treegrid("getParentNode").treegrid("isCollapsed")?!0:b.treegrid("getParentNode").treegrid("isOneOfParentsCollapsed")},expand:function(){return this.treegrid("isLeaf")||this.treegrid("isExpanded")?this:(this.trigger("expand"),this.trigger("change"),this)},expandAll:function(){var b=a(this);return b.treegrid("getRootNodes").treegrid("expandRecursive"),b},expandRecursive:function(){return a(this).each(function(){var b=a(this);b.treegrid("expand"),b.treegrid("isLeaf")||b.treegrid("getChildNodes").treegrid("expandRecursive")})},collapse:function(){return a(this).each(function(){var b=a(this);b.treegrid("isLeaf")||b.treegrid("isCollapsed")||(b.trigger("collapse"),b.trigger("change"))})},collapseAll:function(){var b=a(this);return b.treegrid("getRootNodes").treegrid("collapseRecursive"),b},collapseRecursive:function(){return a(this).each(function(){var b=a(this);b.treegrid("collapse"),b.treegrid("isLeaf")||b.treegrid("getChildNodes").treegrid("collapseRecursive")})},toggle:function(){var b=a(this);return b.treegrid(b.treegrid("isExpanded")?"collapse":"expand"),b},render:function(){return a(this).each(function(){var b=a(this);b.treegrid("isOneOfParentsCollapsed")?b.hide():b.show(),b.treegrid("isLeaf")||(b.treegrid("renderExpander"),b.treegrid("getChildNodes").treegrid("render"))})},renderExpander:function(){return a(this).each(function(){var b=a(this),c=b.treegrid("getSetting","getExpander").apply(this);c?b.treegrid("isCollapsed")?(c.removeClass(b.treegrid("getSetting","expanderExpandedClass")),c.addClass(b.treegrid("getSetting","expanderCollapsedClass"))):(c.removeClass(b.treegrid("getSetting","expanderCollapsedClass")),c.addClass(b.treegrid("getSetting","expanderExpandedClass"))):(b.treegrid("initExpander"),b.treegrid("renderExpander"))})}};a.fn.treegrid=function(c){return b[c]?b[c].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof c&&c?void a.error("Method with name "+c+" does not exists for jQuery.treegrid"):b.initTree.apply(this,arguments)},a.fn.treegrid.defaults={initialState:"expanded",saveState:!1,saveStateMethod:"cookie",saveStateName:"tree-grid-state",expanderTemplate:'<span class="treegrid-expander"></span>',indentTemplate:'<span class="treegrid-indent"></span>',expanderExpandedClass:"treegrid-expander-expanded",expanderCollapsedClass:"treegrid-expander-collapsed",treeColumn:0,getExpander:function(){return a(this).find(".treegrid-expander")},getNodeId:function(){var b=/treegrid-([A-Za-z0-9_-]+)/;return b.test(a(this).attr("class"))?b.exec(a(this).attr("class"))[1]:null},getParentNodeId:function(){var b=/treegrid-parent-([A-Za-z0-9_-]+)/;return b.test(a(this).attr("class"))?b.exec(a(this).attr("class"))[1]:null},getNodeById:function(a,b){var c="treegrid-"+a;return b.find("tr."+c)},getChildNodes:function(a,b){var c="treegrid-parent-"+a;return b.find("tr."+c)},getTreeGridContainer:function(){return a(this).closest("table")},getRootNodes:function(b){var c=a.grep(b.find("tr"),function(b){var c=a(b).attr("class"),d=/treegrid-([A-Za-z0-9_-]+)/,e=/treegrid-parent-([A-Za-z0-9_-]+)/;return d.test(c)&&!e.test(c)});return a(c)},getAllNodes:function(b){var c=a.grep(b.find("tr"),function(b){var c=a(b).attr("class"),d=/treegrid-([A-Za-z0-9_-]+)/;return d.test(c)});return a(c)},onCollapse:null,onExpand:null,onChange:null}}(jQuery); \ No newline at end of file
diff --git a/library/cpp/lwtrace/mon/static/js/jquery.url.min.js b/library/cpp/lwtrace/mon/static/js/jquery.url.min.js
index 8ac9051a2a..f3b029c799 100644
--- a/library/cpp/lwtrace/mon/static/js/jquery.url.min.js
+++ b/library/cpp/lwtrace/mon/static/js/jquery.url.min.js
@@ -1 +1 @@
-/*! js-url - v2.0.2 - 2015-09-17 */window.url=function(){function a(){}function b(a){return decodeURIComponent(a.replace(/\+/g," "))}function c(a,b){var c=a.charAt(0),d=b.split(c);return c===a?d:(a=parseInt(a.substring(1),10),d[0>a?d.length+a:a-1])}function d(a,c){var d=a.charAt(0),e=c.split("&"),f=[],g={},h=[],i=a.substring(1);for(var j in e)if(f=e[j].match(/(.*?)=(.*)/),f||(f=[e[j],e[j],""]),""!==f[1].replace(/\s/g,"")){if(f[2]=b(f[2]||""),i===f[1])return f[2];h=f[1].match(/(.*)\[([0-9]+)\]/),h?(g[h[1]]=g[h[1]]||[],g[h[1]][h[2]]=f[2]):g[f[1]]=f[2]}return d===a?g:g[i]}return function(b,e){var f,g={};if("tld?"===b)return a();if(e=e||window.location.toString(),!b)return e;if(b=b.toString(),f=e.match(/^mailto:([^\/].+)/))g.protocol="mailto",g.email=f[1];else{if((f=e.match(/(.*?)#(.*)/))&&(g.hash=f[2],e=f[1]),g.hash&&b.match(/^#/))return d(b,g.hash);if((f=e.match(/(.*?)\?(.*)/))&&(g.query=f[2],e=f[1]),g.query&&b.match(/^\?/))return d(b,g.query);if((f=e.match(/(.*?)\:?\/\/(.*)/))&&(g.protocol=f[1].toLowerCase(),e=f[2]),(f=e.match(/(.*?)(\/.*)/))&&(g.path=f[2],e=f[1]),g.path=(g.path||"").replace(/^([^\/])/,"/$1").replace(/\/$/,""),b.match(/^[\-0-9]+$/)&&(b=b.replace(/^([^\/])/,"/$1")),b.match(/^\//))return c(b,g.path.substring(1));if(f=c("/-1",g.path.substring(1)),f&&(f=f.match(/(.*?)\.(.*)/))&&(g.file=f[0],g.filename=f[1],g.fileext=f[2]),(f=e.match(/(.*)\:([0-9]+)$/))&&(g.port=f[2],e=f[1]),(f=e.match(/(.*?)@(.*)/))&&(g.auth=f[1],e=f[2]),g.auth&&(f=g.auth.match(/(.*)\:(.*)/),g.user=f?f[1]:g.auth,g.pass=f?f[2]:void 0),g.hostname=e.toLowerCase(),"."===b.charAt(0))return c(b,g.hostname);a()&&(f=g.hostname.match(a()),f&&(g.tld=f[3],g.domain=f[2]?f[2]+"."+f[3]:void 0,g.sub=f[1]||void 0)),g.port=g.port||("https"===g.protocol?"443":"80"),g.protocol=g.protocol||("443"===g.port?"https":"http")}return b in g?g[b]:"[]"===b?g:void 0}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}});
+/*! js-url - v2.0.2 - 2015-09-17 */window.url=function(){function a(){}function b(a){return decodeURIComponent(a.replace(/\+/g," "))}function c(a,b){var c=a.charAt(0),d=b.split(c);return c===a?d:(a=parseInt(a.substring(1),10),d[0>a?d.length+a:a-1])}function d(a,c){var d=a.charAt(0),e=c.split("&"),f=[],g={},h=[],i=a.substring(1);for(var j in e)if(f=e[j].match(/(.*?)=(.*)/),f||(f=[e[j],e[j],""]),""!==f[1].replace(/\s/g,"")){if(f[2]=b(f[2]||""),i===f[1])return f[2];h=f[1].match(/(.*)\[([0-9]+)\]/),h?(g[h[1]]=g[h[1]]||[],g[h[1]][h[2]]=f[2]):g[f[1]]=f[2]}return d===a?g:g[i]}return function(b,e){var f,g={};if("tld?"===b)return a();if(e=e||window.location.toString(),!b)return e;if(b=b.toString(),f=e.match(/^mailto:([^\/].+)/))g.protocol="mailto",g.email=f[1];else{if((f=e.match(/(.*?)#(.*)/))&&(g.hash=f[2],e=f[1]),g.hash&&b.match(/^#/))return d(b,g.hash);if((f=e.match(/(.*?)\?(.*)/))&&(g.query=f[2],e=f[1]),g.query&&b.match(/^\?/))return d(b,g.query);if((f=e.match(/(.*?)\:?\/\/(.*)/))&&(g.protocol=f[1].toLowerCase(),e=f[2]),(f=e.match(/(.*?)(\/.*)/))&&(g.path=f[2],e=f[1]),g.path=(g.path||"").replace(/^([^\/])/,"/$1").replace(/\/$/,""),b.match(/^[\-0-9]+$/)&&(b=b.replace(/^([^\/])/,"/$1")),b.match(/^\//))return c(b,g.path.substring(1));if(f=c("/-1",g.path.substring(1)),f&&(f=f.match(/(.*?)\.(.*)/))&&(g.file=f[0],g.filename=f[1],g.fileext=f[2]),(f=e.match(/(.*)\:([0-9]+)$/))&&(g.port=f[2],e=f[1]),(f=e.match(/(.*?)@(.*)/))&&(g.auth=f[1],e=f[2]),g.auth&&(f=g.auth.match(/(.*)\:(.*)/),g.user=f?f[1]:g.auth,g.pass=f?f[2]:void 0),g.hostname=e.toLowerCase(),"."===b.charAt(0))return c(b,g.hostname);a()&&(f=g.hostname.match(a()),f&&(g.tld=f[3],g.domain=f[2]?f[2]+"."+f[3]:void 0,g.sub=f[1]||void 0)),g.port=g.port||("https"===g.protocol?"443":"80"),g.protocol=g.protocol||("443"===g.port?"https":"http")}return b in g?g[b]:"[]"===b?g:void 0}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}});
diff --git a/library/cpp/lwtrace/mon/trace.sh b/library/cpp/lwtrace/mon/trace.sh
index 8414a9b0ca..0424e1548f 100755
--- a/library/cpp/lwtrace/mon/trace.sh
+++ b/library/cpp/lwtrace/mon/trace.sh
@@ -1,81 +1,81 @@
-#!/bin/sh -e
-# $Id: trace.sh 2313967 2016-05-24 12:52:38Z serxa $
-# $HeadURL: svn+ssh://arcadia.yandex.ru/arc/trunk/arcadia/library/cpp/lwtrace/mon/trace.sh $
-
-usage() {
- if [ -n "$*" ]; then
- echo "ERROR: $*" >&2
- else
- echo "Script for LWTrace tracing management" >&2
- fi
- echo "USAGE: `basename $0` COMMAND TRACEID HOST:PORT PARAM1=VALUE1 ..." >&2
- echo "COMMANDS:" >&2
- echo " new Start new tracing described by query from STDIN," >&2
- echo " uniquely named with TRACEID string," >&2
- echo " using HOST:PORT monitoring service." >&2
- echo " query can contain \$params that are substituted with corresponding values from cmdline" >&2
- echo " (alse \$\$ is replaced by \$, each param must be defined from cmdline)" >&2
- echo " delete Stop existing tracing with specified name TRACEID," >&2
- echo " on HOST:PORT monitoring service." >&2
- exit 1
-}
-
-COMMAND=$1
-ID="$2"
-IDENC="$(perl -MURI::Escape -e '$id = $ARGV[0]; $id=uri_escape($id); $id =~ s{[+%]}{-}g; print $id;' "$ID")"
-ADDRESS="$3"
-if [ "$COMMAND" = "--help" ] || [ -z "$*" ]; then usage; fi
-if [ -z "$ID" ]; then usage "TRACEID is not specified"; fi
-if [ -z "$ADDRESS" ]; then usage "HOST:PORT is not specified"; fi
-
-shift 3
-
-STATUS=0
-ERRFILE=/var/tmp/lwtrace.sh.$$
-
-error() {
- echo "ERROR: $*" >&2
- [ ! -e $ERRFILE ] || cat $ERRFILE >&2
- exit 1
-}
-
-stop() { rm -f $ERRFILE; }
-trap stop INT ABRT EXIT
-
-case "$COMMAND" in
-
- new)
- QUERY="$(perl -e 'use MIME::Base64;
- local $/;
- $a = <STDIN>;
- for $arg (@ARGV) {
- ($k,$v) = split "=",$arg,2;
- $a =~ s{\$$k}{$v}g;
- }
- if ($a =~ /\$([A-Za-z_][\w_]*)/) {
- print STDERR "undefined param in lwtrace query: $1\n";
- exit 0
- }
- $a =~ s{\$\$}{\$}g;
- print encode_base64($a, "");
- ' "$@" 2>$ERRFILE)"
- if [ -z "$QUERY" ]; then error "lwtrace query errors"; fi
- wget --post-data="id=$IDENC&query=$QUERY" \
- -O - http://$ADDRESS/trace?mode=new </dev/null 2>$ERRFILE || STATUS=$?
- if [ $STATUS -ne 0 ]; then error "wget failure"; fi
- ;;
-
- delete)
- wget --post-data="id=$IDENC" \
- -O - http://$ADDRESS/trace?mode=delete </dev/null 2>$ERRFILE || STATUS=$?
- if [ $STATUS -ne 0 ]; then error "wget failure"; fi
- ;;
-
- *)
- echo "usage: `basename $0` new TRACEID ADDRESS < query.txt" >&2
- echo " `basename $0` delete TRACEID ADDRESS" >&2
- exit 1
- ;;
-
-esac
-echo "Done"
+#!/bin/sh -e
+# $Id: trace.sh 2313967 2016-05-24 12:52:38Z serxa $
+# $HeadURL: svn+ssh://arcadia.yandex.ru/arc/trunk/arcadia/library/cpp/lwtrace/mon/trace.sh $
+
+usage() {
+ if [ -n "$*" ]; then
+ echo "ERROR: $*" >&2
+ else
+ echo "Script for LWTrace tracing management" >&2
+ fi
+ echo "USAGE: `basename $0` COMMAND TRACEID HOST:PORT PARAM1=VALUE1 ..." >&2
+ echo "COMMANDS:" >&2
+ echo " new Start new tracing described by query from STDIN," >&2
+ echo " uniquely named with TRACEID string," >&2
+ echo " using HOST:PORT monitoring service." >&2
+ echo " query can contain \$params that are substituted with corresponding values from cmdline" >&2
+ echo " (alse \$\$ is replaced by \$, each param must be defined from cmdline)" >&2
+ echo " delete Stop existing tracing with specified name TRACEID," >&2
+ echo " on HOST:PORT monitoring service." >&2
+ exit 1
+}
+
+COMMAND=$1
+ID="$2"
+IDENC="$(perl -MURI::Escape -e '$id = $ARGV[0]; $id=uri_escape($id); $id =~ s{[+%]}{-}g; print $id;' "$ID")"
+ADDRESS="$3"
+if [ "$COMMAND" = "--help" ] || [ -z "$*" ]; then usage; fi
+if [ -z "$ID" ]; then usage "TRACEID is not specified"; fi
+if [ -z "$ADDRESS" ]; then usage "HOST:PORT is not specified"; fi
+
+shift 3
+
+STATUS=0
+ERRFILE=/var/tmp/lwtrace.sh.$$
+
+error() {
+ echo "ERROR: $*" >&2
+ [ ! -e $ERRFILE ] || cat $ERRFILE >&2
+ exit 1
+}
+
+stop() { rm -f $ERRFILE; }
+trap stop INT ABRT EXIT
+
+case "$COMMAND" in
+
+ new)
+ QUERY="$(perl -e 'use MIME::Base64;
+ local $/;
+ $a = <STDIN>;
+ for $arg (@ARGV) {
+ ($k,$v) = split "=",$arg,2;
+ $a =~ s{\$$k}{$v}g;
+ }
+ if ($a =~ /\$([A-Za-z_][\w_]*)/) {
+ print STDERR "undefined param in lwtrace query: $1\n";
+ exit 0
+ }
+ $a =~ s{\$\$}{\$}g;
+ print encode_base64($a, "");
+ ' "$@" 2>$ERRFILE)"
+ if [ -z "$QUERY" ]; then error "lwtrace query errors"; fi
+ wget --post-data="id=$IDENC&query=$QUERY" \
+ -O - http://$ADDRESS/trace?mode=new </dev/null 2>$ERRFILE || STATUS=$?
+ if [ $STATUS -ne 0 ]; then error "wget failure"; fi
+ ;;
+
+ delete)
+ wget --post-data="id=$IDENC" \
+ -O - http://$ADDRESS/trace?mode=delete </dev/null 2>$ERRFILE || STATUS=$?
+ if [ $STATUS -ne 0 ]; then error "wget failure"; fi
+ ;;
+
+ *)
+ echo "usage: `basename $0` new TRACEID ADDRESS < query.txt" >&2
+ echo " `basename $0` delete TRACEID ADDRESS" >&2
+ exit 1
+ ;;
+
+esac
+echo "Done"
diff --git a/library/cpp/lwtrace/mon/ya.make b/library/cpp/lwtrace/mon/ya.make
index bdcb315754..6c8c11887a 100644
--- a/library/cpp/lwtrace/mon/ya.make
+++ b/library/cpp/lwtrace/mon/ya.make
@@ -1,55 +1,55 @@
-LIBRARY()
-
+LIBRARY()
+
OWNER(serxa g:kikimr)
-
-RESOURCE(
- static/common.css lwtrace/mon/static/common.css
- static/common.js lwtrace/mon/static/common.js
- static/css/bootstrap.min.css lwtrace/mon/static/css/bootstrap.min.css
- static/css/d3-gantt.css lwtrace/mon/static/css/d3-gantt.css
- static/css/jquery.treegrid.css lwtrace/mon/static/css/jquery.treegrid.css
- static/analytics.css lwtrace/mon/static/analytics.css
- static/analytics.flot.html lwtrace/mon/static/analytics.flot.html
- static/analytics.gantt.html lwtrace/mon/static/analytics.gantt.html
- static/analytics.header.html lwtrace/mon/static/analytics.header.html
- static/analytics.js lwtrace/mon/static/analytics.js
- static/fonts/glyphicons-halflings-regular.eot lwtrace/mon/static/fonts/glyphicons-halflings-regular.eot
- static/fonts/glyphicons-halflings-regular.svg lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg
- static/fonts/glyphicons-halflings-regular.ttf lwtrace/mon/static/fonts/glyphicons-halflings-regular.ttf
- static/fonts/glyphicons-halflings-regular.woff2 lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff2
- static/fonts/glyphicons-halflings-regular.woff lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff
- static/footer.html lwtrace/mon/static/footer.html
- static/header.html lwtrace/mon/static/header.html
- static/img/collapse.png lwtrace/mon/static/img/collapse.png
- static/img/expand.png lwtrace/mon/static/img/expand.png
- static/img/file.png lwtrace/mon/static/img/file.png
- static/img/folder.png lwtrace/mon/static/img/folder.png
- static/js/bootstrap.min.js lwtrace/mon/static/js/bootstrap.min.js
- static/js/d3.v4.min.js lwtrace/mon/static/js/d3.v4.min.js
- static/js/d3-gantt.js lwtrace/mon/static/js/d3-gantt.js
- static/js/d3-tip-0.8.0-alpha.1.js lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js
- static/js/filesaver.min.js lwtrace/mon/static/js/filesaver.min.js
- static/js/jquery.flot.extents.js lwtrace/mon/static/js/jquery.flot.extents.js
- static/js/jquery.flot.min.js lwtrace/mon/static/js/jquery.flot.min.js
- static/js/jquery.flot.navigate.min.js lwtrace/mon/static/js/jquery.flot.navigate.min.js
- static/js/jquery.flot.selection.min.js lwtrace/mon/static/js/jquery.flot.selection.min.js
- static/js/jquery.min.js lwtrace/mon/static/js/jquery.min.js
- static/js/jquery.treegrid.bootstrap3.js lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js
- static/js/jquery.treegrid.min.js lwtrace/mon/static/js/jquery.treegrid.min.js
- static/js/jquery.url.min.js lwtrace/mon/static/js/jquery.url.min.js
-)
-
-SRCS(
- mon_lwtrace.cpp
-)
-
-PEERDIR(
+
+RESOURCE(
+ static/common.css lwtrace/mon/static/common.css
+ static/common.js lwtrace/mon/static/common.js
+ static/css/bootstrap.min.css lwtrace/mon/static/css/bootstrap.min.css
+ static/css/d3-gantt.css lwtrace/mon/static/css/d3-gantt.css
+ static/css/jquery.treegrid.css lwtrace/mon/static/css/jquery.treegrid.css
+ static/analytics.css lwtrace/mon/static/analytics.css
+ static/analytics.flot.html lwtrace/mon/static/analytics.flot.html
+ static/analytics.gantt.html lwtrace/mon/static/analytics.gantt.html
+ static/analytics.header.html lwtrace/mon/static/analytics.header.html
+ static/analytics.js lwtrace/mon/static/analytics.js
+ static/fonts/glyphicons-halflings-regular.eot lwtrace/mon/static/fonts/glyphicons-halflings-regular.eot
+ static/fonts/glyphicons-halflings-regular.svg lwtrace/mon/static/fonts/glyphicons-halflings-regular.svg
+ static/fonts/glyphicons-halflings-regular.ttf lwtrace/mon/static/fonts/glyphicons-halflings-regular.ttf
+ static/fonts/glyphicons-halflings-regular.woff2 lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff2
+ static/fonts/glyphicons-halflings-regular.woff lwtrace/mon/static/fonts/glyphicons-halflings-regular.woff
+ static/footer.html lwtrace/mon/static/footer.html
+ static/header.html lwtrace/mon/static/header.html
+ static/img/collapse.png lwtrace/mon/static/img/collapse.png
+ static/img/expand.png lwtrace/mon/static/img/expand.png
+ static/img/file.png lwtrace/mon/static/img/file.png
+ static/img/folder.png lwtrace/mon/static/img/folder.png
+ static/js/bootstrap.min.js lwtrace/mon/static/js/bootstrap.min.js
+ static/js/d3.v4.min.js lwtrace/mon/static/js/d3.v4.min.js
+ static/js/d3-gantt.js lwtrace/mon/static/js/d3-gantt.js
+ static/js/d3-tip-0.8.0-alpha.1.js lwtrace/mon/static/js/d3-tip-0.8.0-alpha.1.js
+ static/js/filesaver.min.js lwtrace/mon/static/js/filesaver.min.js
+ static/js/jquery.flot.extents.js lwtrace/mon/static/js/jquery.flot.extents.js
+ static/js/jquery.flot.min.js lwtrace/mon/static/js/jquery.flot.min.js
+ static/js/jquery.flot.navigate.min.js lwtrace/mon/static/js/jquery.flot.navigate.min.js
+ static/js/jquery.flot.selection.min.js lwtrace/mon/static/js/jquery.flot.selection.min.js
+ static/js/jquery.min.js lwtrace/mon/static/js/jquery.min.js
+ static/js/jquery.treegrid.bootstrap3.js lwtrace/mon/static/js/jquery.treegrid.bootstrap3.js
+ static/js/jquery.treegrid.min.js lwtrace/mon/static/js/jquery.treegrid.min.js
+ static/js/jquery.url.min.js lwtrace/mon/static/js/jquery.url.min.js
+)
+
+SRCS(
+ mon_lwtrace.cpp
+)
+
+PEERDIR(
library/cpp/html/pcdata
library/cpp/lwtrace
- library/cpp/lwtrace/mon/analytics
+ library/cpp/lwtrace/mon/analytics
library/cpp/monlib/dynamic_counters
library/cpp/resource
library/cpp/string_utils/base64
-)
-
-END()
+)
+
+END()
diff --git a/library/cpp/lwtrace/perf.cpp b/library/cpp/lwtrace/perf.cpp
index 03b68586ea..b3f109c1be 100644
--- a/library/cpp/lwtrace/perf.cpp
+++ b/library/cpp/lwtrace/perf.cpp
@@ -1,84 +1,84 @@
-#include "perf.h"
-
+#include "perf.h"
+
#include "probes.h"
-#include <util/system/datetime.h>
-#include <util/system/hp_timer.h>
-
-namespace NLWTrace {
- LWTRACE_USING(LWTRACE_INTERNAL_PROVIDER);
-
- TCpuTracker::TCpuTracker()
- : MinReportPeriod(NHPTimer::GetCyclesPerSecond())
- {
- ResetStats();
- }
-
- void TCpuTracker::Enter() {
- LastTs = GetCycleCount();
- }
-
- void TCpuTracker::Exit(const TProbe* probe) {
- ui64 exitTs = GetCycleCount();
- if (exitTs < LastTs) {
- return; // probably TSC was reset
- }
- ui64 cycles = exitTs - LastTs;
- LastTs = exitTs;
-
- AddStats(probe, cycles);
- }
-
- void TCpuTracker::AddStats(const TProbe* probe, ui64 cycles) {
- if (MaxCycles < cycles) {
- MaxProbe = probe;
- MaxCycles = cycles;
- }
- if (MinCycles > cycles) {
- MinCycles = cycles;
- }
- ProbeCycles += cycles;
- Count++;
-
- if (LastTs - LastReportTs > MinReportPeriod) {
- Report();
- }
- }
-
- void TCpuTracker::ResetStats() {
- MaxCycles = 0;
- MaxProbe = nullptr;
- MinCycles = ui64(-1);
- ProbeCycles = 0;
- Count = 0;
- }
-
- void TCpuTracker::Report() {
- if (!Reporting) {
- Reporting = true;
- ReportNotReentrant();
- Reporting = false;
- }
- }
-
- void TCpuTracker::ReportNotReentrant() {
- if (LastReportTs && Count > 0 && LastTs > LastReportTs) {
- ui64 reportPeriod = LastTs - LastReportTs;
- double share = double(ProbeCycles) / reportPeriod;
- double minMs = MilliSeconds(MinCycles);
- double maxMs = MilliSeconds(MaxCycles);
- double avgMs = MilliSeconds(ProbeCycles) / Count;
- LastReportTs = LastTs;
- ResetStats();
- LWPROBE(PerfReport, share, minMs, maxMs, avgMs);
- } else {
- LastReportTs = LastTs;
- ResetStats();
- }
- }
-
- double TCpuTracker::MilliSeconds(ui64 cycles) {
- return NHPTimer::GetSeconds(cycles) * 1000.0;
- }
-
-}
+#include <util/system/datetime.h>
+#include <util/system/hp_timer.h>
+
+namespace NLWTrace {
+ LWTRACE_USING(LWTRACE_INTERNAL_PROVIDER);
+
+ TCpuTracker::TCpuTracker()
+ : MinReportPeriod(NHPTimer::GetCyclesPerSecond())
+ {
+ ResetStats();
+ }
+
+ void TCpuTracker::Enter() {
+ LastTs = GetCycleCount();
+ }
+
+ void TCpuTracker::Exit(const TProbe* probe) {
+ ui64 exitTs = GetCycleCount();
+ if (exitTs < LastTs) {
+ return; // probably TSC was reset
+ }
+ ui64 cycles = exitTs - LastTs;
+ LastTs = exitTs;
+
+ AddStats(probe, cycles);
+ }
+
+ void TCpuTracker::AddStats(const TProbe* probe, ui64 cycles) {
+ if (MaxCycles < cycles) {
+ MaxProbe = probe;
+ MaxCycles = cycles;
+ }
+ if (MinCycles > cycles) {
+ MinCycles = cycles;
+ }
+ ProbeCycles += cycles;
+ Count++;
+
+ if (LastTs - LastReportTs > MinReportPeriod) {
+ Report();
+ }
+ }
+
+ void TCpuTracker::ResetStats() {
+ MaxCycles = 0;
+ MaxProbe = nullptr;
+ MinCycles = ui64(-1);
+ ProbeCycles = 0;
+ Count = 0;
+ }
+
+ void TCpuTracker::Report() {
+ if (!Reporting) {
+ Reporting = true;
+ ReportNotReentrant();
+ Reporting = false;
+ }
+ }
+
+ void TCpuTracker::ReportNotReentrant() {
+ if (LastReportTs && Count > 0 && LastTs > LastReportTs) {
+ ui64 reportPeriod = LastTs - LastReportTs;
+ double share = double(ProbeCycles) / reportPeriod;
+ double minMs = MilliSeconds(MinCycles);
+ double maxMs = MilliSeconds(MaxCycles);
+ double avgMs = MilliSeconds(ProbeCycles) / Count;
+ LastReportTs = LastTs;
+ ResetStats();
+ LWPROBE(PerfReport, share, minMs, maxMs, avgMs);
+ } else {
+ LastReportTs = LastTs;
+ ResetStats();
+ }
+ }
+
+ double TCpuTracker::MilliSeconds(ui64 cycles) {
+ return NHPTimer::GetSeconds(cycles) * 1000.0;
+ }
+
+}
diff --git a/library/cpp/lwtrace/perf.h b/library/cpp/lwtrace/perf.h
index d535247196..03564eeb3f 100644
--- a/library/cpp/lwtrace/perf.h
+++ b/library/cpp/lwtrace/perf.h
@@ -1,63 +1,63 @@
-#pragma once
-
-#include <util/system/types.h>
-#include <util/thread/singleton.h>
-
-namespace NLWTrace {
- struct TProbe;
-
- class TCpuTracker {
- private:
- const ui64 MinReportPeriod;
-
- // State
- bool Reporting = false;
- ui64 LastTs = 0;
- ui64 LastReportTs = 0;
-
- // Statistics
- ui64 MaxCycles;
- const TProbe* MaxProbe;
- ui64 MinCycles;
- ui64 ProbeCycles;
- ui64 Count;
-
- public:
- TCpuTracker();
- void Enter();
- void Exit(const TProbe* Probe);
- static TCpuTracker* TlsInstance() {
- struct TCpuTrackerkHolder {
- TCpuTracker Tracker;
- };
- return &FastTlsSingletonWithPriority<TCpuTrackerkHolder, 4>()->Tracker;
- }
-
- private:
- void AddStats(const TProbe* probe, ui64 cycles);
- void ResetStats();
- void Report();
- void ReportNotReentrant();
- static double MilliSeconds(ui64 cycles);
- };
-
- class TScopedThreadCpuTracker {
- private:
- const TProbe* Probe;
- TCpuTracker* Tracker;
-
- public:
- template <class T>
- explicit TScopedThreadCpuTracker(const T& probe)
- : Probe(&probe.Probe)
- , Tracker(TCpuTracker::TlsInstance())
- {
- Tracker->Enter();
- }
-
- ~TScopedThreadCpuTracker() {
- Tracker->Exit(Probe);
- }
- };
-
-}
+#pragma once
+
+#include <util/system/types.h>
+#include <util/thread/singleton.h>
+
+namespace NLWTrace {
+ struct TProbe;
+
+ class TCpuTracker {
+ private:
+ const ui64 MinReportPeriod;
+
+ // State
+ bool Reporting = false;
+ ui64 LastTs = 0;
+ ui64 LastReportTs = 0;
+
+ // Statistics
+ ui64 MaxCycles;
+ const TProbe* MaxProbe;
+ ui64 MinCycles;
+ ui64 ProbeCycles;
+ ui64 Count;
+
+ public:
+ TCpuTracker();
+ void Enter();
+ void Exit(const TProbe* Probe);
+ static TCpuTracker* TlsInstance() {
+ struct TCpuTrackerkHolder {
+ TCpuTracker Tracker;
+ };
+ return &FastTlsSingletonWithPriority<TCpuTrackerkHolder, 4>()->Tracker;
+ }
+
+ private:
+ void AddStats(const TProbe* probe, ui64 cycles);
+ void ResetStats();
+ void Report();
+ void ReportNotReentrant();
+ static double MilliSeconds(ui64 cycles);
+ };
+
+ class TScopedThreadCpuTracker {
+ private:
+ const TProbe* Probe;
+ TCpuTracker* Tracker;
+
+ public:
+ template <class T>
+ explicit TScopedThreadCpuTracker(const T& probe)
+ : Probe(&probe.Probe)
+ , Tracker(TCpuTracker::TlsInstance())
+ {
+ Tracker->Enter();
+ }
+
+ ~TScopedThreadCpuTracker() {
+ Tracker->Exit(Probe);
+ }
+ };
+
+}
diff --git a/library/cpp/lwtrace/preprocessor.h b/library/cpp/lwtrace/preprocessor.h
index 40865467b2..abc21870d6 100644
--- a/library/cpp/lwtrace/preprocessor.h
+++ b/library/cpp/lwtrace/preprocessor.h
@@ -1,8 +1,8 @@
-#pragma once
-
-#include "check.h"
-#include "perf.h"
-#include "symbol.h"
+#pragma once
+
+#include "check.h"
+#include "perf.h"
+#include "symbol.h"
#include <util/generic/hide_ptr.h>
#include <util/system/platform.h>
@@ -15,281 +15,281 @@
#endif // LWTRACE_DISABLE
#endif // _win_
-// Maximum number of executors that can be attached to a probe
-#define LWTRACE_MAX_ACTIONS 100
-
-// Maximum number of groups that can be assigned to a probe
-#define LWTRACE_MAX_GROUPS 100
-
-#ifndef LWTRACE_DISABLE
-
-/*
- * WARNING: All macros define in this header must be considered as implementation details and should NOT be used directly
- * WARNING: See lwtrace/all.h for macros that represent a user interface of lwtrace library
- *
- */
-
-// Use for code generation to handle parameter types. USAGE:
-// 1. #define FOREACH_PARAMTYPE_MACRO(n, t, v, your_p1, your_p2) your code snippet
-// 2. FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_value, your_p1_value)
-// FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_another_value, your_p1_another_value)
-// 3. #undef FOREACH_PARAMTYPE_MACRO
+// Maximum number of executors that can be attached to a probe
+#define LWTRACE_MAX_ACTIONS 100
+
+// Maximum number of groups that can be assigned to a probe
+#define LWTRACE_MAX_GROUPS 100
+
+#ifndef LWTRACE_DISABLE
+
+/*
+ * WARNING: All macros define in this header must be considered as implementation details and should NOT be used directly
+ * WARNING: See lwtrace/all.h for macros that represent a user interface of lwtrace library
+ *
+ */
+
+// Use for code generation to handle parameter types. USAGE:
+// 1. #define FOREACH_PARAMTYPE_MACRO(n, t, v, your_p1, your_p2) your code snippet
+// 2. FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_value, your_p1_value)
+// FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_another_value, your_p1_another_value)
+// 3. #undef FOREACH_PARAMTYPE_MACRO
// Type order matters!
-#define FOREACH_PARAMTYPE(MACRO, ...) \
- MACRO("i64", i64, I64, ##__VA_ARGS__) \
- MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \
- MACRO("double", double, Double, ##__VA_ARGS__) \
- MACRO("string", TString, Str, ##__VA_ARGS__) \
- MACRO("symbol", NLWTrace::TSymbol, Symbol, ##__VA_ARGS__) \
- MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \
- /**/
-
-// Used with FOREACH_PARAMTYPE to handle TNil parameter type also
-#define FOR_NIL_PARAMTYPE(MACRO, ...) \
- MACRO(NULL, TNil, Nil, ##__VA_ARGS__) \
- /**/
-
+#define FOREACH_PARAMTYPE(MACRO, ...) \
+ MACRO("i64", i64, I64, ##__VA_ARGS__) \
+ MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \
+ MACRO("double", double, Double, ##__VA_ARGS__) \
+ MACRO("string", TString, Str, ##__VA_ARGS__) \
+ MACRO("symbol", NLWTrace::TSymbol, Symbol, ##__VA_ARGS__) \
+ MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \
+ /**/
+
+// Used with FOREACH_PARAMTYPE to handle TNil parameter type also
+#define FOR_NIL_PARAMTYPE(MACRO, ...) \
+ MACRO(NULL, TNil, Nil, ##__VA_ARGS__) \
+ /**/
+
// Used for math statements
-#define FOR_MATH_PARAMTYPE(MACRO, ...) \
- MACRO("i64", i64, I64, ##__VA_ARGS__) \
- MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \
- MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \
+#define FOR_MATH_PARAMTYPE(MACRO, ...) \
+ MACRO("i64", i64, I64, ##__VA_ARGS__) \
+ MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \
+ MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \
/**/
-// Use for code generation to handle parameter lists
+// Use for code generation to handle parameter lists
// NOTE: this is the only place to change if more parameters needed
-#define FOREACH_PARAMNUM(MACRO, ...) \
- MACRO(0, ##__VA_ARGS__) \
- MACRO(1, ##__VA_ARGS__) \
- MACRO(2, ##__VA_ARGS__) \
- MACRO(3, ##__VA_ARGS__) \
- MACRO(4, ##__VA_ARGS__) \
- MACRO(5, ##__VA_ARGS__) \
- MACRO(6, ##__VA_ARGS__) \
- MACRO(7, ##__VA_ARGS__) \
- MACRO(8, ##__VA_ARGS__) \
- MACRO(9, ##__VA_ARGS__) \
- MACRO(10, ##__VA_ARGS__) \
- MACRO(11, ##__VA_ARGS__) \
- MACRO(12, ##__VA_ARGS__) \
- MACRO(13, ##__VA_ARGS__) \
- MACRO(14, ##__VA_ARGS__) \
- MACRO(15, ##__VA_ARGS__) \
- MACRO(16, ##__VA_ARGS__) \
- /**/
-
+#define FOREACH_PARAMNUM(MACRO, ...) \
+ MACRO(0, ##__VA_ARGS__) \
+ MACRO(1, ##__VA_ARGS__) \
+ MACRO(2, ##__VA_ARGS__) \
+ MACRO(3, ##__VA_ARGS__) \
+ MACRO(4, ##__VA_ARGS__) \
+ MACRO(5, ##__VA_ARGS__) \
+ MACRO(6, ##__VA_ARGS__) \
+ MACRO(7, ##__VA_ARGS__) \
+ MACRO(8, ##__VA_ARGS__) \
+ MACRO(9, ##__VA_ARGS__) \
+ MACRO(10, ##__VA_ARGS__) \
+ MACRO(11, ##__VA_ARGS__) \
+ MACRO(12, ##__VA_ARGS__) \
+ MACRO(13, ##__VA_ARGS__) \
+ MACRO(14, ##__VA_ARGS__) \
+ MACRO(15, ##__VA_ARGS__) \
+ MACRO(16, ##__VA_ARGS__) \
+ /**/
+
#define FOREACH_LEFT_TYPE(MACRO, ...) \
- MACRO(__VA_ARGS__, OT_VARIABLE) \
- MACRO(__VA_ARGS__, OT_LITERAL) \
- MACRO(__VA_ARGS__, OT_PARAMETER) \
+ MACRO(__VA_ARGS__, OT_VARIABLE) \
+ MACRO(__VA_ARGS__, OT_LITERAL) \
+ MACRO(__VA_ARGS__, OT_PARAMETER) \
/**/
#define FOREACH_RIGHT_TYPE(MACRO, ...) \
- MACRO(__VA_ARGS__, OT_VARIABLE) \
- MACRO(__VA_ARGS__, OT_LITERAL) \
- MACRO(__VA_ARGS__, OT_PARAMETER) \
+ MACRO(__VA_ARGS__, OT_VARIABLE) \
+ MACRO(__VA_ARGS__, OT_LITERAL) \
+ MACRO(__VA_ARGS__, OT_PARAMETER) \
/**/
#define FOREACH_DESTINATION_TYPE(MACRO, ...) \
- MACRO(__VA_ARGS__, OT_VARIABLE) \
+ MACRO(__VA_ARGS__, OT_VARIABLE) \
/**/
-// Auxilary macros
-#define LWTRACE_EXPAND(x) x
-#define LWTRACE_EAT(...)
-
-// Eat last/first comma trick
-#define LWTRACE_COMMA(bit) LWTRACE_COMMA_##bit()
-#define LWTRACE_COMMA_0()
-#define LWTRACE_COMMA_1() ,
-
-// Macros to pack/unpack tuples, e.g. (x,y,z)
-#define LWTRACE_UNROLL(...) __VA_ARGS__
-#define LWTRACE_ENROLL(...) (__VA_ARGS__)
-
-// Param types list handling macros
-#define LWTRACE_TEMPLATE_PARAMS_I(i) (1) class TP##i = TNil LWTRACE_COMMA
-#define LWTRACE_TEMPLATE_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_I)(0))
-#define LWTRACE_TEMPLATE_PARAMS_NODEF_I(i) (1) class TP##i LWTRACE_COMMA
-#define LWTRACE_TEMPLATE_PARAMS_NODEF LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_NODEF_I)(0))
-#define LWTRACE_TEMPLATE_ARGS_I(i) (1) TP##i LWTRACE_COMMA
-#define LWTRACE_TEMPLATE_ARGS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_ARGS_I)(0))
+// Auxilary macros
+#define LWTRACE_EXPAND(x) x
+#define LWTRACE_EAT(...)
+
+// Eat last/first comma trick
+#define LWTRACE_COMMA(bit) LWTRACE_COMMA_##bit()
+#define LWTRACE_COMMA_0()
+#define LWTRACE_COMMA_1() ,
+
+// Macros to pack/unpack tuples, e.g. (x,y,z)
+#define LWTRACE_UNROLL(...) __VA_ARGS__
+#define LWTRACE_ENROLL(...) (__VA_ARGS__)
+
+// Param types list handling macros
+#define LWTRACE_TEMPLATE_PARAMS_I(i) (1) class TP##i = TNil LWTRACE_COMMA
+#define LWTRACE_TEMPLATE_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_I)(0))
+#define LWTRACE_TEMPLATE_PARAMS_NODEF_I(i) (1) class TP##i LWTRACE_COMMA
+#define LWTRACE_TEMPLATE_PARAMS_NODEF LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_NODEF_I)(0))
+#define LWTRACE_TEMPLATE_ARGS_I(i) (1) TP##i LWTRACE_COMMA
+#define LWTRACE_TEMPLATE_ARGS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_ARGS_I)(0))
#define LWTRACE_FUNCTION_PARAMS_I(i) (1) typename ::NLWTrace::TParamTraits<TP##i>::TFuncParam p##i = ERROR_not_enough_parameters() LWTRACE_COMMA
-#define LWTRACE_FUNCTION_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_FUNCTION_PARAMS_I)(0))
+#define LWTRACE_FUNCTION_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_FUNCTION_PARAMS_I)(0))
#define LWTRACE_PREPARE_PARAMS_I(i, params) params.Param[i].template CopyConstruct<typename ::NLWTrace::TParamTraits<TP##i>::TStoreType>(::NLWTrace::TParamTraits<TP##i>::ToStoreType(p##i));
-#define LWTRACE_PREPARE_PARAMS(params) \
- do { \
- FOREACH_PARAMNUM(LWTRACE_PREPARE_PARAMS_I, params) \
- } while (false)
-#define LWTRACE_COUNT_PARAMS_I(i) +(std::is_same<TP##i, ::NLWTrace::TNil>::value ? 0 : 1)
-#define LWTRACE_COUNT_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_COUNT_PARAMS_I))
-#define LWTRACE_MAX_PARAMS_I(i) +1
-#define LWTRACE_MAX_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_MAX_PARAMS_I))
-
-// Determine maximum sizeof(t) over all supported types
-#define LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I(n, t, v) v,
-#define LWTRACE_MAX_PARAM_SIZE_TA_TAIL \
- FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I) \
- 0
-#define LWTRACE_MAX_PARAM_SIZE_TP_I(n, t, v) , size_t v = 0
-#define LWTRACE_MAX_PARAM_SIZE_TP size_t Head = 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TP_I)
-#define LWTRACE_MAX_PARAM_SIZE_TA_I(n, t, v) , sizeof(t)
-#define LWTRACE_MAX_PARAM_SIZE_TA 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_I)
-#define LWTRACE_MAX_PARAM_SIZE ::NLWTrace::TMaxParamSize<LWTRACE_MAX_PARAM_SIZE_TA>::Result
-
-namespace NLWTrace {
- template <LWTRACE_MAX_PARAM_SIZE_TP>
- struct TMaxParamSize {
- static const size_t Tail = TMaxParamSize<LWTRACE_MAX_PARAM_SIZE_TA_TAIL>::Result;
- static const size_t Result = (Head > Tail ? Head : Tail);
- };
-
- template <>
- struct TMaxParamSize<> {
- static const size_t Result = 0;
- };
-
-}
-
-// Define stuff that is needed to register probes before main()
-#define LWTRACE_REGISTER_PROBES(provider) \
- namespace LWTRACE_GET_NAMESPACE(provider) { \
- struct TInitLWTrace##provider { \
- TInitLWTrace##provider() { \
- Singleton<NLWTrace::TProbeRegistry>()->AddProbesList(LWTRACE_GET_PROBES(provider)); \
- } \
- /* This may not be in anonymous namespace because otherwise */ \
- /* it is called twice when .so loaded twice */ \
- }* InitLWTrace##provider = Singleton<TInitLWTrace##provider>(); \
- } \
- /**/
-
-// Macro for TSignature POD structure static initialization
-#define LWTRACE_SIGNATURE_CTOR(types, names) \
- { \
- /* ParamTypes */ ::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::ParamTypes, \
- /* ParamNames */ {LWTRACE_EXPAND(LWTRACE_UNROLL names)}, \
- /* ParamCount */ ::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::ParamCount, \
- /* SerializeParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::SerializeParams, \
- /* CloneParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::CloneParams, \
+#define LWTRACE_PREPARE_PARAMS(params) \
+ do { \
+ FOREACH_PARAMNUM(LWTRACE_PREPARE_PARAMS_I, params) \
+ } while (false)
+#define LWTRACE_COUNT_PARAMS_I(i) +(std::is_same<TP##i, ::NLWTrace::TNil>::value ? 0 : 1)
+#define LWTRACE_COUNT_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_COUNT_PARAMS_I))
+#define LWTRACE_MAX_PARAMS_I(i) +1
+#define LWTRACE_MAX_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_MAX_PARAMS_I))
+
+// Determine maximum sizeof(t) over all supported types
+#define LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I(n, t, v) v,
+#define LWTRACE_MAX_PARAM_SIZE_TA_TAIL \
+ FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I) \
+ 0
+#define LWTRACE_MAX_PARAM_SIZE_TP_I(n, t, v) , size_t v = 0
+#define LWTRACE_MAX_PARAM_SIZE_TP size_t Head = 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TP_I)
+#define LWTRACE_MAX_PARAM_SIZE_TA_I(n, t, v) , sizeof(t)
+#define LWTRACE_MAX_PARAM_SIZE_TA 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_I)
+#define LWTRACE_MAX_PARAM_SIZE ::NLWTrace::TMaxParamSize<LWTRACE_MAX_PARAM_SIZE_TA>::Result
+
+namespace NLWTrace {
+ template <LWTRACE_MAX_PARAM_SIZE_TP>
+ struct TMaxParamSize {
+ static const size_t Tail = TMaxParamSize<LWTRACE_MAX_PARAM_SIZE_TA_TAIL>::Result;
+ static const size_t Result = (Head > Tail ? Head : Tail);
+ };
+
+ template <>
+ struct TMaxParamSize<> {
+ static const size_t Result = 0;
+ };
+
+}
+
+// Define stuff that is needed to register probes before main()
+#define LWTRACE_REGISTER_PROBES(provider) \
+ namespace LWTRACE_GET_NAMESPACE(provider) { \
+ struct TInitLWTrace##provider { \
+ TInitLWTrace##provider() { \
+ Singleton<NLWTrace::TProbeRegistry>()->AddProbesList(LWTRACE_GET_PROBES(provider)); \
+ } \
+ /* This may not be in anonymous namespace because otherwise */ \
+ /* it is called twice when .so loaded twice */ \
+ }* InitLWTrace##provider = Singleton<TInitLWTrace##provider>(); \
+ } \
+ /**/
+
+// Macro for TSignature POD structure static initialization
+#define LWTRACE_SIGNATURE_CTOR(types, names) \
+ { \
+ /* ParamTypes */ ::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::ParamTypes, \
+ /* ParamNames */ {LWTRACE_EXPAND(LWTRACE_UNROLL names)}, \
+ /* ParamCount */ ::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::ParamCount, \
+ /* SerializeParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::SerializeParams, \
+ /* CloneParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::CloneParams, \
/* DestroyParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::DestroyParams, \
/* SerializeToPb */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::SerializeToPb, \
/* DeserializeFromPb */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::DeserializeFromPb\
- }
-
-// Macro for TEvent POD structure static initialization
-#define LWTRACE_EVENT_CTOR(name, groups, types, names) \
- { \
- /* Name */ #name, \
- /* Groups */ {LWTRACE_EXPAND(LWTRACE_UNROLL_GROUPS groups)}, \
- /* Signature */ LWTRACE_SIGNATURE_CTOR(types, names) \
- }
-
-// Macro for TProbe POD structure static initialization
-#define LWTRACE_PROBE_CTOR(name, groups, types, names) \
- { \
- /* Event */ LWTRACE_EVENT_CTOR(name, groups, types, names), \
- /* ExecutorsCount */ 0, \
- /* Lock */ {0}, \
- /* Executors */ {0}, \
- /* Front */ 0, \
- /* Back */ 0 \
- }
-
-// Provider static data accessors
-#define LWTRACE_GET_NAMESPACE(provider) NLWTrace_##provider
-#define LWTRACE_GET_NAME(name) lwtrace_##name
-#define LWTRACE_GET_TYPE(name) TLWTrace_##name
-#define LWTRACE_GET_PROBES_I(provider) gProbes##provider
-#define LWTRACE_GET_EVENTS_I(provider) gEvents##provider
-
-// Declaration of provider static data
-#define LWTRACE_DECLARE_PROBE(name, groups, types, names) \
- typedef ::NLWTrace::TUserProbe<LWTRACE_EXPAND(LWTRACE_UNROLL types)> LWTRACE_GET_TYPE(name); \
- extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \
- /**/
-#define LWTRACE_DECLARE_EVENT(name, groups, types, names) \
- typedef ::NLWTrace::TUserEvent<LWTRACE_EXPAND(LWTRACE_UNROLL types)> LWTRACE_GET_TYPE(name); \
- extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \
- /**/
-#define LWTRACE_DECLARE_PROVIDER_I(provider) \
- namespace LWTRACE_GET_NAMESPACE(provider) { \
- provider(LWTRACE_DECLARE_PROBE, LWTRACE_DECLARE_EVENT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
- } \
- extern ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[]; \
- extern ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[]; \
- /**/
-
-// Initialization of provider static data
-#define LWTRACE_UNROLL_GROUPS(x) #x, LWTRACE_UNROLL
-#define LWTRACE_DEFINE_PROBE(name, groups, types, names) \
- LWTRACE_GET_TYPE(name) \
- LWTRACE_GET_NAME(name) = \
- {LWTRACE_PROBE_CTOR(name, groups, types, names)}; \
- /**/
-#define LWTRACE_DEFINE_EVENT(name, groups, types, names) \
- LWTRACE_GET_TYPE(name) \
- LWTRACE_GET_NAME(name) = \
- {LWTRACE_EVENT_CTOR(name, groups, types, names)}; \
- /**/
-#define LWTRACE_PROBE_ADDRESS_I(name, groups, types, names) \
- LWTRACE_GET_NAME(name).Probe, /**/
-#define LWTRACE_PROBE_ADDRESS(provider) \
- &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_PROBE_ADDRESS_I /**/
-#define LWTRACE_EVENT_ADDRESS_I(name, groups, types, names) \
- LWTRACE_GET_NAME(name).Event, /**/
-#define LWTRACE_EVENT_ADDRESS(provider) \
- &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_EVENT_ADDRESS_I /**/
-#define LWTRACE_DEFINE_PROVIDER_I(provider) \
- namespace LWTRACE_GET_NAMESPACE(provider) { \
- provider(LWTRACE_DEFINE_PROBE, LWTRACE_DEFINE_EVENT, (provider)LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
- } \
- ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[] = { \
- provider(LWTRACE_PROBE_ADDRESS(provider), LWTRACE_EAT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
- NULL}; \
- ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[] = { \
- provider(LWTRACE_EAT, LWTRACE_EVENT_ADDRESS(provider), LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
- NULL}; \
- LWTRACE_REGISTER_PROBES(provider)
- /**/
-
-#define LWPROBE_I(probe, ...) \
- do { \
- if ((probe).Probe.GetExecutorsCount() > 0) { \
- ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
- TReadSpinLockGuard g((probe).Probe.Lock); \
- if ((probe).Probe.GetExecutorsCount() > 0) { \
- (probe)(__VA_ARGS__); \
- } \
- } \
- } while (false) /**/
-
+ }
+
+// Macro for TEvent POD structure static initialization
+#define LWTRACE_EVENT_CTOR(name, groups, types, names) \
+ { \
+ /* Name */ #name, \
+ /* Groups */ {LWTRACE_EXPAND(LWTRACE_UNROLL_GROUPS groups)}, \
+ /* Signature */ LWTRACE_SIGNATURE_CTOR(types, names) \
+ }
+
+// Macro for TProbe POD structure static initialization
+#define LWTRACE_PROBE_CTOR(name, groups, types, names) \
+ { \
+ /* Event */ LWTRACE_EVENT_CTOR(name, groups, types, names), \
+ /* ExecutorsCount */ 0, \
+ /* Lock */ {0}, \
+ /* Executors */ {0}, \
+ /* Front */ 0, \
+ /* Back */ 0 \
+ }
+
+// Provider static data accessors
+#define LWTRACE_GET_NAMESPACE(provider) NLWTrace_##provider
+#define LWTRACE_GET_NAME(name) lwtrace_##name
+#define LWTRACE_GET_TYPE(name) TLWTrace_##name
+#define LWTRACE_GET_PROBES_I(provider) gProbes##provider
+#define LWTRACE_GET_EVENTS_I(provider) gEvents##provider
+
+// Declaration of provider static data
+#define LWTRACE_DECLARE_PROBE(name, groups, types, names) \
+ typedef ::NLWTrace::TUserProbe<LWTRACE_EXPAND(LWTRACE_UNROLL types)> LWTRACE_GET_TYPE(name); \
+ extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \
+ /**/
+#define LWTRACE_DECLARE_EVENT(name, groups, types, names) \
+ typedef ::NLWTrace::TUserEvent<LWTRACE_EXPAND(LWTRACE_UNROLL types)> LWTRACE_GET_TYPE(name); \
+ extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \
+ /**/
+#define LWTRACE_DECLARE_PROVIDER_I(provider) \
+ namespace LWTRACE_GET_NAMESPACE(provider) { \
+ provider(LWTRACE_DECLARE_PROBE, LWTRACE_DECLARE_EVENT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
+ } \
+ extern ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[]; \
+ extern ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[]; \
+ /**/
+
+// Initialization of provider static data
+#define LWTRACE_UNROLL_GROUPS(x) #x, LWTRACE_UNROLL
+#define LWTRACE_DEFINE_PROBE(name, groups, types, names) \
+ LWTRACE_GET_TYPE(name) \
+ LWTRACE_GET_NAME(name) = \
+ {LWTRACE_PROBE_CTOR(name, groups, types, names)}; \
+ /**/
+#define LWTRACE_DEFINE_EVENT(name, groups, types, names) \
+ LWTRACE_GET_TYPE(name) \
+ LWTRACE_GET_NAME(name) = \
+ {LWTRACE_EVENT_CTOR(name, groups, types, names)}; \
+ /**/
+#define LWTRACE_PROBE_ADDRESS_I(name, groups, types, names) \
+ LWTRACE_GET_NAME(name).Probe, /**/
+#define LWTRACE_PROBE_ADDRESS(provider) \
+ &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_PROBE_ADDRESS_I /**/
+#define LWTRACE_EVENT_ADDRESS_I(name, groups, types, names) \
+ LWTRACE_GET_NAME(name).Event, /**/
+#define LWTRACE_EVENT_ADDRESS(provider) \
+ &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_EVENT_ADDRESS_I /**/
+#define LWTRACE_DEFINE_PROVIDER_I(provider) \
+ namespace LWTRACE_GET_NAMESPACE(provider) { \
+ provider(LWTRACE_DEFINE_PROBE, LWTRACE_DEFINE_EVENT, (provider)LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
+ } \
+ ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[] = { \
+ provider(LWTRACE_PROBE_ADDRESS(provider), LWTRACE_EAT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
+ NULL}; \
+ ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[] = { \
+ provider(LWTRACE_EAT, LWTRACE_EVENT_ADDRESS(provider), LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
+ NULL}; \
+ LWTRACE_REGISTER_PROBES(provider)
+ /**/
+
+#define LWPROBE_I(probe, ...) \
+ do { \
+ if ((probe).Probe.GetExecutorsCount() > 0) { \
+ ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
+ TReadSpinLockGuard g((probe).Probe.Lock); \
+ if ((probe).Probe.GetExecutorsCount() > 0) { \
+ (probe)(__VA_ARGS__); \
+ } \
+ } \
+ } while (false) /**/
+
#define LWPROBE_ENABLED_I(probe) ((probe).Probe.GetExecutorsCount() > 0)
-#define LWPROBE_DURATION_I(probetype, uniqid, probe, ...) probetype ::TScopedDuration uniqid(probe, 0 /* fake P0 - used for duration */, ##__VA_ARGS__);
-
-#define LWTRACK_I(probe, orbit, ...) \
- do { \
- if ((probe).Probe.GetExecutorsCount() > 0) { \
- ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
- TReadSpinLockGuard g((probe).Probe.Lock); \
- if ((probe).Probe.GetExecutorsCount() > 0) { \
- (probe).Run(orbit, ##__VA_ARGS__); \
- } \
- } else { \
- auto& _orbit = (orbit); \
- if (HasShuttles(_orbit)) { \
- ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
- (probe).RunShuttles(_orbit, ##__VA_ARGS__); \
- } \
- } \
- } while (false) /**/
-
-#define LWEVENT_I(event, ...) (event)(__VA_ARGS__)
-
-#else
-#define LWTRACE_MAX_PARAM_SIZE sizeof(void*)
-#define LWTRACE_MAX_PARAMS 1
-#define FOREACH_PARAMTYPE(MACRO, ...)
-
-#endif
+#define LWPROBE_DURATION_I(probetype, uniqid, probe, ...) probetype ::TScopedDuration uniqid(probe, 0 /* fake P0 - used for duration */, ##__VA_ARGS__);
+
+#define LWTRACK_I(probe, orbit, ...) \
+ do { \
+ if ((probe).Probe.GetExecutorsCount() > 0) { \
+ ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
+ TReadSpinLockGuard g((probe).Probe.Lock); \
+ if ((probe).Probe.GetExecutorsCount() > 0) { \
+ (probe).Run(orbit, ##__VA_ARGS__); \
+ } \
+ } else { \
+ auto& _orbit = (orbit); \
+ if (HasShuttles(_orbit)) { \
+ ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
+ (probe).RunShuttles(_orbit, ##__VA_ARGS__); \
+ } \
+ } \
+ } while (false) /**/
+
+#define LWEVENT_I(event, ...) (event)(__VA_ARGS__)
+
+#else
+#define LWTRACE_MAX_PARAM_SIZE sizeof(void*)
+#define LWTRACE_MAX_PARAMS 1
+#define FOREACH_PARAMTYPE(MACRO, ...)
+
+#endif
diff --git a/library/cpp/lwtrace/probe.h b/library/cpp/lwtrace/probe.h
index 31fa282da3..1efd2361da 100644
--- a/library/cpp/lwtrace/probe.h
+++ b/library/cpp/lwtrace/probe.h
@@ -1,266 +1,266 @@
-#pragma once
-
-#include "event.h"
-#include "preprocessor.h"
-#include "rwspinlock.h"
-#include "shuttle.h"
-
+#pragma once
+
+#include "event.h"
+#include "preprocessor.h"
+#include "rwspinlock.h"
+#include "shuttle.h"
+
#include <util/datetime/cputimer.h>
#include <util/generic/hide_ptr.h>
#include <util/generic/scope.h>
#include <util/system/atomic.h>
-namespace NLWTrace {
- // Represents a chain (linked list) of steps for execution of a trace query block
- // NOTE: different executor objects are used on different probes (even for the same query block)
- class IExecutor {
- private:
- IExecutor* Next;
-
- public:
- IExecutor()
- : Next(nullptr)
- {
- }
-
- virtual ~IExecutor() {
- if (Next != nullptr) {
- delete Next;
- }
- }
-
- void Execute(TOrbit& orbit, const TParams& params) {
- if (DoExecute(orbit, params) && Next != nullptr) {
- Next->Execute(orbit, params);
- }
- }
-
- void SetNext(IExecutor* next) {
- Next = next;
- }
-
- IExecutor* GetNext() {
- return Next;
- }
-
- const IExecutor* GetNext() const {
- return Next;
- }
-
- protected:
- virtual bool DoExecute(TOrbit& orbit, const TParams& params) = 0;
- };
-
- // Common class for all probes
- struct TProbe {
- // Const configuration
- TEvent Event;
-
- // State that don't need any locking
- TAtomic ExecutorsCount;
-
- // State that must be accessed under lock
- TRWSpinLock Lock;
- IExecutor* Executors[LWTRACE_MAX_ACTIONS];
- IExecutor** Front; // Invalid if ExecutorsCount == 0
- IExecutor** Back; // Invalid if ExecutorsCount == 0
-
- void Init() {
- ExecutorsCount = 0;
- Lock.Init();
- Zero(Executors);
- Front = nullptr;
- Back = nullptr;
- }
-
- IExecutor** First() {
- return Executors;
- }
-
- IExecutor** Last() {
- return Executors + LWTRACE_MAX_ACTIONS;
- }
-
- void Inc(IExecutor**& it) {
- it++;
- if (it == Last()) {
- it = First();
- }
- }
-
- intptr_t GetExecutorsCount() const {
- return AtomicGet(ExecutorsCount);
- }
-
- bool Attach(IExecutor* exec) {
- TWriteSpinLockGuard g(Lock);
- if (ExecutorsCount > 0) {
- for (IExecutor** it = Front;; Inc(it)) {
- if (*it == nullptr) {
- *it = exec;
- AtomicIncrement(ExecutorsCount);
- return true; // Inserted into free slot in [First; Last]
- }
- if (it == Back) {
- break;
- }
- }
- IExecutor** newBack = Back;
- Inc(newBack);
- if (newBack == Front) {
- return false; // Buffer is full
- } else {
- Back = newBack;
- *Back = exec;
- AtomicIncrement(ExecutorsCount);
- return true; // Inserted after Last
- }
- } else {
- Front = Back = First();
- *Front = exec;
- AtomicIncrement(ExecutorsCount);
- return true; // Inserted as a first element
- }
- }
-
- bool Detach(IExecutor* exec) {
- TWriteSpinLockGuard g(Lock);
- for (IExecutor** it = First(); it != Last(); it++) {
- if ((*it) == exec) {
- *it = nullptr;
- AtomicDecrement(ExecutorsCount);
- if (ExecutorsCount > 0) {
- for (;; Inc(Front)) {
- if (*Front != nullptr) {
- break;
- }
- if (Front == Back) {
- break;
- }
- }
- }
- return true;
- }
- }
- return false;
- }
-
- void RunExecutors(TOrbit& orbit, const TParams& params) {
- // Read lock is implied
- if (ExecutorsCount > 0) {
- for (IExecutor** it = Front;; Inc(it)) {
- IExecutor* exec = *it;
- if (exec) {
- exec->Execute(orbit, params);
- }
- if (it == Back) {
- break;
- }
- }
- }
- }
-
- void RunShuttles(TOrbit& orbit, const TParams& params) {
- orbit.AddProbe(this, params);
- }
- };
-
-#ifndef LWTRACE_DISABLE
-
- template <class T>
- inline void PreparePtr(const T& ref, const T*& ptr) {
- ptr = &ref;
- }
-
- template <>
- inline void PreparePtr<TNil>(const TNil&, const TNil*&) {
- }
-
+namespace NLWTrace {
+ // Represents a chain (linked list) of steps for execution of a trace query block
+ // NOTE: different executor objects are used on different probes (even for the same query block)
+ class IExecutor {
+ private:
+ IExecutor* Next;
+
+ public:
+ IExecutor()
+ : Next(nullptr)
+ {
+ }
+
+ virtual ~IExecutor() {
+ if (Next != nullptr) {
+ delete Next;
+ }
+ }
+
+ void Execute(TOrbit& orbit, const TParams& params) {
+ if (DoExecute(orbit, params) && Next != nullptr) {
+ Next->Execute(orbit, params);
+ }
+ }
+
+ void SetNext(IExecutor* next) {
+ Next = next;
+ }
+
+ IExecutor* GetNext() {
+ return Next;
+ }
+
+ const IExecutor* GetNext() const {
+ return Next;
+ }
+
+ protected:
+ virtual bool DoExecute(TOrbit& orbit, const TParams& params) = 0;
+ };
+
+ // Common class for all probes
+ struct TProbe {
+ // Const configuration
+ TEvent Event;
+
+ // State that don't need any locking
+ TAtomic ExecutorsCount;
+
+ // State that must be accessed under lock
+ TRWSpinLock Lock;
+ IExecutor* Executors[LWTRACE_MAX_ACTIONS];
+ IExecutor** Front; // Invalid if ExecutorsCount == 0
+ IExecutor** Back; // Invalid if ExecutorsCount == 0
+
+ void Init() {
+ ExecutorsCount = 0;
+ Lock.Init();
+ Zero(Executors);
+ Front = nullptr;
+ Back = nullptr;
+ }
+
+ IExecutor** First() {
+ return Executors;
+ }
+
+ IExecutor** Last() {
+ return Executors + LWTRACE_MAX_ACTIONS;
+ }
+
+ void Inc(IExecutor**& it) {
+ it++;
+ if (it == Last()) {
+ it = First();
+ }
+ }
+
+ intptr_t GetExecutorsCount() const {
+ return AtomicGet(ExecutorsCount);
+ }
+
+ bool Attach(IExecutor* exec) {
+ TWriteSpinLockGuard g(Lock);
+ if (ExecutorsCount > 0) {
+ for (IExecutor** it = Front;; Inc(it)) {
+ if (*it == nullptr) {
+ *it = exec;
+ AtomicIncrement(ExecutorsCount);
+ return true; // Inserted into free slot in [First; Last]
+ }
+ if (it == Back) {
+ break;
+ }
+ }
+ IExecutor** newBack = Back;
+ Inc(newBack);
+ if (newBack == Front) {
+ return false; // Buffer is full
+ } else {
+ Back = newBack;
+ *Back = exec;
+ AtomicIncrement(ExecutorsCount);
+ return true; // Inserted after Last
+ }
+ } else {
+ Front = Back = First();
+ *Front = exec;
+ AtomicIncrement(ExecutorsCount);
+ return true; // Inserted as a first element
+ }
+ }
+
+ bool Detach(IExecutor* exec) {
+ TWriteSpinLockGuard g(Lock);
+ for (IExecutor** it = First(); it != Last(); it++) {
+ if ((*it) == exec) {
+ *it = nullptr;
+ AtomicDecrement(ExecutorsCount);
+ if (ExecutorsCount > 0) {
+ for (;; Inc(Front)) {
+ if (*Front != nullptr) {
+ break;
+ }
+ if (Front == Back) {
+ break;
+ }
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void RunExecutors(TOrbit& orbit, const TParams& params) {
+ // Read lock is implied
+ if (ExecutorsCount > 0) {
+ for (IExecutor** it = Front;; Inc(it)) {
+ IExecutor* exec = *it;
+ if (exec) {
+ exec->Execute(orbit, params);
+ }
+ if (it == Back) {
+ break;
+ }
+ }
+ }
+ }
+
+ void RunShuttles(TOrbit& orbit, const TParams& params) {
+ orbit.AddProbe(this, params);
+ }
+ };
+
+#ifndef LWTRACE_DISABLE
+
+ template <class T>
+ inline void PreparePtr(const T& ref, const T*& ptr) {
+ ptr = &ref;
+ }
+
+ template <>
+ inline void PreparePtr<TNil>(const TNil&, const TNil*&) {
+ }
+
#define LWTRACE_SCOPED_FUNCTION_PARAMS_I(i) (1) typename ::NLWTrace::TParamTraits<TP##i>::TFuncParam p##i = ERROR_not_enough_parameters() LWTRACE_COMMA
-#define LWTRACE_SCOPED_FUNCTION_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_SCOPED_FUNCTION_PARAMS_I)(0))
-#define LWTRACE_SCOPED_FUNCTION_PARAMS_BY_REF_I(i) (1) typename ::NLWTrace::TParamTraits<TP##i>::TStoreType& p##i = *(ERROR_not_enough_parameters*)(HidePointerOrigin(nullptr))LWTRACE_COMMA
-#define LWTRACE_SCOPED_FUNCTION_PARAMS_BY_REF LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_SCOPED_FUNCTION_PARAMS_BY_REF_I)(0))
-#define LWTRACE_SCOPED_PREPARE_PTRS_I(i) PreparePtr(p##i, P##i);
-#define LWTRACE_SCOPED_PREPARE_PTRS() \
- do { \
- FOREACH_PARAMNUM(LWTRACE_SCOPED_PREPARE_PTRS_I) \
- } while (false)
-#define LWTRACE_SCOPED_PREPARE_PARAMS_I(i, params) params.Param[i].CopyConstruct<typename ::NLWTrace::TParamTraits<TP##i>::TStoreType>(*P##i);
-#define LWTRACE_SCOPED_PREPARE_PARAMS(params) \
- do { \
- FOREACH_PARAMNUM(LWTRACE_SCOPED_PREPARE_PARAMS_I, params) \
- } while (false)
-
- template <LWTRACE_TEMPLATE_PARAMS>
- struct TUserProbe;
-
- template <LWTRACE_TEMPLATE_PARAMS>
- class TScopedDurationImpl {
- private:
- TUserProbe<LWTRACE_TEMPLATE_ARGS>* Probe;
- ui64 Started;
- TParams Params;
-
- public:
- explicit TScopedDurationImpl(TUserProbe<LWTRACE_TEMPLATE_ARGS>& probe, LWTRACE_SCOPED_FUNCTION_PARAMS) {
- if (probe.Probe.GetExecutorsCount() > 0) {
- Probe = &probe;
- LWTRACE_PREPARE_PARAMS(Params);
- Started = GetCycleCount();
- } else {
- Probe = nullptr;
- }
- }
- ~TScopedDurationImpl() {
- if (Probe) {
- if (Probe->Probe.GetExecutorsCount() > 0) {
- TReadSpinLockGuard g(Probe->Probe.Lock);
- if (Probe->Probe.GetExecutorsCount() > 0) {
- ui64 duration = CyclesToDuration(GetCycleCount() - Started).MicroSeconds();
- Params.Param[0].template CopyConstruct<typename TParamTraits<TP0>::TStoreType>(duration);
- TOrbit orbit;
- Probe->Probe.RunExecutors(orbit, Params);
- }
- }
- TUserSignature<LWTRACE_TEMPLATE_ARGS>::DestroyParams(Params);
- }
- }
- };
-
- // Class representing a specific probe
- template <LWTRACE_TEMPLATE_PARAMS_NODEF>
- struct TUserProbe {
- TProbe Probe;
-
- inline void operator()(LWTRACE_FUNCTION_PARAMS) {
- TParams params;
- LWTRACE_PREPARE_PARAMS(params);
+#define LWTRACE_SCOPED_FUNCTION_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_SCOPED_FUNCTION_PARAMS_I)(0))
+#define LWTRACE_SCOPED_FUNCTION_PARAMS_BY_REF_I(i) (1) typename ::NLWTrace::TParamTraits<TP##i>::TStoreType& p##i = *(ERROR_not_enough_parameters*)(HidePointerOrigin(nullptr))LWTRACE_COMMA
+#define LWTRACE_SCOPED_FUNCTION_PARAMS_BY_REF LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_SCOPED_FUNCTION_PARAMS_BY_REF_I)(0))
+#define LWTRACE_SCOPED_PREPARE_PTRS_I(i) PreparePtr(p##i, P##i);
+#define LWTRACE_SCOPED_PREPARE_PTRS() \
+ do { \
+ FOREACH_PARAMNUM(LWTRACE_SCOPED_PREPARE_PTRS_I) \
+ } while (false)
+#define LWTRACE_SCOPED_PREPARE_PARAMS_I(i, params) params.Param[i].CopyConstruct<typename ::NLWTrace::TParamTraits<TP##i>::TStoreType>(*P##i);
+#define LWTRACE_SCOPED_PREPARE_PARAMS(params) \
+ do { \
+ FOREACH_PARAMNUM(LWTRACE_SCOPED_PREPARE_PARAMS_I, params) \
+ } while (false)
+
+ template <LWTRACE_TEMPLATE_PARAMS>
+ struct TUserProbe;
+
+ template <LWTRACE_TEMPLATE_PARAMS>
+ class TScopedDurationImpl {
+ private:
+ TUserProbe<LWTRACE_TEMPLATE_ARGS>* Probe;
+ ui64 Started;
+ TParams Params;
+
+ public:
+ explicit TScopedDurationImpl(TUserProbe<LWTRACE_TEMPLATE_ARGS>& probe, LWTRACE_SCOPED_FUNCTION_PARAMS) {
+ if (probe.Probe.GetExecutorsCount() > 0) {
+ Probe = &probe;
+ LWTRACE_PREPARE_PARAMS(Params);
+ Started = GetCycleCount();
+ } else {
+ Probe = nullptr;
+ }
+ }
+ ~TScopedDurationImpl() {
+ if (Probe) {
+ if (Probe->Probe.GetExecutorsCount() > 0) {
+ TReadSpinLockGuard g(Probe->Probe.Lock);
+ if (Probe->Probe.GetExecutorsCount() > 0) {
+ ui64 duration = CyclesToDuration(GetCycleCount() - Started).MicroSeconds();
+ Params.Param[0].template CopyConstruct<typename TParamTraits<TP0>::TStoreType>(duration);
+ TOrbit orbit;
+ Probe->Probe.RunExecutors(orbit, Params);
+ }
+ }
+ TUserSignature<LWTRACE_TEMPLATE_ARGS>::DestroyParams(Params);
+ }
+ }
+ };
+
+ // Class representing a specific probe
+ template <LWTRACE_TEMPLATE_PARAMS_NODEF>
+ struct TUserProbe {
+ TProbe Probe;
+
+ inline void operator()(LWTRACE_FUNCTION_PARAMS) {
+ TParams params;
+ LWTRACE_PREPARE_PARAMS(params);
Y_DEFER { TUserSignature<LWTRACE_TEMPLATE_ARGS>::DestroyParams(params); };
- TOrbit orbit;
- Probe.RunExecutors(orbit, params);
- }
-
- inline void Run(TOrbit& orbit, LWTRACE_FUNCTION_PARAMS) {
- TParams params;
- LWTRACE_PREPARE_PARAMS(params);
+ TOrbit orbit;
+ Probe.RunExecutors(orbit, params);
+ }
+
+ inline void Run(TOrbit& orbit, LWTRACE_FUNCTION_PARAMS) {
+ TParams params;
+ LWTRACE_PREPARE_PARAMS(params);
Y_DEFER { TUserSignature<LWTRACE_TEMPLATE_ARGS>::DestroyParams(params); };
- Probe.RunExecutors(orbit, params);
- Probe.RunShuttles(orbit, params); // Executors can create shuttles
- }
-
- // Required to avoid running executors w/o lock
- inline void RunShuttles(TOrbit& orbit, LWTRACE_FUNCTION_PARAMS) {
- TParams params;
- LWTRACE_PREPARE_PARAMS(params);
- Probe.RunShuttles(orbit, params);
- TUserSignature<LWTRACE_TEMPLATE_ARGS>::DestroyParams(params);
- }
-
- typedef TScopedDurationImpl<LWTRACE_TEMPLATE_ARGS> TScopedDuration;
- };
-
-#endif
-
-}
+ Probe.RunExecutors(orbit, params);
+ Probe.RunShuttles(orbit, params); // Executors can create shuttles
+ }
+
+ // Required to avoid running executors w/o lock
+ inline void RunShuttles(TOrbit& orbit, LWTRACE_FUNCTION_PARAMS) {
+ TParams params;
+ LWTRACE_PREPARE_PARAMS(params);
+ Probe.RunShuttles(orbit, params);
+ TUserSignature<LWTRACE_TEMPLATE_ARGS>::DestroyParams(params);
+ }
+
+ typedef TScopedDurationImpl<LWTRACE_TEMPLATE_ARGS> TScopedDuration;
+ };
+
+#endif
+
+}
diff --git a/library/cpp/lwtrace/probes.cpp b/library/cpp/lwtrace/probes.cpp
index 6f19da0cc8..dba318d340 100644
--- a/library/cpp/lwtrace/probes.cpp
+++ b/library/cpp/lwtrace/probes.cpp
@@ -1,3 +1,3 @@
-#include "probes.h"
-
-LWTRACE_DEFINE_PROVIDER(LWTRACE_INTERNAL_PROVIDER)
+#include "probes.h"
+
+LWTRACE_DEFINE_PROVIDER(LWTRACE_INTERNAL_PROVIDER)
diff --git a/library/cpp/lwtrace/probes.h b/library/cpp/lwtrace/probes.h
index 68810bd118..6c11355038 100644
--- a/library/cpp/lwtrace/probes.h
+++ b/library/cpp/lwtrace/probes.h
@@ -1,12 +1,12 @@
-#pragma once
-
+#pragma once
+
#include "all.h"
-
-#define LWTRACE_INTERNAL_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
- PROBE(PerfReport, GROUPS(), \
- TYPES(double, double, double, double), \
- NAMES("probeShare", "probeMinMs", "probeMaxMs", "probeAvgMs")) \
- PROBE(DeserializationError, GROUPS("LWTraceError"), \
+
+#define LWTRACE_INTERNAL_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
+ PROBE(PerfReport, GROUPS(), \
+ TYPES(double, double, double, double), \
+ NAMES("probeShare", "probeMinMs", "probeMaxMs", "probeAvgMs")) \
+ PROBE(DeserializationError, GROUPS("LWTraceError"), \
TYPES(TString, TString), \
NAMES("probeName", "providerName")) \
PROBE(Fork, GROUPS(), \
@@ -15,9 +15,9 @@
PROBE(Join, GROUPS(), \
TYPES(ui64, ui64), \
NAMES("spanId", "trackLength")) \
- PROBE(OrbitIsUsedConcurrentlyError, GROUPS("LWTraceError"), \
- TYPES(TString), \
- NAMES("backtrace")) \
- /**/
-
-LWTRACE_DECLARE_PROVIDER(LWTRACE_INTERNAL_PROVIDER)
+ PROBE(OrbitIsUsedConcurrentlyError, GROUPS("LWTraceError"), \
+ TYPES(TString), \
+ NAMES("backtrace")) \
+ /**/
+
+LWTRACE_DECLARE_PROVIDER(LWTRACE_INTERNAL_PROVIDER)
diff --git a/library/cpp/lwtrace/protos/lwtrace.proto b/library/cpp/lwtrace/protos/lwtrace.proto
index 0051095719..4c07b54625 100644
--- a/library/cpp/lwtrace/protos/lwtrace.proto
+++ b/library/cpp/lwtrace/protos/lwtrace.proto
@@ -1,64 +1,64 @@
-/*
- * This file defines language for trace queries and serialization format for trace logs
- */
+/*
+ * This file defines language for trace queries and serialization format for trace logs
+ */
syntax = "proto3";
-package NLWTrace;
-
+package NLWTrace;
+
option go_package = "a.yandex-team.ru/library/cpp/lwtrace/protos";
-message TProbeDesc {
+message TProbeDesc {
string Name = 1; // Use either name+provider
string Provider = 3;
string Group = 2; // or group
-}
-
-enum EOperatorType {
+}
+
+enum EOperatorType {
OT_EQ = 0;
OT_NE = 1;
OT_LT = 2;
OT_LE = 3;
OT_GT = 4;
OT_GE = 5;
-}
-
+}
+
message TArgument {
string Param = 1;
- bytes Value = 2;
+ bytes Value = 2;
string Variable = 3;
}
-message TOperator {
+message TOperator {
EOperatorType Type = 1;
repeated TArgument Argument = 8;
-}
-
-message TPredicate {
- repeated TOperator Operators = 1; // All operators are combined using logical AND
- double SampleRate = 2; // value 1.0 means trigger actions on 100% events (do not sample if value is not set)
-}
-
-message TLogAction {
+}
+
+message TPredicate {
+ repeated TOperator Operators = 1; // All operators are combined using logical AND
+ double SampleRate = 2; // value 1.0 means trigger actions on 100% events (do not sample if value is not set)
+}
+
+message TLogAction {
bool DoNotLogParams = 2;
bool LogTimestamp = 3;
uint32 MaxRecords = 4; // Do not write more than MaxRecords records to the log (count from the trace beginning, not start)
-}
-
+}
+
message TPrintToStderrAction {
}
message TKillAction {
-}
-
+}
+
message TSleepAction {
uint64 NanoSeconds = 1;
-}
-
-message TCustomAction {
+}
+
+message TCustomAction {
string Name = 1;
- repeated string Opts = 2;
-}
-
+ repeated string Opts = 2;
+}
+
enum EStatementType {
ST_MOV = 0;
ST_ADD = 1;
@@ -77,133 +77,133 @@ message TStatementAction {
repeated TArgument Argument = 2;
}
-message TRunLogShuttleAction {
+message TRunLogShuttleAction {
bool Ignore = 1;
uint64 ShuttlesCount = 2;
uint64 MaxTrackLength = 3;
-}
-
-message TEditLogShuttleAction {
+}
+
+message TEditLogShuttleAction {
bool Ignore = 1;
-}
-
-message TDropLogShuttleAction {
-}
-
-message TAction {
+}
+
+message TDropLogShuttleAction {
+}
+
+message TAction {
TLogAction LogAction = 2;
TPrintToStderrAction PrintToStderrAction = 3;
TCustomAction CustomAction = 4;
TKillAction KillAction = 6;
TSleepAction SleepAction = 7;
TStatementAction StatementAction = 8;
-
+
TRunLogShuttleAction RunLogShuttleAction = 100;
TEditLogShuttleAction EditLogShuttleAction = 101;
TDropLogShuttleAction DropLogShuttleAction = 102;
-}
-
-message TBlock {
+}
+
+message TBlock {
TProbeDesc ProbeDesc = 1;
TPredicate Predicate = 2;
repeated TAction Action = 3;
-}
-
-message TQuery {
- // Number of events to hold for every thread in cyclic buffer
- // (Won't be used if LogDurationUs is set to non-zero value)
+}
+
+message TQuery {
+ // Number of events to hold for every thread in cyclic buffer
+ // (Won't be used if LogDurationUs is set to non-zero value)
uint32 PerThreadLogSize = 1;
-
- // Hold events for last Duration microseconds
- // (If zero, than per-thread cyclic buffer will be used to store events)
+
+ // Hold events for last Duration microseconds
+ // (If zero, than per-thread cyclic buffer will be used to store events)
uint64 LogDurationUs = 2;
-
- repeated TBlock Blocks = 3;
-}
-
-message TDashboard {
- message TCell {
- optional string Url = 1;
- optional string Title = 2;
- optional string Text = 3;
- optional uint32 RowSpan = 4;
- optional uint32 ColSpan = 5;
- }
-
- message TRow {
- repeated TCell Cells = 1;
- }
-
- optional string Name = 1;
- optional string Description = 2;
- repeated TRow Rows = 3;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-// Serialization format for trace logs //
-//////////////////////////////////////////////////////////////////////////////////////////////
-enum EParamTypePb {
- PT_UNKNOWN = 0;
- PT_I64 = 1;
- PT_Ui64 = 2;
- PT_Double = 3;
- PT_Str = 4;
- PT_Symbol = 5;
- PT_Check = 6;
-}
-
-message TEventPb {
+
+ repeated TBlock Blocks = 3;
+}
+
+message TDashboard {
+ message TCell {
+ optional string Url = 1;
+ optional string Title = 2;
+ optional string Text = 3;
+ optional uint32 RowSpan = 4;
+ optional uint32 ColSpan = 5;
+ }
+
+ message TRow {
+ repeated TCell Cells = 1;
+ }
+
+ optional string Name = 1;
+ optional string Description = 2;
+ repeated TRow Rows = 3;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Serialization format for trace logs //
+//////////////////////////////////////////////////////////////////////////////////////////////
+enum EParamTypePb {
+ PT_UNKNOWN = 0;
+ PT_I64 = 1;
+ PT_Ui64 = 2;
+ PT_Double = 3;
+ PT_Str = 4;
+ PT_Symbol = 5;
+ PT_Check = 6;
+}
+
+message TEventPb {
string Name = 1;
- repeated string Groups = 2; // First group is provider
- repeated EParamTypePb ParamTypes = 3;
- repeated string ParamNames = 4;
-}
-
-message TLogItemPb {
+ repeated string Groups = 2; // First group is provider
+ repeated EParamTypePb ParamTypes = 3;
+ repeated string ParamNames = 4;
+}
+
+message TLogItemPb {
uint64 Thread = 1;
string Name = 2;
string Provider = 3;
- repeated bytes Params = 4;
+ repeated bytes Params = 4;
uint64 Timestamp = 5; // microseconds since epoch
uint64 TimestampCycles = 6; // cycles since machine boot
-}
-
-message TThreadLogPb {
+}
+
+message TThreadLogPb {
uint64 ThreadId = 1;
- repeated TLogItemPb LogItems = 2;
-}
-
-message TLogPb {
- // Trace info
+ repeated TLogItemPb LogItems = 2;
+}
+
+message TLogPb {
+ // Trace info
string Name = 1;
string Description = 2;
uint64 EventsCount = 3;
uint64 CrtTime = 4; // Log creation time (seconds since epoch)
-
- // Traced host info
+
+ // Traced host info
string Hostname = 101;
-
- // Traced process info
+
+ // Traced process info
string ProcessName = 201;
- bytes CommandLine = 202;
+ bytes CommandLine = 202;
uint64 ProcessStartTime = 203;
uint64 Pid = 204;
string VersionInfo = 205; // Svn info
-
- // Trace query and results
+
+ // Trace query and results
TQuery Query = 301;
- repeated TEventPb Events = 302;
- repeated TThreadLogPb ThreadLogs = 303;
-}
-
-message TShuttlePb {
- repeated TLogPb Parts = 1;
+ repeated TEventPb Events = 302;
+ repeated TThreadLogPb ThreadLogs = 303;
+}
+
+message TShuttlePb {
+ repeated TLogPb Parts = 1;
TQuery Query = 2;
-}
-
-message TOrbitPb {
- repeated TShuttlePb Shuttles = 1;
-}
+}
+
+message TOrbitPb {
+ repeated TShuttlePb Shuttles = 1;
+}
////////////////////////////////////////////////////////////////////////////////
// Trace parameter.
@@ -216,7 +216,7 @@ message TTraceParam
int64 IntValue = 2;
uint64 UintValue = 3;
double DoubleValue = 4;
- bytes StrValue = 5;
+ bytes StrValue = 5;
}
}
diff --git a/library/cpp/lwtrace/protos/ya.make b/library/cpp/lwtrace/protos/ya.make
index 503d5e515f..424bdd443b 100644
--- a/library/cpp/lwtrace/protos/ya.make
+++ b/library/cpp/lwtrace/protos/ya.make
@@ -1,6 +1,6 @@
-PROTO_LIBRARY()
+PROTO_LIBRARY()
-OWNER(serxa)
+OWNER(serxa)
INCLUDE_TAGS(GO_PROTO)
diff --git a/library/cpp/lwtrace/rwspinlock.h b/library/cpp/lwtrace/rwspinlock.h
index 7c518ec49e..bd04e2120f 100644
--- a/library/cpp/lwtrace/rwspinlock.h
+++ b/library/cpp/lwtrace/rwspinlock.h
@@ -1,88 +1,88 @@
-#pragma once
-
-#include <util/system/spinlock.h>
-
-// State can be one of:
-// 0) [NOT_USED] State = 0:
-// * any reader can acquire lock (State += 2: -> READING)
-// * one writer can acquire lock (State = -1: -> WRITING)
-// 1) [READING] even number:
-// * State/2 = number of active readers
-// * no writers are waiting
-// * any reader can aqcuire lock (State += 2: -> READING)
-// * active readers can release lock (State -= 2)
-// * one writer can acquire lock (State += 1: -> WAITING)
-// 2) [WAITING] odd number > 0:
-// * (State-1)/2 = number of active readers
-// * no more readers/writers can acquire lock
-// * active readers can release lock (State -= 2: -> WAITING)
-// * exactly one writer is waiting for active readers to release lock
-// * if no more active readers left (State == 1) waiting writer acquires lock (State = -1: -> WRITING)
-// 3) [WRITING] State = -1
-// * exactly one active writer
-// * no active readers
-// * no more readers/writers can acquire lock
-// * writer can release lock (State = 0: -> READING)
-
-struct TRWSpinLock {
- TAtomic State; // must be initialized by 'TRWSpinLock myLock = {0};' construction
-
- void Init() noexcept {
- State = 0;
- }
-
- void AcquireRead() noexcept {
- while (true) {
- TAtomic a = AtomicGet(State);
- if ((a & 1) == 0 && AtomicCas(&State, a + 2, a)) {
- break;
- }
- SpinLockPause();
- }
- }
-
- void ReleaseRead() noexcept {
- AtomicAdd(State, -2);
- }
-
- void AcquireWrite() noexcept {
- while (true) {
- TAtomic a = AtomicGet(State);
- if ((a & 1) == 0 && AtomicCas(&State, a + 1, a)) {
- break;
- }
- SpinLockPause();
- }
-
+#pragma once
+
+#include <util/system/spinlock.h>
+
+// State can be one of:
+// 0) [NOT_USED] State = 0:
+// * any reader can acquire lock (State += 2: -> READING)
+// * one writer can acquire lock (State = -1: -> WRITING)
+// 1) [READING] even number:
+// * State/2 = number of active readers
+// * no writers are waiting
+// * any reader can aqcuire lock (State += 2: -> READING)
+// * active readers can release lock (State -= 2)
+// * one writer can acquire lock (State += 1: -> WAITING)
+// 2) [WAITING] odd number > 0:
+// * (State-1)/2 = number of active readers
+// * no more readers/writers can acquire lock
+// * active readers can release lock (State -= 2: -> WAITING)
+// * exactly one writer is waiting for active readers to release lock
+// * if no more active readers left (State == 1) waiting writer acquires lock (State = -1: -> WRITING)
+// 3) [WRITING] State = -1
+// * exactly one active writer
+// * no active readers
+// * no more readers/writers can acquire lock
+// * writer can release lock (State = 0: -> READING)
+
+struct TRWSpinLock {
+ TAtomic State; // must be initialized by 'TRWSpinLock myLock = {0};' construction
+
+ void Init() noexcept {
+ State = 0;
+ }
+
+ void AcquireRead() noexcept {
+ while (true) {
+ TAtomic a = AtomicGet(State);
+ if ((a & 1) == 0 && AtomicCas(&State, a + 2, a)) {
+ break;
+ }
+ SpinLockPause();
+ }
+ }
+
+ void ReleaseRead() noexcept {
+ AtomicAdd(State, -2);
+ }
+
+ void AcquireWrite() noexcept {
+ while (true) {
+ TAtomic a = AtomicGet(State);
+ if ((a & 1) == 0 && AtomicCas(&State, a + 1, a)) {
+ break;
+ }
+ SpinLockPause();
+ }
+
while (!AtomicCas(&State, TAtomicBase(-1), 1)) {
- SpinLockPause();
- }
- }
-
- void ReleaseWrite() noexcept {
- AtomicSet(State, 0);
- }
-};
-
-struct TRWSpinLockReadOps {
- static inline void Acquire(TRWSpinLock* t) noexcept {
- t->AcquireRead();
- }
-
- static inline void Release(TRWSpinLock* t) noexcept {
- t->ReleaseRead();
- }
-};
-
-struct TRWSpinLockWriteOps {
- static inline void Acquire(TRWSpinLock* t) noexcept {
- t->AcquireWrite();
- }
-
- static inline void Release(TRWSpinLock* t) noexcept {
- t->ReleaseWrite();
- }
-};
-
+ SpinLockPause();
+ }
+ }
+
+ void ReleaseWrite() noexcept {
+ AtomicSet(State, 0);
+ }
+};
+
+struct TRWSpinLockReadOps {
+ static inline void Acquire(TRWSpinLock* t) noexcept {
+ t->AcquireRead();
+ }
+
+ static inline void Release(TRWSpinLock* t) noexcept {
+ t->ReleaseRead();
+ }
+};
+
+struct TRWSpinLockWriteOps {
+ static inline void Acquire(TRWSpinLock* t) noexcept {
+ t->AcquireWrite();
+ }
+
+ static inline void Release(TRWSpinLock* t) noexcept {
+ t->ReleaseWrite();
+ }
+};
+
using TReadSpinLockGuard = TGuard<TRWSpinLock, TRWSpinLockReadOps>;
using TWriteSpinLockGuard = TGuard<TRWSpinLock, TRWSpinLockWriteOps>;
diff --git a/library/cpp/lwtrace/shuttle.cpp b/library/cpp/lwtrace/shuttle.cpp
index 6ef6982aea..de506004ee 100644
--- a/library/cpp/lwtrace/shuttle.cpp
+++ b/library/cpp/lwtrace/shuttle.cpp
@@ -1,20 +1,20 @@
-#include "shuttle.h"
-
-#include "probes.h"
-
-#include <util/system/backtrace.h>
-#include <util/stream/str.h>
-
-namespace NLWTrace {
- LWTRACE_USING(LWTRACE_INTERNAL_PROVIDER);
-
- inline TString CurrentBackTrace() {
- TStringStream ss;
- FormatBackTrace(&ss);
- return ss.Str();
- }
-
- void TOrbit::LockFailed() {
- LWPROBE(OrbitIsUsedConcurrentlyError, CurrentBackTrace());
- }
-} // namespace NLWTrace
+#include "shuttle.h"
+
+#include "probes.h"
+
+#include <util/system/backtrace.h>
+#include <util/stream/str.h>
+
+namespace NLWTrace {
+ LWTRACE_USING(LWTRACE_INTERNAL_PROVIDER);
+
+ inline TString CurrentBackTrace() {
+ TStringStream ss;
+ FormatBackTrace(&ss);
+ return ss.Str();
+ }
+
+ void TOrbit::LockFailed() {
+ LWPROBE(OrbitIsUsedConcurrentlyError, CurrentBackTrace());
+ }
+} // namespace NLWTrace
diff --git a/library/cpp/lwtrace/shuttle.h b/library/cpp/lwtrace/shuttle.h
index 85c6e4da61..24c38e4c47 100644
--- a/library/cpp/lwtrace/shuttle.h
+++ b/library/cpp/lwtrace/shuttle.h
@@ -1,45 +1,45 @@
-#pragma once
-
+#pragma once
+
#include "event.h"
#include <library/cpp/containers/stack_vector/stack_vec.h>
-#include <util/generic/ptr.h>
-#include <util/system/spinlock.h>
-
+#include <util/generic/ptr.h>
+#include <util/system/spinlock.h>
+
#include <algorithm>
-#include <type_traits>
-
-namespace NLWTrace {
- struct TProbe;
-
- class IShuttle;
- using TShuttlePtr = TIntrusivePtr<IShuttle>;
-
- // Represents interface of tracing context passing by application between probes
- class alignas(8) IShuttle: public TThrRefBase {
- private:
- ui64 TraceIdx;
+#include <type_traits>
+
+namespace NLWTrace {
+ struct TProbe;
+
+ class IShuttle;
+ using TShuttlePtr = TIntrusivePtr<IShuttle>;
+
+ // Represents interface of tracing context passing by application between probes
+ class alignas(8) IShuttle: public TThrRefBase {
+ private:
+ ui64 TraceIdx;
ui64 SpanId;
ui64 ParentSpanId = 0;
- TAtomic Status = 0;
- static constexpr ui64 DeadFlag = 0x1ull;
- TShuttlePtr Next;
-
- public:
+ TAtomic Status = 0;
+ static constexpr ui64 DeadFlag = 0x1ull;
+ TShuttlePtr Next;
+
+ public:
explicit IShuttle(ui64 traceIdx, ui64 spanId)
- : TraceIdx(traceIdx)
+ : TraceIdx(traceIdx)
, SpanId(spanId)
- {
- }
-
- virtual ~IShuttle() {
- }
-
- ui64 GetTraceIdx() const {
- return TraceIdx;
- }
-
+ {
+ }
+
+ virtual ~IShuttle() {
+ }
+
+ ui64 GetTraceIdx() const {
+ return TraceIdx;
+ }
+
ui64 GetSpanId() const {
return SpanId;
}
@@ -52,130 +52,130 @@ namespace NLWTrace {
ParentSpanId = parentSpanId;
}
- template <class F, class R>
- R UnlessDead(F func, R dead) {
- while (true) {
- ui64 status = AtomicGet(Status);
- if (status & DeadFlag) {
- return dead;
- }
- if (AtomicCas(&Status, status + 2, status)) {
- R result = func();
- ATOMIC_COMPILER_BARRIER();
- AtomicSub(Status, 2);
- return result;
- }
- }
- }
-
- template <class F>
- void UnlessDead(F func) {
- while (true) {
- ui64 status = AtomicGet(Status);
- if (status & DeadFlag) {
- return;
- }
- if (AtomicCas(&Status, status + 2, status)) {
- func();
- ATOMIC_COMPILER_BARRIER();
- AtomicSub(Status, 2);
- return;
- }
+ template <class F, class R>
+ R UnlessDead(F func, R dead) {
+ while (true) {
+ ui64 status = AtomicGet(Status);
+ if (status & DeadFlag) {
+ return dead;
+ }
+ if (AtomicCas(&Status, status + 2, status)) {
+ R result = func();
+ ATOMIC_COMPILER_BARRIER();
+ AtomicSub(Status, 2);
+ return result;
+ }
}
}
- void Serialize(TShuttleTrace& msg) {
- UnlessDead([&] {
- DoSerialize(msg);
- });
- }
-
- // Returns false iff shuttle should be destroyed
+ template <class F>
+ void UnlessDead(F func) {
+ while (true) {
+ ui64 status = AtomicGet(Status);
+ if (status & DeadFlag) {
+ return;
+ }
+ if (AtomicCas(&Status, status + 2, status)) {
+ func();
+ ATOMIC_COMPILER_BARRIER();
+ AtomicSub(Status, 2);
+ return;
+ }
+ }
+ }
+
+ void Serialize(TShuttleTrace& msg) {
+ UnlessDead([&] {
+ DoSerialize(msg);
+ });
+ }
+
+ // Returns false iff shuttle should be destroyed
bool AddProbe(TProbe* probe, const TParams& params, ui64 timestamp = 0) {
- return UnlessDead([&] {
- return DoAddProbe(probe, params, timestamp);
- }, false);
- }
-
- // Track object was destroyed
- void EndOfTrack() {
- if (Next) {
- Next->EndOfTrack();
- Next.Reset();
- }
- UnlessDead([&] {
- DoEndOfTrack();
- });
- }
-
- // Shuttle was dropped from orbit
- TShuttlePtr Drop() {
- UnlessDead([&] {
- DoDrop();
- });
+ return UnlessDead([&] {
+ return DoAddProbe(probe, params, timestamp);
+ }, false);
+ }
+
+ // Track object was destroyed
+ void EndOfTrack() {
+ if (Next) {
+ Next->EndOfTrack();
+ Next.Reset();
+ }
+ UnlessDead([&] {
+ DoEndOfTrack();
+ });
+ }
+
+ // Shuttle was dropped from orbit
+ TShuttlePtr Drop() {
+ UnlessDead([&] {
+ DoDrop();
+ });
return Detach(); // Detached from orbit on Drop
}
TShuttlePtr Detach() {
- TShuttlePtr result;
+ TShuttlePtr result;
result.Swap(Next);
- return result;
- }
-
- // Trace session was destroyed
- void Kill() {
- AtomicAdd(Status, 1); // Sets DeadFlag
- while (AtomicGet(Status) != 1) { // Wait until any vcall is over
- SpinLockPause();
- }
- // After this point all virtual calls on shuttle are disallowed
- ATOMIC_COMPILER_BARRIER();
- }
-
- const TShuttlePtr& GetNext() const {
- return Next;
- }
-
- TShuttlePtr& GetNext() {
- return Next;
- }
-
- void SetNext(const TShuttlePtr& next) {
- Next = next;
- }
-
- bool Fork(TShuttlePtr& child) {
- return UnlessDead([&] {
- return DoFork(child);
- }, true);
+ return result;
+ }
+
+ // Trace session was destroyed
+ void Kill() {
+ AtomicAdd(Status, 1); // Sets DeadFlag
+ while (AtomicGet(Status) != 1) { // Wait until any vcall is over
+ SpinLockPause();
+ }
+ // After this point all virtual calls on shuttle are disallowed
+ ATOMIC_COMPILER_BARRIER();
+ }
+
+ const TShuttlePtr& GetNext() const {
+ return Next;
+ }
+
+ TShuttlePtr& GetNext() {
+ return Next;
+ }
+
+ void SetNext(const TShuttlePtr& next) {
+ Next = next;
+ }
+
+ bool Fork(TShuttlePtr& child) {
+ return UnlessDead([&] {
+ return DoFork(child);
+ }, true);
}
bool Join(TShuttlePtr& child) {
- return UnlessDead([&] {
- return DoJoin(child);
- }, false);
+ return UnlessDead([&] {
+ return DoJoin(child);
+ }, false);
}
bool IsDead() {
return AtomicGet(Status) & DeadFlag;
}
- protected:
+ protected:
virtual bool DoAddProbe(TProbe* probe, const TParams& params, ui64 timestamp) = 0;
- virtual void DoEndOfTrack() = 0;
- virtual void DoDrop() = 0;
+ virtual void DoEndOfTrack() = 0;
+ virtual void DoDrop() = 0;
virtual void DoSerialize(TShuttleTrace& msg) = 0;
- virtual bool DoFork(TShuttlePtr& child) = 0;
+ virtual bool DoFork(TShuttlePtr& child) = 0;
virtual bool DoJoin(const TShuttlePtr& child) = 0;
- };
-
- // Not thread-safe orbit
- // Orbit should not be used concurrenty, lock is used
- // to ensure this is the case and avoid race condition if not.
- class TOrbit {
- private:
- TShuttlePtr HeadNoLock;
- public:
+ };
+
+ // Not thread-safe orbit
+ // Orbit should not be used concurrenty, lock is used
+ // to ensure this is the case and avoid race condition if not.
+ class TOrbit {
+ private:
+ TShuttlePtr HeadNoLock;
+ public:
TOrbit() = default;
TOrbit(const TOrbit&) = delete;
TOrbit(TOrbit&&) = default;
@@ -183,135 +183,135 @@ namespace NLWTrace {
TOrbit& operator=(const TOrbit&) = delete;
TOrbit& operator=(TOrbit&&) = default;
- ~TOrbit() {
- Reset();
- }
-
- void Reset() {
- NotConcurrent([] (TShuttlePtr& head) {
- if (head) {
- head->EndOfTrack();
- head.Reset();
- }
- });
- }
-
- // Checks if there is at least one shuttle in orbit
- // NOTE: used by every LWTRACK macro check, so keep it optimized - do not lock
- bool HasShuttles() const {
- return HeadNoLock.Get();
- }
-
- void AddShuttle(const TShuttlePtr& shuttle) {
- NotConcurrent([&] (TShuttlePtr& head) {
- Y_VERIFY(!shuttle->GetNext());
- shuttle->SetNext(head);
- head = shuttle;
- });
- }
-
- // Moves every shuttle from `orbit' into this
- void Take(TOrbit& orbit) {
- NotConcurrent([&] (TShuttlePtr& head) {
- orbit.NotConcurrent([&] (TShuttlePtr& oHead) {
- TShuttlePtr* ref = &oHead;
- if (ref->Get()) {
- while (TShuttlePtr& next = (*ref)->GetNext()) {
- ref = &next;
- }
- (*ref)->SetNext(head);
- head.Swap(oHead);
- oHead.Reset();
- }
- });
- });
- }
-
+ ~TOrbit() {
+ Reset();
+ }
+
+ void Reset() {
+ NotConcurrent([] (TShuttlePtr& head) {
+ if (head) {
+ head->EndOfTrack();
+ head.Reset();
+ }
+ });
+ }
+
+ // Checks if there is at least one shuttle in orbit
+ // NOTE: used by every LWTRACK macro check, so keep it optimized - do not lock
+ bool HasShuttles() const {
+ return HeadNoLock.Get();
+ }
+
+ void AddShuttle(const TShuttlePtr& shuttle) {
+ NotConcurrent([&] (TShuttlePtr& head) {
+ Y_VERIFY(!shuttle->GetNext());
+ shuttle->SetNext(head);
+ head = shuttle;
+ });
+ }
+
+ // Moves every shuttle from `orbit' into this
+ void Take(TOrbit& orbit) {
+ NotConcurrent([&] (TShuttlePtr& head) {
+ orbit.NotConcurrent([&] (TShuttlePtr& oHead) {
+ TShuttlePtr* ref = &oHead;
+ if (ref->Get()) {
+ while (TShuttlePtr& next = (*ref)->GetNext()) {
+ ref = &next;
+ }
+ (*ref)->SetNext(head);
+ head.Swap(oHead);
+ oHead.Reset();
+ }
+ });
+ });
+ }
+
void AddProbe(TProbe* probe, const TParams& params, ui64 timestamp = 0) {
- NotConcurrent([&] (TShuttlePtr& head) {
- TShuttlePtr* ref = &head;
- while (IShuttle* s = ref->Get()) {
- if (!s->AddProbe(probe, params, timestamp)) { // Shuttle self-destructed
- *ref = s->Drop(); // May destroy shuttle
- } else {
- ref = &s->GetNext(); // Keep shuttle
- }
- }
- });
- }
-
- template <class TFunc>
- void ForEachShuttle(ui64 traceIdx, TFunc&& func) {
- NotConcurrent([&] (TShuttlePtr& head) {
- TShuttlePtr* ref = &head;
- while (IShuttle* s = ref->Get()) {
- if (s->GetTraceIdx() == traceIdx && !func(s)) { // Shuttle self-destructed
- *ref = s->Drop(); // May destroy shuttle
- } else {
- ref = &s->GetNext(); // Keep shuttle
- }
- }
- });
- }
-
- void Serialize(ui64 traceIdx, TShuttleTrace& msg) {
- ForEachShuttle(traceIdx, [&] (NLWTrace::IShuttle* shuttle) {
+ NotConcurrent([&] (TShuttlePtr& head) {
+ TShuttlePtr* ref = &head;
+ while (IShuttle* s = ref->Get()) {
+ if (!s->AddProbe(probe, params, timestamp)) { // Shuttle self-destructed
+ *ref = s->Drop(); // May destroy shuttle
+ } else {
+ ref = &s->GetNext(); // Keep shuttle
+ }
+ }
+ });
+ }
+
+ template <class TFunc>
+ void ForEachShuttle(ui64 traceIdx, TFunc&& func) {
+ NotConcurrent([&] (TShuttlePtr& head) {
+ TShuttlePtr* ref = &head;
+ while (IShuttle* s = ref->Get()) {
+ if (s->GetTraceIdx() == traceIdx && !func(s)) { // Shuttle self-destructed
+ *ref = s->Drop(); // May destroy shuttle
+ } else {
+ ref = &s->GetNext(); // Keep shuttle
+ }
+ }
+ });
+ }
+
+ void Serialize(ui64 traceIdx, TShuttleTrace& msg) {
+ ForEachShuttle(traceIdx, [&] (NLWTrace::IShuttle* shuttle) {
shuttle->Serialize(msg);
return false;
});
}
- bool HasShuttle(ui64 traceIdx) {
- return NotConcurrent([=] (TShuttlePtr& head) {
- TShuttlePtr ref = head;
- while (IShuttle* s = ref.Get()) {
- if (s->GetTraceIdx() == traceIdx) {
- return true;
- } else {
- ref = s->GetNext();
- }
+ bool HasShuttle(ui64 traceIdx) {
+ return NotConcurrent([=] (TShuttlePtr& head) {
+ TShuttlePtr ref = head;
+ while (IShuttle* s = ref.Get()) {
+ if (s->GetTraceIdx() == traceIdx) {
+ return true;
+ } else {
+ ref = s->GetNext();
+ }
}
- return false;
- });
+ return false;
+ });
}
bool Fork(TOrbit& child) {
- return NotConcurrent([&] (TShuttlePtr& head) {
- return child.NotConcurrent([&] (TShuttlePtr& cHead) {
- bool result = true;
- TShuttlePtr* ref = &head;
- while (IShuttle* shuttle = ref->Get()) {
- if (shuttle->IsDead()) {
- *ref = shuttle->Drop();
- } else {
- result = result && shuttle->Fork(cHead);
- ref = &shuttle->GetNext();
- }
- }
- return result;
- });
- });
+ return NotConcurrent([&] (TShuttlePtr& head) {
+ return child.NotConcurrent([&] (TShuttlePtr& cHead) {
+ bool result = true;
+ TShuttlePtr* ref = &head;
+ while (IShuttle* shuttle = ref->Get()) {
+ if (shuttle->IsDead()) {
+ *ref = shuttle->Drop();
+ } else {
+ result = result && shuttle->Fork(cHead);
+ ref = &shuttle->GetNext();
+ }
+ }
+ return result;
+ });
+ });
}
void Join(TOrbit& child) {
- NotConcurrent([&] (TShuttlePtr& head) {
- child.NotConcurrent([&] (TShuttlePtr& cHead) {
- TShuttlePtr* ref = &head;
- while (IShuttle* shuttle = ref->Get()) {
- if (shuttle->IsDead()) {
- *ref = shuttle->Drop();
- } else {
- child.Join(cHead, shuttle);
- ref = &shuttle->GetNext();
- }
- }
- });
- });
- }
-
- private:
- static void Join(TShuttlePtr& head, IShuttle* parent) {
- TShuttlePtr* ref = &head;
+ NotConcurrent([&] (TShuttlePtr& head) {
+ child.NotConcurrent([&] (TShuttlePtr& cHead) {
+ TShuttlePtr* ref = &head;
+ while (IShuttle* shuttle = ref->Get()) {
+ if (shuttle->IsDead()) {
+ *ref = shuttle->Drop();
+ } else {
+ child.Join(cHead, shuttle);
+ ref = &shuttle->GetNext();
+ }
+ }
+ });
+ });
+ }
+
+ private:
+ static void Join(TShuttlePtr& head, IShuttle* parent) {
+ TShuttlePtr* ref = &head;
while (IShuttle* child = ref->Get()) {
if (parent->GetTraceIdx() == child->GetTraceIdx() && parent->GetSpanId() == child->GetParentSpanId()) {
TShuttlePtr next = child->Detach();
@@ -322,37 +322,37 @@ namespace NLWTrace {
}
}
}
-
- template <class TFunc>
- typename std::invoke_result<TFunc, TShuttlePtr&>::type NotConcurrent(TFunc func) {
- // `HeadNoLock` is binary-copied into local `headCopy` and written with special `locked` value
- // during not concurrent operations. Not concurrent operations should not work
- // with `HeadNoLock` directly. Instead `headCopy` is passed into `func` by reference and
- // after `func()` it is binary-copied back into `HeadNoLock`.
- static_assert(sizeof(HeadNoLock) == sizeof(TAtomic));
- TAtomic* headPtr = reinterpret_cast<TAtomic*>(&HeadNoLock);
- TAtomicBase headCopy = AtomicGet(*headPtr);
- static constexpr TAtomicBase locked = 0x1ull;
- if (headCopy != locked && AtomicCas(headPtr, locked, headCopy)) {
- struct TUnlocker { // to avoid specialization for R=void
- TAtomic* HeadPtr;
- TAtomicBase* HeadCopy;
- ~TUnlocker() {
- ATOMIC_COMPILER_BARRIER();
- AtomicSet(*HeadPtr, *HeadCopy);
- }
- } scoped{headPtr, &headCopy};
- return func(*reinterpret_cast<TShuttlePtr*>(&headCopy));
- } else {
- LockFailed();
- return typename std::invoke_result<TFunc, TShuttlePtr&>::type();
- }
- }
-
- void LockFailed();
- };
-
- inline size_t HasShuttles(const TOrbit& orbit) {
- return orbit.HasShuttles();
- }
-}
+
+ template <class TFunc>
+ typename std::invoke_result<TFunc, TShuttlePtr&>::type NotConcurrent(TFunc func) {
+ // `HeadNoLock` is binary-copied into local `headCopy` and written with special `locked` value
+ // during not concurrent operations. Not concurrent operations should not work
+ // with `HeadNoLock` directly. Instead `headCopy` is passed into `func` by reference and
+ // after `func()` it is binary-copied back into `HeadNoLock`.
+ static_assert(sizeof(HeadNoLock) == sizeof(TAtomic));
+ TAtomic* headPtr = reinterpret_cast<TAtomic*>(&HeadNoLock);
+ TAtomicBase headCopy = AtomicGet(*headPtr);
+ static constexpr TAtomicBase locked = 0x1ull;
+ if (headCopy != locked && AtomicCas(headPtr, locked, headCopy)) {
+ struct TUnlocker { // to avoid specialization for R=void
+ TAtomic* HeadPtr;
+ TAtomicBase* HeadCopy;
+ ~TUnlocker() {
+ ATOMIC_COMPILER_BARRIER();
+ AtomicSet(*HeadPtr, *HeadCopy);
+ }
+ } scoped{headPtr, &headCopy};
+ return func(*reinterpret_cast<TShuttlePtr*>(&headCopy));
+ } else {
+ LockFailed();
+ return typename std::invoke_result<TFunc, TShuttlePtr&>::type();
+ }
+ }
+
+ void LockFailed();
+ };
+
+ inline size_t HasShuttles(const TOrbit& orbit) {
+ return orbit.HasShuttles();
+ }
+}
diff --git a/library/cpp/lwtrace/signature.h b/library/cpp/lwtrace/signature.h
index 868bd9bcf2..87ce835228 100644
--- a/library/cpp/lwtrace/signature.h
+++ b/library/cpp/lwtrace/signature.h
@@ -1,16 +1,16 @@
-#pragma once
-
+#pragma once
+
#include "preprocessor.h"
#include <library/cpp/lwtrace/protos/lwtrace.pb.h>
#include <util/generic/cast.h>
#include <util/generic/string.h>
-#include <util/generic/typetraits.h>
+#include <util/generic/typetraits.h>
#include <util/string/builder.h>
-#include <util/string/cast.h>
-#include <util/string/printf.h>
-
+#include <util/string/cast.h>
+#include <util/string/printf.h>
+
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_enum_reflection.h>
@@ -18,407 +18,407 @@
#include <type_traits>
-namespace NLWTrace {
- // Class to hold parameter values parsed from trace query predicate operators
- template <class T>
- struct TParamConv {
- static T FromString(const TString& text) {
- return ::FromString<T>(text);
- }
- static TString ToString(const T& param) {
- return ::ToString(param);
- }
- };
-
- template <>
- struct TParamConv<TString const*> {
- static TString FromString(const TString& text) {
- return text;
- }
- static TString ToString(TString const* param) {
- return TString(*param);
- }
- };
-
- template <>
- struct TParamConv<ui8> {
- static ui8 FromString(const TString& text) {
- return (ui8)::FromString<ui16>(text);
- }
- static TString ToString(ui8 param) {
- return ::ToString((ui16)param);
- }
- };
-
- template <>
- struct TParamConv<i8> {
- static i8 FromString(const TString& text) {
- return (i8)::FromString<i16>(text);
- }
- static TString ToString(i8 param) {
- return ::ToString((i16)param);
- }
- };
-
- template <>
- struct TParamConv<double> {
- static double FromString(const TString& text) {
- return ::FromString<double>(text);
- }
- static TString ToString(double param) {
- return Sprintf("%.6lf", param);
- }
- };
-
- // Fake parameter type used as a placeholder for not used parameters (above the number of defined params for a specific probe)
- class TNil {
- };
-
- // Struct that holds and handles a value of parameter of any supported type.
- struct TParam {
- char Data[LWTRACE_MAX_PARAM_SIZE];
-
- template <class T>
- const T& Get() const {
+namespace NLWTrace {
+ // Class to hold parameter values parsed from trace query predicate operators
+ template <class T>
+ struct TParamConv {
+ static T FromString(const TString& text) {
+ return ::FromString<T>(text);
+ }
+ static TString ToString(const T& param) {
+ return ::ToString(param);
+ }
+ };
+
+ template <>
+ struct TParamConv<TString const*> {
+ static TString FromString(const TString& text) {
+ return text;
+ }
+ static TString ToString(TString const* param) {
+ return TString(*param);
+ }
+ };
+
+ template <>
+ struct TParamConv<ui8> {
+ static ui8 FromString(const TString& text) {
+ return (ui8)::FromString<ui16>(text);
+ }
+ static TString ToString(ui8 param) {
+ return ::ToString((ui16)param);
+ }
+ };
+
+ template <>
+ struct TParamConv<i8> {
+ static i8 FromString(const TString& text) {
+ return (i8)::FromString<i16>(text);
+ }
+ static TString ToString(i8 param) {
+ return ::ToString((i16)param);
+ }
+ };
+
+ template <>
+ struct TParamConv<double> {
+ static double FromString(const TString& text) {
+ return ::FromString<double>(text);
+ }
+ static TString ToString(double param) {
+ return Sprintf("%.6lf", param);
+ }
+ };
+
+ // Fake parameter type used as a placeholder for not used parameters (above the number of defined params for a specific probe)
+ class TNil {
+ };
+
+ // Struct that holds and handles a value of parameter of any supported type.
+ struct TParam {
+ char Data[LWTRACE_MAX_PARAM_SIZE];
+
+ template <class T>
+ const T& Get() const {
return *reinterpret_cast<const T*>(Data);
- }
-
- template <class T>
- T& Get() {
+ }
+
+ template <class T>
+ T& Get() {
return *reinterpret_cast<T*>(Data);
- }
-
- template <class T>
- void DefaultConstruct() {
- new (&Data) T();
- }
-
- template <class T>
- void CopyConstruct(const T& other) {
- new (&Data) T(other);
- }
-
- template <class T>
- void Destruct() {
- Get<T>().~T();
- }
- };
-
- template <>
- inline void TParam::DefaultConstruct<TNil>() {
- }
-
- template <>
- inline void TParam::CopyConstruct<TNil>(const TNil&) {
- }
-
- template <>
- inline void TParam::Destruct<TNil>() {
- }
-
- class TTypedParam {
- private:
- EParamTypePb Type;
- TParam Param; // Contains garbage if PT_UNKNOWN
- public:
- TTypedParam()
- : Type(PT_UNKNOWN)
- {
- }
-
- explicit TTypedParam(EParamTypePb type)
- : Type(type)
- {
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- Param.DefaultConstruct<t>(); \
- return;
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return;
- default:
- Y_FAIL("unknown param type");
- }
- }
-
- template <class T>
- explicit TTypedParam(const T& x, EParamTypePb type = PT_UNKNOWN)
- : Type(type)
- {
- Param.CopyConstruct<T>(x);
- }
-
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- explicit TTypedParam(const t& x) \
- : Type(PT_##v) { \
- Param.CopyConstruct<t>(x); \
- }
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
-
- TTypedParam(const TTypedParam& o) {
- Assign(o);
- }
-
- TTypedParam& operator=(const TTypedParam& o) {
- Reset();
- Assign(o);
- return *this;
- }
-
- void Assign(const TTypedParam& o) {
- Type = o.Type;
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- Param.CopyConstruct<t>(o.Param.Get<t>()); \
- return;
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return;
- default:
- Y_FAIL("unknown param type");
- }
- }
-
- TTypedParam(TTypedParam&& o)
- : Type(o.Type)
- , Param(o.Param)
- {
- o.Type = PT_UNKNOWN; // To avoid Param destroy by source object dtor
- }
-
- TTypedParam(EParamTypePb type, const TParam& param)
- : Type(type)
- {
- Y_UNUSED(param); // for disabled lwtrace
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- Param.CopyConstruct<t>(param.Get<t>()); \
- return;
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return;
- default:
- Y_FAIL("unknown param type");
- }
- }
-
- ~TTypedParam() {
- Reset();
- }
-
- void Reset() {
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- Param.Destruct<t>(); \
- return;
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return;
- default:
- Y_FAIL("unknown param type");
- }
- Type = PT_UNKNOWN;
- }
-
- bool operator==(const TTypedParam& rhs) const {
- if (Y_LIKELY(Type == rhs.Type)) {
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- return Param.Get<t>() == rhs.Param.Get<t>();
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return false; // All unknowns are equal
- default:
- Y_FAIL("unknown param type");
- }
- } else {
- return false;
- }
- }
- bool operator!=(const TTypedParam& rhs) const {
- return !operator==(rhs);
- }
-
- bool operator<(const TTypedParam& rhs) const {
- if (Y_LIKELY(Type == rhs.Type)) {
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- return Param.Get<t>() < rhs.Param.Get<t>();
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return false; // All unknowns are equal
- default:
- Y_FAIL("unknown param type");
- }
- } else {
- return Type < rhs.Type;
- }
- }
-
- bool operator<=(const TTypedParam& rhs) const {
- if (Y_LIKELY(Type == rhs.Type)) {
- switch (Type) {
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- case PT_##v: \
- return Param.Get<t>() <= rhs.Param.Get<t>();
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- case PT_UNKNOWN:
- return true; // All unknowns are equal
- default:
- Y_FAIL("unknown param type");
- }
- } else {
- return Type < rhs.Type;
- }
- }
-
- bool operator>(const TTypedParam& rhs) const {
- return !operator<=(rhs);
- }
- bool operator>=(const TTypedParam& rhs) const {
- return !operator<(rhs);
- }
-
- EParamTypePb GetType() const {
- return Type;
- }
- const TParam& GetParam() const {
- return Param;
- }
- };
-
- class TLiteral {
- private:
- TTypedParam Values[EParamTypePb_ARRAYSIZE];
-
- public:
- explicit TLiteral(const TString& text) {
- Y_UNUSED(text); /* That's for windows, where we have lwtrace disabled. */
-
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- try { \
- Values[PT_##v] = TTypedParam(TParamConv<t>::FromString(text)); \
- } catch (...) { \
- Values[PT_##v] = TTypedParam(); \
- } \
- /**/
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
- }
-
- TLiteral() {
- }
-
- TLiteral(const TLiteral& o) {
- for (size_t i = 0; i < EParamTypePb_ARRAYSIZE; i++) {
- Values[i] = o.Values[i];
- }
- }
-
- TLiteral& operator=(const TLiteral& o) {
- for (size_t i = 0; i < EParamTypePb_ARRAYSIZE; i++) {
- Values[i] = o.Values[i];
- }
- return *this;
- }
-
- const TTypedParam& GetValue(EParamTypePb type) const {
- return Values[type];
- }
-
- bool operator==(const TTypedParam& rhs) const {
- return Values[rhs.GetType()] == rhs;
- }
- bool operator!=(const TTypedParam& rhs) const {
- return !operator==(rhs);
- }
-
- bool operator<(const TTypedParam& rhs) const {
- return Values[rhs.GetType()] < rhs;
- }
-
- bool operator<=(const TTypedParam& rhs) const {
- return Values[rhs.GetType()] <= rhs;
- }
-
- bool operator>(const TTypedParam& rhs) const {
- return !operator<=(rhs);
- }
- bool operator>=(const TTypedParam& rhs) const {
- return !operator<(rhs);
- }
- };
-
- inline bool operator==(const TTypedParam& lhs, const TLiteral& rhs) {
- return lhs == rhs.GetValue(lhs.GetType());
- }
- inline bool operator!=(const TTypedParam& lhs, const TLiteral& rhs) {
- return !operator==(lhs, rhs);
- }
-
- inline bool operator<(const TTypedParam& lhs, const TLiteral& rhs) {
- return lhs < rhs.GetValue(lhs.GetType());
- }
-
- inline bool operator<=(const TTypedParam& lhs, const TLiteral& rhs) {
- return lhs <= rhs.GetValue(lhs.GetType());
- }
-
- inline bool operator>(const TTypedParam& lhs, const TLiteral& rhs) {
- return !operator<=(lhs, rhs);
- }
- inline bool operator>=(const TTypedParam& lhs, const TLiteral& rhs) {
- return !operator<(lhs, rhs);
- }
-
- // Struct that holds and handles all parameter values of different supported types
- struct TParams {
- TParam Param[LWTRACE_MAX_PARAMS];
- };
-
+ }
+
+ template <class T>
+ void DefaultConstruct() {
+ new (&Data) T();
+ }
+
+ template <class T>
+ void CopyConstruct(const T& other) {
+ new (&Data) T(other);
+ }
+
+ template <class T>
+ void Destruct() {
+ Get<T>().~T();
+ }
+ };
+
+ template <>
+ inline void TParam::DefaultConstruct<TNil>() {
+ }
+
+ template <>
+ inline void TParam::CopyConstruct<TNil>(const TNil&) {
+ }
+
+ template <>
+ inline void TParam::Destruct<TNil>() {
+ }
+
+ class TTypedParam {
+ private:
+ EParamTypePb Type;
+ TParam Param; // Contains garbage if PT_UNKNOWN
+ public:
+ TTypedParam()
+ : Type(PT_UNKNOWN)
+ {
+ }
+
+ explicit TTypedParam(EParamTypePb type)
+ : Type(type)
+ {
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ Param.DefaultConstruct<t>(); \
+ return;
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return;
+ default:
+ Y_FAIL("unknown param type");
+ }
+ }
+
+ template <class T>
+ explicit TTypedParam(const T& x, EParamTypePb type = PT_UNKNOWN)
+ : Type(type)
+ {
+ Param.CopyConstruct<T>(x);
+ }
+
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ explicit TTypedParam(const t& x) \
+ : Type(PT_##v) { \
+ Param.CopyConstruct<t>(x); \
+ }
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+
+ TTypedParam(const TTypedParam& o) {
+ Assign(o);
+ }
+
+ TTypedParam& operator=(const TTypedParam& o) {
+ Reset();
+ Assign(o);
+ return *this;
+ }
+
+ void Assign(const TTypedParam& o) {
+ Type = o.Type;
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ Param.CopyConstruct<t>(o.Param.Get<t>()); \
+ return;
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return;
+ default:
+ Y_FAIL("unknown param type");
+ }
+ }
+
+ TTypedParam(TTypedParam&& o)
+ : Type(o.Type)
+ , Param(o.Param)
+ {
+ o.Type = PT_UNKNOWN; // To avoid Param destroy by source object dtor
+ }
+
+ TTypedParam(EParamTypePb type, const TParam& param)
+ : Type(type)
+ {
+ Y_UNUSED(param); // for disabled lwtrace
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ Param.CopyConstruct<t>(param.Get<t>()); \
+ return;
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return;
+ default:
+ Y_FAIL("unknown param type");
+ }
+ }
+
+ ~TTypedParam() {
+ Reset();
+ }
+
+ void Reset() {
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ Param.Destruct<t>(); \
+ return;
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return;
+ default:
+ Y_FAIL("unknown param type");
+ }
+ Type = PT_UNKNOWN;
+ }
+
+ bool operator==(const TTypedParam& rhs) const {
+ if (Y_LIKELY(Type == rhs.Type)) {
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ return Param.Get<t>() == rhs.Param.Get<t>();
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return false; // All unknowns are equal
+ default:
+ Y_FAIL("unknown param type");
+ }
+ } else {
+ return false;
+ }
+ }
+ bool operator!=(const TTypedParam& rhs) const {
+ return !operator==(rhs);
+ }
+
+ bool operator<(const TTypedParam& rhs) const {
+ if (Y_LIKELY(Type == rhs.Type)) {
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ return Param.Get<t>() < rhs.Param.Get<t>();
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return false; // All unknowns are equal
+ default:
+ Y_FAIL("unknown param type");
+ }
+ } else {
+ return Type < rhs.Type;
+ }
+ }
+
+ bool operator<=(const TTypedParam& rhs) const {
+ if (Y_LIKELY(Type == rhs.Type)) {
+ switch (Type) {
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ case PT_##v: \
+ return Param.Get<t>() <= rhs.Param.Get<t>();
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ case PT_UNKNOWN:
+ return true; // All unknowns are equal
+ default:
+ Y_FAIL("unknown param type");
+ }
+ } else {
+ return Type < rhs.Type;
+ }
+ }
+
+ bool operator>(const TTypedParam& rhs) const {
+ return !operator<=(rhs);
+ }
+ bool operator>=(const TTypedParam& rhs) const {
+ return !operator<(rhs);
+ }
+
+ EParamTypePb GetType() const {
+ return Type;
+ }
+ const TParam& GetParam() const {
+ return Param;
+ }
+ };
+
+ class TLiteral {
+ private:
+ TTypedParam Values[EParamTypePb_ARRAYSIZE];
+
+ public:
+ explicit TLiteral(const TString& text) {
+ Y_UNUSED(text); /* That's for windows, where we have lwtrace disabled. */
+
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ try { \
+ Values[PT_##v] = TTypedParam(TParamConv<t>::FromString(text)); \
+ } catch (...) { \
+ Values[PT_##v] = TTypedParam(); \
+ } \
+ /**/
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+ }
+
+ TLiteral() {
+ }
+
+ TLiteral(const TLiteral& o) {
+ for (size_t i = 0; i < EParamTypePb_ARRAYSIZE; i++) {
+ Values[i] = o.Values[i];
+ }
+ }
+
+ TLiteral& operator=(const TLiteral& o) {
+ for (size_t i = 0; i < EParamTypePb_ARRAYSIZE; i++) {
+ Values[i] = o.Values[i];
+ }
+ return *this;
+ }
+
+ const TTypedParam& GetValue(EParamTypePb type) const {
+ return Values[type];
+ }
+
+ bool operator==(const TTypedParam& rhs) const {
+ return Values[rhs.GetType()] == rhs;
+ }
+ bool operator!=(const TTypedParam& rhs) const {
+ return !operator==(rhs);
+ }
+
+ bool operator<(const TTypedParam& rhs) const {
+ return Values[rhs.GetType()] < rhs;
+ }
+
+ bool operator<=(const TTypedParam& rhs) const {
+ return Values[rhs.GetType()] <= rhs;
+ }
+
+ bool operator>(const TTypedParam& rhs) const {
+ return !operator<=(rhs);
+ }
+ bool operator>=(const TTypedParam& rhs) const {
+ return !operator<(rhs);
+ }
+ };
+
+ inline bool operator==(const TTypedParam& lhs, const TLiteral& rhs) {
+ return lhs == rhs.GetValue(lhs.GetType());
+ }
+ inline bool operator!=(const TTypedParam& lhs, const TLiteral& rhs) {
+ return !operator==(lhs, rhs);
+ }
+
+ inline bool operator<(const TTypedParam& lhs, const TLiteral& rhs) {
+ return lhs < rhs.GetValue(lhs.GetType());
+ }
+
+ inline bool operator<=(const TTypedParam& lhs, const TLiteral& rhs) {
+ return lhs <= rhs.GetValue(lhs.GetType());
+ }
+
+ inline bool operator>(const TTypedParam& lhs, const TLiteral& rhs) {
+ return !operator<=(lhs, rhs);
+ }
+ inline bool operator>=(const TTypedParam& lhs, const TLiteral& rhs) {
+ return !operator<(lhs, rhs);
+ }
+
+ // Struct that holds and handles all parameter values of different supported types
+ struct TParams {
+ TParam Param[LWTRACE_MAX_PARAMS];
+ };
+
using TSerializedParams = google::protobuf::RepeatedPtrField<NLWTrace::TTraceParam>;
- // Represents a common class for all function "signatures" (parameter types and names).
- // Provides non-virtual interface to handle the signature and (emulated) virtual interface to handle TParams corresponding to the signature
- struct TSignature {
- const char** ParamTypes;
- const char* ParamNames[LWTRACE_MAX_PARAMS + 1];
- size_t ParamCount;
-
- // Virtual table
- void (*SerializeParamsFunc)(const TParams& params, TString* values);
- void (*CloneParamsFunc)(TParams& newParams, const TParams& oldParams);
- void (*DestroyParamsFunc)(TParams& params);
+ // Represents a common class for all function "signatures" (parameter types and names).
+ // Provides non-virtual interface to handle the signature and (emulated) virtual interface to handle TParams corresponding to the signature
+ struct TSignature {
+ const char** ParamTypes;
+ const char* ParamNames[LWTRACE_MAX_PARAMS + 1];
+ size_t ParamCount;
+
+ // Virtual table
+ void (*SerializeParamsFunc)(const TParams& params, TString* values);
+ void (*CloneParamsFunc)(TParams& newParams, const TParams& oldParams);
+ void (*DestroyParamsFunc)(TParams& params);
void (*SerializeToPbFunc)(const TParams& params, TSerializedParams& arr);
bool (*DeserializeFromPbFunc)(TParams& params, const TSerializedParams& arr);
-
- // Virtual calls emulation
- void SerializeParams(const TParams& params, TString* values) const {
- (*SerializeParamsFunc)(params, values);
- }
-
- void CloneParams(TParams& newParams, const TParams& oldParams) const {
- (*CloneParamsFunc)(newParams, oldParams);
- }
-
- void DestroyParams(TParams& params) const {
- (*DestroyParamsFunc)(params);
- }
-
+
+ // Virtual calls emulation
+ void SerializeParams(const TParams& params, TString* values) const {
+ (*SerializeParamsFunc)(params, values);
+ }
+
+ void CloneParams(TParams& newParams, const TParams& oldParams) const {
+ (*CloneParamsFunc)(newParams, oldParams);
+ }
+
+ void DestroyParams(TParams& params) const {
+ (*DestroyParamsFunc)(params);
+ }
+
void SerializeToPb(const TParams& params, TSerializedParams& arr) const
{
(*SerializeToPbFunc)(params, arr);
@@ -429,42 +429,42 @@ namespace NLWTrace {
return (*DeserializeFromPbFunc)(params, arr);
}
- void ToProtobuf(TEventPb& pb) const;
-
- size_t FindParamIndex(const TString& param) const {
- for (size_t i = 0; i < ParamCount; i++) {
- if (ParamNames[i] == param) {
- return i;
- }
- }
- return size_t(-1);
- }
- };
-
-#ifndef LWTRACE_DISABLE
-
- // Implementation. Used for compilation error if not all expected parameters passed to a function call
- struct ERROR_not_enough_parameters : TNil {};
-
- // Struct that holds static string with a name of parameter type
- template <class T>
- struct TParamType {
- enum { Supported = 0 };
- static const char* NameString;
- };
-
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- template <> \
- struct TParamType<t> { \
- enum { Supported = 1 }; \
- static const char* NameString; \
- }; \
- /**/
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
- FOR_NIL_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
-
- template <class T>
+ void ToProtobuf(TEventPb& pb) const;
+
+ size_t FindParamIndex(const TString& param) const {
+ for (size_t i = 0; i < ParamCount; i++) {
+ if (ParamNames[i] == param) {
+ return i;
+ }
+ }
+ return size_t(-1);
+ }
+ };
+
+#ifndef LWTRACE_DISABLE
+
+ // Implementation. Used for compilation error if not all expected parameters passed to a function call
+ struct ERROR_not_enough_parameters : TNil {};
+
+ // Struct that holds static string with a name of parameter type
+ template <class T>
+ struct TParamType {
+ enum { Supported = 0 };
+ static const char* NameString;
+ };
+
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ template <> \
+ struct TParamType<t> { \
+ enum { Supported = 1 }; \
+ static const char* NameString; \
+ }; \
+ /**/
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+ FOR_NIL_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+
+ template <class T>
struct TParamTraits;
// Enum types traits impl.
@@ -473,7 +473,7 @@ namespace NLWTrace {
using TStoreType = typename TParamTraits<std::underlying_type_t<TEnum>>::TStoreType;
using TFuncParam = TEnum;
- inline static void ToString(typename TTypeTraits<TStoreType>::TFuncParam stored, TString* out) {
+ inline static void ToString(typename TTypeTraits<TStoreType>::TFuncParam stored, TString* out) {
if constexpr (google::protobuf::is_proto_enum<TEnum>::value) {
const google::protobuf::EnumValueDescriptor* valueDescriptor = google::protobuf::GetEnumDescriptor<TEnum>()->FindValueByNumber(stored);
if (valueDescriptor) {
@@ -484,13 +484,13 @@ namespace NLWTrace {
} else {
*out = TParamConv<TStoreType>::ToString(stored);
}
- }
+ }
inline static TStoreType ToStoreType(TFuncParam v) {
return static_cast<TStoreType>(v);
}
- };
-
+ };
+
template <class TCustomType>
struct TCustomTraitsImpl {
using TStoreType = typename TParamTraits<typename TCustomType::TStoreType>::TStoreType; //see STORE_TYPE_AS
@@ -522,48 +522,48 @@ namespace NLWTrace {
// Standard stored types traits.
-#define STORE_TYPE_AS(input_t, store_as_t) \
- template <> \
- struct TParamTraits<input_t> { \
+#define STORE_TYPE_AS(input_t, store_as_t) \
+ template <> \
+ struct TParamTraits<input_t> { \
using TStoreType = store_as_t; \
using TFuncParam = typename TTypeTraits<input_t>::TFuncParam; \
\
inline static void ToString(typename TTypeTraits<TStoreType>::TFuncParam stored, TString* out) { \
- *out = TParamConv<TStoreType>::ToString(stored); \
- } \
+ *out = TParamConv<TStoreType>::ToString(stored); \
+ } \
\
inline static TStoreType ToStoreType(TFuncParam v) { \
return v; \
} \
- }; \
- /**/
- STORE_TYPE_AS(ui8, ui64);
- STORE_TYPE_AS(i8, i64);
- STORE_TYPE_AS(ui16, ui64);
- STORE_TYPE_AS(i16, i64);
- STORE_TYPE_AS(ui32, ui64);
- STORE_TYPE_AS(i32, i64);
- STORE_TYPE_AS(bool, ui64);
- STORE_TYPE_AS(float, double);
+ }; \
+ /**/
+ STORE_TYPE_AS(ui8, ui64);
+ STORE_TYPE_AS(i8, i64);
+ STORE_TYPE_AS(ui16, ui64);
+ STORE_TYPE_AS(i16, i64);
+ STORE_TYPE_AS(ui32, ui64);
+ STORE_TYPE_AS(i32, i64);
+ STORE_TYPE_AS(bool, ui64);
+ STORE_TYPE_AS(float, double);
#define FOREACH_PARAMTYPE_MACRO(n, t, v) STORE_TYPE_AS(t, t)
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
#undef STORE_TYPE_AS
-#undef FOREACH_PARAMTYPE_MACRO
-
+#undef FOREACH_PARAMTYPE_MACRO
+
// Nil type staits.
- template <>
- struct TParamTraits<TNil> {
+ template <>
+ struct TParamTraits<TNil> {
using TStoreType = TNil;
using TFuncParam = TTypeTraits<TNil>::TFuncParam;
inline static void ToString(typename TTypeTraits<TNil>::TFuncParam, TString*) {
- }
+ }
inline static TNil ToStoreType(TFuncParam v) {
return v;
}
- };
-
+ };
+
inline EParamTypePb ParamTypeToProtobuf(const char* paramType) {
#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
if (strcmp(paramType, n) == 0) { \
@@ -676,35 +676,35 @@ namespace NLWTrace {
Y_UNUSED(param);
}
- // Class representing a specific signature
- template <LWTRACE_TEMPLATE_PARAMS>
- struct TUserSignature {
-#define FOREACH_PARAMNUM_MACRO(i) static_assert(TParamType<typename TParamTraits<TP##i>::TStoreType>::Supported == 1, "expect TParamType< typename TParamTraits<TP ## i>::TStoreType >::Supported == 1");
- FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO) // ERROR: unsupported type used as probe/event parameter type
-#undef FOREACH_PARAMNUM_MACRO
- static const char* ParamTypes[];
- static const int ParamCount = LWTRACE_COUNT_PARAMS;
-
- // Implementation of virtual function (TSignature derived classes vtable emulation)
- inline static void SerializeParams(const TParams& params, TString* values) {
-#define FOREACH_PARAMNUM_MACRO(i) TParamTraits<TP##i>::ToString(params.Param[i].Get<typename TParamTraits<TP##i>::TStoreType>(), values + i);
- FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO);
-#undef FOREACH_PARAMNUM_MACRO
- }
-
- // Implementation of virtual function (TSignature derived classes vtable emulation)
- inline static void CloneParams(TParams& newParams, const TParams& oldParams) {
-#define FOREACH_PARAMNUM_MACRO(i) newParams.Param[i].CopyConstruct<typename TParamTraits<TP##i>::TStoreType>(oldParams.Param[i].Get<typename TParamTraits<TP##i>::TStoreType>());
- FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO);
-#undef FOREACH_PARAMNUM_MACRO
- }
-
- // Implementation of virtual function (TSignature derived classes vtable emulation)
- inline static void DestroyParams(TParams& params) {
-#define FOREACH_PARAMNUM_MACRO(i) params.Param[i].Destruct<typename TParamTraits<TP##i>::TStoreType>();
- FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO);
-#undef FOREACH_PARAMNUM_MACRO
- }
+ // Class representing a specific signature
+ template <LWTRACE_TEMPLATE_PARAMS>
+ struct TUserSignature {
+#define FOREACH_PARAMNUM_MACRO(i) static_assert(TParamType<typename TParamTraits<TP##i>::TStoreType>::Supported == 1, "expect TParamType< typename TParamTraits<TP ## i>::TStoreType >::Supported == 1");
+ FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO) // ERROR: unsupported type used as probe/event parameter type
+#undef FOREACH_PARAMNUM_MACRO
+ static const char* ParamTypes[];
+ static const int ParamCount = LWTRACE_COUNT_PARAMS;
+
+ // Implementation of virtual function (TSignature derived classes vtable emulation)
+ inline static void SerializeParams(const TParams& params, TString* values) {
+#define FOREACH_PARAMNUM_MACRO(i) TParamTraits<TP##i>::ToString(params.Param[i].Get<typename TParamTraits<TP##i>::TStoreType>(), values + i);
+ FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO);
+#undef FOREACH_PARAMNUM_MACRO
+ }
+
+ // Implementation of virtual function (TSignature derived classes vtable emulation)
+ inline static void CloneParams(TParams& newParams, const TParams& oldParams) {
+#define FOREACH_PARAMNUM_MACRO(i) newParams.Param[i].CopyConstruct<typename TParamTraits<TP##i>::TStoreType>(oldParams.Param[i].Get<typename TParamTraits<TP##i>::TStoreType>());
+ FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO);
+#undef FOREACH_PARAMNUM_MACRO
+ }
+
+ // Implementation of virtual function (TSignature derived classes vtable emulation)
+ inline static void DestroyParams(TParams& params) {
+#define FOREACH_PARAMNUM_MACRO(i) params.Param[i].Destruct<typename TParamTraits<TP##i>::TStoreType>();
+ FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO);
+#undef FOREACH_PARAMNUM_MACRO
+ }
// Implementation of virtual function (TSignature derived classes vtable emulation)
inline static void SerializeToPb(const TParams& params, TSerializedParams& arr)
@@ -741,32 +741,32 @@ namespace NLWTrace {
#undef FOREACH_PARAMNUM_MACRO
return true;
}
- };
-
- // Array of static strings pointers for names of parameter types in a specific signature
- template <LWTRACE_TEMPLATE_PARAMS_NODEF>
- const char* TUserSignature<LWTRACE_TEMPLATE_ARGS>::ParamTypes[] = {
-#define FOREACH_PARAMNUM_MACRO(i) TParamType<typename TParamTraits<TP##i>::TStoreType>::NameString,
- FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO) nullptr
-#undef FOREACH_PARAMNUM_MACRO
- };
-
- inline void TSignature::ToProtobuf(TEventPb& pb) const {
- for (size_t i = 0; i < ParamCount; i++) {
- pb.AddParamTypes(ParamTypeToProtobuf(ParamTypes[i]));
- pb.AddParamNames(ParamNames[i]);
- }
- }
-
-#else
-
- inline void TSignature::ToProtobuf(TEventPb&) const {
- }
-
- inline EParamTypePb ParamTypeToProtobuf(const char*) {
- return PT_UNKNOWN;
- }
-
-#endif
-
-}
+ };
+
+ // Array of static strings pointers for names of parameter types in a specific signature
+ template <LWTRACE_TEMPLATE_PARAMS_NODEF>
+ const char* TUserSignature<LWTRACE_TEMPLATE_ARGS>::ParamTypes[] = {
+#define FOREACH_PARAMNUM_MACRO(i) TParamType<typename TParamTraits<TP##i>::TStoreType>::NameString,
+ FOREACH_PARAMNUM(FOREACH_PARAMNUM_MACRO) nullptr
+#undef FOREACH_PARAMNUM_MACRO
+ };
+
+ inline void TSignature::ToProtobuf(TEventPb& pb) const {
+ for (size_t i = 0; i < ParamCount; i++) {
+ pb.AddParamTypes(ParamTypeToProtobuf(ParamTypes[i]));
+ pb.AddParamNames(ParamNames[i]);
+ }
+ }
+
+#else
+
+ inline void TSignature::ToProtobuf(TEventPb&) const {
+ }
+
+ inline EParamTypePb ParamTypeToProtobuf(const char*) {
+ return PT_UNKNOWN;
+ }
+
+#endif
+
+}
diff --git a/library/cpp/lwtrace/sleep_action.cpp b/library/cpp/lwtrace/sleep_action.cpp
index 74977528db..8e5925be38 100644
--- a/library/cpp/lwtrace/sleep_action.cpp
+++ b/library/cpp/lwtrace/sleep_action.cpp
@@ -9,7 +9,7 @@
using namespace NLWTrace;
using namespace NLWTrace::NPrivate;
-bool TSleepActionExecutor::DoExecute(TOrbit&, const TParams&) {
+bool TSleepActionExecutor::DoExecute(TOrbit&, const TParams&) {
NanoSleep(NanoSeconds);
return true;
}
diff --git a/library/cpp/lwtrace/sleep_action.h b/library/cpp/lwtrace/sleep_action.h
index 26f89bd88c..9cece64d40 100644
--- a/library/cpp/lwtrace/sleep_action.h
+++ b/library/cpp/lwtrace/sleep_action.h
@@ -2,20 +2,20 @@
#include "probe.h"
-namespace NLWTrace {
- namespace NPrivate {
- class TSleepActionExecutor: public IExecutor {
- private:
- ui64 NanoSeconds;
+namespace NLWTrace {
+ namespace NPrivate {
+ class TSleepActionExecutor: public IExecutor {
+ private:
+ ui64 NanoSeconds;
- public:
- TSleepActionExecutor(const TProbe*, ui64 nanoSeconds)
- : IExecutor()
- , NanoSeconds(nanoSeconds)
- {
- }
- bool DoExecute(TOrbit& orbit, const TParams& params) override;
- };
+ public:
+ TSleepActionExecutor(const TProbe*, ui64 nanoSeconds)
+ : IExecutor()
+ , NanoSeconds(nanoSeconds)
+ {
+ }
+ bool DoExecute(TOrbit& orbit, const TParams& params) override;
+ };
- }
-}
+ }
+}
diff --git a/library/cpp/lwtrace/start.cpp b/library/cpp/lwtrace/start.cpp
index 121d5472b6..7d17d6c572 100644
--- a/library/cpp/lwtrace/start.cpp
+++ b/library/cpp/lwtrace/start.cpp
@@ -14,56 +14,56 @@
using namespace NLWTrace;
namespace {
- struct TTraceManagerHolder {
- TManager TraceManager;
- TTraceManagerHolder()
- : TraceManager(*Singleton<TProbeRegistry>(), true)
- {
- }
- };
-
- void TraceFromEnv(TString path) {
- TString script = TUnbufferedFileInput(path).ReadAll();
- TQuery query;
- bool ok = google::protobuf::TextFormat::ParseFromString(script, &query);
- Y_VERIFY(ok, "failed to parse protobuf");
- Singleton<TTraceManagerHolder>()->TraceManager.New("env", query);
- }
-
-} // anonymous namespace
-
-void NLWTrace::StartLwtraceFromEnv() {
- static bool started = false;
- if (started) {
- return;
- } else {
- started = true;
- }
-
+ struct TTraceManagerHolder {
+ TManager TraceManager;
+ TTraceManagerHolder()
+ : TraceManager(*Singleton<TProbeRegistry>(), true)
+ {
+ }
+ };
+
+ void TraceFromEnv(TString path) {
+ TString script = TUnbufferedFileInput(path).ReadAll();
+ TQuery query;
+ bool ok = google::protobuf::TextFormat::ParseFromString(script, &query);
+ Y_VERIFY(ok, "failed to parse protobuf");
+ Singleton<TTraceManagerHolder>()->TraceManager.New("env", query);
+ }
+
+} // anonymous namespace
+
+void NLWTrace::StartLwtraceFromEnv() {
+ static bool started = false;
+ if (started) {
+ return;
+ } else {
+ started = true;
+ }
+
TString path = GetEnv("LWTRACE");
if (!path) {
return;
}
try {
- TraceFromEnv(path);
+ TraceFromEnv(path);
} catch (...) {
Cerr << "failed to load lwtrace script: " << CurrentExceptionMessage() << "\n";
abort();
}
}
-
-void NLWTrace::StartLwtraceFromEnv(std::function<void(TManager&)> prepare) {
+
+void NLWTrace::StartLwtraceFromEnv(std::function<void(TManager&)> prepare) {
TString path = GetEnv("LWTRACE");
if (Y_LIKELY(!path)) {
- return;
- }
-
- try {
- prepare(Singleton<TTraceManagerHolder>()->TraceManager);
- TraceFromEnv(path);
- } catch (...) {
- Cerr << "failed to load lwtrace script: " << CurrentExceptionMessage() << "\n";
- abort();
- }
-}
+ return;
+ }
+
+ try {
+ prepare(Singleton<TTraceManagerHolder>()->TraceManager);
+ TraceFromEnv(path);
+ } catch (...) {
+ Cerr << "failed to load lwtrace script: " << CurrentExceptionMessage() << "\n";
+ abort();
+ }
+}
diff --git a/library/cpp/lwtrace/start.h b/library/cpp/lwtrace/start.h
index 2755212bff..9acb8df15e 100644
--- a/library/cpp/lwtrace/start.h
+++ b/library/cpp/lwtrace/start.h
@@ -1,11 +1,11 @@
#pragma once
-#include <functional>
-
+#include <functional>
+
namespace NLWTrace {
- class TManager;
+ class TManager;
- void StartLwtraceFromEnv();
- void StartLwtraceFromEnv(std::function<void(TManager&)> prepare);
+ void StartLwtraceFromEnv();
+ void StartLwtraceFromEnv(std::function<void(TManager&)> prepare);
}
diff --git a/library/cpp/lwtrace/stderr_writer.cpp b/library/cpp/lwtrace/stderr_writer.cpp
index 6e5654c338..43bf9c1d02 100644
--- a/library/cpp/lwtrace/stderr_writer.cpp
+++ b/library/cpp/lwtrace/stderr_writer.cpp
@@ -1,19 +1,19 @@
#include "stderr_writer.h"
-#include <util/stream/str.h>
+#include <util/stream/str.h>
using namespace NLWTrace;
-bool TStderrActionExecutor::DoExecute(TOrbit&, const TParams& params) {
+bool TStderrActionExecutor::DoExecute(TOrbit&, const TParams& params) {
TString ParamValues[LWTRACE_MAX_PARAMS];
Probe->Event.Signature.SerializeParams(params, ParamValues);
- TStringStream ss;
- ss << Probe->Event.GetProvider() << "." << Probe->Event.Name;
+ TStringStream ss;
+ ss << Probe->Event.GetProvider() << "." << Probe->Event.Name;
for (ui32 i = 0; i < Probe->Event.Signature.ParamCount; ++i) {
- ss << " " << Probe->Event.Signature.ParamNames[i] << "=" << ParamValues[i];
+ ss << " " << Probe->Event.Signature.ParamNames[i] << "=" << ParamValues[i];
}
- ss << "\n";
- Cerr << ss.Str();
+ ss << "\n";
+ Cerr << ss.Str();
return true;
}
diff --git a/library/cpp/lwtrace/stderr_writer.h b/library/cpp/lwtrace/stderr_writer.h
index b17fc3136e..17d4789538 100644
--- a/library/cpp/lwtrace/stderr_writer.h
+++ b/library/cpp/lwtrace/stderr_writer.h
@@ -3,17 +3,17 @@
#include "probe.h"
namespace NLWTrace {
- class TStderrActionExecutor: public IExecutor {
- private:
- TProbe* const Probe;
+ class TStderrActionExecutor: public IExecutor {
+ private:
+ TProbe* const Probe;
- public:
- explicit TStderrActionExecutor(TProbe* probe)
- : Probe(probe)
- {
- }
-
- bool DoExecute(TOrbit& orbit, const TParams& params) override;
- };
+ public:
+ explicit TStderrActionExecutor(TProbe* probe)
+ : Probe(probe)
+ {
+ }
+ bool DoExecute(TOrbit& orbit, const TParams& params) override;
+ };
+
}
diff --git a/library/cpp/lwtrace/symbol.cpp b/library/cpp/lwtrace/symbol.cpp
index 456652bcd0..e073772b5e 100644
--- a/library/cpp/lwtrace/symbol.cpp
+++ b/library/cpp/lwtrace/symbol.cpp
@@ -1,15 +1,15 @@
-#include "symbol.h"
+#include "symbol.h"
#include <util/stream/output.h>
-#include <util/string/cast.h>
-
-template <>
-NLWTrace::TSymbol FromStringImpl(const char*, size_t) {
+#include <util/string/cast.h>
+
+template <>
+NLWTrace::TSymbol FromStringImpl(const char*, size_t) {
static TString err("ERROR_dynamic_symbol");
- return NLWTrace::TSymbol(&err);
-}
-
-template <>
-void Out<NLWTrace::TSymbol>(IOutputStream& o, TTypeTraits<NLWTrace::TSymbol>::TFuncParam t) {
+ return NLWTrace::TSymbol(&err);
+}
+
+template <>
+void Out<NLWTrace::TSymbol>(IOutputStream& o, TTypeTraits<NLWTrace::TSymbol>::TFuncParam t) {
Out<TString>(o, *t.Str);
-}
+}
diff --git a/library/cpp/lwtrace/symbol.h b/library/cpp/lwtrace/symbol.h
index ef9e6cdf94..2e7d3da745 100644
--- a/library/cpp/lwtrace/symbol.h
+++ b/library/cpp/lwtrace/symbol.h
@@ -1,68 +1,68 @@
-#pragma once
-
+#pragma once
+
#include <util/generic/string.h>
-#include <util/string/builder.h>
-#include <util/system/src_location.h>
-
-#define LWTRACE_DEFINE_SYMBOL(variable, text) \
- static TString variable##_holder(text); \
- ::NLWTrace::TSymbol variable(&variable##_holder); \
- /**/
-
-#define LWTRACE_INLINE_SYMBOL(text) \
- [&] { \
- static TString _holder(text); \
- return ::NLWTrace::TSymbol(&_holder); \
- }() /**/
-
-#define LWTRACE_LOCATION_SYMBOL \
- [](const char* func) { \
+#include <util/string/builder.h>
+#include <util/system/src_location.h>
+
+#define LWTRACE_DEFINE_SYMBOL(variable, text) \
+ static TString variable##_holder(text); \
+ ::NLWTrace::TSymbol variable(&variable##_holder); \
+ /**/
+
+#define LWTRACE_INLINE_SYMBOL(text) \
+ [&] { \
+ static TString _holder(text); \
+ return ::NLWTrace::TSymbol(&_holder); \
+ }() /**/
+
+#define LWTRACE_LOCATION_SYMBOL \
+ [](const char* func) { \
static TString _holder(TStringBuilder() << func << " (" << __LOCATION__ << ")"); \
- return ::NLWTrace::TSymbol(&_holder); \
- }(Y_FUNC_SIGNATURE) /**/
-
-namespace NLWTrace {
- struct TSymbol {
- TString* Str;
-
- TSymbol()
- : Str(nullptr)
- {
- }
-
- explicit TSymbol(TString* str)
- : Str(str)
- {
- }
-
- TSymbol& operator=(const TSymbol& o) {
- Str = o.Str;
- return *this;
- }
-
- TSymbol(const TSymbol& o)
- : Str(o.Str)
- {
- }
-
- bool operator<(const TSymbol& rhs) const {
- return Str < rhs.Str;
- }
- bool operator>(const TSymbol& rhs) const {
- return Str > rhs.Str;
- }
- bool operator<=(const TSymbol& rhs) const {
- return Str <= rhs.Str;
- }
- bool operator>=(const TSymbol& rhs) const {
- return Str >= rhs.Str;
- }
- bool operator==(const TSymbol& rhs) const {
- return Str == rhs.Str;
- }
- bool operator!=(const TSymbol& rhs) const {
- return Str != rhs.Str;
- }
- };
-
-}
+ return ::NLWTrace::TSymbol(&_holder); \
+ }(Y_FUNC_SIGNATURE) /**/
+
+namespace NLWTrace {
+ struct TSymbol {
+ TString* Str;
+
+ TSymbol()
+ : Str(nullptr)
+ {
+ }
+
+ explicit TSymbol(TString* str)
+ : Str(str)
+ {
+ }
+
+ TSymbol& operator=(const TSymbol& o) {
+ Str = o.Str;
+ return *this;
+ }
+
+ TSymbol(const TSymbol& o)
+ : Str(o.Str)
+ {
+ }
+
+ bool operator<(const TSymbol& rhs) const {
+ return Str < rhs.Str;
+ }
+ bool operator>(const TSymbol& rhs) const {
+ return Str > rhs.Str;
+ }
+ bool operator<=(const TSymbol& rhs) const {
+ return Str <= rhs.Str;
+ }
+ bool operator>=(const TSymbol& rhs) const {
+ return Str >= rhs.Str;
+ }
+ bool operator==(const TSymbol& rhs) const {
+ return Str == rhs.Str;
+ }
+ bool operator!=(const TSymbol& rhs) const {
+ return Str != rhs.Str;
+ }
+ };
+
+}
diff --git a/library/cpp/lwtrace/tests/trace_tests.cpp b/library/cpp/lwtrace/tests/trace_tests.cpp
index 6762e344a7..52f24f3685 100644
--- a/library/cpp/lwtrace/tests/trace_tests.cpp
+++ b/library/cpp/lwtrace/tests/trace_tests.cpp
@@ -6,710 +6,710 @@
#include <util/system/pipe.h>
#include <util/generic/ymath.h>
-#include <util/string/printf.h>
-#include <util/string/vector.h>
-
-#define LWTRACE_TESTS_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
- PROBE(Simplest, GROUPS("Group"), TYPES(), NAMES()) \
- PROBE(IntParam, GROUPS("Group"), TYPES(ui32), NAMES("value")) \
- PROBE(StringParam, GROUPS("Group"), TYPES(TString), NAMES("value")) \
- PROBE(SymbolParam, GROUPS("Group"), TYPES(NLWTrace::TSymbol), NAMES("symbol")) \
- PROBE(CheckParam, GROUPS("Group"), TYPES(NLWTrace::TCheck), NAMES("value")) \
- EVENT(TwoParamsEvent, GROUPS("Group"), TYPES(int, TString), NAMES("param1", "param2")) \
+#include <util/string/printf.h>
+#include <util/string/vector.h>
+
+#define LWTRACE_TESTS_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
+ PROBE(Simplest, GROUPS("Group"), TYPES(), NAMES()) \
+ PROBE(IntParam, GROUPS("Group"), TYPES(ui32), NAMES("value")) \
+ PROBE(StringParam, GROUPS("Group"), TYPES(TString), NAMES("value")) \
+ PROBE(SymbolParam, GROUPS("Group"), TYPES(NLWTrace::TSymbol), NAMES("symbol")) \
+ PROBE(CheckParam, GROUPS("Group"), TYPES(NLWTrace::TCheck), NAMES("value")) \
+ EVENT(TwoParamsEvent, GROUPS("Group"), TYPES(int, TString), NAMES("param1", "param2")) \
EVENT(TwoParamsCheckEvent, GROUPS("Group"), TYPES(NLWTrace::TCheck, TString), NAMES("param1", "param2")) \
- /**/
-
-LWTRACE_DECLARE_PROVIDER(LWTRACE_TESTS_PROVIDER)
-LWTRACE_DEFINE_PROVIDER(LWTRACE_TESTS_PROVIDER)
-LWTRACE_USING(LWTRACE_TESTS_PROVIDER)
-
-namespace NLWTrace {
- namespace NTests {
- TString gStrValue = "a long string value that can be possible passed as a trace probe string parameter";
- //TString gStrValue = "short";
-
- LWTRACE_DEFINE_SYMBOL(gSymbol, "a long symbol value that can be possible passed as a trace probe string parameter");
-
- struct TConfig {
- size_t Cycles;
- size_t Runs;
- bool UnsafeLWTrace;
-
- TConfig() {
- Cycles = 100000;
- Runs = 10;
- UnsafeLWTrace = false;
- }
- };
-
- struct TMeasure {
- double Average;
- double Sigma;
- TMeasure(double a, double s)
- : Average(a)
- , Sigma(s)
- {
- }
- };
-
-#define DEFINE_MEASUREMENT(name, ...) \
- double name##OneRun(const TConfig& cfg) { \
- TInstant t0 = Now(); \
- for (size_t i = 0; i < cfg.Cycles; i++) { \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- HOTSPOT(name, ##__VA_ARGS__); \
- } \
- TInstant t1 = Now(); \
- return double(t1.MicroSeconds() - t0.MicroSeconds()) / (cfg.Cycles * 10); \
- } \
- TMeasure name##Time(const TConfig& cfg) { \
- double v = 0; \
- double vSq = 0; \
- for (size_t i = 0; i < cfg.Runs; i++) { \
- double value = name##OneRun(cfg); \
- v += value; \
- vSq += value * value; \
- } \
- v /= cfg.Runs; \
- vSq /= cfg.Runs; \
- return TMeasure(v, sqrt(vSq - v * v)); \
- } \
- /**/
-
- class TProbes: public TProbeRegistry {
- public:
- TManager Mngr;
-
- TProbes(bool destructiveActionsAllowed)
- : Mngr(*this, destructiveActionsAllowed)
- {
- AddProbesList(LWTRACE_GET_PROBES(LWTRACE_TESTS_PROVIDER));
- }
-
-#define HOTSPOT(name, ...) LWPROBE(name, ##__VA_ARGS__);
- DEFINE_MEASUREMENT(Simplest);
- DEFINE_MEASUREMENT(IntParam, 123);
- DEFINE_MEASUREMENT(StringParam, gStrValue);
- DEFINE_MEASUREMENT(SymbolParam, gSymbol);
- DEFINE_MEASUREMENT(CheckParam, TCheck(13));
-#undef HOTSPOT
- };
-
- class TInMemoryLogTest {
- public:
- TInMemoryLog Log;
-
- TInMemoryLogTest()
- : Log(1000)
- {
- }
-
-#define HOTSPOT(name, ...) LWEVENT(name, Log, true, ##__VA_ARGS__);
- DEFINE_MEASUREMENT(TwoParamsEvent, 666, TString("bla-bla-bla"));
-#undef HOTSPOT
- };
-
- class TInMemoryLogCheckTest {
- public:
- TInMemoryLog Log;
-
- TInMemoryLogCheckTest()
- : Log(1000)
- {
- }
-
-#define HOTSPOT(name, ...) LWEVENT(name, Log, true, ##__VA_ARGS__);
- DEFINE_MEASUREMENT(TwoParamsCheckEvent, TCheck(666), TString("bla-bla-bla"));
-#undef HOTSPOT
- };
-
- NLWTrace::TQuery MakeQuery(const TString& queryStr) {
- NLWTrace::TQuery query;
- google::protobuf::TextFormat::ParseFromString(queryStr, &query);
- return query;
- }
-
- void NoExec(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- Cout << "call to probe w/o executor: " << p.SimplestTime(cfg) << Endl;
- }
-
- void Log(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"Simplest\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with logging executor: " << p.SimplestTime(cfg) << Endl;
- }
-
- void LogTs(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"Simplest\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: true"
- " }"
- " }"
- "}"));
- Cout << "call to probe with logging (+timestamp) executor: " << p.SimplestTime(cfg) << Endl;
- }
-
- void FalseIntFilter(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"IntParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_GT"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"1000\""
- " }"
- " }"
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with int filter (always false) executor: " << p.IntParamTime(cfg) << Endl;
- }
-
- void LogIntAfterFilter(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"IntParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_GT"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"0\""
- " }"
- " }"
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with int filter (always true) and log executors: " << p.IntParamTime(cfg) << Endl;
- }
-
- void LogInt(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"IntParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to int probe with log executor: " << p.IntParamTime(cfg) << Endl;
- }
-
- void FalseStringFilter(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"StringParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_EQ"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"string that never can exist\""
- " }"
- " }"
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with string filter (always false) executor: " << p.StringParamTime(cfg) << Endl;
- }
-
- void FalseStringFilterPartialMatch(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"StringParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_EQ"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"" +
- gStrValue + "-not-full-match\""
- " }"
- " }"
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with string filter (always false) executor: " << p.StringParamTime(cfg) << Endl;
- }
-
- void LogStringAfterFilter(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"StringParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_EQ"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"" +
- gStrValue + "\""
- " }"
- " }"
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with string filter (always true) and log executors: " << p.StringParamTime(cfg) << Endl;
- }
-
- void LogString(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"StringParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to string probe with log executor: " << p.StringParamTime(cfg) << Endl;
- }
-
- void LogSymbol(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"SymbolParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to symbol probe with log executor: " << p.SymbolParamTime(cfg) << Endl;
- }
-
- void LogCheck(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"CheckParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to check probe with log executor: " << p.CheckParamTime(cfg) << Endl;
- }
-
- void InMemoryLog(const TConfig& cfg) {
- TInMemoryLogTest test;
- Cout << "log to in-memory log with (int, string) writer: " << test.TwoParamsEventTime(cfg) << Endl;
- }
-
- void InMemoryLogCheck(const TConfig& cfg) {
- TInMemoryLogCheckTest test;
- Cout << "log to in-memory log with (leak-check, string) writer: " << test.TwoParamsCheckEventTime(cfg) << Endl;
- }
-
- void MultipleActionsCheck(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-multipleActions", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"Simplest\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_LT"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Value: \"2\""
- " }"
- " }"
- " }"
- " Action {"
- " StatementAction {"
- " Type: ST_INC"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " }"
- " }"
- " Action {"
- " StatementAction {"
- " Type: ST_DEC"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " }"
- " }"
- " Action {"
- " StatementAction {"
- " Type: ST_SUB_EQ"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Value: \"-1\""
- " }"
- " }"
- " }"
- " Action {"
- " SleepAction {"
- " NanoSeconds: 25000000" // 25 ms
- " }"
- " }"
- " Action {"
- " SleepAction {"
- " NanoSeconds: 25000000" // 25 ms
- " }"
- " }"
- "}"));
- TInstant t0 = Now();
- for (size_t i = 0; i < 10; i++) {
- LWPROBE(Simplest);
- }
- TInstant t1 = Now();
- ui64 duration = (t1.NanoSeconds() - t0.NanoSeconds());
- Cout << "multiple sleep tested, expected 100000000 ns, measured " << duration << " ns" << Endl;
- }
-
- void SleepCheck(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-sleep", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"Simplest\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " SleepAction {"
- " NanoSeconds: 100000000" // 100 ms
- " }"
- " }"
- "}"));
- TInstant t0 = Now();
- for (size_t i = 0; i < 10; i++) {
- LWPROBE(Simplest);
- }
- TInstant t1 = Now();
- ui64 duration = (t1.NanoSeconds() - t0.NanoSeconds()) / (ui64)10;
- Cout << "sleep tested, expected 100000000 ns, measured " << duration << " ns" << Endl;
- }
-
- void KillCheckChild(const TConfig& cfg, TPipeHandle& writer) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-kill", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"Simplest\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Action {"
- " KillAction {"
- " }"
- " }"
- "}"));
- // Send "i'm alive and ok" to the parent (0)
- char buffer = 0;
- writer.Write(&buffer, 1);
- LWPROBE(Simplest);
- // Send "i'm alive and that's not OK" to the parent (1)
- buffer = 1;
- writer.Write(&buffer, 1);
- }
-
- void KillCheckParent(TPipeHandle& reader) {
- char buffer = -1;
- reader.Read(&buffer, 1);
- reader.Read(&buffer, 1);
- if (buffer == -1)
- Cerr << "\t\terror: process died before transfering OK message during the KillAction test!" << Endl;
- else if (buffer != 0)
- Cerr << "\t\terror: process failed to die on time during the KillAction test!" << Endl;
- else
- Cout << "\t\tkill executor tested OK." << Endl;
- }
-
- void KillCheck(const TConfig& cfg) {
+ /**/
+
+LWTRACE_DECLARE_PROVIDER(LWTRACE_TESTS_PROVIDER)
+LWTRACE_DEFINE_PROVIDER(LWTRACE_TESTS_PROVIDER)
+LWTRACE_USING(LWTRACE_TESTS_PROVIDER)
+
+namespace NLWTrace {
+ namespace NTests {
+ TString gStrValue = "a long string value that can be possible passed as a trace probe string parameter";
+ //TString gStrValue = "short";
+
+ LWTRACE_DEFINE_SYMBOL(gSymbol, "a long symbol value that can be possible passed as a trace probe string parameter");
+
+ struct TConfig {
+ size_t Cycles;
+ size_t Runs;
+ bool UnsafeLWTrace;
+
+ TConfig() {
+ Cycles = 100000;
+ Runs = 10;
+ UnsafeLWTrace = false;
+ }
+ };
+
+ struct TMeasure {
+ double Average;
+ double Sigma;
+ TMeasure(double a, double s)
+ : Average(a)
+ , Sigma(s)
+ {
+ }
+ };
+
+#define DEFINE_MEASUREMENT(name, ...) \
+ double name##OneRun(const TConfig& cfg) { \
+ TInstant t0 = Now(); \
+ for (size_t i = 0; i < cfg.Cycles; i++) { \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ HOTSPOT(name, ##__VA_ARGS__); \
+ } \
+ TInstant t1 = Now(); \
+ return double(t1.MicroSeconds() - t0.MicroSeconds()) / (cfg.Cycles * 10); \
+ } \
+ TMeasure name##Time(const TConfig& cfg) { \
+ double v = 0; \
+ double vSq = 0; \
+ for (size_t i = 0; i < cfg.Runs; i++) { \
+ double value = name##OneRun(cfg); \
+ v += value; \
+ vSq += value * value; \
+ } \
+ v /= cfg.Runs; \
+ vSq /= cfg.Runs; \
+ return TMeasure(v, sqrt(vSq - v * v)); \
+ } \
+ /**/
+
+ class TProbes: public TProbeRegistry {
+ public:
+ TManager Mngr;
+
+ TProbes(bool destructiveActionsAllowed)
+ : Mngr(*this, destructiveActionsAllowed)
+ {
+ AddProbesList(LWTRACE_GET_PROBES(LWTRACE_TESTS_PROVIDER));
+ }
+
+#define HOTSPOT(name, ...) LWPROBE(name, ##__VA_ARGS__);
+ DEFINE_MEASUREMENT(Simplest);
+ DEFINE_MEASUREMENT(IntParam, 123);
+ DEFINE_MEASUREMENT(StringParam, gStrValue);
+ DEFINE_MEASUREMENT(SymbolParam, gSymbol);
+ DEFINE_MEASUREMENT(CheckParam, TCheck(13));
+#undef HOTSPOT
+ };
+
+ class TInMemoryLogTest {
+ public:
+ TInMemoryLog Log;
+
+ TInMemoryLogTest()
+ : Log(1000)
+ {
+ }
+
+#define HOTSPOT(name, ...) LWEVENT(name, Log, true, ##__VA_ARGS__);
+ DEFINE_MEASUREMENT(TwoParamsEvent, 666, TString("bla-bla-bla"));
+#undef HOTSPOT
+ };
+
+ class TInMemoryLogCheckTest {
+ public:
+ TInMemoryLog Log;
+
+ TInMemoryLogCheckTest()
+ : Log(1000)
+ {
+ }
+
+#define HOTSPOT(name, ...) LWEVENT(name, Log, true, ##__VA_ARGS__);
+ DEFINE_MEASUREMENT(TwoParamsCheckEvent, TCheck(666), TString("bla-bla-bla"));
+#undef HOTSPOT
+ };
+
+ NLWTrace::TQuery MakeQuery(const TString& queryStr) {
+ NLWTrace::TQuery query;
+ google::protobuf::TextFormat::ParseFromString(queryStr, &query);
+ return query;
+ }
+
+ void NoExec(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ Cout << "call to probe w/o executor: " << p.SimplestTime(cfg) << Endl;
+ }
+
+ void Log(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"Simplest\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with logging executor: " << p.SimplestTime(cfg) << Endl;
+ }
+
+ void LogTs(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"Simplest\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: true"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with logging (+timestamp) executor: " << p.SimplestTime(cfg) << Endl;
+ }
+
+ void FalseIntFilter(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"IntParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_GT"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"1000\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with int filter (always false) executor: " << p.IntParamTime(cfg) << Endl;
+ }
+
+ void LogIntAfterFilter(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"IntParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_GT"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"0\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with int filter (always true) and log executors: " << p.IntParamTime(cfg) << Endl;
+ }
+
+ void LogInt(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"IntParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to int probe with log executor: " << p.IntParamTime(cfg) << Endl;
+ }
+
+ void FalseStringFilter(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"StringParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_EQ"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"string that never can exist\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with string filter (always false) executor: " << p.StringParamTime(cfg) << Endl;
+ }
+
+ void FalseStringFilterPartialMatch(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"StringParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_EQ"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"" +
+ gStrValue + "-not-full-match\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with string filter (always false) executor: " << p.StringParamTime(cfg) << Endl;
+ }
+
+ void LogStringAfterFilter(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"StringParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_EQ"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"" +
+ gStrValue + "\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with string filter (always true) and log executors: " << p.StringParamTime(cfg) << Endl;
+ }
+
+ void LogString(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"StringParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to string probe with log executor: " << p.StringParamTime(cfg) << Endl;
+ }
+
+ void LogSymbol(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"SymbolParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to symbol probe with log executor: " << p.SymbolParamTime(cfg) << Endl;
+ }
+
+ void LogCheck(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"CheckParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to check probe with log executor: " << p.CheckParamTime(cfg) << Endl;
+ }
+
+ void InMemoryLog(const TConfig& cfg) {
+ TInMemoryLogTest test;
+ Cout << "log to in-memory log with (int, string) writer: " << test.TwoParamsEventTime(cfg) << Endl;
+ }
+
+ void InMemoryLogCheck(const TConfig& cfg) {
+ TInMemoryLogCheckTest test;
+ Cout << "log to in-memory log with (leak-check, string) writer: " << test.TwoParamsCheckEventTime(cfg) << Endl;
+ }
+
+ void MultipleActionsCheck(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-multipleActions", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"Simplest\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_LT"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Value: \"2\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " StatementAction {"
+ " Type: ST_INC"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " StatementAction {"
+ " Type: ST_DEC"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " StatementAction {"
+ " Type: ST_SUB_EQ"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Value: \"-1\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " SleepAction {"
+ " NanoSeconds: 25000000" // 25 ms
+ " }"
+ " }"
+ " Action {"
+ " SleepAction {"
+ " NanoSeconds: 25000000" // 25 ms
+ " }"
+ " }"
+ "}"));
+ TInstant t0 = Now();
+ for (size_t i = 0; i < 10; i++) {
+ LWPROBE(Simplest);
+ }
+ TInstant t1 = Now();
+ ui64 duration = (t1.NanoSeconds() - t0.NanoSeconds());
+ Cout << "multiple sleep tested, expected 100000000 ns, measured " << duration << " ns" << Endl;
+ }
+
+ void SleepCheck(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-sleep", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"Simplest\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " SleepAction {"
+ " NanoSeconds: 100000000" // 100 ms
+ " }"
+ " }"
+ "}"));
+ TInstant t0 = Now();
+ for (size_t i = 0; i < 10; i++) {
+ LWPROBE(Simplest);
+ }
+ TInstant t1 = Now();
+ ui64 duration = (t1.NanoSeconds() - t0.NanoSeconds()) / (ui64)10;
+ Cout << "sleep tested, expected 100000000 ns, measured " << duration << " ns" << Endl;
+ }
+
+ void KillCheckChild(const TConfig& cfg, TPipeHandle& writer) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-kill", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"Simplest\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Action {"
+ " KillAction {"
+ " }"
+ " }"
+ "}"));
+ // Send "i'm alive and ok" to the parent (0)
+ char buffer = 0;
+ writer.Write(&buffer, 1);
+ LWPROBE(Simplest);
+ // Send "i'm alive and that's not OK" to the parent (1)
+ buffer = 1;
+ writer.Write(&buffer, 1);
+ }
+
+ void KillCheckParent(TPipeHandle& reader) {
+ char buffer = -1;
+ reader.Read(&buffer, 1);
+ reader.Read(&buffer, 1);
+ if (buffer == -1)
+ Cerr << "\t\terror: process died before transfering OK message during the KillAction test!" << Endl;
+ else if (buffer != 0)
+ Cerr << "\t\terror: process failed to die on time during the KillAction test!" << Endl;
+ else
+ Cout << "\t\tkill executor tested OK." << Endl;
+ }
+
+ void KillCheck(const TConfig& cfg) {
#ifdef _unix_
- TPipeHandle reader;
- TPipeHandle writer;
- TPipeHandle::Pipe(reader, writer);
- Cout << "forking the process..." << Endl;
- pid_t cpid = fork();
- if (cpid == -1) {
- Cerr << "\t\terror forking for the KillAction test!" << Endl;
- } else if (cpid == 0) {
- reader.Close();
- KillCheckChild(cfg, writer);
- writer.Close();
- exit(EXIT_SUCCESS);
- } else {
- writer.Close();
- KillCheckParent(reader);
- reader.Close();
- }
+ TPipeHandle reader;
+ TPipeHandle writer;
+ TPipeHandle::Pipe(reader, writer);
+ Cout << "forking the process..." << Endl;
+ pid_t cpid = fork();
+ if (cpid == -1) {
+ Cerr << "\t\terror forking for the KillAction test!" << Endl;
+ } else if (cpid == 0) {
+ reader.Close();
+ KillCheckChild(cfg, writer);
+ writer.Close();
+ exit(EXIT_SUCCESS);
+ } else {
+ writer.Close();
+ KillCheckParent(reader);
+ reader.Close();
+ }
#else
- Cout << "kill action test for windows is not implemented." << Endl;
+ Cout << "kill action test for windows is not implemented." << Endl;
#endif
- }
-
- void LogIntModFilter(const TConfig& cfg) {
- TProbes p(cfg.UnsafeLWTrace);
- p.Mngr.New("test-trace", MakeQuery(
- "Blocks {"
- " ProbeDesc {"
- " Name: \"IntParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_GT"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"0\""
- " }"
- " }"
- " }"
- " Action {"
- " StatementAction {"
- " Type: ST_ADD_EQ"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Value: \"1\""
- " }"
- " }"
- " }"
- " Action {"
- " StatementAction {"
- " Type: ST_ADD"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Value: \"1\""
- " }"
- " }"
- " }"
- " Action {"
- " StatementAction {"
- " Type: ST_MOD"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Value: \"20\""
- " }"
- " }"
- " }"
- "}"
- "Blocks {"
- " ProbeDesc {"
- " Name: \"IntParam\""
- " Provider: \"LWTRACE_TESTS_PROVIDER\""
- " }"
- " Predicate {"
- " Operators {"
- " Type: OT_EQ"
- " Argument {"
- " Variable: \"counter\""
- " }"
- " Argument {"
- " Value: \"0\""
- " }"
- " }"
- " Operators {"
- " Type: OT_GT"
- " Argument {"
- " Param: \"value\""
- " }"
- " Argument {"
- " Value: \"0\""
- " }"
- " }"
- " }"
- " Action {"
- " LogAction {"
- " LogTimestamp: false"
- " }"
- " }"
- "}"));
- Cout << "call to probe with int mod filter (always true, mod 10) and log executors: " << p.IntParamTime(cfg) << Endl;
- }
-
-#define FOR_EACH_TEST() \
- FOR_EACH_TEST_MACRO(LogIntModFilter) \
- FOR_EACH_TEST_MACRO(SleepCheck) \
- FOR_EACH_TEST_MACRO(MultipleActionsCheck) \
- FOR_EACH_TEST_MACRO(KillCheck) \
- FOR_EACH_TEST_MACRO(InMemoryLog) \
- FOR_EACH_TEST_MACRO(InMemoryLogCheck) \
- FOR_EACH_TEST_MACRO(NoExec) \
- FOR_EACH_TEST_MACRO(Log) \
- FOR_EACH_TEST_MACRO(LogTs) \
- FOR_EACH_TEST_MACRO(FalseIntFilter) \
- FOR_EACH_TEST_MACRO(LogIntAfterFilter) \
- FOR_EACH_TEST_MACRO(LogInt) \
- FOR_EACH_TEST_MACRO(FalseStringFilter) \
- FOR_EACH_TEST_MACRO(FalseStringFilterPartialMatch) \
- FOR_EACH_TEST_MACRO(LogStringAfterFilter) \
- FOR_EACH_TEST_MACRO(LogString) \
- FOR_EACH_TEST_MACRO(LogSymbol) \
- FOR_EACH_TEST_MACRO(LogCheck) \
- /**/
-
- int Main(int argc, char** argv) {
- TConfig cfg;
- using namespace NLastGetopt;
- TOpts opts = NLastGetopt::TOpts::Default();
- opts.AddLongOption('c', "cycles", "cycles count").RequiredArgument("N").DefaultValue(ToString(cfg.Cycles)).StoreResult(&cfg.Cycles);
- opts.AddLongOption('r', "runs", "runs count").RequiredArgument("N").DefaultValue(ToString(cfg.Runs)).StoreResult(&cfg.Runs);
- opts.AddLongOption('u', "unsafe-lwtrace", "allow destructive actions").OptionalValue(ToString(true)).DefaultValue(ToString(false)).StoreResult(&cfg.UnsafeLWTrace);
- opts.AddHelpOption('h');
- TOptsParseResult res(&opts, argc, argv);
-
- TVector<TString> tests = res.GetFreeArgs();
- if (tests.empty()) {
-#define FOR_EACH_TEST_MACRO(t) tests.push_back(#t);
- FOR_EACH_TEST()
-#undef FOR_EACH_TEST_MACRO
- }
- for (size_t i = 0; i < tests.size(); i++) {
- const TString& test = tests[i];
-#define FOR_EACH_TEST_MACRO(t) \
- if (test == #t) { \
- Cout << #t ": \t"; \
- t(cfg); \
- }
- FOR_EACH_TEST()
-#undef FOR_EACH_TEST_MACRO
- }
-
- if (TCheck::ObjCount != 0) {
- Cout << ">>>>> THERE IS AN OBJECT LEAK <<<<<" << Endl;
- Cout << "NLWTrace::TCheck::ObjCount = " << TCheck::ObjCount << Endl;
- }
-
- Cout << "Done" << Endl;
- return 0;
- }
-
- }
-
-}
-
-template <>
+ }
+
+ void LogIntModFilter(const TConfig& cfg) {
+ TProbes p(cfg.UnsafeLWTrace);
+ p.Mngr.New("test-trace", MakeQuery(
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"IntParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_GT"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"0\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " StatementAction {"
+ " Type: ST_ADD_EQ"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Value: \"1\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " StatementAction {"
+ " Type: ST_ADD"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Value: \"1\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " StatementAction {"
+ " Type: ST_MOD"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Value: \"20\""
+ " }"
+ " }"
+ " }"
+ "}"
+ "Blocks {"
+ " ProbeDesc {"
+ " Name: \"IntParam\""
+ " Provider: \"LWTRACE_TESTS_PROVIDER\""
+ " }"
+ " Predicate {"
+ " Operators {"
+ " Type: OT_EQ"
+ " Argument {"
+ " Variable: \"counter\""
+ " }"
+ " Argument {"
+ " Value: \"0\""
+ " }"
+ " }"
+ " Operators {"
+ " Type: OT_GT"
+ " Argument {"
+ " Param: \"value\""
+ " }"
+ " Argument {"
+ " Value: \"0\""
+ " }"
+ " }"
+ " }"
+ " Action {"
+ " LogAction {"
+ " LogTimestamp: false"
+ " }"
+ " }"
+ "}"));
+ Cout << "call to probe with int mod filter (always true, mod 10) and log executors: " << p.IntParamTime(cfg) << Endl;
+ }
+
+#define FOR_EACH_TEST() \
+ FOR_EACH_TEST_MACRO(LogIntModFilter) \
+ FOR_EACH_TEST_MACRO(SleepCheck) \
+ FOR_EACH_TEST_MACRO(MultipleActionsCheck) \
+ FOR_EACH_TEST_MACRO(KillCheck) \
+ FOR_EACH_TEST_MACRO(InMemoryLog) \
+ FOR_EACH_TEST_MACRO(InMemoryLogCheck) \
+ FOR_EACH_TEST_MACRO(NoExec) \
+ FOR_EACH_TEST_MACRO(Log) \
+ FOR_EACH_TEST_MACRO(LogTs) \
+ FOR_EACH_TEST_MACRO(FalseIntFilter) \
+ FOR_EACH_TEST_MACRO(LogIntAfterFilter) \
+ FOR_EACH_TEST_MACRO(LogInt) \
+ FOR_EACH_TEST_MACRO(FalseStringFilter) \
+ FOR_EACH_TEST_MACRO(FalseStringFilterPartialMatch) \
+ FOR_EACH_TEST_MACRO(LogStringAfterFilter) \
+ FOR_EACH_TEST_MACRO(LogString) \
+ FOR_EACH_TEST_MACRO(LogSymbol) \
+ FOR_EACH_TEST_MACRO(LogCheck) \
+ /**/
+
+ int Main(int argc, char** argv) {
+ TConfig cfg;
+ using namespace NLastGetopt;
+ TOpts opts = NLastGetopt::TOpts::Default();
+ opts.AddLongOption('c', "cycles", "cycles count").RequiredArgument("N").DefaultValue(ToString(cfg.Cycles)).StoreResult(&cfg.Cycles);
+ opts.AddLongOption('r', "runs", "runs count").RequiredArgument("N").DefaultValue(ToString(cfg.Runs)).StoreResult(&cfg.Runs);
+ opts.AddLongOption('u', "unsafe-lwtrace", "allow destructive actions").OptionalValue(ToString(true)).DefaultValue(ToString(false)).StoreResult(&cfg.UnsafeLWTrace);
+ opts.AddHelpOption('h');
+ TOptsParseResult res(&opts, argc, argv);
+
+ TVector<TString> tests = res.GetFreeArgs();
+ if (tests.empty()) {
+#define FOR_EACH_TEST_MACRO(t) tests.push_back(#t);
+ FOR_EACH_TEST()
+#undef FOR_EACH_TEST_MACRO
+ }
+ for (size_t i = 0; i < tests.size(); i++) {
+ const TString& test = tests[i];
+#define FOR_EACH_TEST_MACRO(t) \
+ if (test == #t) { \
+ Cout << #t ": \t"; \
+ t(cfg); \
+ }
+ FOR_EACH_TEST()
+#undef FOR_EACH_TEST_MACRO
+ }
+
+ if (TCheck::ObjCount != 0) {
+ Cout << ">>>>> THERE IS AN OBJECT LEAK <<<<<" << Endl;
+ Cout << "NLWTrace::TCheck::ObjCount = " << TCheck::ObjCount << Endl;
+ }
+
+ Cout << "Done" << Endl;
+ return 0;
+ }
+
+ }
+
+}
+
+template <>
void Out<NLWTrace::NTests::TMeasure>(IOutputStream& os, TTypeTraits<NLWTrace::NTests::TMeasure>::TFuncParam measure) {
- os << Sprintf("\n\t\t%.6lf +- %.6lf us,\tRPS: %30.3lf (%.1fM)", measure.Average, measure.Sigma, 1000000.0 / measure.Average, 1.0 / measure.Average);
-}
-
-int main(int argc, char** argv) {
- try {
- return NLWTrace::NTests::Main(argc, argv);
- } catch (std::exception& e) {
- Cerr << e.what() << Endl;
- return 1;
- } catch (...) {
- Cerr << "Unknown error" << Endl;
- return 1;
- }
-}
+ os << Sprintf("\n\t\t%.6lf +- %.6lf us,\tRPS: %30.3lf (%.1fM)", measure.Average, measure.Sigma, 1000000.0 / measure.Average, 1.0 / measure.Average);
+}
+
+int main(int argc, char** argv) {
+ try {
+ return NLWTrace::NTests::Main(argc, argv);
+ } catch (std::exception& e) {
+ Cerr << e.what() << Endl;
+ return 1;
+ } catch (...) {
+ Cerr << "Unknown error" << Endl;
+ return 1;
+ }
+}
diff --git a/library/cpp/lwtrace/tests/ya.make b/library/cpp/lwtrace/tests/ya.make
index 6225ab1fa0..072cbba5d4 100644
--- a/library/cpp/lwtrace/tests/ya.make
+++ b/library/cpp/lwtrace/tests/ya.make
@@ -1,15 +1,15 @@
OWNER(serxa)
-PROGRAM()
-
-SRCS(
- trace_tests.cpp
-)
-
-PEERDIR(
+PROGRAM()
+
+SRCS(
+ trace_tests.cpp
+)
+
+PEERDIR(
contrib/libs/protobuf
library/cpp/getopt
library/cpp/lwtrace
-)
-
-END()
+)
+
+END()
diff --git a/library/cpp/lwtrace/trace.cpp b/library/cpp/lwtrace/trace.cpp
index 3c974c85a0..c4d30b1796 100644
--- a/library/cpp/lwtrace/trace.cpp
+++ b/library/cpp/lwtrace/trace.cpp
@@ -6,812 +6,812 @@
#include "stderr_writer.h"
#include "google/protobuf/repeated_field.h"
-#include <util/generic/map.h>
-#include <util/random/random.h>
-
+#include <util/generic/map.h>
+#include <util/random/random.h>
+
#include <functional>
-namespace NLWTrace {
-#ifndef LWTRACE_DISABLE
-
-// Define static strings for name of each parameter type
-#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
- const char* TParamType<t>::NameString = n; \
- /**/
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
- FOR_NIL_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
-#undef FOREACH_PARAMTYPE_MACRO
-
-#endif
-
- void TProbeRegistry::AddProbesList(TProbe** reg) {
- TGuard<TMutex> g(Mutex);
- if (reg == nullptr) {
- return;
- }
- for (TProbe** i = reg; *i != nullptr; i++) {
- AddProbeNoLock(new TStaticBox(*i));
- }
- }
-
- void TProbeRegistry::AddProbe(const TBoxPtr& box) {
- TGuard<TMutex> g(Mutex);
- AddProbeNoLock(box);
- }
-
- void TProbeRegistry::RemoveProbe(TProbe* probe) {
- TGuard<TMutex> g(Mutex);
- RemoveProbeNoLock(probe);
- }
-
- void TProbeRegistry::AddProbeNoLock(const TBoxPtr& box) {
- TProbe* probe = box->GetProbe();
+namespace NLWTrace {
+#ifndef LWTRACE_DISABLE
+
+// Define static strings for name of each parameter type
+#define FOREACH_PARAMTYPE_MACRO(n, t, v) \
+ const char* TParamType<t>::NameString = n; \
+ /**/
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+ FOR_NIL_PARAMTYPE(FOREACH_PARAMTYPE_MACRO)
+#undef FOREACH_PARAMTYPE_MACRO
+
+#endif
+
+ void TProbeRegistry::AddProbesList(TProbe** reg) {
+ TGuard<TMutex> g(Mutex);
+ if (reg == nullptr) {
+ return;
+ }
+ for (TProbe** i = reg; *i != nullptr; i++) {
+ AddProbeNoLock(new TStaticBox(*i));
+ }
+ }
+
+ void TProbeRegistry::AddProbe(const TBoxPtr& box) {
+ TGuard<TMutex> g(Mutex);
+ AddProbeNoLock(box);
+ }
+
+ void TProbeRegistry::RemoveProbe(TProbe* probe) {
+ TGuard<TMutex> g(Mutex);
+ RemoveProbeNoLock(probe);
+ }
+
+ void TProbeRegistry::AddProbeNoLock(const TBoxPtr& box) {
+ TProbe* probe = box->GetProbe();
if (Probes.contains(probe)) {
- return; // silently skip probe double registration
- }
- TIds::key_type key(probe->Event.GetProvider(), probe->Event.Name);
+ return; // silently skip probe double registration
+ }
+ TIds::key_type key(probe->Event.GetProvider(), probe->Event.Name);
Y_VERIFY(Ids.count(key) == 0, "duplicate provider:probe pair %s:%s", key.first.data(), key.second.data());
- Probes.emplace(probe, box);
- Ids.insert(key);
- }
-
- void TProbeRegistry::RemoveProbeNoLock(TProbe* probe) {
- auto iter = Probes.find(probe);
- if (iter != Probes.end()) {
- TIds::key_type key(probe->Event.GetProvider(), probe->Event.Name);
- Ids.erase(key);
- Probes.erase(iter);
- } else {
- // silently skip probe double unregistration
- }
- }
-
- TAtomic* GetVariablePtr(TSession::TTraceVariables& traceVariables, const TString& name) {
- TSession::TTraceVariables::iterator it = traceVariables.find(name);
- if (it == traceVariables.end()) {
- TAtomicBase zero = 0;
- traceVariables[name] = zero;
- return &traceVariables[name];
- }
- return &((*it).second);
- }
-
- typedef enum {
- OT_LITERAL = 0,
- OT_PARAMETER = 1,
- OT_VARIABLE = 2
- } EOperandType;
-
- template <class T, EOperandType>
- class TOperand;
-
- template <class T>
- class TOperand<T, OT_LITERAL> {
- private:
- T ImmediateValue;
-
- public:
- TOperand(TSession::TTraceVariables&, const TString&, const TString& value, size_t) {
- ImmediateValue = TParamConv<T>::FromString(value);
- }
- const T& Get(const TParams&) {
- return ImmediateValue;
- }
- };
-
- template <class T>
- class TOperand<T, OT_PARAMETER> {
- private:
- size_t Idx;
-
- public:
- TOperand(TSession::TTraceVariables&, const TString&, const TString&, size_t idx) {
- Idx = idx;
- }
-
- const T& Get(const TParams& params) {
- return params.Param[Idx].template Get<T>();
- }
- };
-
- template <class T>
- class TOperand<T, OT_VARIABLE> {
- private:
- TAtomic* Variable;
-
- public:
- TOperand(TSession::TTraceVariables& traceVariables, const TString& name, const TString&, size_t) {
- Variable = GetVariablePtr(traceVariables, name);
- }
-
- const T Get(const TParams&) {
- return (T)AtomicGet(*Variable);
- }
-
- void Set(const T& value) {
- AtomicSet(*Variable, value);
- }
-
- void Inc() {
- AtomicIncrement(*Variable);
- }
-
- void Dec() {
- AtomicDecrement(*Variable);
- }
-
- void Add(const TAtomicBase value) {
- AtomicAdd(*Variable, value);
- }
-
- void Sub(const TAtomicBase value) {
- AtomicSub(*Variable, value);
- }
- };
-
- template <>
- class TOperand<TCheck, OT_VARIABLE> {
- private:
- TAtomic* Variable;
-
- public:
- TOperand(TSession::TTraceVariables& traceVariables, const TString& name, const TString&, size_t) {
- Variable = GetVariablePtr(traceVariables, name);
- }
-
- const TCheck Get(const TParams&) {
- return TCheck(AtomicGet(*Variable));
- }
-
- void Set(const TCheck& value) {
- AtomicSet(*Variable, value.Value);
- }
-
- void Add(const TCheck& value) {
- AtomicAdd(*Variable, value.Value);
- }
-
- void Sub(const TCheck value) {
- AtomicSub(*Variable, value.Value);
- }
-
- void Inc() {
- AtomicIncrement(*Variable);
- }
-
- void Dec() {
- AtomicDecrement(*Variable);
- }
- };
-
- template <>
- class TOperand<TString, OT_VARIABLE> {
- private:
- TString Dummy;
-
- public:
- TOperand(TSession::TTraceVariables&, const TString&, const TString&, size_t) {
- }
-
- const TString Get(const TParams&) {
- return Dummy;
- }
-
- void Set(const TString&) {
- }
- };
-
- template <>
- class TOperand<TSymbol, OT_VARIABLE> {
- private:
- TSymbol Dummy;
-
- public:
- TOperand(TSession::TTraceVariables&, const TString&, const TString&, size_t) {
- }
-
- const TSymbol Get(const TParams&) {
- return Dummy;
- }
-
- void Set(const TSymbol&) {
- }
- };
-
- // IOperandGetter: hide concrete EOperandType, to save compilation time
- template <class T>
- struct IOperandGetter {
- virtual const T Get(const TParams& params) = 0;
- virtual ~IOperandGetter() {
- }
- };
-
- template <class T, EOperandType TParam>
- class TOperandGetter: public IOperandGetter<T> {
- private:
- TOperand<T, TParam> Op;
-
- public:
- TOperandGetter(const TOperand<T, TParam>& op)
- : Op(op)
- {
- }
-
- const T Get(const TParams& params) override {
- return Op.Get(params);
- }
- };
-
- template <class T>
- class TReceiver: public TOperand<T, OT_VARIABLE> {
- public:
- TReceiver(TSession::TTraceVariables& traceVariables, const TString& name)
- : TOperand<T, OT_VARIABLE>(traceVariables, name, nullptr, 0)
- {
- }
- };
-
- template <class TP, class TPredicate>
- static bool CmpFunc(TP a, TP b) {
- return TPredicate()(a, b);
+ Probes.emplace(probe, box);
+ Ids.insert(key);
+ }
+
+ void TProbeRegistry::RemoveProbeNoLock(TProbe* probe) {
+ auto iter = Probes.find(probe);
+ if (iter != Probes.end()) {
+ TIds::key_type key(probe->Event.GetProvider(), probe->Event.Name);
+ Ids.erase(key);
+ Probes.erase(iter);
+ } else {
+ // silently skip probe double unregistration
+ }
+ }
+
+ TAtomic* GetVariablePtr(TSession::TTraceVariables& traceVariables, const TString& name) {
+ TSession::TTraceVariables::iterator it = traceVariables.find(name);
+ if (it == traceVariables.end()) {
+ TAtomicBase zero = 0;
+ traceVariables[name] = zero;
+ return &traceVariables[name];
+ }
+ return &((*it).second);
}
- template <class TP, class TFunc, EOperandType TLhs, EOperandType TRhs>
- class TOperatorExecutor: public IExecutor {
- private:
- bool InvertCompare;
- TOperand<TP, TLhs> Lhs;
- TOperand<TP, TRhs> Rhs;
-
- bool DoExecute(TOrbit&, const TParams& params) override {
- return TFunc()(Lhs.Get(params), Rhs.Get(params)) != InvertCompare;
- }
-
- public:
- TOperatorExecutor(const TOperand<TP, TLhs>& lhs, const TOperand<TP, TRhs>& rhs, bool invertCompare)
- : InvertCompare(invertCompare)
- , Lhs(lhs)
- , Rhs(rhs)
- {
- }
- };
-
- template <class TR, class TP>
- struct TAddEq {
- void operator()(TR& x, TP y) const {
- x.Add(y);
- }
- };
- template <class TR, class TP>
- struct TSubEq {
- void operator()(TR& x, TP y) const {
- x.Sub(y);
- }
- };
- template <class TR>
- struct TInc {
- void operator()(TR& x) const {
- x.Inc();
- }
- };
- template <class TR>
- struct TDec {
- void operator()(TR& x) const {
- x.Dec();
- }
- };
-
- template <class TP, class TFunc>
- class TUnaryInplaceStatementExecutor: public IExecutor {
- private:
- TFunc Func;
- TReceiver<TP> Receiver;
-
- bool DoExecute(TOrbit&, const TParams&) override {
- Func(Receiver);
- return true;
- }
-
- public:
- TUnaryInplaceStatementExecutor(TReceiver<TP>& receiver)
- : Receiver(receiver)
- {
- }
- };
-
- template <class TP, class TFunc, EOperandType TParam>
- class TBinaryInplaceStatementExecutor: public IExecutor {
- private:
- TFunc Func;
- TReceiver<TP> Receiver;
- TOperand<TP, TParam> Param;
-
- bool DoExecute(TOrbit&, const TParams& params) override {
- Func(Receiver, Param.Get(params));
- return true;
- }
-
- public:
- TBinaryInplaceStatementExecutor(TReceiver<TP>& receiver, const TOperand<TP, TParam>& param)
- : Receiver(receiver)
- , Param(param)
- {
- }
- };
-
- template <class TP, class TFunc, EOperandType TFirstParam>
- class TBinaryStatementExecutor: public IExecutor {
- private:
- TFunc Func;
- TReceiver<TP> Receiver;
- TOperand<TP, TFirstParam> FirstParam;
-
- bool DoExecute(TOrbit&, const TParams& params) override {
- Receiver.Set(Func(Receiver.Get(params), FirstParam.Get(params)));
- return true;
- }
-
- public:
- TBinaryStatementExecutor(TReceiver<TP>& receiver, const TOperand<TP, TFirstParam>& firstParam)
- : Receiver(receiver)
- , FirstParam(firstParam)
- {
- }
- };
-
- template <class TP, class TFunc>
- class TTernaryStatementExecutor: public IExecutor {
- private:
- TFunc Func;
- TReceiver<TP> Receiver;
-
- TAutoPtr<IOperandGetter<TP>> FirstParam;
- TAutoPtr<IOperandGetter<TP>> SecondParam;
-
- bool DoExecute(TOrbit&, const TParams& params) override {
- Receiver.Set(Func(FirstParam->Get(params), SecondParam->Get(params)));
- return true;
- }
-
- public:
- TTernaryStatementExecutor(const TReceiver<TP>& receiver,
- TAutoPtr<IOperandGetter<TP>> firstParam,
- TAutoPtr<IOperandGetter<TP>> secondParam)
- : Receiver(receiver)
- , FirstParam(firstParam)
- , SecondParam(secondParam)
- {
- }
- };
-
- template <class TLog>
- class TLogActionExecutor: public IExecutor {
- private:
- bool LogParams;
- bool LogTimestamp;
- intptr_t* MaxRecords;
- TAtomic Records;
- TProbe* Probe;
- TLog* Log;
-
- bool DoExecute(TOrbit&, const TParams& params) override {
- if (MaxRecords != nullptr) {
- while (true) {
- intptr_t a = AtomicGet(Records);
- if (a >= *MaxRecords) {
- return true;
- }
- if (AtomicCas(&Records, a + 1, a)) {
- Write(params);
- return true;
- }
- }
- } else {
- Write(params);
- return true;
- }
- }
-
- void Write(const TParams& params) {
- typename TLog::TAccessor la(*Log);
- if (typename TLog::TItem* item = la.Add()) {
- item->Probe = Probe;
- if (LogParams) {
- if ((item->SavedParamsCount = Probe->Event.Signature.ParamCount) > 0) {
- Probe->Event.Signature.CloneParams(item->Params, params);
- }
- } else {
- item->SavedParamsCount = 0;
- }
- if (LogTimestamp) {
- item->Timestamp = TInstant::Now();
- }
- item->TimestampCycles = GetCycleCount();
- }
- }
-
- public:
- TLogActionExecutor(TProbe* probe, const TLogAction& action, TLog* log)
+ typedef enum {
+ OT_LITERAL = 0,
+ OT_PARAMETER = 1,
+ OT_VARIABLE = 2
+ } EOperandType;
+
+ template <class T, EOperandType>
+ class TOperand;
+
+ template <class T>
+ class TOperand<T, OT_LITERAL> {
+ private:
+ T ImmediateValue;
+
+ public:
+ TOperand(TSession::TTraceVariables&, const TString&, const TString& value, size_t) {
+ ImmediateValue = TParamConv<T>::FromString(value);
+ }
+ const T& Get(const TParams&) {
+ return ImmediateValue;
+ }
+ };
+
+ template <class T>
+ class TOperand<T, OT_PARAMETER> {
+ private:
+ size_t Idx;
+
+ public:
+ TOperand(TSession::TTraceVariables&, const TString&, const TString&, size_t idx) {
+ Idx = idx;
+ }
+
+ const T& Get(const TParams& params) {
+ return params.Param[Idx].template Get<T>();
+ }
+ };
+
+ template <class T>
+ class TOperand<T, OT_VARIABLE> {
+ private:
+ TAtomic* Variable;
+
+ public:
+ TOperand(TSession::TTraceVariables& traceVariables, const TString& name, const TString&, size_t) {
+ Variable = GetVariablePtr(traceVariables, name);
+ }
+
+ const T Get(const TParams&) {
+ return (T)AtomicGet(*Variable);
+ }
+
+ void Set(const T& value) {
+ AtomicSet(*Variable, value);
+ }
+
+ void Inc() {
+ AtomicIncrement(*Variable);
+ }
+
+ void Dec() {
+ AtomicDecrement(*Variable);
+ }
+
+ void Add(const TAtomicBase value) {
+ AtomicAdd(*Variable, value);
+ }
+
+ void Sub(const TAtomicBase value) {
+ AtomicSub(*Variable, value);
+ }
+ };
+
+ template <>
+ class TOperand<TCheck, OT_VARIABLE> {
+ private:
+ TAtomic* Variable;
+
+ public:
+ TOperand(TSession::TTraceVariables& traceVariables, const TString& name, const TString&, size_t) {
+ Variable = GetVariablePtr(traceVariables, name);
+ }
+
+ const TCheck Get(const TParams&) {
+ return TCheck(AtomicGet(*Variable));
+ }
+
+ void Set(const TCheck& value) {
+ AtomicSet(*Variable, value.Value);
+ }
+
+ void Add(const TCheck& value) {
+ AtomicAdd(*Variable, value.Value);
+ }
+
+ void Sub(const TCheck value) {
+ AtomicSub(*Variable, value.Value);
+ }
+
+ void Inc() {
+ AtomicIncrement(*Variable);
+ }
+
+ void Dec() {
+ AtomicDecrement(*Variable);
+ }
+ };
+
+ template <>
+ class TOperand<TString, OT_VARIABLE> {
+ private:
+ TString Dummy;
+
+ public:
+ TOperand(TSession::TTraceVariables&, const TString&, const TString&, size_t) {
+ }
+
+ const TString Get(const TParams&) {
+ return Dummy;
+ }
+
+ void Set(const TString&) {
+ }
+ };
+
+ template <>
+ class TOperand<TSymbol, OT_VARIABLE> {
+ private:
+ TSymbol Dummy;
+
+ public:
+ TOperand(TSession::TTraceVariables&, const TString&, const TString&, size_t) {
+ }
+
+ const TSymbol Get(const TParams&) {
+ return Dummy;
+ }
+
+ void Set(const TSymbol&) {
+ }
+ };
+
+ // IOperandGetter: hide concrete EOperandType, to save compilation time
+ template <class T>
+ struct IOperandGetter {
+ virtual const T Get(const TParams& params) = 0;
+ virtual ~IOperandGetter() {
+ }
+ };
+
+ template <class T, EOperandType TParam>
+ class TOperandGetter: public IOperandGetter<T> {
+ private:
+ TOperand<T, TParam> Op;
+
+ public:
+ TOperandGetter(const TOperand<T, TParam>& op)
+ : Op(op)
+ {
+ }
+
+ const T Get(const TParams& params) override {
+ return Op.Get(params);
+ }
+ };
+
+ template <class T>
+ class TReceiver: public TOperand<T, OT_VARIABLE> {
+ public:
+ TReceiver(TSession::TTraceVariables& traceVariables, const TString& name)
+ : TOperand<T, OT_VARIABLE>(traceVariables, name, nullptr, 0)
+ {
+ }
+ };
+
+ template <class TP, class TPredicate>
+ static bool CmpFunc(TP a, TP b) {
+ return TPredicate()(a, b);
+ }
+
+ template <class TP, class TFunc, EOperandType TLhs, EOperandType TRhs>
+ class TOperatorExecutor: public IExecutor {
+ private:
+ bool InvertCompare;
+ TOperand<TP, TLhs> Lhs;
+ TOperand<TP, TRhs> Rhs;
+
+ bool DoExecute(TOrbit&, const TParams& params) override {
+ return TFunc()(Lhs.Get(params), Rhs.Get(params)) != InvertCompare;
+ }
+
+ public:
+ TOperatorExecutor(const TOperand<TP, TLhs>& lhs, const TOperand<TP, TRhs>& rhs, bool invertCompare)
+ : InvertCompare(invertCompare)
+ , Lhs(lhs)
+ , Rhs(rhs)
+ {
+ }
+ };
+
+ template <class TR, class TP>
+ struct TAddEq {
+ void operator()(TR& x, TP y) const {
+ x.Add(y);
+ }
+ };
+ template <class TR, class TP>
+ struct TSubEq {
+ void operator()(TR& x, TP y) const {
+ x.Sub(y);
+ }
+ };
+ template <class TR>
+ struct TInc {
+ void operator()(TR& x) const {
+ x.Inc();
+ }
+ };
+ template <class TR>
+ struct TDec {
+ void operator()(TR& x) const {
+ x.Dec();
+ }
+ };
+
+ template <class TP, class TFunc>
+ class TUnaryInplaceStatementExecutor: public IExecutor {
+ private:
+ TFunc Func;
+ TReceiver<TP> Receiver;
+
+ bool DoExecute(TOrbit&, const TParams&) override {
+ Func(Receiver);
+ return true;
+ }
+
+ public:
+ TUnaryInplaceStatementExecutor(TReceiver<TP>& receiver)
+ : Receiver(receiver)
+ {
+ }
+ };
+
+ template <class TP, class TFunc, EOperandType TParam>
+ class TBinaryInplaceStatementExecutor: public IExecutor {
+ private:
+ TFunc Func;
+ TReceiver<TP> Receiver;
+ TOperand<TP, TParam> Param;
+
+ bool DoExecute(TOrbit&, const TParams& params) override {
+ Func(Receiver, Param.Get(params));
+ return true;
+ }
+
+ public:
+ TBinaryInplaceStatementExecutor(TReceiver<TP>& receiver, const TOperand<TP, TParam>& param)
+ : Receiver(receiver)
+ , Param(param)
+ {
+ }
+ };
+
+ template <class TP, class TFunc, EOperandType TFirstParam>
+ class TBinaryStatementExecutor: public IExecutor {
+ private:
+ TFunc Func;
+ TReceiver<TP> Receiver;
+ TOperand<TP, TFirstParam> FirstParam;
+
+ bool DoExecute(TOrbit&, const TParams& params) override {
+ Receiver.Set(Func(Receiver.Get(params), FirstParam.Get(params)));
+ return true;
+ }
+
+ public:
+ TBinaryStatementExecutor(TReceiver<TP>& receiver, const TOperand<TP, TFirstParam>& firstParam)
+ : Receiver(receiver)
+ , FirstParam(firstParam)
+ {
+ }
+ };
+
+ template <class TP, class TFunc>
+ class TTernaryStatementExecutor: public IExecutor {
+ private:
+ TFunc Func;
+ TReceiver<TP> Receiver;
+
+ TAutoPtr<IOperandGetter<TP>> FirstParam;
+ TAutoPtr<IOperandGetter<TP>> SecondParam;
+
+ bool DoExecute(TOrbit&, const TParams& params) override {
+ Receiver.Set(Func(FirstParam->Get(params), SecondParam->Get(params)));
+ return true;
+ }
+
+ public:
+ TTernaryStatementExecutor(const TReceiver<TP>& receiver,
+ TAutoPtr<IOperandGetter<TP>> firstParam,
+ TAutoPtr<IOperandGetter<TP>> secondParam)
+ : Receiver(receiver)
+ , FirstParam(firstParam)
+ , SecondParam(secondParam)
+ {
+ }
+ };
+
+ template <class TLog>
+ class TLogActionExecutor: public IExecutor {
+ private:
+ bool LogParams;
+ bool LogTimestamp;
+ intptr_t* MaxRecords;
+ TAtomic Records;
+ TProbe* Probe;
+ TLog* Log;
+
+ bool DoExecute(TOrbit&, const TParams& params) override {
+ if (MaxRecords != nullptr) {
+ while (true) {
+ intptr_t a = AtomicGet(Records);
+ if (a >= *MaxRecords) {
+ return true;
+ }
+ if (AtomicCas(&Records, a + 1, a)) {
+ Write(params);
+ return true;
+ }
+ }
+ } else {
+ Write(params);
+ return true;
+ }
+ }
+
+ void Write(const TParams& params) {
+ typename TLog::TAccessor la(*Log);
+ if (typename TLog::TItem* item = la.Add()) {
+ item->Probe = Probe;
+ if (LogParams) {
+ if ((item->SavedParamsCount = Probe->Event.Signature.ParamCount) > 0) {
+ Probe->Event.Signature.CloneParams(item->Params, params);
+ }
+ } else {
+ item->SavedParamsCount = 0;
+ }
+ if (LogTimestamp) {
+ item->Timestamp = TInstant::Now();
+ }
+ item->TimestampCycles = GetCycleCount();
+ }
+ }
+
+ public:
+ TLogActionExecutor(TProbe* probe, const TLogAction& action, TLog* log)
: LogParams(!action.GetDoNotLogParams())
- , LogTimestamp(action.GetLogTimestamp())
+ , LogTimestamp(action.GetLogTimestamp())
, MaxRecords(action.GetMaxRecords() ? new intptr_t(action.GetMaxRecords()) : nullptr)
- , Records(0)
- , Probe(probe)
- , Log(log)
- {
- }
-
- ~TLogActionExecutor() override {
- delete MaxRecords;
- }
- };
-
- class TSamplingExecutor: public IExecutor {
- private:
- double SampleRate;
-
- public:
- explicit TSamplingExecutor(double sampleRate)
- : SampleRate(sampleRate)
- {}
-
- bool DoExecute(TOrbit&, const TParams&) override {
- return RandomNumber<double>() < SampleRate;
- }
- };
-
- typedef struct {
- EOperandType Type;
- size_t ParamIdx;
- } TArgumentDescription;
-
- using TArgumentList = TVector<TArgumentDescription>;
-
- template <class T>
- void ParseArguments(const T& op, const TSignature& signature, const TString& exceptionPrefix, size_t expectedArgumentCount, TArgumentList& arguments) {
- arguments.clear();
- size_t firstParamIdx = size_t(-1);
- for (size_t argumentIdx = 0; argumentIdx < op.ArgumentSize(); ++argumentIdx) {
- const TArgument& arg = op.GetArgument(argumentIdx);
- TArgumentDescription operand;
- operand.ParamIdx = size_t(-1);
+ , Records(0)
+ , Probe(probe)
+ , Log(log)
+ {
+ }
+
+ ~TLogActionExecutor() override {
+ delete MaxRecords;
+ }
+ };
+
+ class TSamplingExecutor: public IExecutor {
+ private:
+ double SampleRate;
+
+ public:
+ explicit TSamplingExecutor(double sampleRate)
+ : SampleRate(sampleRate)
+ {}
+
+ bool DoExecute(TOrbit&, const TParams&) override {
+ return RandomNumber<double>() < SampleRate;
+ }
+ };
+
+ typedef struct {
+ EOperandType Type;
+ size_t ParamIdx;
+ } TArgumentDescription;
+
+ using TArgumentList = TVector<TArgumentDescription>;
+
+ template <class T>
+ void ParseArguments(const T& op, const TSignature& signature, const TString& exceptionPrefix, size_t expectedArgumentCount, TArgumentList& arguments) {
+ arguments.clear();
+ size_t firstParamIdx = size_t(-1);
+ for (size_t argumentIdx = 0; argumentIdx < op.ArgumentSize(); ++argumentIdx) {
+ const TArgument& arg = op.GetArgument(argumentIdx);
+ TArgumentDescription operand;
+ operand.ParamIdx = size_t(-1);
if (arg.GetVariable()) {
- operand.Type = OT_VARIABLE;
+ operand.Type = OT_VARIABLE;
} else if (arg.GetValue()) {
- operand.Type = OT_LITERAL;
+ operand.Type = OT_LITERAL;
} else if (arg.GetParam()) {
- operand.Type = OT_PARAMETER;
- operand.ParamIdx = signature.FindParamIndex(arg.GetParam());
- if (operand.ParamIdx == size_t(-1)) {
+ operand.Type = OT_PARAMETER;
+ operand.ParamIdx = signature.FindParamIndex(arg.GetParam());
+ if (operand.ParamIdx == size_t(-1)) {
ythrow yexception() << exceptionPrefix
- << " argument #" << argumentIdx << " param '" << arg.GetParam()
- << "' doesn't exist";
+ << " argument #" << argumentIdx << " param '" << arg.GetParam()
+ << "' doesn't exist";
}
- if (firstParamIdx == size_t(-1)) {
- firstParamIdx = operand.ParamIdx;
- } else {
- if (strcmp(signature.ParamTypes[firstParamIdx], signature.ParamTypes[operand.ParamIdx]) != 0) {
- ythrow yexception() << exceptionPrefix
- << " param types do not match";
- }
- }
- } else {
- ythrow yexception() << exceptionPrefix
- << " argument #" << argumentIdx
- << " is empty";
+ if (firstParamIdx == size_t(-1)) {
+ firstParamIdx = operand.ParamIdx;
+ } else {
+ if (strcmp(signature.ParamTypes[firstParamIdx], signature.ParamTypes[operand.ParamIdx]) != 0) {
+ ythrow yexception() << exceptionPrefix
+ << " param types do not match";
+ }
+ }
+ } else {
+ ythrow yexception() << exceptionPrefix
+ << " argument #" << argumentIdx
+ << " is empty";
}
- arguments.push_back(operand);
- }
- if (arguments.size() != expectedArgumentCount) {
+ arguments.push_back(operand);
+ }
+ if (arguments.size() != expectedArgumentCount) {
ythrow yexception() << exceptionPrefix
- << " incorrect number of arguments (" << arguments.size()
- << " present, " << expectedArgumentCount << " expected)";
- }
- }
-
- template <class TArg1, class TArg2>
- struct TTraceSecondArg {
- // implementation of deprecated std::project2nd
- TArg1 operator()(const TArg1&, const TArg2& y) const {
- return y;
- }
- };
-
- void TSession::InsertExecutor(
- TTraceVariables& traceVariables, size_t bi, const TPredicate* pred,
- const NProtoBuf::RepeatedPtrField<TAction>& actions, TProbe* probe,
- const bool destructiveActionsAllowed,
- const TCustomActionFactory& customActionFactory) {
-#ifndef LWTRACE_DISABLE
- THolder<IExecutor> exec;
- IExecutor* last = nullptr;
- TArgumentList arguments;
- if (pred) {
- double sampleRate = pred->GetSampleRate();
- if (sampleRate != 0.0) {
- if (!(0.0 < sampleRate && sampleRate <= 1.0)) {
- ythrow yexception() << "probe '" << probe->Event.Name << "' block #" << bi + 1 << " sampling operator"
- << " invalid sample rate " << sampleRate << ", expected [0;1]";
- }
- exec.Reset(new TSamplingExecutor(sampleRate));
- last = exec.Get();
- }
-
- for (size_t i = 0; i < pred->OperatorsSize(); i++) {
- const TOperator& op = pred->GetOperators(i);
- TString exceptionPrefix;
- TStringOutput exceptionPrefixOutput(exceptionPrefix);
- exceptionPrefixOutput << "probe '" << probe->Event.Name << "' block #" << bi + 1 << " operator #" << i + 1;
- ParseArguments<TOperator>(op, probe->Event.Signature, exceptionPrefix, 2, arguments);
- THolder<IExecutor> opExec;
-
- TArgumentDescription arg0 = arguments.at(0);
- TArgumentDescription arg1 = arguments.at(1);
+ << " incorrect number of arguments (" << arguments.size()
+ << " present, " << expectedArgumentCount << " expected)";
+ }
+ }
+
+ template <class TArg1, class TArg2>
+ struct TTraceSecondArg {
+ // implementation of deprecated std::project2nd
+ TArg1 operator()(const TArg1&, const TArg2& y) const {
+ return y;
+ }
+ };
+
+ void TSession::InsertExecutor(
+ TTraceVariables& traceVariables, size_t bi, const TPredicate* pred,
+ const NProtoBuf::RepeatedPtrField<TAction>& actions, TProbe* probe,
+ const bool destructiveActionsAllowed,
+ const TCustomActionFactory& customActionFactory) {
+#ifndef LWTRACE_DISABLE
+ THolder<IExecutor> exec;
+ IExecutor* last = nullptr;
+ TArgumentList arguments;
+ if (pred) {
+ double sampleRate = pred->GetSampleRate();
+ if (sampleRate != 0.0) {
+ if (!(0.0 < sampleRate && sampleRate <= 1.0)) {
+ ythrow yexception() << "probe '" << probe->Event.Name << "' block #" << bi + 1 << " sampling operator"
+ << " invalid sample rate " << sampleRate << ", expected [0;1]";
+ }
+ exec.Reset(new TSamplingExecutor(sampleRate));
+ last = exec.Get();
+ }
+
+ for (size_t i = 0; i < pred->OperatorsSize(); i++) {
+ const TOperator& op = pred->GetOperators(i);
+ TString exceptionPrefix;
+ TStringOutput exceptionPrefixOutput(exceptionPrefix);
+ exceptionPrefixOutput << "probe '" << probe->Event.Name << "' block #" << bi + 1 << " operator #" << i + 1;
+ ParseArguments<TOperator>(op, probe->Event.Signature, exceptionPrefix, 2, arguments);
+ THolder<IExecutor> opExec;
+
+ TArgumentDescription arg0 = arguments.at(0);
+ TArgumentDescription arg1 = arguments.at(1);
const char* tName0 = arg0.ParamIdx == size_t(-1) ? nullptr : probe->Event.Signature.ParamTypes[arg0.ParamIdx];
const char* tName1 = arg1.ParamIdx == size_t(-1) ? nullptr : probe->Event.Signature.ParamTypes[arg1.ParamIdx];
- TString var0 = op.GetArgument(0).GetVariable();
- TString var1 = op.GetArgument(1).GetVariable();
-
- TString val0 = op.GetArgument(0).GetValue();
- TString val1 = op.GetArgument(1).GetValue();
-
-#define FOREACH_OPERAND_TYPE_RT(n, t, v, fn, lt, rt) \
- if (rt == arg1.Type) { \
- TOperand<t, rt> rhs(traceVariables, var1, val1, arg1.ParamIdx); \
- opExec.Reset(new TOperatorExecutor<t, fn<t>, lt, rt>(lhs, rhs, invertCompare)); \
- break; \
- }
-
-#define FOREACH_OPERAND_TYPE_LT(n, t, v, fn, lt) \
- if (lt == arg0.Type) { \
- TOperand<t, lt> lhs(traceVariables, var0, val0, arg0.ParamIdx); \
- FOREACH_RIGHT_TYPE(FOREACH_OPERAND_TYPE_RT, n, t, v, fn, lt) \
- }
-
-#define FOREACH_PARAMTYPE_MACRO(n, t, v, fn) \
- if ((arg0.ParamIdx == size_t(-1) || strcmp(tName0, n) == 0) && (arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0)) { \
- FOREACH_LEFT_TYPE(FOREACH_OPERAND_TYPE_LT, n, t, v, fn); \
- }
-
- bool invertCompare = EqualToOneOf(op.GetType(), OT_NE, OT_GE, OT_LE);
-
- switch (op.GetType()) {
- case OT_EQ:
- case OT_NE:
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, std::equal_to);
- break;
- case OT_LT:
- case OT_GE:
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, std::less);
- break;
- case OT_GT:
- case OT_LE:
- FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, std::greater);
- break;
- default:
- ythrow yexception() << exceptionPrefix
- << " has not supported operator type #" << int(op.GetType());
- }
-
+ TString var0 = op.GetArgument(0).GetVariable();
+ TString var1 = op.GetArgument(1).GetVariable();
+
+ TString val0 = op.GetArgument(0).GetValue();
+ TString val1 = op.GetArgument(1).GetValue();
+
+#define FOREACH_OPERAND_TYPE_RT(n, t, v, fn, lt, rt) \
+ if (rt == arg1.Type) { \
+ TOperand<t, rt> rhs(traceVariables, var1, val1, arg1.ParamIdx); \
+ opExec.Reset(new TOperatorExecutor<t, fn<t>, lt, rt>(lhs, rhs, invertCompare)); \
+ break; \
+ }
+
+#define FOREACH_OPERAND_TYPE_LT(n, t, v, fn, lt) \
+ if (lt == arg0.Type) { \
+ TOperand<t, lt> lhs(traceVariables, var0, val0, arg0.ParamIdx); \
+ FOREACH_RIGHT_TYPE(FOREACH_OPERAND_TYPE_RT, n, t, v, fn, lt) \
+ }
+
+#define FOREACH_PARAMTYPE_MACRO(n, t, v, fn) \
+ if ((arg0.ParamIdx == size_t(-1) || strcmp(tName0, n) == 0) && (arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0)) { \
+ FOREACH_LEFT_TYPE(FOREACH_OPERAND_TYPE_LT, n, t, v, fn); \
+ }
+
+ bool invertCompare = EqualToOneOf(op.GetType(), OT_NE, OT_GE, OT_LE);
+
+ switch (op.GetType()) {
+ case OT_EQ:
+ case OT_NE:
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, std::equal_to);
+ break;
+ case OT_LT:
+ case OT_GE:
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, std::less);
+ break;
+ case OT_GT:
+ case OT_LE:
+ FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, std::greater);
+ break;
+ default:
+ ythrow yexception() << exceptionPrefix
+ << " has not supported operator type #" << int(op.GetType());
+ }
+
#undef FOREACH_OPERAND_TYPE_RT
#undef FOREACH_OPERAND_TYPE_LT
-#undef FOREACH_PARAMTYPE_MACRO
-
- if (!opExec) {
- ythrow yexception() << exceptionPrefix
- << " has not supported left param #" << arg0.ParamIdx + 1 << " type '"
- << (arg0.ParamIdx != size_t(-1) ? probe->Event.Signature.ParamTypes[arg0.ParamIdx] : "?")
- << "', or right param #" << arg0.ParamIdx + 1 << " type '"
- << (arg1.ParamIdx != size_t(-1) ? probe->Event.Signature.ParamTypes[arg1.ParamIdx] : "?")
- << "'";
- }
-
- if (!exec) {
- exec.Reset(opExec.Release());
- last = exec.Get();
- } else {
- last->SetNext(opExec.Release());
- last = last->GetNext();
- }
- }
- }
-
- for (int i = 0; i < actions.size(); ++i) {
- const TAction& action = actions.Get(i);
- THolder<IExecutor> actExec;
- if (action.HasPrintToStderrAction()) {
- actExec.Reset(new TStderrActionExecutor(probe));
- } else if (action.HasLogAction()) {
- if (Query.GetLogDurationUs()) {
- actExec.Reset(new TLogActionExecutor<TDurationLog>(probe, action.GetLogAction(), &DurationLog));
- } else {
- actExec.Reset(new TLogActionExecutor<TCyclicLog>(probe, action.GetLogAction(), &CyclicLog));
- }
- } else if (action.HasRunLogShuttleAction()) {
- if (Query.GetLogDurationUs()) {
+#undef FOREACH_PARAMTYPE_MACRO
+
+ if (!opExec) {
+ ythrow yexception() << exceptionPrefix
+ << " has not supported left param #" << arg0.ParamIdx + 1 << " type '"
+ << (arg0.ParamIdx != size_t(-1) ? probe->Event.Signature.ParamTypes[arg0.ParamIdx] : "?")
+ << "', or right param #" << arg0.ParamIdx + 1 << " type '"
+ << (arg1.ParamIdx != size_t(-1) ? probe->Event.Signature.ParamTypes[arg1.ParamIdx] : "?")
+ << "'";
+ }
+
+ if (!exec) {
+ exec.Reset(opExec.Release());
+ last = exec.Get();
+ } else {
+ last->SetNext(opExec.Release());
+ last = last->GetNext();
+ }
+ }
+ }
+
+ for (int i = 0; i < actions.size(); ++i) {
+ const TAction& action = actions.Get(i);
+ THolder<IExecutor> actExec;
+ if (action.HasPrintToStderrAction()) {
+ actExec.Reset(new TStderrActionExecutor(probe));
+ } else if (action.HasLogAction()) {
+ if (Query.GetLogDurationUs()) {
+ actExec.Reset(new TLogActionExecutor<TDurationLog>(probe, action.GetLogAction(), &DurationLog));
+ } else {
+ actExec.Reset(new TLogActionExecutor<TCyclicLog>(probe, action.GetLogAction(), &CyclicLog));
+ }
+ } else if (action.HasRunLogShuttleAction()) {
+ if (Query.GetLogDurationUs()) {
actExec.Reset(new TRunLogShuttleActionExecutor<TDurationDepot>(TraceIdx, action.GetRunLogShuttleAction(), &DurationDepot, &LastTrackId, &LastSpanId));
- } else {
+ } else {
actExec.Reset(new TRunLogShuttleActionExecutor<TCyclicDepot>(TraceIdx, action.GetRunLogShuttleAction(), &CyclicDepot, &LastTrackId, &LastSpanId));
- }
- } else if (action.HasEditLogShuttleAction()) {
- if (Query.GetLogDurationUs()) {
- actExec.Reset(new TEditLogShuttleActionExecutor<TDurationDepot>(TraceIdx, action.GetEditLogShuttleAction()));
- } else {
- actExec.Reset(new TEditLogShuttleActionExecutor<TCyclicDepot>(TraceIdx, action.GetEditLogShuttleAction()));
- }
- } else if (action.HasDropLogShuttleAction()) {
- if (Query.GetLogDurationUs()) {
- actExec.Reset(new TDropLogShuttleActionExecutor<TDurationDepot>(TraceIdx, action.GetDropLogShuttleAction()));
- } else {
- actExec.Reset(new TDropLogShuttleActionExecutor<TCyclicDepot>(TraceIdx, action.GetDropLogShuttleAction()));
- }
- } else if (action.HasCustomAction()) {
- THolder<TCustomActionExecutor> customExec(customActionFactory.Create(probe, action.GetCustomAction(), this));
- if (customExec) {
- if (!customExec->IsDestructive() || destructiveActionsAllowed) {
- actExec.Reset(customExec.Release());
- } else {
- ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
- << " contains destructive CustomAction, but destructive actions are disabled."
- << " Please, consider using --unsafe-lwtrace command line parameter.";
- }
- } else {
- ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
- << " contains unregistered CustomAction '" << action.GetCustomAction().GetName() << "'";
- }
- } else if (action.HasKillAction()) {
- if (destructiveActionsAllowed) {
- actExec.Reset(new NPrivate::TKillActionExecutor(probe));
- } else {
- ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
- << " contains destructive KillAction, but destructive actions are disabled."
- << " Please, consider using --unsafe-lwtrace command line parameter.";
- }
- } else if (action.HasSleepAction()) {
- if (destructiveActionsAllowed) {
- const TSleepAction& sleepAction = action.GetSleepAction();
+ }
+ } else if (action.HasEditLogShuttleAction()) {
+ if (Query.GetLogDurationUs()) {
+ actExec.Reset(new TEditLogShuttleActionExecutor<TDurationDepot>(TraceIdx, action.GetEditLogShuttleAction()));
+ } else {
+ actExec.Reset(new TEditLogShuttleActionExecutor<TCyclicDepot>(TraceIdx, action.GetEditLogShuttleAction()));
+ }
+ } else if (action.HasDropLogShuttleAction()) {
+ if (Query.GetLogDurationUs()) {
+ actExec.Reset(new TDropLogShuttleActionExecutor<TDurationDepot>(TraceIdx, action.GetDropLogShuttleAction()));
+ } else {
+ actExec.Reset(new TDropLogShuttleActionExecutor<TCyclicDepot>(TraceIdx, action.GetDropLogShuttleAction()));
+ }
+ } else if (action.HasCustomAction()) {
+ THolder<TCustomActionExecutor> customExec(customActionFactory.Create(probe, action.GetCustomAction(), this));
+ if (customExec) {
+ if (!customExec->IsDestructive() || destructiveActionsAllowed) {
+ actExec.Reset(customExec.Release());
+ } else {
+ ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
+ << " contains destructive CustomAction, but destructive actions are disabled."
+ << " Please, consider using --unsafe-lwtrace command line parameter.";
+ }
+ } else {
+ ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
+ << " contains unregistered CustomAction '" << action.GetCustomAction().GetName() << "'";
+ }
+ } else if (action.HasKillAction()) {
+ if (destructiveActionsAllowed) {
+ actExec.Reset(new NPrivate::TKillActionExecutor(probe));
+ } else {
+ ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
+ << " contains destructive KillAction, but destructive actions are disabled."
+ << " Please, consider using --unsafe-lwtrace command line parameter.";
+ }
+ } else if (action.HasSleepAction()) {
+ if (destructiveActionsAllowed) {
+ const TSleepAction& sleepAction = action.GetSleepAction();
if (sleepAction.GetNanoSeconds()) {
- ui64 nanoSeconds = sleepAction.GetNanoSeconds();
- actExec.Reset(new NPrivate::TSleepActionExecutor(probe, nanoSeconds));
- } else {
- ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
- << " SleepAction missing parameter 'NanoSeconds'";
- }
- } else {
+ ui64 nanoSeconds = sleepAction.GetNanoSeconds();
+ actExec.Reset(new NPrivate::TSleepActionExecutor(probe, nanoSeconds));
+ } else {
+ ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
+ << " SleepAction missing parameter 'NanoSeconds'";
+ }
+ } else {
ythrow yexception() << "probe '" << probe->Event.Name << "block #" << bi + 1 << " action #" << i + 1
- << " contains destructive SleepAction, but destructive actions are disabled."
- << " Please, consider using --unsafe-lwtrace command line parameter.";
+ << " contains destructive SleepAction, but destructive actions are disabled."
+ << " Please, consider using --unsafe-lwtrace command line parameter.";
}
- } else if (action.HasStatementAction()) {
- const TStatementAction& statement = action.GetStatementAction();
- TString exceptionPrefix;
- TStringOutput exceptionPrefixOutput(exceptionPrefix);
- exceptionPrefixOutput << "probe '" << probe->Event.Name << "' block #" << bi + 1 << " action #" << i + 1;
- size_t expectedArgumentCount = 3;
- if (statement.GetType() == ST_MOV || statement.GetType() == ST_ADD_EQ || statement.GetType() == ST_SUB_EQ) {
- expectedArgumentCount = 2;
- } else if (statement.GetType() == ST_INC || statement.GetType() == ST_DEC) {
- expectedArgumentCount = 1;
- }
- ParseArguments<TStatementAction>(statement, probe->Event.Signature, exceptionPrefix, expectedArgumentCount, arguments);
-
- TArgumentDescription arg0 = (expectedArgumentCount <= 0) ? TArgumentDescription() : arguments.at(0);
- TArgumentDescription arg1 = (expectedArgumentCount <= 1) ? TArgumentDescription() : arguments.at(1);
- TArgumentDescription arg2 = (expectedArgumentCount <= 2) ? TArgumentDescription() : arguments.at(2);
-
- TString var0 = (expectedArgumentCount <= 0) ? "" : statement.GetArgument(0).GetVariable();
- TString var1 = (expectedArgumentCount <= 1) ? "" : statement.GetArgument(1).GetVariable();
- TString var2 = (expectedArgumentCount <= 2) ? "" : statement.GetArgument(2).GetVariable();
-
- TString val0 = (expectedArgumentCount <= 0) ? "" : statement.GetArgument(0).GetValue();
- TString val1 = (expectedArgumentCount <= 1) ? "" : statement.GetArgument(1).GetValue();
- TString val2 = (expectedArgumentCount <= 2) ? "" : statement.GetArgument(2).GetValue();
+ } else if (action.HasStatementAction()) {
+ const TStatementAction& statement = action.GetStatementAction();
+ TString exceptionPrefix;
+ TStringOutput exceptionPrefixOutput(exceptionPrefix);
+ exceptionPrefixOutput << "probe '" << probe->Event.Name << "' block #" << bi + 1 << " action #" << i + 1;
+ size_t expectedArgumentCount = 3;
+ if (statement.GetType() == ST_MOV || statement.GetType() == ST_ADD_EQ || statement.GetType() == ST_SUB_EQ) {
+ expectedArgumentCount = 2;
+ } else if (statement.GetType() == ST_INC || statement.GetType() == ST_DEC) {
+ expectedArgumentCount = 1;
+ }
+ ParseArguments<TStatementAction>(statement, probe->Event.Signature, exceptionPrefix, expectedArgumentCount, arguments);
+
+ TArgumentDescription arg0 = (expectedArgumentCount <= 0) ? TArgumentDescription() : arguments.at(0);
+ TArgumentDescription arg1 = (expectedArgumentCount <= 1) ? TArgumentDescription() : arguments.at(1);
+ TArgumentDescription arg2 = (expectedArgumentCount <= 2) ? TArgumentDescription() : arguments.at(2);
+
+ TString var0 = (expectedArgumentCount <= 0) ? "" : statement.GetArgument(0).GetVariable();
+ TString var1 = (expectedArgumentCount <= 1) ? "" : statement.GetArgument(1).GetVariable();
+ TString var2 = (expectedArgumentCount <= 2) ? "" : statement.GetArgument(2).GetVariable();
+
+ TString val0 = (expectedArgumentCount <= 0) ? "" : statement.GetArgument(0).GetValue();
+ TString val1 = (expectedArgumentCount <= 1) ? "" : statement.GetArgument(1).GetValue();
+ TString val2 = (expectedArgumentCount <= 2) ? "" : statement.GetArgument(2).GetValue();
const char* tName1 = (expectedArgumentCount <= 1 || arg1.ParamIdx == size_t(-1))
? nullptr : probe->Event.Signature.ParamTypes[arg1.ParamIdx];
const char* tName2 = (expectedArgumentCount <= 2 || arg2.ParamIdx == size_t(-1))
? nullptr : probe->Event.Signature.ParamTypes[arg2.ParamIdx];
- if (arg0.Type == OT_VARIABLE) {
- switch (statement.GetType()) {
-#define PARSE_UNARY_INPLACE_STATEMENT_MACRO(n, t, v, fn) \
- { \
- typedef TUnaryInplaceStatementExecutor<t, fn<TReceiver<t>>> TExec; \
- TReceiver<t> receiver(traceVariables, var0); \
- actExec.Reset(new TExec(receiver)); \
- break; \
- }
-
-#define PARSE_BINARY_INPLACE_STATEMENT_MACRO2(n, t, v, fn, ft) \
- if (arg1.Type == ft) { \
- typedef TBinaryInplaceStatementExecutor<t, fn<TReceiver<t>, t>, ft> TExec; \
- TOperand<t, ft> firstParam(traceVariables, var1, val1, arg1.ParamIdx); \
- actExec.Reset(new TExec(receiver, firstParam)); \
- break; \
- }
-
-#define PARSE_BINARY_INPLACE_STATEMENT_MACRO(n, t, v, fn) \
- if (arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0) { \
- TReceiver<t> receiver(traceVariables, var0); \
- FOREACH_RIGHT_TYPE(PARSE_BINARY_INPLACE_STATEMENT_MACRO2, n, t, v, fn); \
- }
-
-#define PARSE_BINARY_STATEMENT_MACRO2(n, t, v, fn, ft) \
- if (arg1.Type == ft) { \
- typedef TBinaryStatementExecutor<t, fn<t, t>, ft> TExec; \
- TOperand<t, ft> firstParam(traceVariables, var1, val1, arg1.ParamIdx); \
- actExec.Reset(new TExec(receiver, firstParam)); \
- break; \
- }
-
-#define PARSE_BINARY_STATEMENT_MACRO(n, t, v, fn) \
- if (arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0) { \
- TReceiver<t> receiver(traceVariables, var0); \
- FOREACH_RIGHT_TYPE(PARSE_BINARY_STATEMENT_MACRO2, n, t, v, fn); \
- }
-
-#define CREATE_OPERAND_GETTER_N(N, type, arg_type) \
- if (arg##N.Type == arg_type) { \
+ if (arg0.Type == OT_VARIABLE) {
+ switch (statement.GetType()) {
+#define PARSE_UNARY_INPLACE_STATEMENT_MACRO(n, t, v, fn) \
+ { \
+ typedef TUnaryInplaceStatementExecutor<t, fn<TReceiver<t>>> TExec; \
+ TReceiver<t> receiver(traceVariables, var0); \
+ actExec.Reset(new TExec(receiver)); \
+ break; \
+ }
+
+#define PARSE_BINARY_INPLACE_STATEMENT_MACRO2(n, t, v, fn, ft) \
+ if (arg1.Type == ft) { \
+ typedef TBinaryInplaceStatementExecutor<t, fn<TReceiver<t>, t>, ft> TExec; \
+ TOperand<t, ft> firstParam(traceVariables, var1, val1, arg1.ParamIdx); \
+ actExec.Reset(new TExec(receiver, firstParam)); \
+ break; \
+ }
+
+#define PARSE_BINARY_INPLACE_STATEMENT_MACRO(n, t, v, fn) \
+ if (arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0) { \
+ TReceiver<t> receiver(traceVariables, var0); \
+ FOREACH_RIGHT_TYPE(PARSE_BINARY_INPLACE_STATEMENT_MACRO2, n, t, v, fn); \
+ }
+
+#define PARSE_BINARY_STATEMENT_MACRO2(n, t, v, fn, ft) \
+ if (arg1.Type == ft) { \
+ typedef TBinaryStatementExecutor<t, fn<t, t>, ft> TExec; \
+ TOperand<t, ft> firstParam(traceVariables, var1, val1, arg1.ParamIdx); \
+ actExec.Reset(new TExec(receiver, firstParam)); \
+ break; \
+ }
+
+#define PARSE_BINARY_STATEMENT_MACRO(n, t, v, fn) \
+ if (arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0) { \
+ TReceiver<t> receiver(traceVariables, var0); \
+ FOREACH_RIGHT_TYPE(PARSE_BINARY_STATEMENT_MACRO2, n, t, v, fn); \
+ }
+
+#define CREATE_OPERAND_GETTER_N(N, type, arg_type) \
+ if (arg##N.Type == arg_type) { \
operand##N.Reset(new TOperandGetter<type, arg_type>(TOperand<type, arg_type>(traceVariables, var##N, val##N, arg##N.ParamIdx))); \
}
-#define TERNARY_ON_TYPE(n, t, v, fn) \
+#define TERNARY_ON_TYPE(n, t, v, fn) \
if ((arg1.ParamIdx == size_t(-1) || strcmp(tName1, n) == 0) && (arg2.ParamIdx == size_t(-1) || strcmp(tName2, n) == 0)) { \
- TAutoPtr<IOperandGetter<t>> operand1, operand2; \
- FOREACH_LEFT_TYPE(CREATE_OPERAND_GETTER_N, 1, t); \
- FOREACH_RIGHT_TYPE(CREATE_OPERAND_GETTER_N, 2, t); \
- if (operand1 && operand2) { \
- actExec.Reset(new TTernaryStatementExecutor<t, fn<t>>( \
- TReceiver<t>(traceVariables, var0), \
- operand1, \
- operand2)); \
- } \
- break; \
+ TAutoPtr<IOperandGetter<t>> operand1, operand2; \
+ FOREACH_LEFT_TYPE(CREATE_OPERAND_GETTER_N, 1, t); \
+ FOREACH_RIGHT_TYPE(CREATE_OPERAND_GETTER_N, 2, t); \
+ if (operand1 && operand2) { \
+ actExec.Reset(new TTernaryStatementExecutor<t, fn<t>>( \
+ TReceiver<t>(traceVariables, var0), \
+ operand1, \
+ operand2)); \
+ } \
+ break; \
}
#define IMPLEMENT_TERNARY_STATEMENT(fn) FOR_MATH_PARAMTYPE(TERNARY_ON_TYPE, fn)
- case ST_INC:
- FOR_MATH_PARAMTYPE(PARSE_UNARY_INPLACE_STATEMENT_MACRO, TInc);
- break;
- case ST_DEC:
- FOR_MATH_PARAMTYPE(PARSE_UNARY_INPLACE_STATEMENT_MACRO, TDec);
- break;
- case ST_MOV:
- FOR_MATH_PARAMTYPE(PARSE_BINARY_STATEMENT_MACRO, TTraceSecondArg);
- break;
- case ST_ADD_EQ:
- FOR_MATH_PARAMTYPE(PARSE_BINARY_INPLACE_STATEMENT_MACRO, TAddEq);
- break;
- case ST_SUB_EQ:
- FOR_MATH_PARAMTYPE(PARSE_BINARY_INPLACE_STATEMENT_MACRO, TSubEq);
- break;
- case ST_ADD:
- IMPLEMENT_TERNARY_STATEMENT(std::plus)
- break;
- case ST_SUB:
- IMPLEMENT_TERNARY_STATEMENT(std::minus)
- break;
- case ST_MUL:
- IMPLEMENT_TERNARY_STATEMENT(std::multiplies)
- break;
- case ST_DIV:
- IMPLEMENT_TERNARY_STATEMENT(std::divides)
- break;
- case ST_MOD:
- IMPLEMENT_TERNARY_STATEMENT(std::modulus)
- break;
- default:
- ythrow yexception() << "block #" << bi + 1 << " action #" << i + 1
- << " has not supported statement type #" << int(statement.GetType());
- }
+ case ST_INC:
+ FOR_MATH_PARAMTYPE(PARSE_UNARY_INPLACE_STATEMENT_MACRO, TInc);
+ break;
+ case ST_DEC:
+ FOR_MATH_PARAMTYPE(PARSE_UNARY_INPLACE_STATEMENT_MACRO, TDec);
+ break;
+ case ST_MOV:
+ FOR_MATH_PARAMTYPE(PARSE_BINARY_STATEMENT_MACRO, TTraceSecondArg);
+ break;
+ case ST_ADD_EQ:
+ FOR_MATH_PARAMTYPE(PARSE_BINARY_INPLACE_STATEMENT_MACRO, TAddEq);
+ break;
+ case ST_SUB_EQ:
+ FOR_MATH_PARAMTYPE(PARSE_BINARY_INPLACE_STATEMENT_MACRO, TSubEq);
+ break;
+ case ST_ADD:
+ IMPLEMENT_TERNARY_STATEMENT(std::plus)
+ break;
+ case ST_SUB:
+ IMPLEMENT_TERNARY_STATEMENT(std::minus)
+ break;
+ case ST_MUL:
+ IMPLEMENT_TERNARY_STATEMENT(std::multiplies)
+ break;
+ case ST_DIV:
+ IMPLEMENT_TERNARY_STATEMENT(std::divides)
+ break;
+ case ST_MOD:
+ IMPLEMENT_TERNARY_STATEMENT(std::modulus)
+ break;
+ default:
+ ythrow yexception() << "block #" << bi + 1 << " action #" << i + 1
+ << " has not supported statement type #" << int(statement.GetType());
+ }
}
- if (!actExec) {
+ if (!actExec) {
ythrow yexception() << "block #" << bi + 1 << " action #" << i + 1
<< " can't create action";
- }
+ }
#undef CREATE_OPERAND_GETTER_N
#undef TERNARY_ON_TYPE
#undef IMPLEMENT_TERNARY_STATEMENT
@@ -819,233 +819,233 @@ namespace NLWTrace {
#undef PARSE_BINARY_STATEMENT_MACRO
#undef PARSE_BINARY_INPLACE_STATEMENT_MACRO
#undef PARSE_UNARY_INPLACE_STATEMENT_MACRO
- } else {
- ythrow yexception() << "block #" << bi + 1 << " action #" << i + 1
- << " has not supported action '" << action.ShortDebugString() << "'";
- }
- if (!exec) {
- exec.Reset(actExec.Release());
- last = exec.Get();
- } else {
- last->SetNext(actExec.Release());
- last = last->GetNext();
- }
- }
-
- if (!probe->Attach(exec.Get())) {
- ythrow yexception() << "block #" << bi + 1
- << " cannot be attached to probe '" << probe->Event.Name << "': no free slots";
- }
- Probes.push_back(std::make_pair(probe, exec.Release()));
-#else
- Y_UNUSED(bi);
- Y_UNUSED(pred);
- Y_UNUSED(actions);
- Y_UNUSED(probe);
- Y_UNUSED(destructiveActionsAllowed);
- Y_UNUSED(traceVariables);
- Y_UNUSED(customActionFactory);
-#endif
- }
-
- TSession::TSession(ui64 traceIdx,
- TProbeRegistry& registry,
- const TQuery& query,
- const bool destructiveActionsAllowed,
- const TCustomActionFactory& customActionFactory)
- : StartTime(TInstant::Now())
- , TraceIdx(traceIdx)
- , Registry(registry)
- , StoreDuration(TDuration::MicroSeconds(query.GetLogDurationUs() * 11 / 10)) // +10% to try avoid truncation while reading multiple threads/traces
- , ReadDuration(TDuration::MicroSeconds(query.GetLogDurationUs()))
+ } else {
+ ythrow yexception() << "block #" << bi + 1 << " action #" << i + 1
+ << " has not supported action '" << action.ShortDebugString() << "'";
+ }
+ if (!exec) {
+ exec.Reset(actExec.Release());
+ last = exec.Get();
+ } else {
+ last->SetNext(actExec.Release());
+ last = last->GetNext();
+ }
+ }
+
+ if (!probe->Attach(exec.Get())) {
+ ythrow yexception() << "block #" << bi + 1
+ << " cannot be attached to probe '" << probe->Event.Name << "': no free slots";
+ }
+ Probes.push_back(std::make_pair(probe, exec.Release()));
+#else
+ Y_UNUSED(bi);
+ Y_UNUSED(pred);
+ Y_UNUSED(actions);
+ Y_UNUSED(probe);
+ Y_UNUSED(destructiveActionsAllowed);
+ Y_UNUSED(traceVariables);
+ Y_UNUSED(customActionFactory);
+#endif
+ }
+
+ TSession::TSession(ui64 traceIdx,
+ TProbeRegistry& registry,
+ const TQuery& query,
+ const bool destructiveActionsAllowed,
+ const TCustomActionFactory& customActionFactory)
+ : StartTime(TInstant::Now())
+ , TraceIdx(traceIdx)
+ , Registry(registry)
+ , StoreDuration(TDuration::MicroSeconds(query.GetLogDurationUs() * 11 / 10)) // +10% to try avoid truncation while reading multiple threads/traces
+ , ReadDuration(TDuration::MicroSeconds(query.GetLogDurationUs()))
, CyclicLog(query.GetPerThreadLogSize() ? query.GetPerThreadLogSize() : 1000)
- , DurationLog(StoreDuration)
+ , DurationLog(StoreDuration)
, CyclicDepot(query.GetPerThreadLogSize() ? query.GetPerThreadLogSize() : 1000)
- , DurationDepot(StoreDuration)
- , LastTrackId(0)
+ , DurationDepot(StoreDuration)
+ , LastTrackId(0)
, LastSpanId(0)
- , Attached(true)
- , Query(query)
- {
- try {
- for (size_t bi = 0; bi < query.BlocksSize(); bi++) {
- const TBlock& block = query.GetBlocks(bi);
- if (!block.HasProbeDesc()) {
- ythrow yexception() << "block #" << bi + 1 << " has no probe description";
- }
- const TProbeDesc& pdesc = block.GetProbeDesc();
- const TPredicate* pred = block.HasPredicate() ? &block.GetPredicate() : nullptr;
- if (block.ActionSize() < 1) {
- ythrow yexception() << "block #" << bi + 1 << " has no action";
- }
- const NProtoBuf::RepeatedPtrField<TAction>& actions = block.action();
+ , Attached(true)
+ , Query(query)
+ {
+ try {
+ for (size_t bi = 0; bi < query.BlocksSize(); bi++) {
+ const TBlock& block = query.GetBlocks(bi);
+ if (!block.HasProbeDesc()) {
+ ythrow yexception() << "block #" << bi + 1 << " has no probe description";
+ }
+ const TProbeDesc& pdesc = block.GetProbeDesc();
+ const TPredicate* pred = block.HasPredicate() ? &block.GetPredicate() : nullptr;
+ if (block.ActionSize() < 1) {
+ ythrow yexception() << "block #" << bi + 1 << " has no action";
+ }
+ const NProtoBuf::RepeatedPtrField<TAction>& actions = block.action();
if (pdesc.GetName() && pdesc.GetProvider()) {
- TProbeRegistry::TProbesAccessor probes(Registry);
- bool found = false;
- for (auto& kv : probes) {
- TProbe* probe = kv.first;
- if (probe->Event.Name == pdesc.GetName() && probe->Event.GetProvider() == pdesc.GetProvider()) {
- InsertExecutor(TraceVariables, bi, pred, actions, probe, destructiveActionsAllowed, customActionFactory);
- found = true;
- break;
- }
- }
- if (!found) {
- ythrow yexception() << "block #" << bi + 1 << " has no matching probe with name '"
- << pdesc.GetName() << "' provider '" << pdesc.GetProvider() << "'";
- }
+ TProbeRegistry::TProbesAccessor probes(Registry);
+ bool found = false;
+ for (auto& kv : probes) {
+ TProbe* probe = kv.first;
+ if (probe->Event.Name == pdesc.GetName() && probe->Event.GetProvider() == pdesc.GetProvider()) {
+ InsertExecutor(TraceVariables, bi, pred, actions, probe, destructiveActionsAllowed, customActionFactory);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ythrow yexception() << "block #" << bi + 1 << " has no matching probe with name '"
+ << pdesc.GetName() << "' provider '" << pdesc.GetProvider() << "'";
+ }
} else if (pdesc.GetGroup()) {
- bool found = false;
- TProbeRegistry::TProbesAccessor probes(Registry);
- for (auto& kv : probes) {
- TProbe* probe = kv.first;
- for (const char* const* gi = probe->Event.Groups; *gi != nullptr; gi++) {
- if (*gi == pdesc.GetGroup()) {
- InsertExecutor(TraceVariables, bi, pred, actions, probe, destructiveActionsAllowed, customActionFactory);
- found = true;
- break;
- }
- }
- }
- if (!found) {
- ythrow yexception() << "block #" << bi + 1
- << " has no matching probes for group '" << pdesc.GetGroup() << "'";
- }
- } else {
- ythrow yexception() << "block #" << bi + 1 << " has bad probe description: name '" << pdesc.GetName()
- << "' provider '" << pdesc.GetProvider()
- << "' group '" << pdesc.GetGroup() << "'";
- }
- }
- } catch (...) {
- Destroy();
- throw;
- }
- }
-
- void TSession::Destroy() {
- Detach();
- for (auto& probe : Probes) {
- delete probe.second;
- }
- }
-
- TSession::~TSession() {
- Destroy();
- }
-
- void TSession::Detach() {
- if (Attached) {
- for (auto& p : Probes) {
- TProbe* probe = p.first;
- IExecutor* exec = p.second;
- probe->Detach(exec);
- }
- Attached = false;
- }
- }
-
- size_t TSession::GetEventsCount() const {
- return CyclicLog.GetEventsCount() + DurationLog.GetEventsCount() + CyclicDepot.GetEventsCount() + DurationDepot.GetEventsCount();
- }
-
- size_t TSession::GetThreadsCount() const {
- return CyclicLog.GetThreadsCount() + DurationLog.GetThreadsCount() + CyclicDepot.GetThreadsCount() + DurationDepot.GetThreadsCount();
- }
-
- class TReadToProtobuf {
- private:
- TMap<TThread::TId, TVector<TLogItem>> Items;
-
- public:
- void ToProtobuf(TLogPb& pb) const {
- TSet<TProbe*> probes;
- ui64 eventsCount = 0;
- for (auto kv : Items) {
- TThreadLogPb* tpb = pb.AddThreadLogs();
- tpb->SetThreadId(kv.first);
- for (TLogItem& item : kv.second) {
- item.ToProtobuf(*tpb->AddLogItems());
- probes.insert(item.Probe);
- eventsCount++;
- }
- }
- pb.SetEventsCount(eventsCount);
- for (TProbe* probe : probes) {
- probe->Event.ToProtobuf(*pb.AddEvents());
- }
- }
-
- void Push(TThread::TId tid, const TLogItem& item) {
- // Avoid any expansive operations in Push(), because it executes under lock and blocks program being traced
- Items[tid].push_back(item);
- }
- };
-
- void TSession::ToProtobuf(TLogPb& pb) const {
- TReadToProtobuf reader;
- ReadItems(reader);
- reader.ToProtobuf(pb);
- pb.MutableQuery()->CopyFrom(Query);
- pb.SetCrtTime(TInstant::Now().GetValue());
- }
-
- TManager::TManager(TProbeRegistry& registry, bool allowDestructiveActions)
- : Registry(registry)
- , DestructiveActionsAllowed(allowDestructiveActions)
+ bool found = false;
+ TProbeRegistry::TProbesAccessor probes(Registry);
+ for (auto& kv : probes) {
+ TProbe* probe = kv.first;
+ for (const char* const* gi = probe->Event.Groups; *gi != nullptr; gi++) {
+ if (*gi == pdesc.GetGroup()) {
+ InsertExecutor(TraceVariables, bi, pred, actions, probe, destructiveActionsAllowed, customActionFactory);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ ythrow yexception() << "block #" << bi + 1
+ << " has no matching probes for group '" << pdesc.GetGroup() << "'";
+ }
+ } else {
+ ythrow yexception() << "block #" << bi + 1 << " has bad probe description: name '" << pdesc.GetName()
+ << "' provider '" << pdesc.GetProvider()
+ << "' group '" << pdesc.GetGroup() << "'";
+ }
+ }
+ } catch (...) {
+ Destroy();
+ throw;
+ }
+ }
+
+ void TSession::Destroy() {
+ Detach();
+ for (auto& probe : Probes) {
+ delete probe.second;
+ }
+ }
+
+ TSession::~TSession() {
+ Destroy();
+ }
+
+ void TSession::Detach() {
+ if (Attached) {
+ for (auto& p : Probes) {
+ TProbe* probe = p.first;
+ IExecutor* exec = p.second;
+ probe->Detach(exec);
+ }
+ Attached = false;
+ }
+ }
+
+ size_t TSession::GetEventsCount() const {
+ return CyclicLog.GetEventsCount() + DurationLog.GetEventsCount() + CyclicDepot.GetEventsCount() + DurationDepot.GetEventsCount();
+ }
+
+ size_t TSession::GetThreadsCount() const {
+ return CyclicLog.GetThreadsCount() + DurationLog.GetThreadsCount() + CyclicDepot.GetThreadsCount() + DurationDepot.GetThreadsCount();
+ }
+
+ class TReadToProtobuf {
+ private:
+ TMap<TThread::TId, TVector<TLogItem>> Items;
+
+ public:
+ void ToProtobuf(TLogPb& pb) const {
+ TSet<TProbe*> probes;
+ ui64 eventsCount = 0;
+ for (auto kv : Items) {
+ TThreadLogPb* tpb = pb.AddThreadLogs();
+ tpb->SetThreadId(kv.first);
+ for (TLogItem& item : kv.second) {
+ item.ToProtobuf(*tpb->AddLogItems());
+ probes.insert(item.Probe);
+ eventsCount++;
+ }
+ }
+ pb.SetEventsCount(eventsCount);
+ for (TProbe* probe : probes) {
+ probe->Event.ToProtobuf(*pb.AddEvents());
+ }
+ }
+
+ void Push(TThread::TId tid, const TLogItem& item) {
+ // Avoid any expansive operations in Push(), because it executes under lock and blocks program being traced
+ Items[tid].push_back(item);
+ }
+ };
+
+ void TSession::ToProtobuf(TLogPb& pb) const {
+ TReadToProtobuf reader;
+ ReadItems(reader);
+ reader.ToProtobuf(pb);
+ pb.MutableQuery()->CopyFrom(Query);
+ pb.SetCrtTime(TInstant::Now().GetValue());
+ }
+
+ TManager::TManager(TProbeRegistry& registry, bool allowDestructiveActions)
+ : Registry(registry)
+ , DestructiveActionsAllowed(allowDestructiveActions)
, SerializingExecutor(new TRunLogShuttleActionExecutor<TCyclicDepot>(0, {}, nullptr, nullptr, nullptr))
- {
- }
-
- TManager::~TManager() {
- for (auto& trace : Traces) {
- delete trace.second;
- }
- }
-
- bool TManager::HasTrace(const TString& id) const {
- TGuard<TMutex> g(Mtx);
+ {
+ }
+
+ TManager::~TManager() {
+ for (auto& trace : Traces) {
+ delete trace.second;
+ }
+ }
+
+ bool TManager::HasTrace(const TString& id) const {
+ TGuard<TMutex> g(Mtx);
return Traces.contains(id);
- }
-
- const TSession* TManager::GetTrace(const TString& id) const {
- TGuard<TMutex> g(Mtx);
- TTraces::const_iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- return it->second;
- }
- }
-
- void TManager::New(const TString& id, const TQuery& query) {
- TGuard<TMutex> g(Mtx);
- if (Traces.find(id) == Traces.end()) {
- TSession* trace = new TSession(++LastTraceIdx, Registry, query, GetDestructiveActionsAllowed(), CustomActionFactory);
- Traces[id] = trace;
- } else {
- ythrow yexception() << "trace id '" << id << "' is already used";
- }
- }
-
- void TManager::Delete(const TString& id) {
- TGuard<TMutex> g(Mtx);
- TTraces::iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- delete it->second;
- Traces.erase(it);
- }
- }
-
- void TManager::Stop(const TString& id) {
- TGuard<TMutex> g(Mtx);
- TTraces::iterator it = Traces.find(id);
- if (it == Traces.end()) {
- ythrow yexception() << "trace id '" << id << "' is not used";
- } else {
- it->second->Detach();
- }
- }
-}
+ }
+
+ const TSession* TManager::GetTrace(const TString& id) const {
+ TGuard<TMutex> g(Mtx);
+ TTraces::const_iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ return it->second;
+ }
+ }
+
+ void TManager::New(const TString& id, const TQuery& query) {
+ TGuard<TMutex> g(Mtx);
+ if (Traces.find(id) == Traces.end()) {
+ TSession* trace = new TSession(++LastTraceIdx, Registry, query, GetDestructiveActionsAllowed(), CustomActionFactory);
+ Traces[id] = trace;
+ } else {
+ ythrow yexception() << "trace id '" << id << "' is already used";
+ }
+ }
+
+ void TManager::Delete(const TString& id) {
+ TGuard<TMutex> g(Mtx);
+ TTraces::iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ delete it->second;
+ Traces.erase(it);
+ }
+ }
+
+ void TManager::Stop(const TString& id) {
+ TGuard<TMutex> g(Mtx);
+ TTraces::iterator it = Traces.find(id);
+ if (it == Traces.end()) {
+ ythrow yexception() << "trace id '" << id << "' is not used";
+ } else {
+ it->second->Detach();
+ }
+ }
+}
diff --git a/library/cpp/lwtrace/trace_ut.cpp b/library/cpp/lwtrace/trace_ut.cpp
index cb03e4fbde..dd67212ea2 100644
--- a/library/cpp/lwtrace/trace_ut.cpp
+++ b/library/cpp/lwtrace/trace_ut.cpp
@@ -1,11 +1,11 @@
-#include "all.h"
-
+#include "all.h"
+
#include <library/cpp/lwtrace/protos/lwtrace.pb.h>
#include <library/cpp/testing/unittest/registar.h>
-
+
#include <google/protobuf/text_format.h>
-
+
enum ESimpleEnum {
ValueA,
ValueB,
@@ -27,53 +27,53 @@ enum class EEnumClass {
PROBE(DurationParam, GROUPS("Group"), TYPES(TDuration), NAMES("value")) \
PROBE(ProtoEnum, GROUPS("Group"), TYPES(NLWTrace::EOperatorType), NAMES("value")) \
PROBE(IntIntParams, GROUPS("Group"), TYPES(ui32, ui64), NAMES("value1", "value2")) \
- /**/
-
-LWTRACE_DECLARE_PROVIDER(LWTRACE_UT_PROVIDER)
-LWTRACE_DEFINE_PROVIDER(LWTRACE_UT_PROVIDER)
-LWTRACE_USING(LWTRACE_UT_PROVIDER)
-
-using namespace NLWTrace;
-
+ /**/
+
+LWTRACE_DECLARE_PROVIDER(LWTRACE_UT_PROVIDER)
+LWTRACE_DEFINE_PROVIDER(LWTRACE_UT_PROVIDER)
+LWTRACE_USING(LWTRACE_UT_PROVIDER)
+
+using namespace NLWTrace;
+
Y_UNIT_TEST_SUITE(LWTraceTrace) {
#ifndef LWTRACE_DISABLE
Y_UNIT_TEST(Smoke) {
- TManager mngr(*Singleton<TProbeRegistry>(), true);
- TQuery q;
- bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
- Blocks {
- ProbeDesc {
- Name: "NoParam"
- Provider: "LWTRACE_UT_PROVIDER"
- }
- Action {
- LogAction { }
- }
- }
- )END",
- &q);
- UNIT_ASSERT(parsed);
- mngr.New("Query1", q);
- LWPROBE(NoParam);
- struct {
- void Push(TThread::TId, const TLogItem& item) {
- UNIT_ASSERT(TString(item.Probe->Event.Name) == "NoParam");
- }
- } reader;
- mngr.ReadLog("Query1", reader);
+ TManager mngr(*Singleton<TProbeRegistry>(), true);
+ TQuery q;
+ bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
+ Blocks {
+ ProbeDesc {
+ Name: "NoParam"
+ Provider: "LWTRACE_UT_PROVIDER"
+ }
+ Action {
+ LogAction { }
+ }
+ }
+ )END",
+ &q);
+ UNIT_ASSERT(parsed);
+ mngr.New("Query1", q);
+ LWPROBE(NoParam);
+ struct {
+ void Push(TThread::TId, const TLogItem& item) {
+ UNIT_ASSERT(TString(item.Probe->Event.Name) == "NoParam");
+ }
+ } reader;
+ mngr.ReadLog("Query1", reader);
LWPROBE(EnumParams, ValueA, EEnumClass::ValueC);
LWPROBE(InstantParam, TInstant::Seconds(42));
LWPROBE(DurationParam, TDuration::MilliSeconds(146));
LWPROBE(ProtoEnum, OT_EQ);
- }
+ }
Y_UNIT_TEST(Predicate) {
TManager mngr(*Singleton<TProbeRegistry>(), true);
TQuery q;
bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "IntParam"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -85,7 +85,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
}
}
Action {
- LogAction { }
+ LogAction { }
}
}
)END", &q);
@@ -117,7 +117,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
TQuery q;
bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "IntParam"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -203,7 +203,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
}
}
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "IntParam"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -216,53 +216,53 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
Operators {
Type: OT_EQ
Argument { Variable: "varDec" }
- Argument { Value: "-1" }
+ Argument { Value: "-1" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varMov" }
- Argument { Value: "3" }
+ Argument { Value: "3" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varAddEq" }
- Argument { Value: "5" }
+ Argument { Value: "5" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varSubEq" }
- Argument { Value: "-5" }
+ Argument { Value: "-5" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varAdd" }
- Argument { Value: "5" }
+ Argument { Value: "5" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varSub" }
- Argument { Value: "1" }
+ Argument { Value: "1" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varMul" }
- Argument { Value: "12" }
+ Argument { Value: "12" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varDiv" }
- Argument { Value: "3" }
+ Argument { Value: "3" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varMod" }
- Argument { Value: "2" }
+ Argument { Value: "2" }
}
}
Action {
LogAction { }
}
- }
+ }
)END", &q);
UNIT_ASSERT(parsed);
mngr.New("QueryName", q);
@@ -286,7 +286,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
TQuery q;
bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "IntIntParams"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -353,7 +353,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
}
}
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "IntIntParams"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -361,48 +361,48 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
Operators {
Type: OT_EQ
Argument { Variable: "varMov" }
- Argument { Param: "value1" }
+ Argument { Param: "value1" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varAddEq" }
- Argument { Param: "value1" }
+ Argument { Param: "value1" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varSubEq" }
- Argument { Value: "-22" }
+ Argument { Value: "-22" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varAdd" }
- Argument { Value: "25" }
+ Argument { Value: "25" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varSub" }
- Argument { Value: "19" }
+ Argument { Value: "19" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varMul" }
- Argument { Value: "66" }
+ Argument { Value: "66" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varDiv" }
- Argument { Value: "7" }
+ Argument { Value: "7" }
}
Operators {
Type: OT_EQ
Argument { Variable: "varMod" }
- Argument { Value: "1" }
+ Argument { Value: "1" }
}
}
Action {
LogAction { }
}
- }
+ }
)END", &q);
UNIT_ASSERT(parsed);
mngr.New("QueryName", q);
@@ -424,12 +424,12 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
PerThreadLogSize: 3
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "IntParam"
Provider: "LWTRACE_UT_PROVIDER"
}
Action {
- LogAction { }
+ LogAction { }
}
}
)END", &q);
@@ -501,7 +501,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
TQuery q;
bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "NoParam"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -521,7 +521,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
TQuery q;
bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
Blocks {
- ProbeDesc {
+ ProbeDesc {
Name: "NoParam"
Provider: "LWTRACE_UT_PROVIDER"
}
@@ -539,7 +539,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
TInstant t0 = Now();
LWPROBE(NoParam);
TInstant t1 = Now();
- UNIT_ASSERT(t1.NanoSeconds() - t0.NanoSeconds() >= sleepTimeNs);
+ UNIT_ASSERT(t1.NanoSeconds() - t0.NanoSeconds() >= sleepTimeNs);
}
Y_UNIT_TEST(ProtoEnumTraits) {
@@ -550,37 +550,37 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
}
Y_UNIT_TEST(Track) {
- TManager mngr(*Singleton<TProbeRegistry>(), true);
- TQuery q;
- bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
- Blocks {
- ProbeDesc {
- Name: "IntParam"
- Provider: "LWTRACE_UT_PROVIDER"
- }
- Action {
- RunLogShuttleAction { }
- }
- }
+ TManager mngr(*Singleton<TProbeRegistry>(), true);
+ TQuery q;
+ bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END(
+ Blocks {
+ ProbeDesc {
+ Name: "IntParam"
+ Provider: "LWTRACE_UT_PROVIDER"
+ }
+ Action {
+ RunLogShuttleAction { }
+ }
+ }
)END", &q);
- UNIT_ASSERT(parsed);
- mngr.New("Query1", q);
-
- {
- TOrbit orbit;
- LWTRACK(IntParam, orbit, 1);
- LWTRACK(StringParam, orbit, "str");
- }
-
- struct {
- void Push(TThread::TId, const TTrackLog& tl) {
- UNIT_ASSERT(tl.Items.size() == 2);
- UNIT_ASSERT(TString(tl.Items[0].Probe->Event.Name) == "IntParam");
- UNIT_ASSERT(TString(tl.Items[1].Probe->Event.Name) == "StringParam");
- }
- } reader;
- mngr.ReadDepot("Query1", reader);
- }
+ UNIT_ASSERT(parsed);
+ mngr.New("Query1", q);
+
+ {
+ TOrbit orbit;
+ LWTRACK(IntParam, orbit, 1);
+ LWTRACK(StringParam, orbit, "str");
+ }
+
+ struct {
+ void Push(TThread::TId, const TTrackLog& tl) {
+ UNIT_ASSERT(tl.Items.size() == 2);
+ UNIT_ASSERT(TString(tl.Items[0].Probe->Event.Name) == "IntParam");
+ UNIT_ASSERT(TString(tl.Items[1].Probe->Event.Name) == "StringParam");
+ }
+ } reader;
+ mngr.ReadDepot("Query1", reader);
+ }
Y_UNIT_TEST(ShouldSerializeTracks)
{
@@ -877,4 +877,4 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) {
mngr.ReadDepot("Query1", reader);
}
#endif // LWTRACE_DISABLE
-}
+}
diff --git a/library/cpp/lwtrace/ut/ya.make b/library/cpp/lwtrace/ut/ya.make
index f43118bab7..03599cad26 100644
--- a/library/cpp/lwtrace/ut/ya.make
+++ b/library/cpp/lwtrace/ut/ya.make
@@ -1,11 +1,11 @@
UNITTEST_FOR(library/cpp/lwtrace)
-
-OWNER(serxa)
-
-FORK_SUBTESTS()
-
-SRCS(
- trace_ut.cpp
-)
-
-END()
+
+OWNER(serxa)
+
+FORK_SUBTESTS()
+
+SRCS(
+ trace_ut.cpp
+)
+
+END()
diff --git a/library/cpp/lwtrace/ya.make b/library/cpp/lwtrace/ya.make
index d9accb3006..3f19aa1973 100644
--- a/library/cpp/lwtrace/ya.make
+++ b/library/cpp/lwtrace/ya.make
@@ -1,25 +1,25 @@
LIBRARY()
-OWNER(serxa)
+OWNER(serxa)
-PEERDIR(
+PEERDIR(
library/cpp/lwtrace/protos
-)
-
+)
+
SRCS(
- check.cpp
+ check.cpp
control.cpp
- custom_action.cpp
+ custom_action.cpp
kill_action.cpp
log_shuttle.cpp
- perf.cpp
- probes.cpp
- shuttle.cpp
+ perf.cpp
+ probes.cpp
+ shuttle.cpp
sleep_action.cpp
- start.cpp
- stderr_writer.cpp
- symbol.cpp
- trace.cpp
+ start.cpp
+ stderr_writer.cpp
+ symbol.cpp
+ trace.cpp
)
END()
diff --git a/library/cpp/monlib/counters/counters.cpp b/library/cpp/monlib/counters/counters.cpp
index 50dca4c577..6ea370e081 100644
--- a/library/cpp/monlib/counters/counters.cpp
+++ b/library/cpp/monlib/counters/counters.cpp
@@ -21,7 +21,7 @@ namespace NMonitoring {
if (i == 0 || i >= imax)
*buf = '\0';
else
- snprintf(buf, size, "%" PRId64 ".%" PRId64 "%c", major, minor, shorts[i]);
+ snprintf(buf, size, "%" PRId64 ".%" PRId64 "%c", major, minor, shorts[i]);
return buf;
}
@@ -32,18 +32,18 @@ namespace NMonitoring {
buf[0] = 0;
return buf;
}
- PrettyNumShort(val, buf + 2, size - 3);
- if (buf[2] == 0) {
- *buf = '\0';
- } else {
+ PrettyNumShort(val, buf + 2, size - 3);
+ if (buf[2] == 0) {
+ *buf = '\0';
+ } else {
size_t len = 2 + strnlen(buf + 2, size - 4);
Y_ASSERT(len < size);
- buf[0] = ' ';
- buf[1] = '(';
- buf[len] = ')';
- buf[len + 1] = '\0';
- }
-
- return buf;
- }
+ buf[0] = ' ';
+ buf[1] = '(';
+ buf[len] = ')';
+ buf[len + 1] = '\0';
+ }
+
+ return buf;
+ }
}
diff --git a/library/cpp/monlib/dynamic_counters/counters.cpp b/library/cpp/monlib/dynamic_counters/counters.cpp
index 3635d87d0d..b4ee2942aa 100644
--- a/library/cpp/monlib/dynamic_counters/counters.cpp
+++ b/library/cpp/monlib/dynamic_counters/counters.cpp
@@ -184,11 +184,11 @@ void TDynamicCounters::RegisterSubgroup(const TString& name, const TString& valu
}
void TDynamicCounters::OutputHtml(IOutputStream& os) const {
- HTML(os) {
- PRE() {
+ HTML(os) {
+ PRE() {
OutputPlainText(os);
- }
- }
+ }
+ }
}
void TDynamicCounters::EnumerateSubgroups(const std::function<void(const TString& name, const TString& value)>& output) const {
diff --git a/library/cpp/monlib/dynamic_counters/page.cpp b/library/cpp/monlib/dynamic_counters/page.cpp
index 5124a47bb3..6fc7719a48 100644
--- a/library/cpp/monlib/dynamic_counters/page.cpp
+++ b/library/cpp/monlib/dynamic_counters/page.cpp
@@ -107,15 +107,15 @@ void TDynamicCountersPage::HandleAbsentSubgroup(IMonHttpRequest& request) {
void TDynamicCountersPage::BeforePre(IMonHttpRequest& request) {
IOutputStream& out = request.Output();
- HTML(out) {
- DIV() {
+ HTML(out) {
+ DIV() {
out << "<a href='" << request.GetPath() << "/json'>Counters as JSON</a>";
out << " for <a href='https://wiki.yandex-team.ru/solomon/'>Solomon</a>";
- }
+ }
H5() {
out << "Counters subgroups";
- }
+ }
UL() {
currentCounters->EnumerateSubgroups([&](const TString& name, const TString& value) {
LI() {
@@ -129,7 +129,7 @@ void TDynamicCountersPage::BeforePre(IMonHttpRequest& request) {
H4() {
out << "Counters as text";
}
- }
+ }
}
void TDynamicCountersPage::OutputText(IOutputStream& out, IMonHttpRequest&) {
diff --git a/library/cpp/monlib/service/pages/html_mon_page.cpp b/library/cpp/monlib/service/pages/html_mon_page.cpp
index eb4eb3b66c..fdb9229f04 100644
--- a/library/cpp/monlib/service/pages/html_mon_page.cpp
+++ b/library/cpp/monlib/service/pages/html_mon_page.cpp
@@ -8,10 +8,10 @@ void THtmlMonPage::Output(NMonitoring::IMonHttpRequest& request) {
IOutputStream& out = request.Output();
out << HTTPOKHTML;
- HTML(out) {
+ HTML(out) {
out << "<!DOCTYPE html>\n";
- HTML_TAG() {
- HEAD() {
+ HTML_TAG() {
+ HEAD() {
if (!!Title) {
out << "<title>" << Title << "</title>\n";
}
@@ -32,19 +32,19 @@ void THtmlMonPage::Output(NMonitoring::IMonHttpRequest& request) {
out << ".narrow-line80 {line-height: 80%}\n";
out << ".narrow-line90 {line-height: 90%}\n";
out << "</style>\n";
- }
- BODY() {
+ }
+ BODY() {
OutputNavBar(out);
- DIV_CLASS("container") {
+ DIV_CLASS("container") {
if (!!Title) {
out << "<h2>" << Title << "</h2>";
}
OutputContent(request);
- }
- }
- }
- }
+ }
+ }
+ }
+ }
}
void THtmlMonPage::NotFound(NMonitoring::IMonHttpRequest& request) const {
diff --git a/library/cpp/monlib/service/pages/mon_page.h b/library/cpp/monlib/service/pages/mon_page.h
index e396612bb0..4e244b292d 100644
--- a/library/cpp/monlib/service/pages/mon_page.h
+++ b/library/cpp/monlib/service/pages/mon_page.h
@@ -29,7 +29,7 @@ namespace NMonitoring {
// Images
static const char HTTPOKPNG[] = "HTTP/1.1 200 Ok\r\nContent-Type: image/png\r\nConnection: Close\r\n\r\n";
static const char HTTPOKSVG[] = "HTTP/1.1 200 Ok\r\nContent-Type: image/svg+xml\r\nConnection: Close\r\n\r\n";
-
+
class IMonPage;
using TMonPagePtr = TIntrusivePtr<IMonPage>;
diff --git a/library/cpp/monlib/service/pages/resource_mon_page.cpp b/library/cpp/monlib/service/pages/resource_mon_page.cpp
index ec4ac6a1a7..5571b70575 100644
--- a/library/cpp/monlib/service/pages/resource_mon_page.cpp
+++ b/library/cpp/monlib/service/pages/resource_mon_page.cpp
@@ -17,27 +17,27 @@ void TResourceMonPage::Output(NMonitoring::IMonHttpRequest& request) {
case JAVASCRIPT:
out << HTTPOKJAVASCRIPT;
break;
- case FONT_EOT:
- out << HTTPOKFONTEOT;
- break;
- case FONT_TTF:
- out << HTTPOKFONTTTF;
- break;
- case FONT_WOFF:
- out << HTTPOKFONTWOFF;
- break;
- case FONT_WOFF2:
- out << HTTPOKFONTWOFF2;
- break;
- case PNG:
- out << HTTPOKPNG;
- break;
- case SVG:
- out << HTTPOKSVG;
- break;
+ case FONT_EOT:
+ out << HTTPOKFONTEOT;
+ break;
+ case FONT_TTF:
+ out << HTTPOKFONTTTF;
+ break;
+ case FONT_WOFF:
+ out << HTTPOKFONTWOFF;
+ break;
+ case FONT_WOFF2:
+ out << HTTPOKFONTWOFF2;
+ break;
+ case PNG:
+ out << HTTPOKPNG;
+ break;
+ case SVG:
+ out << HTTPOKSVG;
+ break;
default:
out << HTTPOKBIN;
- break;
+ break;
}
out << NResource::Find(ResourceName);
}
diff --git a/library/cpp/monlib/service/pages/resource_mon_page.h b/library/cpp/monlib/service/pages/resource_mon_page.h
index f6ab67200e..aecb83c7be 100644
--- a/library/cpp/monlib/service/pages/resource_mon_page.h
+++ b/library/cpp/monlib/service/pages/resource_mon_page.h
@@ -18,11 +18,11 @@ namespace NMonitoring {
FONT_TTF,
FONT_WOFF,
FONT_WOFF2,
-
+
PNG,
SVG
};
-
+
TResourceMonPage(const TString& path, const TString& resourceName,
const EResourceType& resourceType = BINARY)
: IMonPage(path, "")
diff --git a/library/cpp/monlib/service/pages/templates.h b/library/cpp/monlib/service/pages/templates.h
index b4656f059f..4a96171f7c 100644
--- a/library/cpp/monlib/service/pages/templates.h
+++ b/library/cpp/monlib/service/pages/templates.h
@@ -1,11 +1,11 @@
#pragma once
#include <util/stream/output.h>
-#include <util/system/defaults.h>
+#include <util/system/defaults.h>
-#define WITH_SCOPED(var, value) WITH_SCOPED_I(var, value, Y_GENERATE_UNIQUE_ID(WITH_SCOPED_LABEL_))
+#define WITH_SCOPED(var, value) WITH_SCOPED_I(var, value, Y_GENERATE_UNIQUE_ID(WITH_SCOPED_LABEL_))
-#define WITH_SCOPED_I(var, value, label) \
+#define WITH_SCOPED_I(var, value, label) \
if (auto var = (value)) { \
Y_UNUSED(var); \
goto label; \
@@ -27,12 +27,12 @@
#define HTML_TAG() TAG(THtml)
#define DIV() TAG(TDiv)
#define DIV_CLASS(cls) TAG_CLASS(TDiv, cls)
-#define DIV_CLASS_ID(cls, id) TAG_CLASS_ID(TDiv, cls, id)
+#define DIV_CLASS_ID(cls, id) TAG_CLASS_ID(TDiv, cls, id)
#define PRE() TAG(TPre)
#define TABLE() TAG(TTable)
#define TABLE_CLASS(cls) TAG_CLASS(TTable, cls)
#define TABLE_SORTABLE() TABLE_CLASS("table-sortable")
-#define TABLE_SORTABLE_CLASS(cls) TABLE_CLASS(cls " table-sortable")
+#define TABLE_SORTABLE_CLASS(cls) TABLE_CLASS(cls " table-sortable")
#define TABLEHEAD() TAG(TTableHead)
#define TABLEHEAD_CLASS(cls) TAG_CLASS(TTableHead, cls)
#define TABLEBODY() TAG(TTableBody)
@@ -48,9 +48,9 @@
#define FORM_CLASS(cls) TAG_CLASS(TFormC, cls)
#define LABEL() TAG(TLabelC)
#define LABEL_CLASS(cls) TAG_CLASS(TLabelC, cls)
-#define LABEL_CLASS_FOR(cls, for0) TAG_CLASS_FOR(TLabelC, cls, for0)
+#define LABEL_CLASS_FOR(cls, for0) TAG_CLASS_FOR(TLabelC, cls, for0)
#define SPAN_CLASS(cls) TAG_CLASS(TSpanC, cls)
-#define SPAN_CLASS_STYLE(cls, style) TAG_CLASS_STYLE(TSpanC, cls, style)
+#define SPAN_CLASS_STYLE(cls, style) TAG_CLASS_STYLE(TSpanC, cls, style)
#define PARA() TAG(TPara)
#define PARA_CLASS(cls) TAG_CLASS(TPara, cls)
@@ -87,12 +87,12 @@
#define CAPTION() TAG(TCaption)
#define CAPTION_CLASS(cls) CAPTION_CLASS(TCaption, cls)
-
+
#define HTML_OUTPUT_PARAM(str, param) str << #param << ": " << param << "<br/>"
#define HTML_OUTPUT_TIME_PARAM(str, param) str << #param << ": " << ToStringLocalTimeUpToSeconds(param) << "<br/>"
-#define COLLAPSED_BUTTON_CONTENT(targetId, buttonText) \
- WITH_SCOPED(tmp, NMonitoring::TCollapsedButton(__stream, targetId, buttonText))
+#define COLLAPSED_BUTTON_CONTENT(targetId, buttonText) \
+ WITH_SCOPED(tmp, NMonitoring::TCollapsedButton(__stream, targetId, buttonText))
#define HREF(path) \
WITH_SCOPED(tmp, NMonitoring::THref(__stream, path))
@@ -156,10 +156,10 @@ namespace NMonitoring {
}
}
- explicit inline operator bool() const noexcept {
- return true; // just to work with WITH_SCOPED
- }
-
+ explicit inline operator bool() const noexcept {
+ return true; // just to work with WITH_SCOPED
+ }
+
IOutputStream& Str;
};
@@ -180,30 +180,30 @@ namespace NMonitoring {
}
}
- explicit inline operator bool() const noexcept {
- return true; // just to work with WITH_SCOPED
- }
-
+ explicit inline operator bool() const noexcept {
+ return true; // just to work with WITH_SCOPED
+ }
+
IOutputStream& Str;
};
- struct TOutputStreamRef {
+ struct TOutputStreamRef {
TOutputStreamRef(IOutputStream& str)
- : Str(str)
+ : Str(str)
{
}
-
+
inline operator IOutputStream&() noexcept {
- return Str;
- }
-
- explicit inline operator bool() const noexcept {
- return true; // just to work with WITH_SCOPED
- }
-
+ return Str;
+ }
+
+ explicit inline operator bool() const noexcept {
+ return true; // just to work with WITH_SCOPED
+ }
+
IOutputStream& Str;
- };
-
+ };
+
extern const char HtmlTag[5];
extern const char HeadTag[5];
extern const char BodyTag[5];
diff --git a/library/cpp/scheme/scheme.h b/library/cpp/scheme/scheme.h
index 3d7c59f3c9..cfbb61580d 100644
--- a/library/cpp/scheme/scheme.h
+++ b/library/cpp/scheme/scheme.h
@@ -387,7 +387,7 @@ namespace NSc {
static TValue From(const ::google::protobuf::Message&, bool mapAsDict = false);
- void To(::google::protobuf::Message&, const TProtoOpts& opts = {}) const;
+ void To(::google::protobuf::Message&, const TProtoOpts& opts = {}) const;
public:
inline explicit TValue(TPoolPtr&);
@@ -421,11 +421,11 @@ namespace NSc {
static TValue FromField(const ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*);
static TValue FromRepeatedField(const ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, int index);
- void ValueToField(const TValue& value, ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
- void ToField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
- void ToEnumField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
- void ToRepeatedField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
- void ToMapField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
+ void ValueToField(const TValue& value, ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
+ void ToField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
+ void ToEnumField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
+ void ToRepeatedField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
+ void ToMapField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
};
diff --git a/library/cpp/scheme/scimpl_defs.h b/library/cpp/scheme/scimpl_defs.h
index f3dd66b437..8937b75837 100644
--- a/library/cpp/scheme/scimpl_defs.h
+++ b/library/cpp/scheme/scimpl_defs.h
@@ -117,14 +117,14 @@ namespace NSc {
}
};
- struct TProtoOpts {
- // Serialization throws on unknown enum value if not set, else use default value
- bool UnknownEnumValueIsDefault = false;
-
- // Serialization throws on type mismatch if not set, else leaves protobuf empty
- bool SkipTypeMismatch = false;
- };
-
+ struct TProtoOpts {
+ // Serialization throws on unknown enum value if not set, else use default value
+ bool UnknownEnumValueIsDefault = false;
+
+ // Serialization throws on type mismatch if not set, else leaves protobuf empty
+ bool SkipTypeMismatch = false;
+ };
+
namespace NImpl {
class TKeySortContext;
class TSelfLoopContext;
diff --git a/library/cpp/scheme/scimpl_protobuf.cpp b/library/cpp/scheme/scimpl_protobuf.cpp
index 0c99122c69..190449effa 100644
--- a/library/cpp/scheme/scimpl_protobuf.cpp
+++ b/library/cpp/scheme/scimpl_protobuf.cpp
@@ -129,7 +129,7 @@ namespace NSc {
return v;
}
- void TValue::To(Message& msg, const TProtoOpts& opts) const {
+ void TValue::To(Message& msg, const TProtoOpts& opts) const {
msg.Clear();
if (IsNull()) {
@@ -144,16 +144,16 @@ namespace NSc {
for (int i = 0, count = descriptor->field_count(); i < count; ++i) {
const FieldDescriptor* field = descriptor->field(i);
if (field->is_map()) {
- ToMapField(msg, field, opts);
+ ToMapField(msg, field, opts);
} else if (field->is_repeated()) {
- ToRepeatedField(msg, field, opts);
+ ToRepeatedField(msg, field, opts);
} else {
- ToField(msg, field, opts);
+ ToField(msg, field, opts);
}
}
}
- void TValue::ValueToField(const TValue& value, Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
+ void TValue::ValueToField(const TValue& value, Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
const TString& name = field->name();
if (value.IsNull()) {
if (field->is_required() && !field->has_default_value()) {
@@ -190,10 +190,10 @@ namespace NSc {
reflection->SetString(&msg, field, value.ForceString());
break;
case FieldDescriptor::CPPTYPE_ENUM:
- value.ToEnumField(msg, field, opts);
+ value.ToEnumField(msg, field, opts);
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
- value.To(*reflection->MutableMessage(&msg, field), opts);
+ value.To(*reflection->MutableMessage(&msg, field), opts);
break;
default:
ythrow TSchemeException()
@@ -202,13 +202,13 @@ namespace NSc {
}
}
- void TValue::ToField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
+ void TValue::ToField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
const TString& name = field->name();
const TValue& value = Get(name);
- ValueToField(value, msg, field, opts);
+ ValueToField(value, msg, field, opts);
}
- void TValue::ToEnumField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
+ void TValue::ToEnumField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
const EnumDescriptor* enumField = field->enum_type();
const EnumValueDescriptor* enumFieldValue = IsString()
@@ -216,11 +216,11 @@ namespace NSc {
: enumField->FindValueByNumber(ForceIntNumber());
if (!enumFieldValue) {
- if (opts.UnknownEnumValueIsDefault) {
- enumFieldValue = field->default_value_enum();
- } else {
- ythrow TSchemeException() << "invalid value of enum field " << field->name();
- }
+ if (opts.UnknownEnumValueIsDefault) {
+ enumFieldValue = field->default_value_enum();
+ } else {
+ ythrow TSchemeException() << "invalid value of enum field " << field->name();
+ }
}
const Reflection* reflection = msg.GetReflection();
@@ -232,7 +232,7 @@ namespace NSc {
}
}
- void TValue::ToRepeatedField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
+ void TValue::ToRepeatedField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
const TString& name = field->name();
const TValue& fieldValue = Get(name);
@@ -241,11 +241,11 @@ namespace NSc {
}
if (!fieldValue.IsArray()) {
- if (opts.SkipTypeMismatch) {
- return; // leave repeated field empty
- } else {
- ythrow TSchemeException() << "invalid type of repeated field " << name << ": not an array";
- }
+ if (opts.SkipTypeMismatch) {
+ return; // leave repeated field empty
+ } else {
+ ythrow TSchemeException() << "invalid type of repeated field " << name << ": not an array";
+ }
}
const Reflection* reflection = msg.GetReflection();
@@ -277,7 +277,7 @@ namespace NSc {
reflection->AddString(&msg, field, value.ForceString());
break;
case FieldDescriptor::CPPTYPE_ENUM:
- value.ToEnumField(msg, field, opts);
+ value.ToEnumField(msg, field, opts);
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
value.To(*reflection->AddMessage(&msg, field));
@@ -290,7 +290,7 @@ namespace NSc {
}
}
- void TValue::ToMapField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
+ void TValue::ToMapField(Message& msg, const FieldDescriptor* field, const TProtoOpts& opts) const {
const TString& name = field->name();
const TValue& fieldValue = Get(name);
@@ -300,16 +300,16 @@ namespace NSc {
if (fieldValue.IsArray()) {
// read dict from key, value array
- ToRepeatedField(msg, field, opts);
+ ToRepeatedField(msg, field, opts);
return;
}
if (!fieldValue.IsDict()) {
- if (opts.SkipTypeMismatch) {
- return; // leave map field empty
- } else {
- ythrow TSchemeException() << "invalid type of map field " << name << ": not dict or array";
- }
+ if (opts.SkipTypeMismatch) {
+ return; // leave map field empty
+ } else {
+ ythrow TSchemeException() << "invalid type of map field " << name << ": not dict or array";
+ }
}
const Reflection* reflection = msg.GetReflection();
@@ -322,7 +322,7 @@ namespace NSc {
auto valueField = entryDesc->FindFieldByNumber(2);
auto entryReflection = entry->GetReflection();
entryReflection->SetString(entry.Get(), keyField, TString(value.first));
- ValueToField(value.second, *entry, valueField, opts);
+ ValueToField(value.second, *entry, valueField, opts);
mutableField.Add(*entry);
}
}