From 1deeceae439cacff4f4b35eb8d83f8ddc4ba1b5a Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Tue, 13 Mar 2018 16:50:58 +0000 Subject: [PATCH 1/2] Revert "Fix task reaper not cleaning up COMPLETE tasks" This reverts commit 0797241e1b13fe5a6f8a739d473df221cda83d92. Signed-off-by: Andrew Hsu --- .../orchestrator/taskreaper/task_reaper.go | 10 +- .../taskreaper/task_reaper_test.go | 162 ------------------ 2 files changed, 4 insertions(+), 168 deletions(-) delete mode 100644 manager/orchestrator/taskreaper/task_reaper_test.go diff --git a/manager/orchestrator/taskreaper/task_reaper.go b/manager/orchestrator/taskreaper/task_reaper.go index 678d4148ad..602752f91f 100644 --- a/manager/orchestrator/taskreaper/task_reaper.go +++ b/manager/orchestrator/taskreaper/task_reaper.go @@ -94,10 +94,10 @@ func (tr *TaskReaper) Run() { // Serviceless tasks can be cleaned up right away since they are not attached to a service. tr.cleanup = append(tr.cleanup, t.ID) } - // tasks with desired state REMOVE that have progressed beyond COMPLETE can be cleaned up + // tasks with desired state REMOVE that have progressed beyond SHUTDOWN can be cleaned up // right away for _, t := range removeTasks { - if t.Status.State >= api.TaskStateCompleted { + if t.Status.State >= api.TaskStateShutdown { tr.cleanup = append(tr.cleanup, t.ID) } } @@ -134,10 +134,10 @@ func (tr *TaskReaper) Run() { if t.Status.State >= api.TaskStateOrphaned && t.ServiceID == "" { tr.cleanup = append(tr.cleanup, t.ID) } - // add tasks that have progressed beyond COMPLETE and have desired state REMOVE. These + // add tasks that have progressed beyond SHUTDOWN and have desired state REMOVE. These // tasks are associated with slots that were removed as part of a service scale down // or service removal. - if t.DesiredState == api.TaskStateRemove && t.Status.State >= api.TaskStateCompleted { + if t.DesiredState == api.TaskStateRemove && t.Status.State >= api.TaskStateShutdown { tr.cleanup = append(tr.cleanup, t.ID) } case api.EventUpdateCluster: @@ -254,8 +254,6 @@ func (tr *TaskReaper) tick() { // Stop stops the TaskReaper and waits for the main loop to exit. func (tr *TaskReaper) Stop() { tr.cancelWatch() - // TODO(dperny) calling stop on the task reaper twice will cause a panic - // because we try to close a channel that will already have been closed. close(tr.stopChan) <-tr.doneChan } diff --git a/manager/orchestrator/taskreaper/task_reaper_test.go b/manager/orchestrator/taskreaper/task_reaper_test.go deleted file mode 100644 index 5ea9c6d30c..0000000000 --- a/manager/orchestrator/taskreaper/task_reaper_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package taskreaper - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/docker/swarmkit/api" - "github.com/docker/swarmkit/manager/state/store" -) - -// TestTaskReaperInit tests that the task reaper correctly cleans up tasks when -// it is initialized. This will happen every time cluster leadership changes. -func TestTaskReaperInit(t *testing.T) { - // start up the memory store - s := store.NewMemoryStore(nil) - require.NotNil(t, s) - defer s.Close() - - // Create the basic cluster with precooked tasks we need for the taskreaper - cluster := &api.Cluster{ - Spec: api.ClusterSpec{ - Annotations: api.Annotations{ - Name: store.DefaultClusterName, - }, - Orchestration: api.OrchestrationConfig{ - TaskHistoryRetentionLimit: 2, - }, - }, - } - - // this service is alive and active, has no tasks to clean up - service := &api.Service{ - ID: "cleanservice", - Spec: api.ServiceSpec{ - Annotations: api.Annotations{ - Name: "cleanservice", - }, - Task: api.TaskSpec{ - // the runtime spec isn't looked at and doesn't really need to - // be filled in - Runtime: &api.TaskSpec_Container{ - Container: &api.ContainerSpec{}, - }, - }, - Mode: &api.ServiceSpec_Replicated{ - Replicated: &api.ReplicatedService{ - Replicas: 2, - }, - }, - }, - } - - // Two clean tasks, these should not be removed - cleantask1 := &api.Task{ - ID: "cleantask1", - Slot: 1, - DesiredState: api.TaskStateRunning, - Status: api.TaskStatus{ - State: api.TaskStateRunning, - }, - ServiceID: "cleanservice", - } - - cleantask2 := &api.Task{ - ID: "cleantask2", - Slot: 2, - DesiredState: api.TaskStateRunning, - Status: api.TaskStatus{ - State: api.TaskStateRunning, - }, - ServiceID: "cleanservice", - } - - // this is an old task from when an earlier task failed. It should not be - // removed because it's retained history - retainedtask := &api.Task{ - ID: "retainedtask", - Slot: 1, - DesiredState: api.TaskStateShutdown, - Status: api.TaskStatus{ - State: api.TaskStateFailed, - }, - ServiceID: "cleanservice", - } - - // This is a removed task after cleanservice was scaled down - removedtask := &api.Task{ - ID: "removedtask", - Slot: 3, - DesiredState: api.TaskStateRemove, - Status: api.TaskStatus{ - State: api.TaskStateShutdown, - }, - ServiceID: "cleanservice", - } - - // two tasks belonging to a service that does not exist. - // this first one is sitll running and should not be cleaned up - terminaltask1 := &api.Task{ - ID: "terminaltask1", - Slot: 1, - DesiredState: api.TaskStateRemove, - Status: api.TaskStatus{ - State: api.TaskStateRunning, - }, - ServiceID: "goneservice", - } - - // this second task is shutdown, and can be cleaned up - terminaltask2 := &api.Task{ - ID: "terminaltask2", - Slot: 2, - DesiredState: api.TaskStateRemove, - Status: api.TaskStatus{ - // use COMPLETE because it's the earliest terminal state - State: api.TaskStateCompleted, - }, - ServiceID: "goneservice", - } - - err := s.Update(func(tx store.Tx) error { - require.NoError(t, store.CreateCluster(tx, cluster)) - require.NoError(t, store.CreateService(tx, service)) - require.NoError(t, store.CreateTask(tx, cleantask1)) - require.NoError(t, store.CreateTask(tx, cleantask2)) - require.NoError(t, store.CreateTask(tx, retainedtask)) - require.NoError(t, store.CreateTask(tx, removedtask)) - require.NoError(t, store.CreateTask(tx, terminaltask1)) - require.NoError(t, store.CreateTask(tx, terminaltask2)) - return nil - }) - require.NoError(t, err, "Error setting up test fixtures") - - // set up the task reaper we'll use for this test - reaper := New(s) - - // Now, start the reaper - go reaper.Run() - - // And then stop the reaper. This will cause the reaper to run through its - // whole init phase and then immediately enter the loop body, get the stop - // signal, and exit. plus, it will block until that loop body has been - // reached and the reaper is stopped. - reaper.Stop() - - // Now check that all of the tasks are in the state we expect - s.View(func(tx store.ReadTx) { - // the first two clean tasks should exist - assert.NotNil(t, store.GetTask(tx, "cleantask1")) - assert.NotNil(t, store.GetTask(tx, "cleantask1")) - // the retained task should still exist - assert.NotNil(t, store.GetTask(tx, "retainedtask")) - // the removed task should be gone - assert.Nil(t, store.GetTask(tx, "removedtask")) - // the first terminal task, which has not yet shut down, should exist - assert.NotNil(t, store.GetTask(tx, "terminaltask1")) - // and the second terminal task should have been removed - assert.Nil(t, store.GetTask(tx, "terminaltask2")) - }) -} From fc46b107b94e6c8c548a02bee1bcea2026aff884 Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Tue, 13 Mar 2018 16:51:27 +0000 Subject: [PATCH 2/2] Revert "Adding new Task Status REMOVE" This reverts commit 5582db0bfeb6005e24578dc75815ccd8fc96be02. Signed-off-by: Andrew Hsu --- agent/exec/controller.go | 4 +- agent/exec/controller_test.go | 68 -- api/types.pb.go | 606 +++++++++--------- api/types.proto | 11 +- manager/orchestrator/global/global.go | 2 +- manager/orchestrator/global/global_test.go | 2 +- .../replicated/replicated_test.go | 24 +- manager/orchestrator/replicated/services.go | 42 +- .../replicated/task_reaper_test.go | 272 -------- manager/orchestrator/service.go | 25 +- .../orchestrator/taskreaper/task_reaper.go | 69 +- 11 files changed, 337 insertions(+), 788 deletions(-) diff --git a/agent/exec/controller.go b/agent/exec/controller.go index 63d03ddde0..1cafb47fd1 100644 --- a/agent/exec/controller.go +++ b/agent/exec/controller.go @@ -286,9 +286,7 @@ func Do(ctx context.Context, task *api.Task, ctlr Controller) (*api.TaskStatus, status.PortStatus = portStatus }() - // this branch bounds the largest state achievable in the agent as SHUTDOWN, which - // is exactly the correct behavior for the agent. - if task.DesiredState >= api.TaskStateShutdown { + if task.DesiredState == api.TaskStateShutdown { if status.State >= api.TaskStateCompleted { return noop() } diff --git a/agent/exec/controller_test.go b/agent/exec/controller_test.go index 2de4f436f3..7fe9f724f6 100644 --- a/agent/exec/controller_test.go +++ b/agent/exec/controller_test.go @@ -368,74 +368,6 @@ func TestShutdown(t *testing.T) { }) } -// TestDesiredStateRemove checks that the agent maintains SHUTDOWN as the -// maximum state in the agent. This is particularly relevant for the case -// where a service scale down or deletion sets the desired state of tasks -// that are supposed to be removed to REMOVE. -func TestDesiredStateRemove(t *testing.T) { - var ( - task = newTestTask(t, api.TaskStateNew, api.TaskStateRemove) - ctx, ctlr, finish = buildTestEnv(t, task) - ) - defer func() { - finish() - assert.Equal(t, 1, ctlr.calls["Shutdown"]) - }() - ctlr.ShutdownFn = func(_ context.Context) error { - return nil - } - - checkDo(ctx, t, task, ctlr, &api.TaskStatus{ - State: api.TaskStateShutdown, - Message: "shutdown", - }) -} - -// TestDesiredStateRemoveOnlyNonterminal checks that the agent will only stop -// a container on REMOVE if it's not already in a terminal state. If the -// container is already in a terminal state, (like COMPLETE) the agent should -// take no action -func TestDesiredStateRemoveOnlyNonterminal(t *testing.T) { - // go through all terminal states, just for completeness' sake - for _, state := range []api.TaskState{ - api.TaskStateCompleted, - api.TaskStateShutdown, - api.TaskStateFailed, - api.TaskStateRejected, - api.TaskStateRemove, - // no TaskStateOrphaned becaused that's not a state the task can be in - // on the agent - } { - // capture state variable here to run in parallel - state := state - t.Run(state.String(), func(t *testing.T) { - // go parallel to go faster - t.Parallel() - var ( - // create a new task, actual state `state`, desired state - // shutdown - task = newTestTask(t, state, api.TaskStateShutdown) - ctx, ctlr, finish = buildTestEnv(t, task) - ) - // make the shutdown function a noop - ctlr.ShutdownFn = func(_ context.Context) error { - return nil - } - - // Note we check for error ErrTaskNoop, which will be raised - // because nothing happens - checkDo(ctx, t, task, ctlr, &api.TaskStatus{ - State: state, - }, ErrTaskNoop) - defer func() { - finish() - // we should never have called shutdown - assert.Equal(t, 0, ctlr.calls["Shutdown"]) - }() - }) - } -} - // StatuserController is used to create a new Controller, which is also a ContainerStatuser. // We cannot add ContainerStatus() to the Controller, due to the check in controller.go:242 type StatuserController struct { diff --git a/api/types.pb.go b/api/types.pb.go index 7494983f25..7ff65e47ca 100644 --- a/api/types.pb.go +++ b/api/types.pb.go @@ -266,16 +266,7 @@ const ( TaskStateShutdown TaskState = 640 TaskStateFailed TaskState = 704 TaskStateRejected TaskState = 768 - // TaskStateRemove is used to correctly handle service deletions and scale - // downs. This allows us to keep track of tasks that have been marked for - // deletion, but can't yet be removed because the agent is in the process of - // shutting them down. Once the agent has shut down tasks with desired state - // REMOVE, the task reaper is responsible for removing them. - TaskStateRemove TaskState = 800 - // TaskStateOrphaned is used to free up resources associated with service - // tasks on unresponsive nodes without having to delete those tasks. This - // state is directly assigned to the task by the orchestrator. - TaskStateOrphaned TaskState = 832 + TaskStateOrphaned TaskState = 832 ) var TaskState_name = map[int32]string{ @@ -291,7 +282,6 @@ var TaskState_name = map[int32]string{ 640: "SHUTDOWN", 704: "FAILED", 768: "REJECTED", - 800: "REMOVE", 832: "ORPHANED", } var TaskState_value = map[string]int32{ @@ -307,7 +297,6 @@ var TaskState_value = map[string]int32{ "SHUTDOWN": 640, "FAILED": 704, "REJECTED": 768, - "REMOVE": 800, "ORPHANED": 832, } @@ -16256,301 +16245,300 @@ var ( func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 4725 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0x4d, 0x6c, 0x24, 0xd7, - 0x56, 0x76, 0xff, 0xba, 0xfb, 0x74, 0xdb, 0xae, 0xb9, 0xe3, 0x37, 0xf1, 0x74, 0x26, 0x76, 0xa7, - 0x92, 0x79, 0xf9, 0x79, 0xa1, 0x33, 0x3f, 0x49, 0x34, 0x49, 0x78, 0x49, 0xfa, 0xcf, 0xe3, 0x7e, - 0x63, 0x77, 0xb7, 0x6e, 0xb7, 0x67, 0x5e, 0x16, 0x50, 0x2a, 0x57, 0x5d, 0xb7, 0x2b, 0xae, 0xae, - 0xdb, 0x54, 0x55, 0xdb, 0xd3, 0x3c, 0x10, 0x23, 0x16, 0x80, 0xbc, 0x82, 0x15, 0x48, 0xc8, 0x08, - 0x09, 0x56, 0x08, 0x89, 0x05, 0x48, 0x08, 0x36, 0x04, 0x89, 0x45, 0x76, 0x3c, 0x40, 0x42, 0x4f, - 0x20, 0x19, 0xe2, 0x05, 0x3b, 0x04, 0x1b, 0xc4, 0x06, 0x24, 0x74, 0x7f, 0xaa, 0xba, 0xba, 0xa7, - 0x6c, 0x4f, 0xc8, 0xdb, 0xd8, 0x75, 0xcf, 0xf9, 0xce, 0xb9, 0xf7, 0x9e, 0x7b, 0xee, 0xb9, 0xe7, - 0xdc, 0xdb, 0x50, 0xf0, 0x27, 0x23, 0xe2, 0x55, 0x46, 0x2e, 0xf5, 0x29, 0x42, 0x26, 0x35, 0x0e, - 0x89, 0x5b, 0xf1, 0x8e, 0x75, 0x77, 0x78, 0x68, 0xf9, 0x95, 0xa3, 0xbb, 0xa5, 0x8d, 0x01, 0xa5, - 0x03, 0x9b, 0xbc, 0xcb, 0x11, 0x7b, 0xe3, 0xfd, 0x77, 0x7d, 0x6b, 0x48, 0x3c, 0x5f, 0x1f, 0x8e, - 0x84, 0x50, 0x69, 0x7d, 0x1e, 0x60, 0x8e, 0x5d, 0xdd, 0xb7, 0xa8, 0x23, 0xf9, 0xab, 0x03, 0x3a, - 0xa0, 0xfc, 0xf3, 0x5d, 0xf6, 0x25, 0xa8, 0xea, 0x06, 0x2c, 0x3e, 0x26, 0xae, 0x67, 0x51, 0x07, - 0xad, 0x42, 0xc6, 0x72, 0x4c, 0xf2, 0x74, 0x2d, 0x51, 0x4e, 0xbc, 0x99, 0xc6, 0xa2, 0xa1, 0xde, - 0x01, 0x68, 0xb1, 0x8f, 0xa6, 0xe3, 0xbb, 0x13, 0xa4, 0x40, 0xea, 0x90, 0x4c, 0x38, 0x22, 0x8f, - 0xd9, 0x27, 0xa3, 0x1c, 0xe9, 0xf6, 0x5a, 0x52, 0x50, 0x8e, 0x74, 0x5b, 0xfd, 0x3a, 0x01, 0x85, - 0xaa, 0xe3, 0x50, 0x9f, 0xf7, 0xee, 0x21, 0x04, 0x69, 0x47, 0x1f, 0x12, 0x29, 0xc4, 0xbf, 0x51, - 0x1d, 0xb2, 0xb6, 0xbe, 0x47, 0x6c, 0x6f, 0x2d, 0x59, 0x4e, 0xbd, 0x59, 0xb8, 0xf7, 0xbd, 0xca, - 0xf3, 0x53, 0xae, 0x44, 0x94, 0x54, 0xb6, 0x39, 0x9a, 0x0f, 0x02, 0x4b, 0x51, 0xf4, 0x09, 0x2c, - 0x5a, 0x8e, 0x69, 0x19, 0xc4, 0x5b, 0x4b, 0x73, 0x2d, 0xeb, 0x71, 0x5a, 0xa6, 0xa3, 0xaf, 0xa5, - 0xbf, 0x3a, 0xdb, 0x58, 0xc0, 0x81, 0x50, 0xe9, 0x43, 0x28, 0x44, 0xd4, 0xc6, 0xcc, 0x6d, 0x15, - 0x32, 0x47, 0xba, 0x3d, 0x26, 0x72, 0x76, 0xa2, 0xf1, 0x51, 0xf2, 0x41, 0x42, 0xfd, 0x1c, 0xf2, - 0x98, 0x78, 0x74, 0xec, 0x1a, 0xc4, 0x43, 0x6f, 0x41, 0xde, 0xd1, 0x1d, 0xaa, 0x19, 0xa3, 0xb1, - 0xc7, 0xc5, 0x53, 0xb5, 0xe2, 0xf9, 0xd9, 0x46, 0xae, 0xad, 0x3b, 0xb4, 0xde, 0xdd, 0xf5, 0x70, - 0x8e, 0xb1, 0xeb, 0xa3, 0xb1, 0x87, 0x5e, 0x85, 0xe2, 0x90, 0x0c, 0xa9, 0x3b, 0xd1, 0xf6, 0x26, - 0x3e, 0xf1, 0xb8, 0xe2, 0x14, 0x2e, 0x08, 0x5a, 0x8d, 0x91, 0xd4, 0xdf, 0x4c, 0xc0, 0x6a, 0xa0, - 0x1b, 0x93, 0x5f, 0x18, 0x5b, 0x2e, 0x19, 0x12, 0xc7, 0xf7, 0xd0, 0xfb, 0x90, 0xb5, 0xad, 0xa1, - 0xe5, 0x8b, 0x3e, 0x0a, 0xf7, 0x5e, 0x89, 0x9b, 0x6d, 0x38, 0x2a, 0x2c, 0xc1, 0xa8, 0x0a, 0x45, - 0x97, 0x78, 0xc4, 0x3d, 0x12, 0x96, 0xe4, 0x5d, 0x5e, 0x29, 0x3c, 0x23, 0xa2, 0x6e, 0x42, 0xae, - 0x6b, 0xeb, 0xfe, 0x3e, 0x75, 0x87, 0x48, 0x85, 0xa2, 0xee, 0x1a, 0x07, 0x96, 0x4f, 0x0c, 0x7f, - 0xec, 0x06, 0xab, 0x3a, 0x43, 0x43, 0x37, 0x20, 0x49, 0x45, 0x47, 0xf9, 0x5a, 0xf6, 0xfc, 0x6c, - 0x23, 0xd9, 0xe9, 0xe1, 0x24, 0xf5, 0xd4, 0x8f, 0xe1, 0x5a, 0xd7, 0x1e, 0x0f, 0x2c, 0xa7, 0x41, - 0x3c, 0xc3, 0xb5, 0x46, 0x4c, 0x3b, 0x73, 0x0f, 0xe6, 0xfb, 0x81, 0x7b, 0xb0, 0xef, 0xd0, 0x65, - 0x92, 0x53, 0x97, 0x51, 0x7f, 0x3d, 0x09, 0xd7, 0x9a, 0xce, 0xc0, 0x72, 0x48, 0x54, 0xfa, 0x36, - 0x2c, 0x13, 0x4e, 0xd4, 0x8e, 0x84, 0x1b, 0x4b, 0x3d, 0x4b, 0x82, 0x1a, 0xf8, 0x76, 0x6b, 0xce, - 0xdf, 0xee, 0xc6, 0x4d, 0xff, 0x39, 0xed, 0xb1, 0x5e, 0xd7, 0x84, 0xc5, 0x11, 0x9f, 0x84, 0xb7, - 0x96, 0xe2, 0xba, 0x6e, 0xc7, 0xe9, 0x7a, 0x6e, 0x9e, 0x81, 0xf3, 0x49, 0xd9, 0x6f, 0xe3, 0x7c, - 0x7f, 0x9c, 0x84, 0x95, 0x36, 0x35, 0x67, 0xec, 0x50, 0x82, 0xdc, 0x01, 0xf5, 0xfc, 0xc8, 0x46, - 0x0b, 0xdb, 0xe8, 0x01, 0xe4, 0x46, 0x72, 0xf9, 0xe4, 0xea, 0xdf, 0x8a, 0x1f, 0xb2, 0xc0, 0xe0, - 0x10, 0x8d, 0x3e, 0x86, 0xbc, 0x1b, 0xf8, 0xc4, 0x5a, 0xea, 0x45, 0x1c, 0x67, 0x8a, 0x47, 0xdf, - 0x87, 0xac, 0x58, 0x84, 0xb5, 0x34, 0x97, 0xbc, 0xfd, 0x42, 0x36, 0xc7, 0x52, 0x08, 0x3d, 0x84, - 0x9c, 0x6f, 0x7b, 0x9a, 0xe5, 0xec, 0xd3, 0xb5, 0x0c, 0x57, 0xb0, 0x11, 0xa7, 0x80, 0x19, 0xa2, - 0xbf, 0xdd, 0x6b, 0x39, 0xfb, 0xb4, 0x56, 0x38, 0x3f, 0xdb, 0x58, 0x94, 0x0d, 0xbc, 0xe8, 0xdb, - 0x1e, 0xfb, 0x50, 0x7f, 0x2b, 0x01, 0x85, 0x08, 0x0a, 0xbd, 0x02, 0xe0, 0xbb, 0x63, 0xcf, 0xd7, - 0x5c, 0x4a, 0x7d, 0x6e, 0xac, 0x22, 0xce, 0x73, 0x0a, 0xa6, 0xd4, 0x47, 0x15, 0xb8, 0x6e, 0x10, - 0xd7, 0xd7, 0x2c, 0xcf, 0x1b, 0x13, 0x57, 0xf3, 0xc6, 0x7b, 0x5f, 0x10, 0xc3, 0xe7, 0x86, 0x2b, - 0xe2, 0x6b, 0x8c, 0xd5, 0xe2, 0x9c, 0x9e, 0x60, 0xa0, 0xfb, 0x70, 0x23, 0x8a, 0x1f, 0x8d, 0xf7, - 0x6c, 0xcb, 0xd0, 0xd8, 0x62, 0xa6, 0xb8, 0xc8, 0xf5, 0xa9, 0x48, 0x97, 0xf3, 0x1e, 0x91, 0x89, - 0xfa, 0x93, 0x04, 0x28, 0x58, 0xdf, 0xf7, 0x77, 0xc8, 0x70, 0x8f, 0xb8, 0x3d, 0x5f, 0xf7, 0xc7, - 0x1e, 0xba, 0x01, 0x59, 0x9b, 0xe8, 0x26, 0x71, 0xf9, 0xa0, 0x72, 0x58, 0xb6, 0xd0, 0x2e, 0xdb, - 0xc1, 0xba, 0x71, 0xa0, 0xef, 0x59, 0xb6, 0xe5, 0x4f, 0xf8, 0x50, 0x96, 0xe3, 0x5d, 0x78, 0x5e, - 0x67, 0x05, 0x47, 0x04, 0xf1, 0x8c, 0x1a, 0xb4, 0x06, 0x8b, 0x43, 0xe2, 0x79, 0xfa, 0x80, 0xf0, - 0x91, 0xe6, 0x71, 0xd0, 0x54, 0x3f, 0x86, 0x62, 0x54, 0x0e, 0x15, 0x60, 0x71, 0xb7, 0xfd, 0xa8, - 0xdd, 0x79, 0xd2, 0x56, 0x16, 0xd0, 0x0a, 0x14, 0x76, 0xdb, 0xb8, 0x59, 0xad, 0x6f, 0x55, 0x6b, - 0xdb, 0x4d, 0x25, 0x81, 0x96, 0x20, 0x3f, 0x6d, 0x26, 0xd5, 0x3f, 0x4d, 0x00, 0x30, 0x73, 0xcb, - 0x49, 0x7d, 0x04, 0x19, 0xcf, 0xd7, 0x7d, 0xe1, 0x95, 0xcb, 0xf7, 0x5e, 0xbf, 0x68, 0x0d, 0xe5, - 0x78, 0xd9, 0x3f, 0x82, 0x85, 0x48, 0x74, 0x84, 0xc9, 0x99, 0x11, 0xb2, 0x00, 0xa1, 0x9b, 0xa6, - 0x2b, 0x07, 0xce, 0xbf, 0xd5, 0x8f, 0x21, 0xc3, 0xa5, 0x67, 0x87, 0x9b, 0x83, 0x74, 0x83, 0x7d, - 0x25, 0x50, 0x1e, 0x32, 0xb8, 0x59, 0x6d, 0x7c, 0xae, 0x24, 0x91, 0x02, 0xc5, 0x46, 0xab, 0x57, - 0xef, 0xb4, 0xdb, 0xcd, 0x7a, 0xbf, 0xd9, 0x50, 0x52, 0xea, 0x6d, 0xc8, 0xb4, 0x86, 0x4c, 0xf3, - 0x2d, 0xe6, 0xf2, 0xfb, 0xc4, 0x25, 0x8e, 0x11, 0xec, 0xa4, 0x29, 0x41, 0xfd, 0x71, 0x1e, 0x32, - 0x3b, 0x74, 0xec, 0xf8, 0xe8, 0x5e, 0x24, 0x6c, 0x2d, 0xc7, 0x9f, 0x3c, 0x1c, 0x58, 0xe9, 0x4f, - 0x46, 0x44, 0x86, 0xb5, 0x1b, 0x90, 0x15, 0x9b, 0x43, 0x4e, 0x47, 0xb6, 0x18, 0xdd, 0xd7, 0xdd, - 0x01, 0xf1, 0xe5, 0x7c, 0x64, 0x0b, 0xbd, 0x09, 0x39, 0x97, 0xe8, 0x26, 0x75, 0xec, 0x09, 0xdf, - 0x43, 0x39, 0x71, 0xae, 0x60, 0xa2, 0x9b, 0x1d, 0xc7, 0x9e, 0xe0, 0x90, 0x8b, 0xb6, 0xa0, 0xb8, - 0x67, 0x39, 0xa6, 0x46, 0x47, 0x22, 0xc8, 0x67, 0x2e, 0xde, 0x71, 0x62, 0x54, 0x35, 0xcb, 0x31, - 0x3b, 0x02, 0x8c, 0x0b, 0x7b, 0xd3, 0x06, 0x6a, 0xc3, 0xf2, 0x11, 0xb5, 0xc7, 0x43, 0x12, 0xea, - 0xca, 0x72, 0x5d, 0x6f, 0x5c, 0xac, 0xeb, 0x31, 0xc7, 0x07, 0xda, 0x96, 0x8e, 0xa2, 0x4d, 0xf4, - 0x08, 0x96, 0xfc, 0xe1, 0x68, 0xdf, 0x0b, 0xd5, 0x2d, 0x72, 0x75, 0xdf, 0xbd, 0xc4, 0x60, 0x0c, - 0x1e, 0x68, 0x2b, 0xfa, 0x91, 0x56, 0xe9, 0x57, 0x53, 0x50, 0x88, 0x8c, 0x1c, 0xf5, 0xa0, 0x30, - 0x72, 0xe9, 0x48, 0x1f, 0xf0, 0x83, 0x4a, 0xae, 0xc5, 0xdd, 0x17, 0x9a, 0x75, 0xa5, 0x3b, 0x15, - 0xc4, 0x51, 0x2d, 0xea, 0x69, 0x12, 0x0a, 0x11, 0x26, 0x7a, 0x1b, 0x72, 0xb8, 0x8b, 0x5b, 0x8f, - 0xab, 0xfd, 0xa6, 0xb2, 0x50, 0xba, 0x75, 0x72, 0x5a, 0x5e, 0xe3, 0xda, 0xa2, 0x0a, 0xba, 0xae, - 0x75, 0xc4, 0x5c, 0xef, 0x4d, 0x58, 0x0c, 0xa0, 0x89, 0xd2, 0xcb, 0x27, 0xa7, 0xe5, 0x97, 0xe6, - 0xa1, 0x11, 0x24, 0xee, 0x6d, 0x55, 0x71, 0xb3, 0xa1, 0x24, 0xe3, 0x91, 0xb8, 0x77, 0xa0, 0xbb, - 0xc4, 0x44, 0xdf, 0x85, 0xac, 0x04, 0xa6, 0x4a, 0xa5, 0x93, 0xd3, 0xf2, 0x8d, 0x79, 0xe0, 0x14, - 0x87, 0x7b, 0xdb, 0xd5, 0xc7, 0x4d, 0x25, 0x1d, 0x8f, 0xc3, 0x3d, 0x5b, 0x3f, 0x22, 0xe8, 0x75, - 0xc8, 0x08, 0x58, 0xa6, 0x74, 0xf3, 0xe4, 0xb4, 0xfc, 0x9d, 0xe7, 0xd4, 0x31, 0x54, 0x69, 0xed, - 0x37, 0xfe, 0x60, 0x7d, 0xe1, 0x2f, 0xff, 0x70, 0x5d, 0x99, 0x67, 0x97, 0xfe, 0x27, 0x01, 0x4b, - 0x33, 0x4b, 0x8e, 0x54, 0xc8, 0x3a, 0xd4, 0xa0, 0x23, 0x71, 0x7e, 0xe5, 0x6a, 0x70, 0x7e, 0xb6, - 0x91, 0x6d, 0xd3, 0x3a, 0x1d, 0x4d, 0xb0, 0xe4, 0xa0, 0x47, 0x73, 0x27, 0xf0, 0xfd, 0x17, 0xf4, - 0xa7, 0xd8, 0x33, 0xf8, 0x53, 0x58, 0x32, 0x5d, 0xeb, 0x88, 0xb8, 0x9a, 0x41, 0x9d, 0x7d, 0x6b, - 0x20, 0xcf, 0xa6, 0x52, 0x9c, 0xce, 0x06, 0x07, 0xe2, 0xa2, 0x10, 0xa8, 0x73, 0xfc, 0xb7, 0x38, - 0x7d, 0x4b, 0x8f, 0xa1, 0x18, 0xf5, 0x50, 0x76, 0x9c, 0x78, 0xd6, 0x2f, 0x12, 0x99, 0xd0, 0xf1, - 0xf4, 0x0f, 0xe7, 0x19, 0x85, 0xa7, 0x73, 0xe8, 0x0d, 0x48, 0x0f, 0xa9, 0x29, 0xf4, 0x2c, 0xd5, - 0xae, 0xb3, 0x24, 0xe0, 0x9f, 0xce, 0x36, 0x0a, 0xd4, 0xab, 0x6c, 0x5a, 0x36, 0xd9, 0xa1, 0x26, - 0xc1, 0x1c, 0xa0, 0x1e, 0x41, 0x9a, 0x85, 0x0a, 0xf4, 0x32, 0xa4, 0x6b, 0xad, 0x76, 0x43, 0x59, - 0x28, 0x5d, 0x3b, 0x39, 0x2d, 0x2f, 0x71, 0x93, 0x30, 0x06, 0xf3, 0x5d, 0xb4, 0x01, 0xd9, 0xc7, - 0x9d, 0xed, 0xdd, 0x1d, 0xe6, 0x5e, 0xd7, 0x4f, 0x4e, 0xcb, 0x2b, 0x21, 0x5b, 0x18, 0x0d, 0xbd, - 0x02, 0x99, 0xfe, 0x4e, 0x77, 0xb3, 0xa7, 0x24, 0x4b, 0xe8, 0xe4, 0xb4, 0xbc, 0x1c, 0xf2, 0xf9, - 0x98, 0x4b, 0xd7, 0xe4, 0xaa, 0xe6, 0x43, 0xba, 0xfa, 0x5f, 0x49, 0x58, 0xc2, 0xac, 0x92, 0x70, - 0xfd, 0x2e, 0xb5, 0x2d, 0x63, 0x82, 0xba, 0x90, 0x37, 0xa8, 0x63, 0x5a, 0x91, 0x3d, 0x75, 0xef, - 0x82, 0x53, 0x7f, 0x2a, 0x15, 0xb4, 0xea, 0x81, 0x24, 0x9e, 0x2a, 0x41, 0xef, 0x42, 0xc6, 0x24, - 0xb6, 0x3e, 0x91, 0xe9, 0xc7, 0xcd, 0x8a, 0xa8, 0x55, 0x2a, 0x41, 0xad, 0x52, 0x69, 0xc8, 0x5a, - 0x05, 0x0b, 0x1c, 0xcf, 0x93, 0xf5, 0xa7, 0x9a, 0xee, 0xfb, 0x64, 0x38, 0xf2, 0x45, 0xee, 0x91, - 0xc6, 0x85, 0xa1, 0xfe, 0xb4, 0x2a, 0x49, 0xe8, 0x2e, 0x64, 0x8f, 0x2d, 0xc7, 0xa4, 0xc7, 0x32, - 0xbd, 0xb8, 0x44, 0xa9, 0x04, 0xaa, 0x27, 0xec, 0xd4, 0x9d, 0x1b, 0x26, 0xb3, 0x77, 0xbb, 0xd3, - 0x6e, 0x06, 0xf6, 0x96, 0xfc, 0x8e, 0xd3, 0xa6, 0x0e, 0xdb, 0x2b, 0xd0, 0x69, 0x6b, 0x9b, 0xd5, - 0xd6, 0xf6, 0x2e, 0x66, 0x36, 0x5f, 0x3d, 0x39, 0x2d, 0x2b, 0x21, 0x64, 0x53, 0xb7, 0x6c, 0x96, - 0xef, 0xde, 0x84, 0x54, 0xb5, 0xfd, 0xb9, 0x92, 0x2c, 0x29, 0x27, 0xa7, 0xe5, 0x62, 0xc8, 0xae, - 0x3a, 0x93, 0xe9, 0x36, 0x9a, 0xef, 0x57, 0xfd, 0xdb, 0x14, 0x14, 0x77, 0x47, 0xa6, 0xee, 0x13, - 0xe1, 0x93, 0xa8, 0x0c, 0x85, 0x91, 0xee, 0xea, 0xb6, 0x4d, 0x6c, 0xcb, 0x1b, 0xca, 0x2a, 0x2c, - 0x4a, 0x42, 0x1f, 0xbe, 0xa8, 0x19, 0x6b, 0x39, 0xe6, 0x67, 0xbf, 0xf3, 0x2f, 0x1b, 0x89, 0xc0, - 0xa0, 0xbb, 0xb0, 0xbc, 0x2f, 0x46, 0xab, 0xe9, 0x06, 0x5f, 0xd8, 0x14, 0x5f, 0xd8, 0x4a, 0xdc, - 0xc2, 0x46, 0x87, 0x55, 0x91, 0x93, 0xac, 0x72, 0x29, 0xbc, 0xb4, 0x1f, 0x6d, 0xa2, 0xfb, 0xb0, - 0x38, 0xa4, 0x8e, 0xe5, 0x53, 0xf7, 0xea, 0x55, 0x08, 0x90, 0xe8, 0x6d, 0xb8, 0xc6, 0x16, 0x37, - 0x18, 0x0f, 0x67, 0xf3, 0x13, 0x2b, 0x89, 0x57, 0x86, 0xfa, 0x53, 0xd9, 0x21, 0x66, 0x64, 0x54, - 0x83, 0x0c, 0x75, 0x59, 0x4a, 0x94, 0xe5, 0xc3, 0x7d, 0xe7, 0xca, 0xe1, 0x8a, 0x46, 0x87, 0xc9, - 0x60, 0x21, 0xaa, 0x7e, 0x00, 0x4b, 0x33, 0x93, 0x60, 0x99, 0x40, 0xb7, 0xba, 0xdb, 0x6b, 0x2a, - 0x0b, 0xa8, 0x08, 0xb9, 0x7a, 0xa7, 0xdd, 0x6f, 0xb5, 0x77, 0x59, 0x2a, 0x53, 0x84, 0x1c, 0xee, - 0x6c, 0x6f, 0xd7, 0xaa, 0xf5, 0x47, 0x4a, 0x52, 0xad, 0x40, 0x21, 0xa2, 0x0d, 0x2d, 0x03, 0xf4, - 0xfa, 0x9d, 0xae, 0xb6, 0xd9, 0xc2, 0xbd, 0xbe, 0x48, 0x84, 0x7a, 0xfd, 0x2a, 0xee, 0x4b, 0x42, - 0x42, 0xfd, 0x8f, 0x64, 0xb0, 0xa2, 0x32, 0xf7, 0xa9, 0xcd, 0xe6, 0x3e, 0x97, 0x0c, 0x5e, 0x66, - 0x3f, 0xd3, 0x46, 0x98, 0x03, 0x7d, 0x08, 0xc0, 0x1d, 0x87, 0x98, 0x9a, 0xee, 0xcb, 0x85, 0x2f, - 0x3d, 0x67, 0xe4, 0x7e, 0x70, 0x19, 0x80, 0xf3, 0x12, 0x5d, 0xf5, 0xd1, 0xf7, 0xa1, 0x68, 0xd0, - 0xe1, 0xc8, 0x26, 0x52, 0x38, 0x75, 0xa5, 0x70, 0x21, 0xc4, 0x57, 0xfd, 0x68, 0xf6, 0x95, 0x9e, - 0xcd, 0x0f, 0x7f, 0x2d, 0x11, 0x58, 0x26, 0x26, 0xe1, 0x2a, 0x42, 0x6e, 0xb7, 0xdb, 0xa8, 0xf6, - 0x5b, 0xed, 0x87, 0x4a, 0x02, 0x01, 0x64, 0xb9, 0xa9, 0x1b, 0x4a, 0x92, 0x25, 0x8a, 0xf5, 0xce, - 0x4e, 0x77, 0xbb, 0xc9, 0x53, 0x2e, 0xb4, 0x0a, 0x4a, 0x60, 0x6c, 0x8d, 0x1b, 0xb2, 0xd9, 0x50, - 0xd2, 0xe8, 0x3a, 0xac, 0x84, 0x54, 0x29, 0x99, 0x41, 0x37, 0x00, 0x85, 0xc4, 0xa9, 0x8a, 0xac, - 0xfa, 0xcb, 0xb0, 0x52, 0xa7, 0x8e, 0xaf, 0x5b, 0x4e, 0x98, 0x44, 0xdf, 0x63, 0x93, 0x96, 0x24, - 0xcd, 0x32, 0x45, 0x4c, 0xaf, 0xad, 0x9c, 0x9f, 0x6d, 0x14, 0x42, 0x68, 0xab, 0xc1, 0x66, 0x1a, - 0x34, 0x4c, 0xb6, 0x7f, 0x47, 0x96, 0xc9, 0x8d, 0x9b, 0xa9, 0x2d, 0x9e, 0x9f, 0x6d, 0xa4, 0xba, - 0xad, 0x06, 0x66, 0x34, 0xf4, 0x32, 0xe4, 0xc9, 0x53, 0xcb, 0xd7, 0x0c, 0x16, 0xc3, 0x99, 0x01, - 0x33, 0x38, 0xc7, 0x08, 0x75, 0x16, 0xb2, 0x6b, 0x00, 0x5d, 0xea, 0xfa, 0xb2, 0xe7, 0xf7, 0x20, - 0x33, 0xa2, 0x2e, 0x2f, 0xcf, 0x2f, 0xbc, 0x8c, 0x60, 0x70, 0xe1, 0xa8, 0x58, 0x80, 0xd5, 0xbf, - 0x4a, 0x02, 0xf4, 0x75, 0xef, 0x50, 0x2a, 0x79, 0x00, 0xf9, 0xf0, 0x62, 0x47, 0xd6, 0xf9, 0x97, - 0xae, 0x76, 0x08, 0x46, 0xf7, 0x03, 0x67, 0x13, 0xe5, 0x41, 0x6c, 0x9d, 0x16, 0x74, 0x14, 0x97, - 0x61, 0xcf, 0xd6, 0x00, 0xec, 0x48, 0x24, 0xae, 0x2b, 0x57, 0x9e, 0x7d, 0xa2, 0x3a, 0x3f, 0x16, - 0x84, 0xd1, 0x64, 0x82, 0xf9, 0x5a, 0x5c, 0x27, 0x73, 0x2b, 0xb2, 0xb5, 0x80, 0xa7, 0x72, 0xe8, - 0x53, 0x28, 0xb0, 0x79, 0x6b, 0x1e, 0xe7, 0xc9, 0xdc, 0xf2, 0x42, 0x53, 0x09, 0x0d, 0x18, 0x46, - 0xe1, 0x77, 0x4d, 0x81, 0x65, 0x77, 0xec, 0xb0, 0x69, 0x4b, 0x1d, 0xea, 0x9f, 0x24, 0xe1, 0xa5, - 0x36, 0xf1, 0x8f, 0xa9, 0x7b, 0x58, 0xf5, 0x7d, 0xdd, 0x38, 0x18, 0x12, 0x47, 0x1a, 0x39, 0x92, - 0x59, 0x27, 0x66, 0x32, 0xeb, 0x35, 0x58, 0xd4, 0x6d, 0x4b, 0xf7, 0x88, 0x48, 0x47, 0xf2, 0x38, - 0x68, 0xb2, 0xfc, 0x9f, 0x55, 0x13, 0xc4, 0xf3, 0x88, 0x28, 0xf0, 0xf3, 0x78, 0x4a, 0x40, 0x3f, - 0x82, 0x1b, 0x32, 0xf1, 0xd0, 0xc3, 0xae, 0x58, 0x66, 0x1b, 0xdc, 0x40, 0x35, 0x63, 0xcb, 0x9b, - 0xf8, 0xc1, 0xc9, 0xcc, 0x64, 0x4a, 0xee, 0x8c, 0x7c, 0x99, 0xe7, 0xac, 0x9a, 0x31, 0xac, 0xd2, - 0x43, 0xb8, 0x79, 0xa1, 0xc8, 0x37, 0xba, 0x40, 0xf8, 0x87, 0x24, 0x40, 0xab, 0x5b, 0xdd, 0x91, - 0x46, 0x6a, 0x40, 0x76, 0x5f, 0x1f, 0x5a, 0xf6, 0xe4, 0xb2, 0x38, 0x35, 0xc5, 0x57, 0xaa, 0xc2, - 0x1c, 0x9b, 0x5c, 0x06, 0x4b, 0x59, 0x5e, 0xdc, 0x8c, 0xf7, 0x1c, 0xe2, 0x87, 0xc5, 0x0d, 0x6f, - 0xb1, 0x61, 0xb8, 0xba, 0x13, 0x3a, 0x98, 0x68, 0xb0, 0x05, 0x18, 0xe8, 0x3e, 0x39, 0xd6, 0x27, - 0x41, 0x70, 0x91, 0x4d, 0xb4, 0xc5, 0x8a, 0x1e, 0x8f, 0xb8, 0x47, 0xc4, 0x5c, 0xcb, 0x70, 0xa3, - 0x5e, 0x35, 0x1e, 0x2c, 0xe1, 0xc2, 0x76, 0xa1, 0x74, 0xe9, 0x63, 0x9e, 0xd8, 0x4c, 0x59, 0xdf, - 0xc8, 0x46, 0x77, 0x60, 0x69, 0x66, 0x9e, 0xcf, 0x55, 0x95, 0xad, 0xee, 0xe3, 0xf7, 0x94, 0xb4, - 0xfc, 0xfa, 0x40, 0xc9, 0xaa, 0x7f, 0x94, 0x12, 0xe1, 0x40, 0x5a, 0x35, 0xfe, 0xda, 0x33, 0xc7, - 0x37, 0xb1, 0x41, 0x6d, 0xb9, 0x4d, 0xdf, 0xb8, 0x3c, 0x4a, 0xb0, 0x2a, 0x85, 0xc3, 0x71, 0x28, - 0x88, 0x36, 0xa0, 0x20, 0xbc, 0x58, 0x63, 0xdb, 0x82, 0x9b, 0x75, 0x09, 0x83, 0x20, 0x31, 0x49, - 0x74, 0x1b, 0x96, 0xf9, 0x2d, 0x84, 0x77, 0x40, 0x4c, 0x81, 0x49, 0x73, 0xcc, 0x52, 0x48, 0xe5, - 0xb0, 0x1d, 0x28, 0x4a, 0x82, 0xc6, 0x33, 0xd4, 0x0c, 0x1f, 0xd0, 0xdb, 0x57, 0x0d, 0x48, 0x88, - 0xf0, 0xc4, 0xb5, 0x30, 0x9a, 0x36, 0xd4, 0x06, 0xe4, 0x82, 0xc1, 0xa2, 0x35, 0x48, 0xf5, 0xeb, - 0x5d, 0x65, 0xa1, 0xb4, 0x72, 0x72, 0x5a, 0x2e, 0x04, 0xe4, 0x7e, 0xbd, 0xcb, 0x38, 0xbb, 0x8d, - 0xae, 0x92, 0x98, 0xe5, 0xec, 0x36, 0xba, 0xa5, 0x34, 0xcb, 0x94, 0xd4, 0x7d, 0x28, 0x44, 0x7a, - 0x40, 0xaf, 0xc1, 0x62, 0xab, 0xfd, 0x10, 0x37, 0x7b, 0x3d, 0x65, 0xa1, 0x74, 0xe3, 0xe4, 0xb4, - 0x8c, 0x22, 0xdc, 0x96, 0x33, 0x60, 0xeb, 0x83, 0x5e, 0x81, 0xf4, 0x56, 0x87, 0x9d, 0xc0, 0x22, - 0x25, 0x8e, 0x20, 0xb6, 0xa8, 0xe7, 0x97, 0xae, 0xcb, 0x14, 0x2c, 0xaa, 0x58, 0xfd, 0xdd, 0x04, - 0x64, 0xc5, 0x66, 0x8a, 0x5d, 0xa8, 0x2a, 0x2c, 0x06, 0xf5, 0xaa, 0x28, 0x57, 0xde, 0xb8, 0xb8, - 0xb4, 0xa8, 0xc8, 0x4a, 0x40, 0xb8, 0x5f, 0x20, 0x57, 0xfa, 0x08, 0x8a, 0x51, 0xc6, 0x37, 0x72, - 0xbe, 0x1f, 0x41, 0x81, 0xf9, 0x77, 0x50, 0x62, 0xdc, 0x83, 0xac, 0x08, 0x08, 0xe1, 0x89, 0x70, - 0x71, 0x9d, 0x23, 0x91, 0xe8, 0x01, 0x2c, 0x8a, 0xda, 0x28, 0xb8, 0xa6, 0x5c, 0xbf, 0x7c, 0x17, - 0xe1, 0x00, 0xae, 0x7e, 0x0a, 0xe9, 0x2e, 0x21, 0x2e, 0xb3, 0xbd, 0x43, 0x4d, 0x32, 0x3d, 0x44, - 0x65, 0x59, 0x67, 0x92, 0x56, 0x83, 0x95, 0x75, 0x26, 0x69, 0x99, 0xe1, 0x45, 0x4c, 0x32, 0x72, - 0x11, 0xd3, 0x87, 0xe2, 0x13, 0x62, 0x0d, 0x0e, 0x7c, 0x62, 0x72, 0x45, 0xef, 0x40, 0x7a, 0x44, - 0xc2, 0xc1, 0xaf, 0xc5, 0x3a, 0x18, 0x21, 0x2e, 0xe6, 0x28, 0x16, 0x47, 0x8e, 0xb9, 0xb4, 0xbc, - 0x1c, 0x97, 0x2d, 0xf5, 0xef, 0x93, 0xb0, 0xdc, 0xf2, 0xbc, 0xb1, 0xee, 0x18, 0x41, 0x7e, 0xf5, - 0xc9, 0x6c, 0x7e, 0xf5, 0x66, 0xec, 0x0c, 0x67, 0x44, 0x66, 0xef, 0x97, 0xe4, 0x19, 0x97, 0x0c, - 0xcf, 0x38, 0xf5, 0xdf, 0x13, 0xc1, 0x25, 0xd2, 0xed, 0xc8, 0x76, 0x2f, 0xad, 0x9d, 0x9c, 0x96, - 0x57, 0xa3, 0x9a, 0xc8, 0xae, 0x73, 0xe8, 0xd0, 0x63, 0x07, 0xbd, 0x0a, 0x19, 0xdc, 0x6c, 0x37, - 0x9f, 0x28, 0x09, 0xe1, 0x9e, 0x33, 0x20, 0x4c, 0x1c, 0x72, 0xcc, 0x34, 0x75, 0x9b, 0xed, 0x06, - 0xcb, 0x87, 0x92, 0x31, 0x9a, 0xba, 0xc4, 0x31, 0x2d, 0x67, 0x80, 0x5e, 0x83, 0x6c, 0xab, 0xd7, - 0xdb, 0xe5, 0x65, 0xfe, 0x4b, 0x27, 0xa7, 0xe5, 0xeb, 0x33, 0x28, 0x7e, 0x81, 0x68, 0x32, 0x10, - 0x2b, 0x46, 0x58, 0xa6, 0x14, 0x03, 0x62, 0x59, 0xae, 0x00, 0xe1, 0x4e, 0xbf, 0xda, 0x67, 0x15, - 0xfe, 0xf3, 0x20, 0x4c, 0xd9, 0x5f, 0xb9, 0xdd, 0xfe, 0x39, 0x09, 0x4a, 0xd5, 0x30, 0xc8, 0xc8, - 0x67, 0x7c, 0x59, 0xff, 0xf5, 0x21, 0x37, 0x62, 0x5f, 0x16, 0x09, 0x72, 0x99, 0x07, 0xb1, 0xcf, - 0x33, 0x73, 0x72, 0x15, 0x4c, 0x6d, 0x52, 0x35, 0x87, 0x96, 0xe7, 0x59, 0xd4, 0x11, 0x34, 0x1c, - 0x6a, 0x2a, 0xfd, 0x67, 0x02, 0xae, 0xc7, 0x20, 0xd0, 0x1d, 0x48, 0xbb, 0xd4, 0x0e, 0xd6, 0xf0, - 0xd6, 0x45, 0xf7, 0x83, 0x4c, 0x14, 0x73, 0x24, 0x5a, 0x07, 0xd0, 0xc7, 0x3e, 0xd5, 0x79, 0xff, - 0x7c, 0xf5, 0x72, 0x38, 0x42, 0x41, 0x4f, 0x20, 0xeb, 0x11, 0xc3, 0x25, 0x41, 0xc6, 0xfb, 0xe9, - 0xff, 0x77, 0xf4, 0x95, 0x1e, 0x57, 0x83, 0xa5, 0xba, 0x52, 0x05, 0xb2, 0x82, 0xc2, 0xdc, 0xde, - 0xd4, 0x7d, 0x5d, 0xde, 0x1e, 0xf3, 0x6f, 0xe6, 0x4d, 0xba, 0x3d, 0x08, 0xbc, 0x49, 0xb7, 0x07, - 0xea, 0xdf, 0x24, 0x01, 0x9a, 0x4f, 0x7d, 0xe2, 0x3a, 0xba, 0x5d, 0xaf, 0xa2, 0x66, 0x24, 0xfa, - 0x8b, 0xd9, 0xbe, 0x15, 0x7b, 0x25, 0x1e, 0x4a, 0x54, 0xea, 0xd5, 0x98, 0xf8, 0x7f, 0x13, 0x52, - 0x63, 0x57, 0xbe, 0xb8, 0x89, 0x6c, 0x75, 0x17, 0x6f, 0x63, 0x46, 0x43, 0xcd, 0x69, 0xd8, 0x4a, - 0x5d, 0xfc, 0xae, 0x16, 0xe9, 0x20, 0x36, 0x74, 0xb1, 0x9d, 0x6f, 0xe8, 0x9a, 0x41, 0xe4, 0xc9, - 0x51, 0x14, 0x3b, 0xbf, 0x5e, 0xad, 0x13, 0xd7, 0xc7, 0x59, 0x43, 0x67, 0xff, 0xbf, 0x55, 0x7c, - 0x7b, 0x07, 0x60, 0x3a, 0x35, 0xb4, 0x0e, 0x99, 0xfa, 0x66, 0xaf, 0xb7, 0xad, 0x2c, 0x88, 0x00, - 0x3e, 0x65, 0x71, 0xb2, 0xfa, 0x17, 0x49, 0xc8, 0xd5, 0xab, 0xf2, 0x58, 0xad, 0x83, 0xc2, 0xa3, - 0x12, 0xbf, 0x73, 0x27, 0x4f, 0x47, 0x96, 0x3b, 0x91, 0x81, 0xe5, 0x92, 0xd2, 0x73, 0x99, 0x89, - 0xb0, 0x51, 0x37, 0xb9, 0x00, 0xc2, 0x50, 0x24, 0xd2, 0x08, 0x9a, 0xa1, 0x07, 0x31, 0x7e, 0xfd, - 0x72, 0x63, 0x89, 0x22, 0x62, 0xda, 0xf6, 0x70, 0x21, 0x50, 0x52, 0xd7, 0x3d, 0xf4, 0x21, 0xac, - 0x78, 0xd6, 0xc0, 0xb1, 0x9c, 0x81, 0x16, 0x18, 0x8f, 0x3f, 0x00, 0xd4, 0xae, 0x9d, 0x9f, 0x6d, - 0x2c, 0xf5, 0x04, 0x4b, 0xda, 0x70, 0x49, 0x22, 0xeb, 0xdc, 0x94, 0xe8, 0x03, 0x58, 0x8e, 0x88, - 0x32, 0x2b, 0x0a, 0xb3, 0x2b, 0xe7, 0x67, 0x1b, 0xc5, 0x50, 0xf2, 0x11, 0x99, 0xe0, 0x62, 0x28, - 0xf8, 0x88, 0xf0, 0x5b, 0x92, 0x7d, 0xea, 0x1a, 0x44, 0x73, 0xf9, 0x9e, 0xe6, 0x27, 0x78, 0x1a, - 0x17, 0x38, 0x4d, 0x6c, 0x73, 0xf5, 0x31, 0x5c, 0xef, 0xb8, 0xc6, 0x01, 0xf1, 0x7c, 0x61, 0x0a, - 0x69, 0xc5, 0x4f, 0xe1, 0x96, 0xaf, 0x7b, 0x87, 0xda, 0x81, 0xe5, 0xf9, 0xd4, 0x9d, 0x68, 0x2e, - 0xf1, 0x89, 0xc3, 0xf8, 0x1a, 0x7f, 0x35, 0x94, 0xd7, 0x58, 0x37, 0x19, 0x66, 0x4b, 0x40, 0x70, - 0x80, 0xd8, 0x66, 0x00, 0xb5, 0x05, 0x45, 0x56, 0x4c, 0x34, 0xc8, 0xbe, 0x3e, 0xb6, 0x7d, 0x36, - 0x7b, 0xb0, 0xe9, 0x40, 0x7b, 0xe1, 0x63, 0x2a, 0x6f, 0xd3, 0x81, 0xf8, 0x54, 0x7f, 0x08, 0x4a, - 0xc3, 0xf2, 0x46, 0xba, 0x6f, 0x1c, 0x04, 0xf7, 0x73, 0xa8, 0x01, 0xca, 0x01, 0xd1, 0x5d, 0x7f, - 0x8f, 0xe8, 0xbe, 0x36, 0x22, 0xae, 0x45, 0xcd, 0xab, 0x57, 0x79, 0x25, 0x14, 0xe9, 0x72, 0x09, - 0xf5, 0xbf, 0x13, 0x00, 0x58, 0xdf, 0x0f, 0x32, 0xb2, 0xef, 0xc1, 0x35, 0xcf, 0xd1, 0x47, 0xde, - 0x01, 0xf5, 0x35, 0xcb, 0xf1, 0x89, 0x7b, 0xa4, 0xdb, 0xf2, 0x9a, 0x45, 0x09, 0x18, 0x2d, 0x49, - 0x47, 0xef, 0x00, 0x3a, 0x24, 0x64, 0xa4, 0x51, 0xdb, 0xd4, 0x02, 0xa6, 0x78, 0xd3, 0x4c, 0x63, - 0x85, 0x71, 0x3a, 0xb6, 0xd9, 0x0b, 0xe8, 0xa8, 0x06, 0xeb, 0x6c, 0xfa, 0xc4, 0xf1, 0x5d, 0x8b, - 0x78, 0xda, 0x3e, 0x75, 0x35, 0xcf, 0xa6, 0xc7, 0xda, 0x3e, 0xb5, 0x6d, 0x7a, 0x4c, 0xdc, 0xe0, - 0x06, 0xab, 0x64, 0xd3, 0x41, 0x53, 0x80, 0x36, 0xa9, 0xdb, 0xb3, 0xe9, 0xf1, 0x66, 0x80, 0x60, - 0x69, 0xdb, 0x74, 0xce, 0xbe, 0x65, 0x1c, 0x06, 0x69, 0x5b, 0x48, 0xed, 0x5b, 0xc6, 0x21, 0x7a, - 0x0d, 0x96, 0x88, 0x4d, 0xf8, 0x45, 0x86, 0x40, 0x65, 0x38, 0xaa, 0x18, 0x10, 0x19, 0x48, 0xfd, - 0x0c, 0x94, 0xa6, 0x63, 0xb8, 0x93, 0x51, 0x64, 0xcd, 0xdf, 0x01, 0xc4, 0x82, 0xa4, 0x66, 0x53, - 0xe3, 0x50, 0x1b, 0xea, 0x8e, 0x3e, 0x60, 0xe3, 0x12, 0x4f, 0x4d, 0x0a, 0xe3, 0x6c, 0x53, 0xe3, - 0x70, 0x47, 0xd2, 0xd5, 0x0f, 0x01, 0x7a, 0x23, 0x97, 0xe8, 0x66, 0x87, 0x65, 0x13, 0xcc, 0x74, - 0xbc, 0xa5, 0x99, 0xf2, 0xa9, 0x8e, 0xba, 0x72, 0xab, 0x2b, 0x82, 0xd1, 0x08, 0xe9, 0xea, 0xcf, - 0xc1, 0xf5, 0xae, 0xad, 0x1b, 0xfc, 0xd9, 0xba, 0x1b, 0xbe, 0x9d, 0xa0, 0x07, 0x90, 0x15, 0x50, - 0xb9, 0x92, 0xb1, 0xdb, 0x6d, 0xda, 0xe7, 0xd6, 0x02, 0x96, 0xf8, 0x5a, 0x11, 0x60, 0xaa, 0x47, - 0xfd, 0xb3, 0x04, 0xe4, 0x43, 0xfd, 0xa8, 0x0c, 0xac, 0x94, 0x67, 0xee, 0x6d, 0x39, 0xb2, 0xf6, - 0xce, 0xe3, 0x28, 0x09, 0xb5, 0xa0, 0x30, 0x0a, 0xa5, 0x2f, 0xcd, 0xe7, 0x62, 0x46, 0x8d, 0xa3, - 0xb2, 0xe8, 0x23, 0xc8, 0x07, 0x6f, 0xa3, 0x41, 0x84, 0xbd, 0xfc, 0x29, 0x75, 0x0a, 0x57, 0x3f, - 0x01, 0xf8, 0x01, 0xb5, 0x9c, 0x3e, 0x3d, 0x24, 0x0e, 0x7f, 0xeb, 0x63, 0x35, 0x21, 0x09, 0xac, - 0x28, 0x5b, 0xbc, 0x20, 0x17, 0x4b, 0x10, 0x3e, 0x79, 0x89, 0xa6, 0xfa, 0xd7, 0x49, 0xc8, 0x62, - 0x4a, 0xfd, 0x7a, 0x15, 0x95, 0x21, 0x2b, 0xe3, 0x04, 0x3f, 0x7f, 0x6a, 0xf9, 0xf3, 0xb3, 0x8d, - 0x8c, 0x08, 0x10, 0x19, 0x83, 0x47, 0x86, 0x48, 0x04, 0x4f, 0x5e, 0x14, 0xc1, 0xd1, 0x1d, 0x28, - 0x4a, 0x90, 0x76, 0xa0, 0x7b, 0x07, 0xa2, 0x40, 0xab, 0x2d, 0x9f, 0x9f, 0x6d, 0x80, 0x40, 0x6e, - 0xe9, 0xde, 0x01, 0x06, 0x81, 0x66, 0xdf, 0xa8, 0x09, 0x85, 0x2f, 0xa8, 0xe5, 0x68, 0x3e, 0x9f, - 0x84, 0xbc, 0xf2, 0x8b, 0x5d, 0xc7, 0xe9, 0x54, 0xe5, 0xc3, 0x37, 0x7c, 0x31, 0x9d, 0x7c, 0x13, - 0x96, 0x5c, 0x4a, 0x7d, 0x11, 0xb6, 0x2c, 0xea, 0xc8, 0xdb, 0x84, 0x72, 0xec, 0x25, 0x33, 0xa5, - 0x3e, 0x96, 0x38, 0x5c, 0x74, 0x23, 0x2d, 0x74, 0x07, 0x56, 0x6d, 0xdd, 0xf3, 0x35, 0x1e, 0xef, - 0xcc, 0xa9, 0xb6, 0x2c, 0xdf, 0x6a, 0x88, 0xf1, 0x36, 0x39, 0x2b, 0x90, 0x50, 0xff, 0x31, 0x01, - 0x05, 0x36, 0x19, 0x6b, 0xdf, 0x32, 0x58, 0x92, 0xf7, 0xcd, 0x73, 0x8f, 0x9b, 0x90, 0x32, 0x3c, - 0x57, 0x1a, 0x95, 0x1f, 0xbe, 0xf5, 0x1e, 0xc6, 0x8c, 0x86, 0x3e, 0x83, 0xac, 0xbc, 0xd5, 0x10, - 0x69, 0x87, 0x7a, 0x75, 0x3a, 0x2a, 0x6d, 0x23, 0xe5, 0xb8, 0x2f, 0x4f, 0x47, 0x27, 0x0e, 0x01, - 0x1c, 0x25, 0xa1, 0x1b, 0x90, 0x34, 0x84, 0xb9, 0xe4, 0x2f, 0x2b, 0xea, 0x6d, 0x9c, 0x34, 0x1c, - 0xf5, 0xef, 0x12, 0xb0, 0x34, 0xdd, 0xf0, 0xcc, 0x03, 0x6e, 0x41, 0xde, 0x1b, 0xef, 0x79, 0x13, - 0xcf, 0x27, 0xc3, 0xe0, 0x1d, 0x33, 0x24, 0xa0, 0x16, 0xe4, 0x75, 0x7b, 0x40, 0x5d, 0xcb, 0x3f, - 0x18, 0xca, 0x4a, 0x34, 0x3e, 0x55, 0x88, 0xea, 0xac, 0x54, 0x03, 0x11, 0x3c, 0x95, 0x0e, 0xce, - 0x7d, 0xf1, 0xd8, 0xcd, 0xcf, 0xfd, 0x57, 0xa1, 0x68, 0xeb, 0x43, 0x7e, 0xcd, 0xe3, 0x5b, 0x43, - 0x31, 0x8f, 0x34, 0x2e, 0x48, 0x5a, 0xdf, 0x1a, 0x12, 0x55, 0x85, 0x7c, 0xa8, 0x0c, 0xad, 0x40, - 0xa1, 0xda, 0xec, 0x69, 0x77, 0xef, 0x3d, 0xd0, 0x1e, 0xd6, 0x77, 0x94, 0x05, 0x99, 0x9b, 0xfe, - 0x79, 0x02, 0x96, 0x64, 0x38, 0x92, 0xf9, 0xfe, 0x6b, 0xb0, 0xe8, 0xea, 0xfb, 0x7e, 0x50, 0x91, - 0xa4, 0x85, 0x57, 0xb3, 0x08, 0xcf, 0x2a, 0x12, 0xc6, 0x8a, 0xaf, 0x48, 0x22, 0x2f, 0xeb, 0xa9, - 0x4b, 0x5f, 0xd6, 0xd3, 0x3f, 0x95, 0x97, 0x75, 0xf5, 0x57, 0x00, 0x36, 0x2d, 0x9b, 0xf4, 0xc5, - 0x5d, 0x53, 0x5c, 0x7d, 0xc9, 0x72, 0x38, 0x79, 0xe3, 0x18, 0xe4, 0x70, 0xad, 0x06, 0x66, 0x34, - 0xc6, 0x1a, 0x58, 0xa6, 0xdc, 0x8c, 0x9c, 0xf5, 0x90, 0xb1, 0x06, 0x96, 0x19, 0xbe, 0x25, 0xa5, - 0xaf, 0x7a, 0x4b, 0x3a, 0x4d, 0xc0, 0x8a, 0xcc, 0x5d, 0xc3, 0xf0, 0xfb, 0x16, 0xe4, 0x45, 0x1a, - 0x3b, 0x2d, 0xe8, 0xf8, 0x6b, 0xb2, 0xc0, 0xb5, 0x1a, 0x38, 0x27, 0xd8, 0x2d, 0x13, 0x6d, 0x40, - 0x41, 0x42, 0x23, 0xbf, 0xc2, 0x01, 0x41, 0x6a, 0xb3, 0xe1, 0xbf, 0x07, 0xe9, 0x7d, 0xcb, 0x26, - 0xd2, 0xd1, 0x63, 0x03, 0xc0, 0xd4, 0x00, 0x5b, 0x0b, 0x98, 0xa3, 0x6b, 0xb9, 0xe0, 0x32, 0x8e, - 0x8f, 0x4f, 0x96, 0x9d, 0xd1, 0xf1, 0x89, 0x0a, 0x74, 0x6e, 0x7c, 0x02, 0xc7, 0xc6, 0x27, 0xd8, - 0x62, 0x7c, 0x12, 0x1a, 0x1d, 0x9f, 0x20, 0xfd, 0x54, 0xc6, 0xb7, 0x0d, 0x37, 0x6a, 0xb6, 0x6e, - 0x1c, 0xda, 0x96, 0xe7, 0x13, 0x33, 0x1a, 0x31, 0xee, 0x41, 0x76, 0x26, 0xe9, 0xbc, 0xec, 0x72, - 0x56, 0x22, 0xd5, 0x7f, 0x4b, 0x40, 0x71, 0x8b, 0xe8, 0xb6, 0x7f, 0x30, 0xbd, 0x1a, 0xf2, 0x89, - 0xe7, 0xcb, 0xc3, 0x8a, 0x7f, 0xa3, 0xf7, 0x21, 0x17, 0xe6, 0x24, 0x57, 0xbe, 0x92, 0x85, 0x50, - 0x74, 0x1f, 0x16, 0xd9, 0x1e, 0xa3, 0xe3, 0xa0, 0xd8, 0xb9, 0xec, 0x01, 0x46, 0x22, 0xd9, 0x21, - 0xe3, 0x12, 0x9e, 0x84, 0x70, 0x57, 0xca, 0xe0, 0xa0, 0x89, 0x7e, 0x16, 0x8a, 0xfc, 0xfd, 0x20, - 0xc8, 0xb9, 0x32, 0x57, 0xe9, 0x2c, 0x88, 0x27, 0x40, 0x91, 0x6f, 0xfd, 0x6f, 0x02, 0x56, 0x77, - 0xf4, 0xc9, 0x1e, 0x91, 0x61, 0x83, 0x98, 0x98, 0x18, 0xd4, 0x35, 0x51, 0x37, 0x1a, 0x6e, 0x2e, - 0x79, 0x51, 0x8c, 0x13, 0x8e, 0x8f, 0x3a, 0x41, 0x01, 0x96, 0x8c, 0x14, 0x60, 0xab, 0x90, 0x71, - 0xa8, 0x63, 0x10, 0x19, 0x8b, 0x44, 0x43, 0xb5, 0xa2, 0xa1, 0xa6, 0x14, 0x3e, 0xf6, 0xf1, 0xa7, - 0xba, 0x36, 0xf5, 0xc3, 0xde, 0xd0, 0x67, 0x50, 0xea, 0x35, 0xeb, 0xb8, 0xd9, 0xaf, 0x75, 0x7e, - 0xa8, 0xf5, 0xaa, 0xdb, 0xbd, 0xea, 0xbd, 0x3b, 0x5a, 0xb7, 0xb3, 0xfd, 0xf9, 0xdd, 0xfb, 0x77, - 0xde, 0x57, 0x12, 0xa5, 0xf2, 0xc9, 0x69, 0xf9, 0x56, 0xbb, 0x5a, 0xdf, 0x16, 0x3b, 0x66, 0x8f, - 0x3e, 0xed, 0xe9, 0xb6, 0xa7, 0xdf, 0xbb, 0xd3, 0xa5, 0xf6, 0x84, 0x61, 0x98, 0x5b, 0x17, 0xa3, - 0xe7, 0x55, 0xf4, 0x18, 0x4e, 0x5c, 0x78, 0x0c, 0x4f, 0x4f, 0xf3, 0xe4, 0x05, 0xa7, 0xf9, 0x26, - 0xac, 0x1a, 0x2e, 0xf5, 0x3c, 0x8d, 0x65, 0xff, 0xc4, 0x9c, 0xab, 0x2f, 0xbe, 0x73, 0x7e, 0xb6, - 0x71, 0xad, 0xce, 0xf8, 0x3d, 0xce, 0x96, 0xea, 0xaf, 0x19, 0x11, 0x12, 0xef, 0x49, 0xfd, 0xbd, - 0x14, 0x4b, 0xa4, 0xac, 0x23, 0xcb, 0x26, 0x03, 0xe2, 0xa1, 0xc7, 0xb0, 0x62, 0xb8, 0xc4, 0x64, - 0x69, 0xbd, 0x6e, 0x6b, 0xde, 0x88, 0x18, 0xd2, 0xa9, 0x7f, 0x26, 0x36, 0xa7, 0x09, 0x05, 0x2b, - 0xf5, 0x50, 0xaa, 0x37, 0x22, 0x06, 0x5e, 0x36, 0x66, 0xda, 0xe8, 0x0b, 0x58, 0xf1, 0x88, 0x6d, - 0x39, 0xe3, 0xa7, 0x9a, 0x41, 0x1d, 0x9f, 0x3c, 0x0d, 0xde, 0xad, 0xae, 0xd2, 0xdb, 0x6b, 0x6e, - 0x33, 0xa9, 0xba, 0x10, 0xaa, 0xa1, 0xf3, 0xb3, 0x8d, 0xe5, 0x59, 0x1a, 0x5e, 0x96, 0x9a, 0x65, - 0xbb, 0xd4, 0x86, 0xe5, 0xd9, 0xd1, 0xa0, 0x55, 0xb9, 0xf7, 0x79, 0x08, 0x09, 0xf6, 0x36, 0xba, - 0x05, 0x39, 0x97, 0x0c, 0x2c, 0xcf, 0x77, 0x85, 0x99, 0x19, 0x27, 0xa4, 0xb0, 0x9d, 0x2f, 0x7e, - 0x8a, 0x53, 0xfa, 0x25, 0x98, 0xeb, 0x91, 0x6d, 0x16, 0xd3, 0xf2, 0xf4, 0x3d, 0xa9, 0x32, 0x87, - 0x83, 0x26, 0xf3, 0xc1, 0xb1, 0x17, 0x26, 0x6a, 0xfc, 0x9b, 0xd1, 0x78, 0x46, 0x21, 0x7f, 0x98, - 0xc4, 0x73, 0x86, 0xe0, 0x17, 0x8e, 0xe9, 0xc8, 0x2f, 0x1c, 0x57, 0x21, 0x63, 0x93, 0x23, 0x62, - 0x8b, 0xb3, 0x1c, 0x8b, 0xc6, 0xdb, 0xbf, 0x9d, 0x86, 0x7c, 0xf8, 0x46, 0xc3, 0x4e, 0x82, 0x76, - 0xf3, 0x49, 0xe0, 0xab, 0x21, 0xbd, 0x4d, 0x8e, 0xd1, 0xab, 0xd3, 0x3b, 0xa5, 0xcf, 0xc4, 0xa3, - 0x74, 0xc8, 0x0e, 0xee, 0x93, 0x5e, 0x87, 0x5c, 0xb5, 0xd7, 0x6b, 0x3d, 0x6c, 0x37, 0x1b, 0xca, - 0x97, 0x89, 0xd2, 0x77, 0x4e, 0x4e, 0xcb, 0xd7, 0x42, 0x50, 0xd5, 0x13, 0xae, 0xc4, 0x51, 0xf5, - 0x7a, 0xb3, 0xdb, 0x6f, 0x36, 0x94, 0x67, 0xc9, 0x79, 0x14, 0xbf, 0x23, 0xe1, 0x3f, 0x2d, 0xc9, - 0x77, 0x71, 0xb3, 0x5b, 0xc5, 0xac, 0xc3, 0x2f, 0x93, 0xe2, 0xaa, 0x6b, 0xda, 0xa3, 0x4b, 0x46, - 0xba, 0xcb, 0xfa, 0x5c, 0x0f, 0x7e, 0x62, 0xf5, 0x2c, 0x25, 0x7e, 0x7e, 0x30, 0x7d, 0x70, 0x22, - 0xba, 0x39, 0x61, 0xbd, 0xf1, 0x97, 0x3e, 0xae, 0x26, 0x35, 0xd7, 0x5b, 0x8f, 0x45, 0x12, 0xa6, - 0x45, 0x85, 0x45, 0xbc, 0xdb, 0x6e, 0x33, 0xd0, 0xb3, 0xf4, 0xdc, 0xec, 0xf0, 0xd8, 0x61, 0xf5, - 0x2f, 0xba, 0x0d, 0xb9, 0xe0, 0x21, 0x50, 0xf9, 0x32, 0x3d, 0x37, 0xa0, 0x7a, 0xf0, 0x8a, 0xc9, - 0x3b, 0xdc, 0xda, 0xed, 0xf3, 0x5f, 0x80, 0x3d, 0xcb, 0xcc, 0x77, 0x78, 0x30, 0xf6, 0x4d, 0x7a, - 0xec, 0xb0, 0x1d, 0x28, 0x6f, 0xd5, 0xbe, 0xcc, 0x88, 0x2b, 0x88, 0x10, 0x23, 0xaf, 0xd4, 0x5e, - 0x87, 0x1c, 0x6e, 0xfe, 0x40, 0xfc, 0x58, 0xec, 0x59, 0x76, 0x4e, 0x0f, 0x26, 0x5f, 0x10, 0x83, - 0xf5, 0x56, 0x86, 0x2c, 0x6e, 0xee, 0x74, 0x1e, 0x37, 0x95, 0xdf, 0xcf, 0xce, 0xe9, 0xc1, 0x64, - 0x48, 0xf9, 0x6f, 0x6f, 0x72, 0x1d, 0xdc, 0xdd, 0xaa, 0xf2, 0x45, 0x99, 0xd7, 0xd3, 0x71, 0x47, - 0x07, 0xba, 0x43, 0xcc, 0xe9, 0xaf, 0x34, 0x42, 0xd6, 0xdb, 0x3f, 0x0f, 0xb9, 0x20, 0x13, 0x45, - 0xeb, 0x90, 0x7d, 0xd2, 0xc1, 0x8f, 0x9a, 0x58, 0x59, 0x10, 0x56, 0x0e, 0x38, 0x4f, 0x44, 0x0d, - 0x51, 0x86, 0xc5, 0x9d, 0x6a, 0xbb, 0xfa, 0xb0, 0x89, 0x83, 0x2b, 0xf1, 0x00, 0x20, 0xd3, 0xa9, - 0x92, 0x22, 0x3b, 0x08, 0x75, 0xd6, 0xd6, 0xbe, 0xfa, 0x7a, 0x7d, 0xe1, 0x27, 0x5f, 0xaf, 0x2f, - 0x3c, 0x3b, 0x5f, 0x4f, 0x7c, 0x75, 0xbe, 0x9e, 0xf8, 0xf1, 0xf9, 0x7a, 0xe2, 0x5f, 0xcf, 0xd7, - 0x13, 0x7b, 0x59, 0x1e, 0xf4, 0xef, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x10, 0x5d, - 0x3d, 0xa2, 0x2e, 0x00, 0x00, + // 4705 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x7a, 0x4d, 0x6c, 0x24, 0xd7, + 0x56, 0xbf, 0xfb, 0xd3, 0xdd, 0xa7, 0xdb, 0x76, 0xf9, 0x8e, 0x33, 0xf1, 0x74, 0x26, 0x76, 0xa7, + 0x92, 0x79, 0xf9, 0x78, 0xf9, 0x77, 0x66, 0x3c, 0x49, 0x34, 0x49, 0xfe, 0x2f, 0x49, 0x7f, 0x79, + 0xdc, 0x6f, 0xec, 0xee, 0xd6, 0xed, 0xf6, 0xcc, 0xcb, 0x02, 0x4a, 0xe5, 0xaa, 0xeb, 0x76, 0xc5, + 0xd5, 0x75, 0x9b, 0xaa, 0x6a, 0x7b, 0x9a, 0x07, 0x62, 0xc4, 0x02, 0x90, 0x57, 0xb0, 0x43, 0x42, + 0x66, 0x03, 0x2b, 0x84, 0xc4, 0x02, 0x24, 0x04, 0x1b, 0x82, 0xc4, 0x22, 0x3b, 0x1e, 0x20, 0xa1, + 0x27, 0x90, 0x0c, 0xf1, 0x82, 0x1d, 0x82, 0xcd, 0x13, 0x1b, 0x90, 0xd0, 0xfd, 0xa8, 0xea, 0x6a, + 0x4f, 0xd9, 0x9e, 0x90, 0xb7, 0xb1, 0xeb, 0x9e, 0xf3, 0x3b, 0xe7, 0xde, 0x7b, 0xee, 0xb9, 0xe7, + 0x9e, 0x73, 0x6f, 0x43, 0xc1, 0x9f, 0x8c, 0x88, 0x57, 0x19, 0xb9, 0xd4, 0xa7, 0x08, 0x99, 0xd4, + 0x38, 0x24, 0x6e, 0xc5, 0x3b, 0xd6, 0xdd, 0xe1, 0xa1, 0xe5, 0x57, 0x8e, 0xee, 0x95, 0xd6, 0x07, + 0x94, 0x0e, 0x6c, 0xf2, 0x1e, 0x47, 0xec, 0x8d, 0xf7, 0xdf, 0xf3, 0xad, 0x21, 0xf1, 0x7c, 0x7d, + 0x38, 0x12, 0x42, 0xa5, 0xb5, 0x8b, 0x00, 0x73, 0xec, 0xea, 0xbe, 0x45, 0x1d, 0xc9, 0x5f, 0x19, + 0xd0, 0x01, 0xe5, 0x9f, 0xef, 0xb1, 0x2f, 0x41, 0x55, 0xd7, 0x61, 0xfe, 0x31, 0x71, 0x3d, 0x8b, + 0x3a, 0x68, 0x05, 0x32, 0x96, 0x63, 0x92, 0xa7, 0xab, 0x89, 0x72, 0xe2, 0xad, 0x34, 0x16, 0x0d, + 0xf5, 0x2e, 0x40, 0x8b, 0x7d, 0x34, 0x1d, 0xdf, 0x9d, 0x20, 0x05, 0x52, 0x87, 0x64, 0xc2, 0x11, + 0x79, 0xcc, 0x3e, 0x19, 0xe5, 0x48, 0xb7, 0x57, 0x93, 0x82, 0x72, 0xa4, 0xdb, 0xea, 0x37, 0x09, + 0x28, 0x54, 0x1d, 0x87, 0xfa, 0xbc, 0x77, 0x0f, 0x21, 0x48, 0x3b, 0xfa, 0x90, 0x48, 0x21, 0xfe, + 0x8d, 0xea, 0x90, 0xb5, 0xf5, 0x3d, 0x62, 0x7b, 0xab, 0xc9, 0x72, 0xea, 0xad, 0xc2, 0xc6, 0xf7, + 0x2b, 0xcf, 0x4f, 0xb9, 0x12, 0x51, 0x52, 0xd9, 0xe6, 0x68, 0x3e, 0x08, 0x2c, 0x45, 0xd1, 0xa7, + 0x30, 0x6f, 0x39, 0xa6, 0x65, 0x10, 0x6f, 0x35, 0xcd, 0xb5, 0xac, 0xc5, 0x69, 0x99, 0x8e, 0xbe, + 0x96, 0xfe, 0xfa, 0x6c, 0x7d, 0x0e, 0x07, 0x42, 0xa5, 0x8f, 0xa0, 0x10, 0x51, 0x1b, 0x33, 0xb7, + 0x15, 0xc8, 0x1c, 0xe9, 0xf6, 0x98, 0xc8, 0xd9, 0x89, 0xc6, 0xc7, 0xc9, 0x07, 0x09, 0xf5, 0x0b, + 0xc8, 0x63, 0xe2, 0xd1, 0xb1, 0x6b, 0x10, 0x0f, 0xbd, 0x0d, 0x79, 0x47, 0x77, 0xa8, 0x66, 0x8c, + 0xc6, 0x1e, 0x17, 0x4f, 0xd5, 0x8a, 0xe7, 0x67, 0xeb, 0xb9, 0xb6, 0xee, 0xd0, 0x7a, 0x77, 0xd7, + 0xc3, 0x39, 0xc6, 0xae, 0x8f, 0xc6, 0x1e, 0x7a, 0x0d, 0x8a, 0x43, 0x32, 0xa4, 0xee, 0x44, 0xdb, + 0x9b, 0xf8, 0xc4, 0xe3, 0x8a, 0x53, 0xb8, 0x20, 0x68, 0x35, 0x46, 0x52, 0x7f, 0x3b, 0x01, 0x2b, + 0x81, 0x6e, 0x4c, 0x7e, 0x69, 0x6c, 0xb9, 0x64, 0x48, 0x1c, 0xdf, 0x43, 0x1f, 0x40, 0xd6, 0xb6, + 0x86, 0x96, 0x2f, 0xfa, 0x28, 0x6c, 0xbc, 0x1a, 0x37, 0xdb, 0x70, 0x54, 0x58, 0x82, 0x51, 0x15, + 0x8a, 0x2e, 0xf1, 0x88, 0x7b, 0x24, 0x2c, 0xc9, 0xbb, 0xbc, 0x56, 0x78, 0x46, 0x44, 0xdd, 0x84, + 0x5c, 0xd7, 0xd6, 0xfd, 0x7d, 0xea, 0x0e, 0x91, 0x0a, 0x45, 0xdd, 0x35, 0x0e, 0x2c, 0x9f, 0x18, + 0xfe, 0xd8, 0x0d, 0x56, 0x75, 0x86, 0x86, 0x6e, 0x42, 0x92, 0x8a, 0x8e, 0xf2, 0xb5, 0xec, 0xf9, + 0xd9, 0x7a, 0xb2, 0xd3, 0xc3, 0x49, 0xea, 0xa9, 0x9f, 0xc0, 0x72, 0xd7, 0x1e, 0x0f, 0x2c, 0xa7, + 0x41, 0x3c, 0xc3, 0xb5, 0x46, 0x4c, 0x3b, 0x73, 0x0f, 0xe6, 0xfb, 0x81, 0x7b, 0xb0, 0xef, 0xd0, + 0x65, 0x92, 0x53, 0x97, 0x51, 0x7f, 0x33, 0x09, 0xcb, 0x4d, 0x67, 0x60, 0x39, 0x24, 0x2a, 0x7d, + 0x07, 0x16, 0x09, 0x27, 0x6a, 0x47, 0xc2, 0x8d, 0xa5, 0x9e, 0x05, 0x41, 0x0d, 0x7c, 0xbb, 0x75, + 0xc1, 0xdf, 0xee, 0xc5, 0x4d, 0xff, 0x39, 0xed, 0xb1, 0x5e, 0xd7, 0x84, 0xf9, 0x11, 0x9f, 0x84, + 0xb7, 0x9a, 0xe2, 0xba, 0xee, 0xc4, 0xe9, 0x7a, 0x6e, 0x9e, 0x81, 0xf3, 0x49, 0xd9, 0xef, 0xe2, + 0x7c, 0x7f, 0x9c, 0x84, 0xa5, 0x36, 0x35, 0x67, 0xec, 0x50, 0x82, 0xdc, 0x01, 0xf5, 0xfc, 0xc8, + 0x46, 0x0b, 0xdb, 0xe8, 0x01, 0xe4, 0x46, 0x72, 0xf9, 0xe4, 0xea, 0xdf, 0x8e, 0x1f, 0xb2, 0xc0, + 0xe0, 0x10, 0x8d, 0x3e, 0x81, 0xbc, 0x1b, 0xf8, 0xc4, 0x6a, 0xea, 0x45, 0x1c, 0x67, 0x8a, 0x47, + 0x3f, 0x80, 0xac, 0x58, 0x84, 0xd5, 0x34, 0x97, 0xbc, 0xf3, 0x42, 0x36, 0xc7, 0x52, 0x08, 0x3d, + 0x84, 0x9c, 0x6f, 0x7b, 0x9a, 0xe5, 0xec, 0xd3, 0xd5, 0x0c, 0x57, 0xb0, 0x1e, 0xa7, 0x80, 0x19, + 0xa2, 0xbf, 0xdd, 0x6b, 0x39, 0xfb, 0xb4, 0x56, 0x38, 0x3f, 0x5b, 0x9f, 0x97, 0x0d, 0x3c, 0xef, + 0xdb, 0x1e, 0xfb, 0x50, 0x7f, 0x27, 0x01, 0x85, 0x08, 0x0a, 0xbd, 0x0a, 0xe0, 0xbb, 0x63, 0xcf, + 0xd7, 0x5c, 0x4a, 0x7d, 0x6e, 0xac, 0x22, 0xce, 0x73, 0x0a, 0xa6, 0xd4, 0x47, 0x15, 0xb8, 0x61, + 0x10, 0xd7, 0xd7, 0x2c, 0xcf, 0x1b, 0x13, 0x57, 0xf3, 0xc6, 0x7b, 0x5f, 0x12, 0xc3, 0xe7, 0x86, + 0x2b, 0xe2, 0x65, 0xc6, 0x6a, 0x71, 0x4e, 0x4f, 0x30, 0xd0, 0x7d, 0xb8, 0x19, 0xc5, 0x8f, 0xc6, + 0x7b, 0xb6, 0x65, 0x68, 0x6c, 0x31, 0x53, 0x5c, 0xe4, 0xc6, 0x54, 0xa4, 0xcb, 0x79, 0x8f, 0xc8, + 0x44, 0xfd, 0x69, 0x02, 0x14, 0xac, 0xef, 0xfb, 0x3b, 0x64, 0xb8, 0x47, 0xdc, 0x9e, 0xaf, 0xfb, + 0x63, 0x0f, 0xdd, 0x84, 0xac, 0x4d, 0x74, 0x93, 0xb8, 0x7c, 0x50, 0x39, 0x2c, 0x5b, 0x68, 0x97, + 0xed, 0x60, 0xdd, 0x38, 0xd0, 0xf7, 0x2c, 0xdb, 0xf2, 0x27, 0x7c, 0x28, 0x8b, 0xf1, 0x2e, 0x7c, + 0x51, 0x67, 0x05, 0x47, 0x04, 0xf1, 0x8c, 0x1a, 0xb4, 0x0a, 0xf3, 0x43, 0xe2, 0x79, 0xfa, 0x80, + 0xf0, 0x91, 0xe6, 0x71, 0xd0, 0x54, 0x3f, 0x81, 0x62, 0x54, 0x0e, 0x15, 0x60, 0x7e, 0xb7, 0xfd, + 0xa8, 0xdd, 0x79, 0xd2, 0x56, 0xe6, 0xd0, 0x12, 0x14, 0x76, 0xdb, 0xb8, 0x59, 0xad, 0x6f, 0x55, + 0x6b, 0xdb, 0x4d, 0x25, 0x81, 0x16, 0x20, 0x3f, 0x6d, 0x26, 0xd5, 0x3f, 0x4d, 0x00, 0x30, 0x73, + 0xcb, 0x49, 0x7d, 0x0c, 0x19, 0xcf, 0xd7, 0x7d, 0xe1, 0x95, 0x8b, 0x1b, 0x6f, 0x5c, 0xb6, 0x86, + 0x72, 0xbc, 0xec, 0x1f, 0xc1, 0x42, 0x24, 0x3a, 0xc2, 0xe4, 0xcc, 0x08, 0x59, 0x80, 0xd0, 0x4d, + 0xd3, 0x95, 0x03, 0xe7, 0xdf, 0xea, 0x27, 0x90, 0xe1, 0xd2, 0xb3, 0xc3, 0xcd, 0x41, 0xba, 0xc1, + 0xbe, 0x12, 0x28, 0x0f, 0x19, 0xdc, 0xac, 0x36, 0xbe, 0x50, 0x92, 0x48, 0x81, 0x62, 0xa3, 0xd5, + 0xab, 0x77, 0xda, 0xed, 0x66, 0xbd, 0xdf, 0x6c, 0x28, 0x29, 0xf5, 0x0e, 0x64, 0x5a, 0x43, 0xa6, + 0xf9, 0x36, 0x73, 0xf9, 0x7d, 0xe2, 0x12, 0xc7, 0x08, 0x76, 0xd2, 0x94, 0xa0, 0xfe, 0x24, 0x0f, + 0x99, 0x1d, 0x3a, 0x76, 0x7c, 0xb4, 0x11, 0x09, 0x5b, 0x8b, 0xf1, 0x27, 0x0f, 0x07, 0x56, 0xfa, + 0x93, 0x11, 0x91, 0x61, 0xed, 0x26, 0x64, 0xc5, 0xe6, 0x90, 0xd3, 0x91, 0x2d, 0x46, 0xf7, 0x75, + 0x77, 0x40, 0x7c, 0x39, 0x1f, 0xd9, 0x42, 0x6f, 0x41, 0xce, 0x25, 0xba, 0x49, 0x1d, 0x7b, 0xc2, + 0xf7, 0x50, 0x4e, 0x9c, 0x2b, 0x98, 0xe8, 0x66, 0xc7, 0xb1, 0x27, 0x38, 0xe4, 0xa2, 0x2d, 0x28, + 0xee, 0x59, 0x8e, 0xa9, 0xd1, 0x91, 0x08, 0xf2, 0x99, 0xcb, 0x77, 0x9c, 0x18, 0x55, 0xcd, 0x72, + 0xcc, 0x8e, 0x00, 0xe3, 0xc2, 0xde, 0xb4, 0x81, 0xda, 0xb0, 0x78, 0x44, 0xed, 0xf1, 0x90, 0x84, + 0xba, 0xb2, 0x5c, 0xd7, 0x9b, 0x97, 0xeb, 0x7a, 0xcc, 0xf1, 0x81, 0xb6, 0x85, 0xa3, 0x68, 0x13, + 0x3d, 0x82, 0x05, 0x7f, 0x38, 0xda, 0xf7, 0x42, 0x75, 0xf3, 0x5c, 0xdd, 0xf7, 0xae, 0x30, 0x18, + 0x83, 0x07, 0xda, 0x8a, 0x7e, 0xa4, 0x55, 0xfa, 0xf5, 0x14, 0x14, 0x22, 0x23, 0x47, 0x3d, 0x28, + 0x8c, 0x5c, 0x3a, 0xd2, 0x07, 0xfc, 0xa0, 0x92, 0x6b, 0x71, 0xef, 0x85, 0x66, 0x5d, 0xe9, 0x4e, + 0x05, 0x71, 0x54, 0x8b, 0x7a, 0x9a, 0x84, 0x42, 0x84, 0x89, 0xde, 0x81, 0x1c, 0xee, 0xe2, 0xd6, + 0xe3, 0x6a, 0xbf, 0xa9, 0xcc, 0x95, 0x6e, 0x9f, 0x9c, 0x96, 0x57, 0xb9, 0xb6, 0xa8, 0x82, 0xae, + 0x6b, 0x1d, 0x31, 0xd7, 0x7b, 0x0b, 0xe6, 0x03, 0x68, 0xa2, 0xf4, 0xca, 0xc9, 0x69, 0xf9, 0xe5, + 0x8b, 0xd0, 0x08, 0x12, 0xf7, 0xb6, 0xaa, 0xb8, 0xd9, 0x50, 0x92, 0xf1, 0x48, 0xdc, 0x3b, 0xd0, + 0x5d, 0x62, 0xa2, 0xef, 0x41, 0x56, 0x02, 0x53, 0xa5, 0xd2, 0xc9, 0x69, 0xf9, 0xe6, 0x45, 0xe0, + 0x14, 0x87, 0x7b, 0xdb, 0xd5, 0xc7, 0x4d, 0x25, 0x1d, 0x8f, 0xc3, 0x3d, 0x5b, 0x3f, 0x22, 0xe8, + 0x0d, 0xc8, 0x08, 0x58, 0xa6, 0x74, 0xeb, 0xe4, 0xb4, 0xfc, 0xd2, 0x73, 0xea, 0x18, 0xaa, 0xb4, + 0xfa, 0x5b, 0x7f, 0xb0, 0x36, 0xf7, 0x97, 0x7f, 0xb8, 0xa6, 0x5c, 0x64, 0x97, 0xfe, 0x3b, 0x01, + 0x0b, 0x33, 0x4b, 0x8e, 0x54, 0xc8, 0x3a, 0xd4, 0xa0, 0x23, 0x71, 0x7e, 0xe5, 0x6a, 0x70, 0x7e, + 0xb6, 0x9e, 0x6d, 0xd3, 0x3a, 0x1d, 0x4d, 0xb0, 0xe4, 0xa0, 0x47, 0x17, 0x4e, 0xe0, 0xfb, 0x2f, + 0xe8, 0x4f, 0xb1, 0x67, 0xf0, 0x67, 0xb0, 0x60, 0xba, 0xd6, 0x11, 0x71, 0x35, 0x83, 0x3a, 0xfb, + 0xd6, 0x40, 0x9e, 0x4d, 0xa5, 0x38, 0x9d, 0x0d, 0x0e, 0xc4, 0x45, 0x21, 0x50, 0xe7, 0xf8, 0xef, + 0x70, 0xfa, 0x96, 0x1e, 0x43, 0x31, 0xea, 0xa1, 0xec, 0x38, 0xf1, 0xac, 0x5f, 0x26, 0x32, 0xa1, + 0xe3, 0xe9, 0x1f, 0xce, 0x33, 0x0a, 0x4f, 0xe7, 0xd0, 0x9b, 0x90, 0x1e, 0x52, 0x53, 0xe8, 0x59, + 0xa8, 0xdd, 0x60, 0x49, 0xc0, 0x3f, 0x9d, 0xad, 0x17, 0xa8, 0x57, 0xd9, 0xb4, 0x6c, 0xb2, 0x43, + 0x4d, 0x82, 0x39, 0x40, 0x3d, 0x82, 0x34, 0x0b, 0x15, 0xe8, 0x15, 0x48, 0xd7, 0x5a, 0xed, 0x86, + 0x32, 0x57, 0x5a, 0x3e, 0x39, 0x2d, 0x2f, 0x70, 0x93, 0x30, 0x06, 0xf3, 0x5d, 0xb4, 0x0e, 0xd9, + 0xc7, 0x9d, 0xed, 0xdd, 0x1d, 0xe6, 0x5e, 0x37, 0x4e, 0x4e, 0xcb, 0x4b, 0x21, 0x5b, 0x18, 0x0d, + 0xbd, 0x0a, 0x99, 0xfe, 0x4e, 0x77, 0xb3, 0xa7, 0x24, 0x4b, 0xe8, 0xe4, 0xb4, 0xbc, 0x18, 0xf2, + 0xf9, 0x98, 0x4b, 0xcb, 0x72, 0x55, 0xf3, 0x21, 0x5d, 0xfd, 0x59, 0x12, 0x16, 0x30, 0xab, 0x24, + 0x5c, 0xbf, 0x4b, 0x6d, 0xcb, 0x98, 0xa0, 0x2e, 0xe4, 0x0d, 0xea, 0x98, 0x56, 0x64, 0x4f, 0x6d, + 0x5c, 0x72, 0xea, 0x4f, 0xa5, 0x82, 0x56, 0x3d, 0x90, 0xc4, 0x53, 0x25, 0xe8, 0x3d, 0xc8, 0x98, + 0xc4, 0xd6, 0x27, 0x32, 0xfd, 0xb8, 0x55, 0x11, 0xb5, 0x4a, 0x25, 0xa8, 0x55, 0x2a, 0x0d, 0x59, + 0xab, 0x60, 0x81, 0xe3, 0x79, 0xb2, 0xfe, 0x54, 0xd3, 0x7d, 0x9f, 0x0c, 0x47, 0xbe, 0xc8, 0x3d, + 0xd2, 0xb8, 0x30, 0xd4, 0x9f, 0x56, 0x25, 0x09, 0xdd, 0x83, 0xec, 0xb1, 0xe5, 0x98, 0xf4, 0x58, + 0xa6, 0x17, 0x57, 0x28, 0x95, 0x40, 0xf5, 0x84, 0x9d, 0xba, 0x17, 0x86, 0xc9, 0xec, 0xdd, 0xee, + 0xb4, 0x9b, 0x81, 0xbd, 0x25, 0xbf, 0xe3, 0xb4, 0xa9, 0xc3, 0xf6, 0x0a, 0x74, 0xda, 0xda, 0x66, + 0xb5, 0xb5, 0xbd, 0x8b, 0x99, 0xcd, 0x57, 0x4e, 0x4e, 0xcb, 0x4a, 0x08, 0xd9, 0xd4, 0x2d, 0x9b, + 0xe5, 0xbb, 0xb7, 0x20, 0x55, 0x6d, 0x7f, 0xa1, 0x24, 0x4b, 0xca, 0xc9, 0x69, 0xb9, 0x18, 0xb2, + 0xab, 0xce, 0x64, 0xba, 0x8d, 0x2e, 0xf6, 0xab, 0xfe, 0x6d, 0x0a, 0x8a, 0xbb, 0x23, 0x53, 0xf7, + 0x89, 0xf0, 0x49, 0x54, 0x86, 0xc2, 0x48, 0x77, 0x75, 0xdb, 0x26, 0xb6, 0xe5, 0x0d, 0x65, 0x15, + 0x16, 0x25, 0xa1, 0x8f, 0x5e, 0xd4, 0x8c, 0xb5, 0x1c, 0xf3, 0xb3, 0xdf, 0xfd, 0x97, 0xf5, 0x44, + 0x60, 0xd0, 0x5d, 0x58, 0xdc, 0x17, 0xa3, 0xd5, 0x74, 0x83, 0x2f, 0x6c, 0x8a, 0x2f, 0x6c, 0x25, + 0x6e, 0x61, 0xa3, 0xc3, 0xaa, 0xc8, 0x49, 0x56, 0xb9, 0x14, 0x5e, 0xd8, 0x8f, 0x36, 0xd1, 0x7d, + 0x98, 0x1f, 0x52, 0xc7, 0xf2, 0xa9, 0x7b, 0xfd, 0x2a, 0x04, 0x48, 0xf4, 0x0e, 0x2c, 0xb3, 0xc5, + 0x0d, 0xc6, 0xc3, 0xd9, 0xfc, 0xc4, 0x4a, 0xe2, 0xa5, 0xa1, 0xfe, 0x54, 0x76, 0x88, 0x19, 0x19, + 0xd5, 0x20, 0x43, 0x5d, 0x96, 0x12, 0x65, 0xf9, 0x70, 0xdf, 0xbd, 0x76, 0xb8, 0xa2, 0xd1, 0x61, + 0x32, 0x58, 0x88, 0xaa, 0x1f, 0xc2, 0xc2, 0xcc, 0x24, 0x58, 0x26, 0xd0, 0xad, 0xee, 0xf6, 0x9a, + 0xca, 0x1c, 0x2a, 0x42, 0xae, 0xde, 0x69, 0xf7, 0x5b, 0xed, 0x5d, 0x96, 0xca, 0x14, 0x21, 0x87, + 0x3b, 0xdb, 0xdb, 0xb5, 0x6a, 0xfd, 0x91, 0x92, 0x54, 0x2b, 0x50, 0x88, 0x68, 0x43, 0x8b, 0x00, + 0xbd, 0x7e, 0xa7, 0xab, 0x6d, 0xb6, 0x70, 0xaf, 0x2f, 0x12, 0xa1, 0x5e, 0xbf, 0x8a, 0xfb, 0x92, + 0x90, 0x50, 0xff, 0x23, 0x19, 0xac, 0xa8, 0xcc, 0x7d, 0x6a, 0xb3, 0xb9, 0xcf, 0x15, 0x83, 0x97, + 0xd9, 0xcf, 0xb4, 0x11, 0xe6, 0x40, 0x1f, 0x01, 0x70, 0xc7, 0x21, 0xa6, 0xa6, 0xfb, 0x72, 0xe1, + 0x4b, 0xcf, 0x19, 0xb9, 0x1f, 0x5c, 0x06, 0xe0, 0xbc, 0x44, 0x57, 0x7d, 0xf4, 0x03, 0x28, 0x1a, + 0x74, 0x38, 0xb2, 0x89, 0x14, 0x4e, 0x5d, 0x2b, 0x5c, 0x08, 0xf1, 0x55, 0x3f, 0x9a, 0x7d, 0xa5, + 0x67, 0xf3, 0xc3, 0xdf, 0x48, 0x04, 0x96, 0x89, 0x49, 0xb8, 0x8a, 0x90, 0xdb, 0xed, 0x36, 0xaa, + 0xfd, 0x56, 0xfb, 0xa1, 0x92, 0x40, 0x00, 0x59, 0x6e, 0xea, 0x86, 0x92, 0x64, 0x89, 0x62, 0xbd, + 0xb3, 0xd3, 0xdd, 0x6e, 0xf2, 0x94, 0x0b, 0xad, 0x80, 0x12, 0x18, 0x5b, 0xe3, 0x86, 0x6c, 0x36, + 0x94, 0x34, 0xba, 0x01, 0x4b, 0x21, 0x55, 0x4a, 0x66, 0xd0, 0x4d, 0x40, 0x21, 0x71, 0xaa, 0x22, + 0xab, 0xfe, 0x2a, 0x2c, 0xd5, 0xa9, 0xe3, 0xeb, 0x96, 0x13, 0x26, 0xd1, 0x1b, 0x6c, 0xd2, 0x92, + 0xa4, 0x59, 0xa6, 0x88, 0xe9, 0xb5, 0xa5, 0xf3, 0xb3, 0xf5, 0x42, 0x08, 0x6d, 0x35, 0xd8, 0x4c, + 0x83, 0x86, 0xc9, 0xf6, 0xef, 0xc8, 0x32, 0xb9, 0x71, 0x33, 0xb5, 0xf9, 0xf3, 0xb3, 0xf5, 0x54, + 0xb7, 0xd5, 0xc0, 0x8c, 0x86, 0x5e, 0x81, 0x3c, 0x79, 0x6a, 0xf9, 0x9a, 0xc1, 0x62, 0x38, 0x33, + 0x60, 0x06, 0xe7, 0x18, 0xa1, 0xce, 0x42, 0x76, 0x0d, 0xa0, 0x4b, 0x5d, 0x5f, 0xf6, 0xfc, 0x3e, + 0x64, 0x46, 0xd4, 0xe5, 0xe5, 0xf9, 0xa5, 0x97, 0x11, 0x0c, 0x2e, 0x1c, 0x15, 0x0b, 0xb0, 0xfa, + 0x57, 0x49, 0x80, 0xbe, 0xee, 0x1d, 0x4a, 0x25, 0x0f, 0x20, 0x1f, 0x5e, 0xec, 0xc8, 0x3a, 0xff, + 0xca, 0xd5, 0x0e, 0xc1, 0xe8, 0x7e, 0xe0, 0x6c, 0xa2, 0x3c, 0x88, 0xad, 0xd3, 0x82, 0x8e, 0xe2, + 0x32, 0xec, 0xd9, 0x1a, 0x80, 0x1d, 0x89, 0xc4, 0x75, 0xe5, 0xca, 0xb3, 0x4f, 0x54, 0xe7, 0xc7, + 0x82, 0x30, 0x9a, 0x4c, 0x30, 0x5f, 0x8f, 0xeb, 0xe4, 0xc2, 0x8a, 0x6c, 0xcd, 0xe1, 0xa9, 0x1c, + 0xfa, 0x0c, 0x0a, 0x6c, 0xde, 0x9a, 0xc7, 0x79, 0x32, 0xb7, 0xbc, 0xd4, 0x54, 0x42, 0x03, 0x86, + 0x51, 0xf8, 0x5d, 0x53, 0x60, 0xd1, 0x1d, 0x3b, 0x6c, 0xda, 0x52, 0x87, 0xfa, 0x27, 0x49, 0x78, + 0xb9, 0x4d, 0xfc, 0x63, 0xea, 0x1e, 0x56, 0x7d, 0x5f, 0x37, 0x0e, 0x86, 0xc4, 0x91, 0x46, 0x8e, + 0x64, 0xd6, 0x89, 0x99, 0xcc, 0x7a, 0x15, 0xe6, 0x75, 0xdb, 0xd2, 0x3d, 0x22, 0xd2, 0x91, 0x3c, + 0x0e, 0x9a, 0x2c, 0xff, 0x67, 0xd5, 0x04, 0xf1, 0x3c, 0x22, 0x0a, 0xfc, 0x3c, 0x9e, 0x12, 0xd0, + 0x8f, 0xe1, 0xa6, 0x4c, 0x3c, 0xf4, 0xb0, 0x2b, 0x96, 0xd9, 0x06, 0x37, 0x50, 0xcd, 0xd8, 0xf2, + 0x26, 0x7e, 0x70, 0x32, 0x33, 0x99, 0x92, 0x3b, 0x23, 0x5f, 0xe6, 0x39, 0x2b, 0x66, 0x0c, 0xab, + 0xf4, 0x10, 0x6e, 0x5d, 0x2a, 0xf2, 0xad, 0x2e, 0x10, 0xfe, 0x21, 0x09, 0xd0, 0xea, 0x56, 0x77, + 0xa4, 0x91, 0x1a, 0x90, 0xdd, 0xd7, 0x87, 0x96, 0x3d, 0xb9, 0x2a, 0x4e, 0x4d, 0xf1, 0x95, 0xaa, + 0x30, 0xc7, 0x26, 0x97, 0xc1, 0x52, 0x96, 0x17, 0x37, 0xe3, 0x3d, 0x87, 0xf8, 0x61, 0x71, 0xc3, + 0x5b, 0x6c, 0x18, 0xae, 0xee, 0x84, 0x0e, 0x26, 0x1a, 0x6c, 0x01, 0x06, 0xba, 0x4f, 0x8e, 0xf5, + 0x49, 0x10, 0x5c, 0x64, 0x13, 0x6d, 0xb1, 0xa2, 0xc7, 0x23, 0xee, 0x11, 0x31, 0x57, 0x33, 0xdc, + 0xa8, 0xd7, 0x8d, 0x07, 0x4b, 0xb8, 0xb0, 0x5d, 0x28, 0x5d, 0xfa, 0x84, 0x27, 0x36, 0x53, 0xd6, + 0xb7, 0xb2, 0xd1, 0x5d, 0x58, 0x98, 0x99, 0xe7, 0x73, 0x55, 0x65, 0xab, 0xfb, 0xf8, 0x7d, 0x25, + 0x2d, 0xbf, 0x3e, 0x54, 0xb2, 0xea, 0x1f, 0xa5, 0x44, 0x38, 0x90, 0x56, 0x8d, 0xbf, 0xf6, 0xcc, + 0xf1, 0x4d, 0x6c, 0x50, 0x5b, 0x6e, 0xd3, 0x37, 0xaf, 0x8e, 0x12, 0xac, 0x4a, 0xe1, 0x70, 0x1c, + 0x0a, 0xa2, 0x75, 0x28, 0x08, 0x2f, 0xd6, 0xd8, 0xb6, 0xe0, 0x66, 0x5d, 0xc0, 0x20, 0x48, 0x4c, + 0x12, 0xdd, 0x81, 0x45, 0x7e, 0x0b, 0xe1, 0x1d, 0x10, 0x53, 0x60, 0xd2, 0x1c, 0xb3, 0x10, 0x52, + 0x39, 0x6c, 0x07, 0x8a, 0x92, 0xa0, 0xf1, 0x0c, 0x35, 0xc3, 0x07, 0xf4, 0xce, 0x75, 0x03, 0x12, + 0x22, 0x3c, 0x71, 0x2d, 0x8c, 0xa6, 0x0d, 0xb5, 0x01, 0xb9, 0x60, 0xb0, 0x68, 0x15, 0x52, 0xfd, + 0x7a, 0x57, 0x99, 0x2b, 0x2d, 0x9d, 0x9c, 0x96, 0x0b, 0x01, 0xb9, 0x5f, 0xef, 0x32, 0xce, 0x6e, + 0xa3, 0xab, 0x24, 0x66, 0x39, 0xbb, 0x8d, 0x6e, 0x29, 0xcd, 0x32, 0x25, 0x75, 0x1f, 0x0a, 0x91, + 0x1e, 0xd0, 0xeb, 0x30, 0xdf, 0x6a, 0x3f, 0xc4, 0xcd, 0x5e, 0x4f, 0x99, 0x2b, 0xdd, 0x3c, 0x39, + 0x2d, 0xa3, 0x08, 0xb7, 0xe5, 0x0c, 0xd8, 0xfa, 0xa0, 0x57, 0x21, 0xbd, 0xd5, 0x61, 0x27, 0xb0, + 0x48, 0x89, 0x23, 0x88, 0x2d, 0xea, 0xf9, 0xa5, 0x1b, 0x32, 0x05, 0x8b, 0x2a, 0x56, 0x7f, 0x2f, + 0x01, 0x59, 0xb1, 0x99, 0x62, 0x17, 0xaa, 0x0a, 0xf3, 0x41, 0xbd, 0x2a, 0xca, 0x95, 0x37, 0x2f, + 0x2f, 0x2d, 0x2a, 0xb2, 0x12, 0x10, 0xee, 0x17, 0xc8, 0x95, 0x3e, 0x86, 0x62, 0x94, 0xf1, 0xad, + 0x9c, 0xef, 0xc7, 0x50, 0x60, 0xfe, 0x1d, 0x94, 0x18, 0x1b, 0x90, 0x15, 0x01, 0x21, 0x3c, 0x11, + 0x2e, 0xaf, 0x73, 0x24, 0x12, 0x3d, 0x80, 0x79, 0x51, 0x1b, 0x05, 0xd7, 0x94, 0x6b, 0x57, 0xef, + 0x22, 0x1c, 0xc0, 0xd5, 0xcf, 0x20, 0xdd, 0x25, 0xc4, 0x65, 0xb6, 0x77, 0xa8, 0x49, 0xa6, 0x87, + 0xa8, 0x2c, 0xeb, 0x4c, 0xd2, 0x6a, 0xb0, 0xb2, 0xce, 0x24, 0x2d, 0x33, 0xbc, 0x88, 0x49, 0x46, + 0x2e, 0x62, 0xfa, 0x50, 0x7c, 0x42, 0xac, 0xc1, 0x81, 0x4f, 0x4c, 0xae, 0xe8, 0x5d, 0x48, 0x8f, + 0x48, 0x38, 0xf8, 0xd5, 0x58, 0x07, 0x23, 0xc4, 0xc5, 0x1c, 0xc5, 0xe2, 0xc8, 0x31, 0x97, 0x96, + 0x97, 0xe3, 0xb2, 0xa5, 0xfe, 0x7d, 0x12, 0x16, 0x5b, 0x9e, 0x37, 0xd6, 0x1d, 0x23, 0xc8, 0xaf, + 0x3e, 0x9d, 0xcd, 0xaf, 0xde, 0x8a, 0x9d, 0xe1, 0x8c, 0xc8, 0xec, 0xfd, 0x92, 0x3c, 0xe3, 0x92, + 0xe1, 0x19, 0xa7, 0xfe, 0x7b, 0x22, 0xb8, 0x44, 0xba, 0x13, 0xd9, 0xee, 0xa5, 0xd5, 0x93, 0xd3, + 0xf2, 0x4a, 0x54, 0x13, 0xd9, 0x75, 0x0e, 0x1d, 0x7a, 0xec, 0xa0, 0xd7, 0x20, 0x83, 0x9b, 0xed, + 0xe6, 0x13, 0x25, 0x21, 0xdc, 0x73, 0x06, 0x84, 0x89, 0x43, 0x8e, 0x99, 0xa6, 0x6e, 0xb3, 0xdd, + 0x60, 0xf9, 0x50, 0x32, 0x46, 0x53, 0x97, 0x38, 0xa6, 0xe5, 0x0c, 0xd0, 0xeb, 0x90, 0x6d, 0xf5, + 0x7a, 0xbb, 0xbc, 0xcc, 0x7f, 0xf9, 0xe4, 0xb4, 0x7c, 0x63, 0x06, 0xc5, 0x2f, 0x10, 0x4d, 0x06, + 0x62, 0xc5, 0x08, 0xcb, 0x94, 0x62, 0x40, 0x2c, 0xcb, 0x15, 0x20, 0xdc, 0xe9, 0x57, 0xfb, 0xac, + 0xc2, 0x7f, 0x1e, 0x84, 0x29, 0xfb, 0x2b, 0xb7, 0xdb, 0x3f, 0x27, 0x41, 0xa9, 0x1a, 0x06, 0x19, + 0xf9, 0x8c, 0x2f, 0xeb, 0xbf, 0x3e, 0xe4, 0x46, 0xec, 0xcb, 0x22, 0x41, 0x2e, 0xf3, 0x20, 0xf6, + 0x79, 0xe6, 0x82, 0x5c, 0x05, 0x53, 0x9b, 0x54, 0xcd, 0xa1, 0xe5, 0x79, 0x16, 0x75, 0x04, 0x0d, + 0x87, 0x9a, 0x4a, 0xff, 0x99, 0x80, 0x1b, 0x31, 0x08, 0x74, 0x17, 0xd2, 0x2e, 0xb5, 0x83, 0x35, + 0xbc, 0x7d, 0xd9, 0xfd, 0x20, 0x13, 0xc5, 0x1c, 0x89, 0xd6, 0x00, 0xf4, 0xb1, 0x4f, 0x75, 0xde, + 0x3f, 0x5f, 0xbd, 0x1c, 0x8e, 0x50, 0xd0, 0x13, 0xc8, 0x7a, 0xc4, 0x70, 0x49, 0x90, 0xf1, 0x7e, + 0xf6, 0x7f, 0x1d, 0x7d, 0xa5, 0xc7, 0xd5, 0x60, 0xa9, 0xae, 0x54, 0x81, 0xac, 0xa0, 0x30, 0xb7, + 0x37, 0x75, 0x5f, 0x97, 0xb7, 0xc7, 0xfc, 0x9b, 0x79, 0x93, 0x6e, 0x0f, 0x02, 0x6f, 0xd2, 0xed, + 0x81, 0xfa, 0x37, 0x49, 0x80, 0xe6, 0x53, 0x9f, 0xb8, 0x8e, 0x6e, 0xd7, 0xab, 0xa8, 0x19, 0x89, + 0xfe, 0x62, 0xb6, 0x6f, 0xc7, 0x5e, 0x89, 0x87, 0x12, 0x95, 0x7a, 0x35, 0x26, 0xfe, 0xdf, 0x82, + 0xd4, 0xd8, 0x95, 0x2f, 0x6e, 0x22, 0x5b, 0xdd, 0xc5, 0xdb, 0x98, 0xd1, 0x50, 0x73, 0x1a, 0xb6, + 0x52, 0x97, 0xbf, 0xab, 0x45, 0x3a, 0x88, 0x0d, 0x5d, 0x6c, 0xe7, 0x1b, 0xba, 0x66, 0x10, 0x79, + 0x72, 0x14, 0xc5, 0xce, 0xaf, 0x57, 0xeb, 0xc4, 0xf5, 0x71, 0xd6, 0xd0, 0xd9, 0xff, 0xef, 0x14, + 0xdf, 0xde, 0x05, 0x98, 0x4e, 0x0d, 0xad, 0x41, 0xa6, 0xbe, 0xd9, 0xeb, 0x6d, 0x2b, 0x73, 0x22, + 0x80, 0x4f, 0x59, 0x9c, 0xac, 0xfe, 0x45, 0x12, 0x72, 0xf5, 0xaa, 0x3c, 0x56, 0xeb, 0xa0, 0xf0, + 0xa8, 0xc4, 0xef, 0xdc, 0xc9, 0xd3, 0x91, 0xe5, 0x4e, 0x64, 0x60, 0xb9, 0xa2, 0xf4, 0x5c, 0x64, + 0x22, 0x6c, 0xd4, 0x4d, 0x2e, 0x80, 0x30, 0x14, 0x89, 0x34, 0x82, 0x66, 0xe8, 0x41, 0x8c, 0x5f, + 0xbb, 0xda, 0x58, 0xa2, 0x88, 0x98, 0xb6, 0x3d, 0x5c, 0x08, 0x94, 0xd4, 0x75, 0x0f, 0x7d, 0x04, + 0x4b, 0x9e, 0x35, 0x70, 0x2c, 0x67, 0xa0, 0x05, 0xc6, 0xe3, 0x0f, 0x00, 0xb5, 0xe5, 0xf3, 0xb3, + 0xf5, 0x85, 0x9e, 0x60, 0x49, 0x1b, 0x2e, 0x48, 0x64, 0x9d, 0x9b, 0x12, 0x7d, 0x08, 0x8b, 0x11, + 0x51, 0x66, 0x45, 0x61, 0x76, 0xe5, 0xfc, 0x6c, 0xbd, 0x18, 0x4a, 0x3e, 0x22, 0x13, 0x5c, 0x0c, + 0x05, 0x1f, 0x11, 0x7e, 0x4b, 0xb2, 0x4f, 0x5d, 0x83, 0x68, 0x2e, 0xdf, 0xd3, 0xfc, 0x04, 0x4f, + 0xe3, 0x02, 0xa7, 0x89, 0x6d, 0xae, 0x3e, 0x86, 0x1b, 0x1d, 0xd7, 0x38, 0x20, 0x9e, 0x2f, 0x4c, + 0x21, 0xad, 0xf8, 0x19, 0xdc, 0xf6, 0x75, 0xef, 0x50, 0x3b, 0xb0, 0x3c, 0x9f, 0xba, 0x13, 0xcd, + 0x25, 0x3e, 0x71, 0x18, 0x5f, 0xe3, 0xaf, 0x86, 0xf2, 0x1a, 0xeb, 0x16, 0xc3, 0x6c, 0x09, 0x08, + 0x0e, 0x10, 0xdb, 0x0c, 0xa0, 0xb6, 0xa0, 0xc8, 0x8a, 0x89, 0x06, 0xd9, 0xd7, 0xc7, 0xb6, 0xcf, + 0x66, 0x0f, 0x36, 0x1d, 0x68, 0x2f, 0x7c, 0x4c, 0xe5, 0x6d, 0x3a, 0x10, 0x9f, 0xea, 0x8f, 0x40, + 0x69, 0x58, 0xde, 0x48, 0xf7, 0x8d, 0x83, 0xe0, 0x7e, 0x0e, 0x35, 0x40, 0x39, 0x20, 0xba, 0xeb, + 0xef, 0x11, 0xdd, 0xd7, 0x46, 0xc4, 0xb5, 0xa8, 0x79, 0xfd, 0x2a, 0x2f, 0x85, 0x22, 0x5d, 0x2e, + 0xa1, 0xfe, 0x57, 0x02, 0x00, 0xeb, 0xfb, 0x41, 0x46, 0xf6, 0x7d, 0x58, 0xf6, 0x1c, 0x7d, 0xe4, + 0x1d, 0x50, 0x5f, 0xb3, 0x1c, 0x9f, 0xb8, 0x47, 0xba, 0x2d, 0xaf, 0x59, 0x94, 0x80, 0xd1, 0x92, + 0x74, 0xf4, 0x2e, 0xa0, 0x43, 0x42, 0x46, 0x1a, 0xb5, 0x4d, 0x2d, 0x60, 0x8a, 0x37, 0xcd, 0x34, + 0x56, 0x18, 0xa7, 0x63, 0x9b, 0xbd, 0x80, 0x8e, 0x6a, 0xb0, 0xc6, 0xa6, 0x4f, 0x1c, 0xdf, 0xb5, + 0x88, 0xa7, 0xed, 0x53, 0x57, 0xf3, 0x6c, 0x7a, 0xac, 0xed, 0x53, 0xdb, 0xa6, 0xc7, 0xc4, 0x0d, + 0x6e, 0xb0, 0x4a, 0x36, 0x1d, 0x34, 0x05, 0x68, 0x93, 0xba, 0x3d, 0x9b, 0x1e, 0x6f, 0x06, 0x08, + 0x96, 0xb6, 0x4d, 0xe7, 0xec, 0x5b, 0xc6, 0x61, 0x90, 0xb6, 0x85, 0xd4, 0xbe, 0x65, 0x1c, 0xa2, + 0xd7, 0x61, 0x81, 0xd8, 0x84, 0x5f, 0x64, 0x08, 0x54, 0x86, 0xa3, 0x8a, 0x01, 0x91, 0x81, 0xd4, + 0xcf, 0x41, 0x69, 0x3a, 0x86, 0x3b, 0x19, 0x45, 0xd6, 0xfc, 0x5d, 0x40, 0x2c, 0x48, 0x6a, 0x36, + 0x35, 0x0e, 0xb5, 0xa1, 0xee, 0xe8, 0x03, 0x36, 0x2e, 0xf1, 0xd4, 0xa4, 0x30, 0xce, 0x36, 0x35, + 0x0e, 0x77, 0x24, 0x5d, 0xfd, 0x08, 0xa0, 0x37, 0x72, 0x89, 0x6e, 0x76, 0x58, 0x36, 0xc1, 0x4c, + 0xc7, 0x5b, 0x9a, 0x29, 0x9f, 0xea, 0xa8, 0x2b, 0xb7, 0xba, 0x22, 0x18, 0x8d, 0x90, 0xae, 0xfe, + 0x02, 0xdc, 0xe8, 0xda, 0xba, 0xc1, 0x9f, 0xad, 0xbb, 0xe1, 0xdb, 0x09, 0x7a, 0x00, 0x59, 0x01, + 0x95, 0x2b, 0x19, 0xbb, 0xdd, 0xa6, 0x7d, 0x6e, 0xcd, 0x61, 0x89, 0xaf, 0x15, 0x01, 0xa6, 0x7a, + 0xd4, 0x3f, 0x4b, 0x40, 0x3e, 0xd4, 0x8f, 0xca, 0xc0, 0x4a, 0x79, 0xe6, 0xde, 0x96, 0x23, 0x6b, + 0xef, 0x3c, 0x8e, 0x92, 0x50, 0x0b, 0x0a, 0xa3, 0x50, 0xfa, 0xca, 0x7c, 0x2e, 0x66, 0xd4, 0x38, + 0x2a, 0x8b, 0x3e, 0x86, 0x7c, 0xf0, 0x36, 0x1a, 0x44, 0xd8, 0xab, 0x9f, 0x52, 0xa7, 0x70, 0xf5, + 0x53, 0x80, 0x1f, 0x52, 0xcb, 0xe9, 0xd3, 0x43, 0xe2, 0xf0, 0xb7, 0x3e, 0x56, 0x13, 0x92, 0xc0, + 0x8a, 0xb2, 0xc5, 0x0b, 0x72, 0xb1, 0x04, 0xe1, 0x93, 0x97, 0x68, 0xaa, 0x7f, 0x9d, 0x84, 0x2c, + 0xa6, 0xd4, 0xaf, 0x57, 0x51, 0x19, 0xb2, 0x32, 0x4e, 0xf0, 0xf3, 0xa7, 0x96, 0x3f, 0x3f, 0x5b, + 0xcf, 0x88, 0x00, 0x91, 0x31, 0x78, 0x64, 0x88, 0x44, 0xf0, 0xe4, 0x65, 0x11, 0x1c, 0xdd, 0x85, + 0xa2, 0x04, 0x69, 0x07, 0xba, 0x77, 0x20, 0x0a, 0xb4, 0xda, 0xe2, 0xf9, 0xd9, 0x3a, 0x08, 0xe4, + 0x96, 0xee, 0x1d, 0x60, 0x10, 0x68, 0xf6, 0x8d, 0x9a, 0x50, 0xf8, 0x92, 0x5a, 0x8e, 0xe6, 0xf3, + 0x49, 0xc8, 0x2b, 0xbf, 0xd8, 0x75, 0x9c, 0x4e, 0x55, 0x3e, 0x7c, 0xc3, 0x97, 0xd3, 0xc9, 0x37, + 0x61, 0xc1, 0xa5, 0xd4, 0x17, 0x61, 0xcb, 0xa2, 0x8e, 0xbc, 0x4d, 0x28, 0xc7, 0x5e, 0x32, 0x53, + 0xea, 0x63, 0x89, 0xc3, 0x45, 0x37, 0xd2, 0x42, 0x77, 0x61, 0xc5, 0xd6, 0x3d, 0x5f, 0xe3, 0xf1, + 0xce, 0x9c, 0x6a, 0xcb, 0xf2, 0xad, 0x86, 0x18, 0x6f, 0x93, 0xb3, 0x02, 0x09, 0xf5, 0x1f, 0x13, + 0x50, 0x60, 0x93, 0xb1, 0xf6, 0x2d, 0x83, 0x25, 0x79, 0xdf, 0x3e, 0xf7, 0xb8, 0x05, 0x29, 0xc3, + 0x73, 0xa5, 0x51, 0xf9, 0xe1, 0x5b, 0xef, 0x61, 0xcc, 0x68, 0xe8, 0x73, 0xc8, 0xca, 0x5b, 0x0d, + 0x91, 0x76, 0xa8, 0xd7, 0xa7, 0xa3, 0xd2, 0x36, 0x52, 0x8e, 0xfb, 0xf2, 0x74, 0x74, 0xe2, 0x10, + 0xc0, 0x51, 0x12, 0xba, 0x09, 0x49, 0x43, 0x98, 0x4b, 0xfe, 0xb2, 0xa2, 0xde, 0xc6, 0x49, 0xc3, + 0x51, 0xff, 0x2e, 0x01, 0x0b, 0xd3, 0x0d, 0xcf, 0x3c, 0xe0, 0x36, 0xe4, 0xbd, 0xf1, 0x9e, 0x37, + 0xf1, 0x7c, 0x32, 0x0c, 0xde, 0x31, 0x43, 0x02, 0x6a, 0x41, 0x5e, 0xb7, 0x07, 0xd4, 0xb5, 0xfc, + 0x83, 0xa1, 0xac, 0x44, 0xe3, 0x53, 0x85, 0xa8, 0xce, 0x4a, 0x35, 0x10, 0xc1, 0x53, 0xe9, 0xe0, + 0xdc, 0x17, 0x8f, 0xdd, 0xfc, 0xdc, 0x7f, 0x0d, 0x8a, 0xb6, 0x3e, 0xe4, 0xd7, 0x3c, 0xbe, 0x35, + 0x14, 0xf3, 0x48, 0xe3, 0x82, 0xa4, 0xf5, 0xad, 0x21, 0x51, 0x55, 0xc8, 0x87, 0xca, 0xd0, 0x12, + 0x14, 0xaa, 0xcd, 0x9e, 0x76, 0x6f, 0xe3, 0x81, 0xf6, 0xb0, 0xbe, 0xa3, 0xcc, 0xc9, 0xdc, 0xf4, + 0xcf, 0x13, 0xb0, 0x20, 0xc3, 0x91, 0xcc, 0xf7, 0x5f, 0x87, 0x79, 0x57, 0xdf, 0xf7, 0x83, 0x8a, + 0x24, 0x2d, 0xbc, 0x9a, 0x45, 0x78, 0x56, 0x91, 0x30, 0x56, 0x7c, 0x45, 0x12, 0x79, 0x59, 0x4f, + 0x5d, 0xf9, 0xb2, 0x9e, 0xfe, 0xb9, 0xbc, 0xac, 0xab, 0xbf, 0x06, 0xb0, 0x69, 0xd9, 0xa4, 0x2f, + 0xee, 0x9a, 0xe2, 0xea, 0x4b, 0x96, 0xc3, 0xc9, 0x1b, 0xc7, 0x20, 0x87, 0x6b, 0x35, 0x30, 0xa3, + 0x31, 0xd6, 0xc0, 0x32, 0xe5, 0x66, 0xe4, 0xac, 0x87, 0x8c, 0x35, 0xb0, 0xcc, 0xf0, 0x2d, 0x29, + 0x7d, 0xdd, 0x5b, 0xd2, 0x69, 0x02, 0x96, 0x64, 0xee, 0x1a, 0x86, 0xdf, 0xb7, 0x21, 0x2f, 0xd2, + 0xd8, 0x69, 0x41, 0xc7, 0x5f, 0x93, 0x05, 0xae, 0xd5, 0xc0, 0x39, 0xc1, 0x6e, 0x99, 0x68, 0x1d, + 0x0a, 0x12, 0x1a, 0xf9, 0x15, 0x0e, 0x08, 0x52, 0x9b, 0x0d, 0xff, 0x7d, 0x48, 0xef, 0x5b, 0x36, + 0x91, 0x8e, 0x1e, 0x1b, 0x00, 0xa6, 0x06, 0xd8, 0x9a, 0xc3, 0x1c, 0x5d, 0xcb, 0x05, 0x97, 0x71, + 0x7c, 0x7c, 0xb2, 0xec, 0x8c, 0x8e, 0x4f, 0x54, 0xa0, 0x17, 0xc6, 0x27, 0x70, 0x6c, 0x7c, 0x82, + 0x2d, 0xc6, 0x27, 0xa1, 0xd1, 0xf1, 0x09, 0xd2, 0xcf, 0x65, 0x7c, 0xdb, 0x70, 0xb3, 0x66, 0xeb, + 0xc6, 0xa1, 0x6d, 0x79, 0x3e, 0x31, 0xa3, 0x11, 0x63, 0x03, 0xb2, 0x33, 0x49, 0xe7, 0x55, 0x97, + 0xb3, 0x12, 0xa9, 0xfe, 0x5b, 0x02, 0x8a, 0x5b, 0x44, 0xb7, 0xfd, 0x83, 0xe9, 0xd5, 0x90, 0x4f, + 0x3c, 0x5f, 0x1e, 0x56, 0xfc, 0x1b, 0x7d, 0x00, 0xb9, 0x30, 0x27, 0xb9, 0xf6, 0x95, 0x2c, 0x84, + 0xa2, 0xfb, 0x30, 0xcf, 0xf6, 0x18, 0x1d, 0x07, 0xc5, 0xce, 0x55, 0x0f, 0x30, 0x12, 0xc9, 0x0e, + 0x19, 0x97, 0xf0, 0x24, 0x84, 0xbb, 0x52, 0x06, 0x07, 0x4d, 0xf4, 0xff, 0xa1, 0xc8, 0xdf, 0x0f, + 0x82, 0x9c, 0x2b, 0x73, 0x9d, 0xce, 0x82, 0x78, 0x02, 0x14, 0xf9, 0xd6, 0xff, 0x24, 0x60, 0x65, + 0x47, 0x9f, 0xec, 0x11, 0x19, 0x36, 0x88, 0x89, 0x89, 0x41, 0x5d, 0x13, 0x75, 0xa3, 0xe1, 0xe6, + 0x8a, 0x17, 0xc5, 0x38, 0xe1, 0xf8, 0xa8, 0x13, 0x14, 0x60, 0xc9, 0x48, 0x01, 0xb6, 0x02, 0x19, + 0x87, 0x3a, 0x06, 0x91, 0xb1, 0x48, 0x34, 0x54, 0x2b, 0x1a, 0x6a, 0x4a, 0xe1, 0x63, 0x1f, 0x7f, + 0xaa, 0x6b, 0x53, 0x3f, 0xec, 0x0d, 0x7d, 0x0e, 0xa5, 0x5e, 0xb3, 0x8e, 0x9b, 0xfd, 0x5a, 0xe7, + 0x47, 0x5a, 0xaf, 0xba, 0xdd, 0xab, 0x6e, 0xdc, 0xd5, 0xba, 0x9d, 0xed, 0x2f, 0xee, 0xdd, 0xbf, + 0xfb, 0x81, 0x92, 0x28, 0x95, 0x4f, 0x4e, 0xcb, 0xb7, 0xdb, 0xd5, 0xfa, 0xb6, 0xd8, 0x31, 0x7b, + 0xf4, 0x69, 0x4f, 0xb7, 0x3d, 0x7d, 0xe3, 0x6e, 0x97, 0xda, 0x13, 0x86, 0x61, 0x6e, 0x5d, 0x8c, + 0x9e, 0x57, 0xd1, 0x63, 0x38, 0x71, 0xe9, 0x31, 0x3c, 0x3d, 0xcd, 0x93, 0x97, 0x9c, 0xe6, 0x9b, + 0xb0, 0x62, 0xb8, 0xd4, 0xf3, 0x34, 0x96, 0xfd, 0x13, 0xf3, 0x42, 0x7d, 0xf1, 0xd2, 0xf9, 0xd9, + 0xfa, 0x72, 0x9d, 0xf1, 0x7b, 0x9c, 0x2d, 0xd5, 0x2f, 0x1b, 0x11, 0x12, 0xef, 0x49, 0xfd, 0xfd, + 0x14, 0x4b, 0xa4, 0xac, 0x23, 0xcb, 0x26, 0x03, 0xe2, 0xa1, 0xc7, 0xb0, 0x64, 0xb8, 0xc4, 0x64, + 0x69, 0xbd, 0x6e, 0x6b, 0xde, 0x88, 0x18, 0xd2, 0xa9, 0xff, 0x5f, 0x6c, 0x4e, 0x13, 0x0a, 0x56, + 0xea, 0xa1, 0x54, 0x6f, 0x44, 0x0c, 0xbc, 0x68, 0xcc, 0xb4, 0xd1, 0x97, 0xb0, 0xe4, 0x11, 0xdb, + 0x72, 0xc6, 0x4f, 0x35, 0x83, 0x3a, 0x3e, 0x79, 0x1a, 0xbc, 0x5b, 0x5d, 0xa7, 0xb7, 0xd7, 0xdc, + 0x66, 0x52, 0x75, 0x21, 0x54, 0x43, 0xe7, 0x67, 0xeb, 0x8b, 0xb3, 0x34, 0xbc, 0x28, 0x35, 0xcb, + 0x76, 0xa9, 0x0d, 0x8b, 0xb3, 0xa3, 0x41, 0x2b, 0x72, 0xef, 0xf3, 0x10, 0x12, 0xec, 0x6d, 0x74, + 0x1b, 0x72, 0x2e, 0x19, 0x58, 0x9e, 0xef, 0x0a, 0x33, 0x33, 0x4e, 0x48, 0x61, 0x3b, 0x5f, 0xfc, + 0x14, 0xa7, 0xf4, 0x2b, 0x70, 0xa1, 0x47, 0xb6, 0x59, 0x4c, 0xcb, 0xd3, 0xf7, 0xa4, 0xca, 0x1c, + 0x0e, 0x9a, 0xcc, 0x07, 0xc7, 0x5e, 0x98, 0xa8, 0xf1, 0x6f, 0x46, 0xe3, 0x19, 0x85, 0xfc, 0x61, + 0x12, 0xcf, 0x19, 0x82, 0x5f, 0x38, 0xa6, 0x23, 0xbf, 0x70, 0x5c, 0x81, 0x8c, 0x4d, 0x8e, 0x88, + 0x2d, 0xce, 0x72, 0x2c, 0x1a, 0xef, 0xfc, 0x2c, 0x05, 0xf9, 0xf0, 0x8d, 0x86, 0x9d, 0x04, 0xed, + 0xe6, 0x93, 0xc0, 0x57, 0x43, 0x7a, 0x9b, 0x1c, 0xa3, 0xd7, 0xa6, 0x77, 0x4a, 0x9f, 0x8b, 0x47, + 0xe9, 0x90, 0x1d, 0xdc, 0x27, 0xbd, 0x01, 0xb9, 0x6a, 0xaf, 0xd7, 0x7a, 0xd8, 0x6e, 0x36, 0x94, + 0xaf, 0x12, 0xa5, 0x97, 0x4e, 0x4e, 0xcb, 0xcb, 0x21, 0xa8, 0xea, 0x09, 0x57, 0xe2, 0xa8, 0x7a, + 0xbd, 0xd9, 0xed, 0x37, 0x1b, 0xca, 0xb3, 0xe4, 0x45, 0x14, 0xbf, 0x23, 0xe1, 0x3f, 0x2d, 0xc9, + 0x77, 0x71, 0xb3, 0x5b, 0xc5, 0xac, 0xc3, 0xaf, 0x92, 0xe2, 0xaa, 0x6b, 0xda, 0xa3, 0x4b, 0x46, + 0xba, 0xcb, 0xfa, 0x5c, 0x0b, 0x7e, 0x62, 0xf5, 0x2c, 0x25, 0x7e, 0x7e, 0x30, 0x7d, 0x70, 0x22, + 0xba, 0x39, 0x61, 0xbd, 0xf1, 0x97, 0x3e, 0xae, 0x26, 0x75, 0xa1, 0xb7, 0x1e, 0x8b, 0x24, 0x4c, + 0x8b, 0x0a, 0xf3, 0x78, 0xb7, 0xdd, 0x66, 0xa0, 0x67, 0xe9, 0x0b, 0xb3, 0xc3, 0x63, 0x87, 0xd5, + 0xbf, 0xe8, 0x0e, 0xe4, 0x82, 0x87, 0x40, 0xe5, 0xab, 0xf4, 0x85, 0x01, 0xd5, 0x83, 0x57, 0x4c, + 0xde, 0xe1, 0xd6, 0x6e, 0x9f, 0xff, 0x02, 0xec, 0x59, 0xe6, 0x62, 0x87, 0x07, 0x63, 0xdf, 0xa4, + 0xc7, 0x0e, 0xdb, 0x81, 0xf2, 0x56, 0xed, 0xab, 0x8c, 0xb8, 0x82, 0x08, 0x31, 0xf2, 0x4a, 0xed, + 0x0d, 0xc8, 0xe1, 0xe6, 0x0f, 0xc5, 0x8f, 0xc5, 0x9e, 0x65, 0x2f, 0xe8, 0xc1, 0xe4, 0x4b, 0x62, + 0xc8, 0xde, 0x3a, 0xb8, 0xbb, 0x55, 0xe5, 0x26, 0xbf, 0x88, 0xea, 0xb8, 0xa3, 0x03, 0xdd, 0x21, + 0xe6, 0xf4, 0x37, 0x18, 0x21, 0xeb, 0x9d, 0x5f, 0x84, 0x5c, 0x90, 0x67, 0xa2, 0x35, 0xc8, 0x3e, + 0xe9, 0xe0, 0x47, 0x4d, 0xac, 0xcc, 0x09, 0x1b, 0x06, 0x9c, 0x27, 0xa2, 0x42, 0x28, 0xc3, 0xfc, + 0x4e, 0xb5, 0x5d, 0x7d, 0xd8, 0xc4, 0xc1, 0x85, 0x77, 0x00, 0x90, 0xc9, 0x52, 0x49, 0x91, 0x1d, + 0x84, 0x3a, 0x6b, 0xab, 0x5f, 0x7f, 0xb3, 0x36, 0xf7, 0xd3, 0x6f, 0xd6, 0xe6, 0x9e, 0x9d, 0xaf, + 0x25, 0xbe, 0x3e, 0x5f, 0x4b, 0xfc, 0xe4, 0x7c, 0x2d, 0xf1, 0xaf, 0xe7, 0x6b, 0x89, 0xbd, 0x2c, + 0x0f, 0xe9, 0xf7, 0xff, 0x37, 0x00, 0x00, 0xff, 0xff, 0x62, 0x46, 0x73, 0x55, 0x80, 0x2e, 0x00, + 0x00, } diff --git a/api/types.proto b/api/types.proto index 5d4c972e13..719b88a9c6 100644 --- a/api/types.proto +++ b/api/types.proto @@ -410,16 +410,7 @@ enum TaskState { SHUTDOWN = 640 [(gogoproto.enumvalue_customname)="TaskStateShutdown"]; // orchestrator requested shutdown FAILED = 704 [(gogoproto.enumvalue_customname)="TaskStateFailed"]; // task execution failed with error REJECTED = 768 [(gogoproto.enumvalue_customname)="TaskStateRejected"]; // task could not be executed here. - // TaskStateRemove is used to correctly handle service deletions and scale - // downs. This allows us to keep track of tasks that have been marked for - // deletion, but can't yet be removed because the agent is in the process of - // shutting them down. Once the agent has shut down tasks with desired state - // REMOVE, the task reaper is responsible for removing them. - REMOVE = 800 [(gogoproto.enumvalue_customname)="TaskStateRemove"]; - // TaskStateOrphaned is used to free up resources associated with service - // tasks on unresponsive nodes without having to delete those tasks. This - // state is directly assigned to the task by the orchestrator. - ORPHANED = 832 [(gogoproto.enumvalue_customname)="TaskStateOrphaned"]; + ORPHANED = 832 [(gogoproto.enumvalue_customname)="TaskStateOrphaned"]; // The node on which this task is scheduled is Down for too long // NOTE(stevvooe): The state of a task is actually a lamport clock, in that // given two observations, the greater of the two can be considered diff --git a/manager/orchestrator/global/global.go b/manager/orchestrator/global/global.go index 0cb802bb99..389e1914bb 100644 --- a/manager/orchestrator/global/global.go +++ b/manager/orchestrator/global/global.go @@ -147,7 +147,7 @@ func (g *Orchestrator) Run(ctx context.Context) error { if !orchestrator.IsGlobalService(v.Service) { continue } - orchestrator.SetServiceTasksRemove(ctx, g.store, v.Service) + orchestrator.DeleteServiceTasks(ctx, g.store, v.Service) // delete the service from service map delete(g.globalServices, v.Service.ID) g.restarts.ClearServiceHistory(v.Service.ID) diff --git a/manager/orchestrator/global/global_test.go b/manager/orchestrator/global/global_test.go index 7e934b548b..f2ba0c292c 100644 --- a/manager/orchestrator/global/global_test.go +++ b/manager/orchestrator/global/global_test.go @@ -216,7 +216,7 @@ func TestDeleteService(t *testing.T) { deleteService(t, store, service1) // task should be deleted - observedTask := testutils.WatchTaskUpdate(t, watch) + observedTask := testutils.WatchTaskDelete(t, watch) assert.Equal(t, observedTask.ServiceAnnotations.Name, "name1") assert.Equal(t, observedTask.NodeID, "nodeid1") } diff --git a/manager/orchestrator/replicated/replicated_test.go b/manager/orchestrator/replicated/replicated_test.go index 344975623e..9d23641e4f 100644 --- a/manager/orchestrator/replicated/replicated_test.go +++ b/manager/orchestrator/replicated/replicated_test.go @@ -154,13 +154,13 @@ func TestReplicatedOrchestrator(t *testing.T) { }) assert.NoError(t, err) - observedUpdateRemove1 := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, observedUpdateRemove1.DesiredState, api.TaskStateRemove) - assert.Equal(t, observedUpdateRemove1.ServiceAnnotations.Name, "name2") + observedDeletion1 := testutils.WatchTaskDelete(t, watch) + assert.Equal(t, observedDeletion1.Status.State, api.TaskStateNew) + assert.Equal(t, observedDeletion1.ServiceAnnotations.Name, "name2") - observedUpdateRemove2 := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, observedUpdateRemove2.DesiredState, api.TaskStateRemove) - assert.Equal(t, observedUpdateRemove2.ServiceAnnotations.Name, "name2") + observedDeletion2 := testutils.WatchTaskDelete(t, watch) + assert.Equal(t, observedDeletion2.Status.State, api.TaskStateNew) + assert.Equal(t, observedDeletion2.ServiceAnnotations.Name, "name2") // There should be one remaining task attached to service id2/name2. var liveTasks []*api.Task @@ -383,11 +383,10 @@ func TestReplicatedScaleDown(t *testing.T) { // Replicas was set to 6, but we started with 7 tasks. task7 should // be the one the orchestrator chose to shut down because it was not - // assigned yet. The desired state of task7 will be set to "REMOVE" + // assigned yet. - observedUpdateRemove := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, api.TaskStateRemove, observedUpdateRemove.DesiredState) - assert.Equal(t, "task7", observedUpdateRemove.ID) + observedShutdown := testutils.WatchTaskDelete(t, watch) + assert.Equal(t, "task7", observedShutdown.ID) // Now scale down to 2 instances. err = s.Update(func(tx store.Tx) error { @@ -407,9 +406,8 @@ func TestReplicatedScaleDown(t *testing.T) { shutdowns := make(map[string]int) for i := 0; i != 4; i++ { - observedUpdateDesiredRemove := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, api.TaskStateRemove, observedUpdateDesiredRemove.DesiredState) - shutdowns[observedUpdateDesiredRemove.NodeID]++ + observedShutdown := testutils.WatchTaskDelete(t, watch) + shutdowns[observedShutdown.NodeID]++ } assert.Equal(t, 1, shutdowns["node1"]) diff --git a/manager/orchestrator/replicated/services.go b/manager/orchestrator/replicated/services.go index db01012595..d74167a9d8 100644 --- a/manager/orchestrator/replicated/services.go +++ b/manager/orchestrator/replicated/services.go @@ -50,7 +50,7 @@ func (r *Orchestrator) handleServiceEvent(ctx context.Context, event events.Even if !orchestrator.IsReplicatedService(v.Service) { return } - orchestrator.SetServiceTasksRemove(ctx, r.store, v.Service) + orchestrator.DeleteServiceTasks(ctx, r.store, v.Service) r.restarts.ClearServiceHistory(v.Service.ID) delete(r.reconcileServices, v.Service.ID) case api.EventCreateService: @@ -86,12 +86,6 @@ func (r *Orchestrator) resolveService(ctx context.Context, task *api.Task) *api. return service } -// reconcile decides what actions must be taken depending on the number of -// specificed slots and actual running slots. If the actual running slots are -// fewer than what is requested, it creates new tasks. If the actual running -// slots are more than requested, then it decides which slots must be removed -// and sets desired state of those tasks to REMOVE (the actual removal is handled -// by the task reaper, after the agent shuts the tasks down). func (r *Orchestrator) reconcile(ctx context.Context, service *api.Service) { runningSlots, deadSlots, err := orchestrator.GetRunnableAndDeadSlots(r.store, service.ID) if err != nil { @@ -163,11 +157,7 @@ func (r *Orchestrator) reconcile(ctx context.Context, service *api.Service) { r.updater.Update(ctx, r.cluster, service, sortedSlots[:specifiedSlots]) err = r.store.Batch(func(batch *store.Batch) error { r.deleteTasksMap(ctx, batch, deadSlots) - // for all slots that we are removing, we set the desired state of those tasks - // to REMOVE. Then, the agent is responsible for shutting them down, and the - // task reaper is responsible for actually removing them from the store after - // shutdown. - r.setTasksDesiredState(ctx, batch, sortedSlots[specifiedSlots:], api.TaskStateRemove) + r.deleteTasks(ctx, batch, sortedSlots[specifiedSlots:]) return nil }) if err != nil { @@ -208,34 +198,10 @@ func (r *Orchestrator) addTasks(ctx context.Context, batch *store.Batch, service } } -// setTasksDesiredState sets the desired state for all tasks for the given slots to the -// requested state -func (r *Orchestrator) setTasksDesiredState(ctx context.Context, batch *store.Batch, slots []orchestrator.Slot, newDesiredState api.TaskState) { +func (r *Orchestrator) deleteTasks(ctx context.Context, batch *store.Batch, slots []orchestrator.Slot) { for _, slot := range slots { for _, t := range slot { - err := batch.Update(func(tx store.Tx) error { - // time travel is not allowed. if the current desired state is - // above the one we're trying to go to we can't go backwards. - // we have nothing to do and we should skip to the next task - if t.DesiredState > newDesiredState { - // log a warning, though. we shouln't be trying to rewrite - // a state to an earlier state - log.G(ctx).Warnf( - "cannot update task %v in desired state %v to an earlier desired state %v", - t.ID, t.DesiredState, newDesiredState, - ) - return nil - } - // update desired state - t.DesiredState = newDesiredState - - return store.UpdateTask(tx, t) - }) - - // log an error if we get one - if err != nil { - log.G(ctx).WithError(err).Errorf("failed to update task to %v", newDesiredState.String()) - } + r.deleteTask(ctx, batch, t) } } } diff --git a/manager/orchestrator/replicated/task_reaper_test.go b/manager/orchestrator/replicated/task_reaper_test.go index 3897c73595..8b50ca9523 100644 --- a/manager/orchestrator/replicated/task_reaper_test.go +++ b/manager/orchestrator/replicated/task_reaper_test.go @@ -140,275 +140,3 @@ func TestTaskHistory(t *testing.T) { assert.NoError(t, err) assert.Len(t, foundTasks, 4) } - -// TestTaskStateRemoveOnScaledown tests that on service scale down, task desired -// states are set to REMOVE. Then, when the agent shuts the task down (simulated -// by setting the task state to SHUTDOWN), the task reaper actually deletes -// the tasks from the store. -func TestTaskStateRemoveOnScaledown(t *testing.T) { - ctx := context.Background() - s := store.NewMemoryStore(nil) - assert.NotNil(t, s) - defer s.Close() - - assert.NoError(t, s.Update(func(tx store.Tx) error { - store.CreateCluster(tx, &api.Cluster{ - ID: identity.NewID(), - Spec: api.ClusterSpec{ - Annotations: api.Annotations{ - Name: store.DefaultClusterName, - }, - Orchestration: api.OrchestrationConfig{ - // set TaskHistoryRetentionLimit to a negative value, so - // that it is not considered in this test - TaskHistoryRetentionLimit: -1, - }, - }, - }) - return nil - })) - - taskReaper := taskreaper.New(s) - defer taskReaper.Stop() - orchestrator := NewReplicatedOrchestrator(s) - defer orchestrator.Stop() - - // watch all incoming events - watch, cancel := state.Watch(s.WatchQueue()) - defer cancel() - - service1 := &api.Service{ - ID: "id1", - Spec: api.ServiceSpec{ - Annotations: api.Annotations{ - Name: "name1", - }, - Mode: &api.ServiceSpec_Replicated{ - Replicated: &api.ReplicatedService{ - Replicas: 2, - }, - }, - Task: api.TaskSpec{ - Restart: &api.RestartPolicy{ - Condition: api.RestartOnAny, - Delay: gogotypes.DurationProto(0), - }, - }, - }, - } - - // Create a service with two instances specified before the orchestrator is - // started. This should result in two tasks when the orchestrator - // starts up. - err := s.Update(func(tx store.Tx) error { - assert.NoError(t, store.CreateService(tx, service1)) - return nil - }) - assert.NoError(t, err) - - // Start the orchestrator. - go func() { - assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run() - - observedTask1 := testutils.WatchTaskCreate(t, watch) - assert.Equal(t, observedTask1.Status.State, api.TaskStateNew) - assert.Equal(t, observedTask1.ServiceAnnotations.Name, "name1") - - observedTask2 := testutils.WatchTaskCreate(t, watch) - assert.Equal(t, observedTask2.Status.State, api.TaskStateNew) - assert.Equal(t, observedTask2.ServiceAnnotations.Name, "name1") - - // Set both tasks to RUNNING, so the service is successfully running - updatedTask1 := observedTask1.Copy() - updatedTask1.Status.State = api.TaskStateRunning - updatedTask1.ServiceAnnotations = api.Annotations{Name: "original"} - updatedTask2 := observedTask2.Copy() - updatedTask2.Status.State = api.TaskStateRunning - updatedTask2.ServiceAnnotations = api.Annotations{Name: "original"} - err = s.Update(func(tx store.Tx) error { - assert.NoError(t, store.UpdateTask(tx, updatedTask1)) - assert.NoError(t, store.UpdateTask(tx, updatedTask2)) - return nil - }) - - testutils.Expect(t, watch, state.EventCommit{}) - testutils.Expect(t, watch, api.EventUpdateTask{}) - testutils.Expect(t, watch, api.EventUpdateTask{}) - testutils.Expect(t, watch, state.EventCommit{}) - - // Scale the service down to one instance. This should trigger one of the task - // statuses to be set to REMOVE. - service1.Spec.GetReplicated().Replicas = 1 - err = s.Update(func(tx store.Tx) error { - assert.NoError(t, store.UpdateService(tx, service1)) - return nil - }) - - observedTask3 := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, observedTask3.DesiredState, api.TaskStateRemove) - assert.Equal(t, observedTask3.ServiceAnnotations.Name, "original") - - testutils.Expect(t, watch, state.EventCommit{}) - - // Now the task for which desired state was set to REMOVE must be deleted by the task reaper. - // Shut this task down first (simulates shut down by agent) - updatedTask3 := observedTask3.Copy() - updatedTask3.Status.State = api.TaskStateShutdown - err = s.Update(func(tx store.Tx) error { - assert.NoError(t, store.UpdateTask(tx, updatedTask3)) - return nil - }) - - deletedTask1 := testutils.WatchTaskDelete(t, watch) - - assert.Equal(t, api.TaskStateShutdown, deletedTask1.Status.State) - assert.Equal(t, "original", deletedTask1.ServiceAnnotations.Name) - - var foundTasks []*api.Task - s.View(func(tx store.ReadTx) { - foundTasks, err = store.FindTasks(tx, store.All) - }) - assert.NoError(t, err) - assert.Len(t, foundTasks, 1) -} - -// TestTaskStateRemoveOnServiceRemoval tests that on service removal, task desired -// states are set to REMOVE. Then, when the agent shuts the task down (simulated -// by setting the task state to SHUTDOWN), the task reaper actually deletes -// the tasks from the store. -func TestTaskStateRemoveOnServiceRemoval(t *testing.T) { - ctx := context.Background() - s := store.NewMemoryStore(nil) - assert.NotNil(t, s) - defer s.Close() - - assert.NoError(t, s.Update(func(tx store.Tx) error { - store.CreateCluster(tx, &api.Cluster{ - ID: identity.NewID(), - Spec: api.ClusterSpec{ - Annotations: api.Annotations{ - Name: store.DefaultClusterName, - }, - Orchestration: api.OrchestrationConfig{ - // set TaskHistoryRetentionLimit to a negative value, so - // that it is not considered in this test - TaskHistoryRetentionLimit: -1, - }, - }, - }) - return nil - })) - - taskReaper := taskreaper.New(s) - defer taskReaper.Stop() - orchestrator := NewReplicatedOrchestrator(s) - defer orchestrator.Stop() - - watch, cancel := state.Watch(s.WatchQueue() /*api.EventCreateTask{}, api.EventUpdateTask{}*/) - defer cancel() - - service1 := &api.Service{ - ID: "id1", - Spec: api.ServiceSpec{ - Annotations: api.Annotations{ - Name: "name1", - }, - Mode: &api.ServiceSpec_Replicated{ - Replicated: &api.ReplicatedService{ - Replicas: 2, - }, - }, - Task: api.TaskSpec{ - Restart: &api.RestartPolicy{ - Condition: api.RestartOnAny, - Delay: gogotypes.DurationProto(0), - }, - }, - }, - } - - // Create a service with two instances specified before the orchestrator is - // started. This should result in two tasks when the orchestrator - // starts up. - err := s.Update(func(tx store.Tx) error { - assert.NoError(t, store.CreateService(tx, service1)) - return nil - }) - assert.NoError(t, err) - - // Start the orchestrator. - go func() { - assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run() - - observedTask1 := testutils.WatchTaskCreate(t, watch) - assert.Equal(t, observedTask1.Status.State, api.TaskStateNew) - assert.Equal(t, observedTask1.ServiceAnnotations.Name, "name1") - - observedTask2 := testutils.WatchTaskCreate(t, watch) - assert.Equal(t, observedTask2.Status.State, api.TaskStateNew) - assert.Equal(t, observedTask2.ServiceAnnotations.Name, "name1") - - // Set both tasks to RUNNING, so the service is successfully running - updatedTask1 := observedTask1.Copy() - updatedTask1.Status.State = api.TaskStateRunning - updatedTask1.ServiceAnnotations = api.Annotations{Name: "original"} - updatedTask2 := observedTask2.Copy() - updatedTask2.Status.State = api.TaskStateRunning - updatedTask2.ServiceAnnotations = api.Annotations{Name: "original"} - err = s.Update(func(tx store.Tx) error { - assert.NoError(t, store.UpdateTask(tx, updatedTask1)) - assert.NoError(t, store.UpdateTask(tx, updatedTask2)) - return nil - }) - - testutils.Expect(t, watch, state.EventCommit{}) - testutils.Expect(t, watch, api.EventUpdateTask{}) - testutils.Expect(t, watch, api.EventUpdateTask{}) - testutils.Expect(t, watch, state.EventCommit{}) - - // Delete the service. This should trigger both the task desired statuses to be set to REMOVE. - err = s.Update(func(tx store.Tx) error { - assert.NoError(t, store.DeleteService(tx, service1.ID)) - return nil - }) - - observedTask3 := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, observedTask3.DesiredState, api.TaskStateRemove) - assert.Equal(t, observedTask3.ServiceAnnotations.Name, "original") - observedTask4 := testutils.WatchTaskUpdate(t, watch) - assert.Equal(t, observedTask4.DesiredState, api.TaskStateRemove) - assert.Equal(t, observedTask4.ServiceAnnotations.Name, "original") - - testutils.Expect(t, watch, state.EventCommit{}) - - // Now the tasks must be deleted by the task reaper. - // Shut them down first (simulates shut down by agent) - updatedTask3 := observedTask3.Copy() - updatedTask3.Status.State = api.TaskStateShutdown - updatedTask4 := observedTask4.Copy() - updatedTask4.Status.State = api.TaskStateShutdown - err = s.Update(func(tx store.Tx) error { - assert.NoError(t, store.UpdateTask(tx, updatedTask3)) - assert.NoError(t, store.UpdateTask(tx, updatedTask4)) - return nil - }) - - deletedTask1 := testutils.WatchTaskDelete(t, watch) - assert.Equal(t, api.TaskStateShutdown, deletedTask1.Status.State) - assert.Equal(t, "original", deletedTask1.ServiceAnnotations.Name) - - deletedTask2 := testutils.WatchTaskDelete(t, watch) - assert.Equal(t, api.TaskStateShutdown, deletedTask2.Status.State) - assert.Equal(t, "original", deletedTask1.ServiceAnnotations.Name) - - var foundTasks []*api.Task - s.View(func(tx store.ReadTx) { - foundTasks, err = store.FindTasks(tx, store.All) - }) - assert.NoError(t, err) - assert.Len(t, foundTasks, 0) -} diff --git a/manager/orchestrator/service.go b/manager/orchestrator/service.go index 7356c38cd5..4e52c83abf 100644 --- a/manager/orchestrator/service.go +++ b/manager/orchestrator/service.go @@ -27,10 +27,8 @@ func IsGlobalService(service *api.Service) bool { return ok } -// SetServiceTasksRemove sets the desired state of tasks associated with a service -// to REMOVE, so that they can be properly shut down by the agent and later removed -// by the task reaper. -func SetServiceTasksRemove(ctx context.Context, s *store.MemoryStore, service *api.Service) { +// DeleteServiceTasks deletes the tasks associated with a service. +func DeleteServiceTasks(ctx context.Context, s *store.MemoryStore, service *api.Service) { var ( tasks []*api.Task err error @@ -46,23 +44,8 @@ func SetServiceTasksRemove(ctx context.Context, s *store.MemoryStore, service *a err = s.Batch(func(batch *store.Batch) error { for _, t := range tasks { err := batch.Update(func(tx store.Tx) error { - // time travel is not allowed. if the current desired state is - // above the one we're trying to go to we can't go backwards. - // we have nothing to do and we should skip to the next task - if t.DesiredState > api.TaskStateRemove { - // log a warning, though. we shouln't be trying to rewrite - // a state to an earlier state - log.G(ctx).Warnf( - "cannot update task %v in desired state %v to an earlier desired state %v", - t.ID, t.DesiredState, api.TaskStateRemove, - ) - return nil - } - // update desired state to REMOVE - t.DesiredState = api.TaskStateRemove - - if err := store.UpdateTask(tx, t); err != nil { - log.G(ctx).WithError(err).Errorf("failed transaction: update task desired state to REMOVE") + if err := store.DeleteTask(tx, t.ID); err != nil { + log.G(ctx).WithError(err).Errorf("failed to delete task") } return nil }) diff --git a/manager/orchestrator/taskreaper/task_reaper.go b/manager/orchestrator/taskreaper/task_reaper.go index 602752f91f..e051155dff 100644 --- a/manager/orchestrator/taskreaper/task_reaper.go +++ b/manager/orchestrator/taskreaper/task_reaper.go @@ -31,16 +31,12 @@ type TaskReaper struct { store *store.MemoryStore // taskHistory is the number of tasks to keep taskHistory int64 + dirty map[instanceTuple]struct{} + orphaned []string watcher chan events.Event cancelWatch func() - dirty map[instanceTuple]struct{} - - // List of tasks collected for cleanup, which includes two kinds of tasks - // - serviceless orphaned tasks - // - tasks with desired state REMOVE that have already been shut down - cleanup []string - stopChan chan struct{} - doneChan chan struct{} + stopChan chan struct{} + doneChan chan struct{} } // New creates a new TaskReaper. @@ -61,8 +57,7 @@ func New(store *store.MemoryStore) *TaskReaper { func (tr *TaskReaper) Run() { defer close(tr.doneChan) - var orphanedTasks []*api.Task - var removeTasks []*api.Task + var tasks []*api.Task tr.store.View(func(readTx store.ReadTx) { var err error @@ -71,52 +66,29 @@ func (tr *TaskReaper) Run() { tr.taskHistory = clusters[0].Spec.Orchestration.TaskHistoryRetentionLimit } - // On startup, scan the entire store and inspect orphaned tasks from previous life. - orphanedTasks, err = store.FindTasks(readTx, store.ByTaskState(api.TaskStateOrphaned)) + tasks, err = store.FindTasks(readTx, store.ByTaskState(api.TaskStateOrphaned)) if err != nil { log.G(context.TODO()).WithError(err).Error("failed to find Orphaned tasks in task reaper init") } - removeTasks, err = store.FindTasks(readTx, store.ByDesiredState(api.TaskStateRemove)) - if err != nil { - log.G(context.TODO()).WithError(err).Error("failed to find tasks with desired state REMOVE in task reaper init") - } }) - if len(orphanedTasks)+len(removeTasks) > 0 { - for _, t := range orphanedTasks { - // Do not reap service tasks immediately. - // Let them go through the regular history cleanup process - // of checking TaskHistoryRetentionLimit. + if len(tasks) > 0 { + for _, t := range tasks { + // Do not reap service tasks immediately if t.ServiceID != "" { continue } - // Serviceless tasks can be cleaned up right away since they are not attached to a service. - tr.cleanup = append(tr.cleanup, t.ID) + tr.orphaned = append(tr.orphaned, t.ID) } - // tasks with desired state REMOVE that have progressed beyond SHUTDOWN can be cleaned up - // right away - for _, t := range removeTasks { - if t.Status.State >= api.TaskStateShutdown { - tr.cleanup = append(tr.cleanup, t.ID) - } - } - // Clean up tasks in 'cleanup' right away - if len(tr.cleanup) > 0 { + + if len(tr.orphaned) > 0 { tr.tick() } } timer := time.NewTimer(reaperBatchingInterval) - // Watch for: - // 1. EventCreateTask for cleaning slots, which is the best time to cleanup that node/slot. - // 2. EventUpdateTask for cleaning - // - serviceless orphaned tasks (when orchestrator updates the task status to ORPHANED) - // - tasks which have desired state REMOVE and have been shut down by the agent - // (these are tasks which are associated with slots removed as part of service - // remove or scale down) - // 3. EventUpdateCluster for TaskHistoryRetentionLimit update. for { select { case event := <-tr.watcher: @@ -130,21 +102,14 @@ func (tr *TaskReaper) Run() { }] = struct{}{} case api.EventUpdateTask: t := v.Task - // add serviceless orphaned tasks if t.Status.State >= api.TaskStateOrphaned && t.ServiceID == "" { - tr.cleanup = append(tr.cleanup, t.ID) - } - // add tasks that have progressed beyond SHUTDOWN and have desired state REMOVE. These - // tasks are associated with slots that were removed as part of a service scale down - // or service removal. - if t.DesiredState == api.TaskStateRemove && t.Status.State >= api.TaskStateShutdown { - tr.cleanup = append(tr.cleanup, t.ID) + tr.orphaned = append(tr.orphaned, t.ID) } case api.EventUpdateCluster: tr.taskHistory = v.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit } - if len(tr.dirty)+len(tr.cleanup) > maxDirty { + if len(tr.dirty)+len(tr.orphaned) > maxDirty { timer.Stop() tr.tick() } else { @@ -161,16 +126,16 @@ func (tr *TaskReaper) Run() { } func (tr *TaskReaper) tick() { - if len(tr.dirty) == 0 && len(tr.cleanup) == 0 { + if len(tr.dirty) == 0 && len(tr.orphaned) == 0 { return } defer func() { - tr.cleanup = nil + tr.orphaned = nil }() deleteTasks := make(map[string]struct{}) - for _, tID := range tr.cleanup { + for _, tID := range tr.orphaned { deleteTasks[tID] = struct{}{} } tr.store.View(func(tx store.ReadTx) {