From 3287887761fa5a8da12ca70c5ce53947cbe896ec Mon Sep 17 00:00:00 2001 From: Derek Wang Date: Fri, 6 Sep 2024 18:44:47 -0700 Subject: [PATCH] feat: rolling update for MonoVertex (#2029) --- api/json-schema/schema.json | 44 +- api/openapi-spec/swagger.json | 44 +- config/advanced-install/minimal-crds.yaml | 2 +- .../numaflow.numaproj.io_monovertices.yaml | 24 +- .../numaflow.numaproj.io_monovertices.yaml | 2 +- config/install.yaml | 24 +- config/namespace-install.yaml | 24 +- docs/APIs.md | 268 ++- .../numaflow-transformer-config.yaml | 1 + pkg/apis/numaflow/v1alpha1/generated.pb.go | 1558 +++++++++++------ pkg/apis/numaflow/v1alpha1/generated.proto | 68 +- .../numaflow/v1alpha1/mono_vertex_types.go | 53 +- .../numaflow/v1alpha1/openapi_generated.go | 81 +- pkg/apis/numaflow/v1alpha1/update_strategy.go | 80 + .../numaflow/v1alpha1/update_strategy_test.go | 128 ++ .../v1alpha1/zz_generated.deepcopy.go | 44 + .../server/service/health_status.go | 8 +- pkg/reconciler/monovertex/controller.go | 265 ++- pkg/reconciler/monovertex/controller_test.go | 299 ++++ pkg/reconciler/monovertex/scaling/scaling.go | 8 +- pkg/reconciler/pipeline/controller.go | 2 +- pkg/reconciler/util.go | 21 +- pkg/reconciler/util_test.go | 21 + rust/numaflow-models/Makefile | 2 + rust/numaflow-models/src/models/mod.rs | 4 + .../src/models/mono_vertex_spec.rs | 3 + .../src/models/mono_vertex_status.rs | 19 +- .../src/models/rolling_update_strategy.rs | 34 + .../src/models/update_strategy.rs | 51 + test/fixtures/util.go | 2 +- 30 files changed, 2477 insertions(+), 707 deletions(-) create mode 100644 pkg/apis/numaflow/v1alpha1/update_strategy.go create mode 100644 pkg/apis/numaflow/v1alpha1/update_strategy_test.go create mode 100644 rust/numaflow-models/src/models/rolling_update_strategy.rs create mode 100644 rust/numaflow-models/src/models/update_strategy.rs diff --git a/api/json-schema/schema.json b/api/json-schema/schema.json index d58a13beb6..27796003ba 100644 --- a/api/json-schema/schema.json +++ b/api/json-schema/schema.json @@ -19270,6 +19270,10 @@ }, "type": "array" }, + "updateStrategy": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.UpdateStrategy", + "description": "The strategy to use to replace existing pods with new ones." + }, "volumes": { "items": { "$ref": "#/definitions/io.k8s.api.core.v1.Volume" @@ -19293,11 +19297,11 @@ "x-kubernetes-patch-strategy": "merge" }, "currentHash": { - "description": "If not empty, indicates the version of the MonoVertex used to generate Pods in the sequence [0,currentReplicas).", + "description": "If not empty, indicates the current version of the MonoVertex used to generate Pods.", "type": "string" }, - "currentReplicas": { - "description": "The number of Pods created by the controller from the MonoVertex version indicated by currentHash.", + "desiredReplicas": { + "description": "The number of desired replicas.", "format": "int64", "type": "integer" }, @@ -19336,9 +19340,14 @@ "type": "string" }, "updateHash": { - "description": "If not empty, indicates the version of the MonoVertx used to generate Pods in the sequence [replicas-updatedReplicas,replicas)", + "description": "If not empty, indicates the updated version of the MonoVertex used to generate Pods.", "type": "string" }, + "updatedReadyReplicas": { + "description": "The number of ready Pods created by the controller from the MonoVertex version indicated by updateHash.", + "format": "int64", + "type": "integer" + }, "updatedReplicas": { "description": "The number of Pods created by the controller from the MonoVertex version indicated by updateHash.", "format": "int64", @@ -19803,6 +19812,16 @@ }, "type": "object" }, + "io.numaproj.numaflow.v1alpha1.RollingUpdateStrategy": { + "description": "RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType.", + "properties": { + "maxUnavailable": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString", + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. Defaults to 25%. Example: when this is set to 30%, the old pods can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old pods can be scaled down further, followed by scaling up the new pods, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." + } + }, + "type": "object" + }, "io.numaproj.numaflow.v1alpha1.SASL": { "properties": { "gssapi": { @@ -20318,6 +20337,23 @@ }, "type": "object" }, + "io.numaproj.numaflow.v1alpha1.UpdateStrategy": { + "description": "UpdateStrategy indicates the strategy that the controller will use to perform updates for Vertex or MonoVertex.", + "properties": { + "rollingUpdate": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.RollingUpdateStrategy", + "description": "RollingUpdate is used to communicate parameters when Type is RollingUpdateStrategy." + }, + "type": { + "description": "Type indicates the type of the StatefulSetUpdateStrategy. Default is RollingUpdate.\n\nPossible enum values:\n - `\"RollingUpdate\"`", + "enum": [ + "RollingUpdate" + ], + "type": "string" + } + }, + "type": "object" + }, "io.numaproj.numaflow.v1alpha1.Vertex": { "properties": { "apiVersion": { diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index b3cdb6b120..bb918bac66 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -19266,6 +19266,10 @@ "$ref": "#/definitions/io.k8s.api.core.v1.Toleration" } }, + "updateStrategy": { + "description": "The strategy to use to replace existing pods with new ones.", + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.UpdateStrategy" + }, "volumes": { "type": "array", "items": { @@ -19289,11 +19293,11 @@ "x-kubernetes-patch-strategy": "merge" }, "currentHash": { - "description": "If not empty, indicates the version of the MonoVertex used to generate Pods in the sequence [0,currentReplicas).", + "description": "If not empty, indicates the current version of the MonoVertex used to generate Pods.", "type": "string" }, - "currentReplicas": { - "description": "The number of Pods created by the controller from the MonoVertex version indicated by currentHash.", + "desiredReplicas": { + "description": "The number of desired replicas.", "type": "integer", "format": "int64" }, @@ -19332,9 +19336,14 @@ "type": "string" }, "updateHash": { - "description": "If not empty, indicates the version of the MonoVertx used to generate Pods in the sequence [replicas-updatedReplicas,replicas)", + "description": "If not empty, indicates the updated version of the MonoVertex used to generate Pods.", "type": "string" }, + "updatedReadyReplicas": { + "description": "The number of ready Pods created by the controller from the MonoVertex version indicated by updateHash.", + "type": "integer", + "format": "int64" + }, "updatedReplicas": { "description": "The number of Pods created by the controller from the MonoVertex version indicated by updateHash.", "type": "integer", @@ -19789,6 +19798,16 @@ } } }, + "io.numaproj.numaflow.v1alpha1.RollingUpdateStrategy": { + "description": "RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType.", + "type": "object", + "properties": { + "maxUnavailable": { + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. Defaults to 25%. Example: when this is set to 30%, the old pods can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old pods can be scaled down further, followed by scaling up the new pods, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, "io.numaproj.numaflow.v1alpha1.SASL": { "type": "object", "required": [ @@ -20304,6 +20323,23 @@ } } }, + "io.numaproj.numaflow.v1alpha1.UpdateStrategy": { + "description": "UpdateStrategy indicates the strategy that the controller will use to perform updates for Vertex or MonoVertex.", + "type": "object", + "properties": { + "rollingUpdate": { + "description": "RollingUpdate is used to communicate parameters when Type is RollingUpdateStrategy.", + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.RollingUpdateStrategy" + }, + "type": { + "description": "Type indicates the type of the StatefulSetUpdateStrategy. Default is RollingUpdate.\n\nPossible enum values:\n - `\"RollingUpdate\"`", + "type": "string", + "enum": [ + "RollingUpdate" + ] + } + } + }, "io.numaproj.numaflow.v1alpha1.Vertex": { "type": "object", "required": [ diff --git a/config/advanced-install/minimal-crds.yaml b/config/advanced-install/minimal-crds.yaml index 3e647ee3d6..a8eac9fc22 100644 --- a/config/advanced-install/minimal-crds.yaml +++ b/config/advanced-install/minimal-crds.yaml @@ -69,7 +69,7 @@ spec: - jsonPath: .status.phase name: Phase type: string - - jsonPath: .spec.replicas + - jsonPath: .status.desiredReplicas name: Desired type: string - jsonPath: .status.replicas diff --git a/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml b/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml index 8e503f47d6..02ae281ebd 100644 --- a/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml @@ -21,7 +21,7 @@ spec: - jsonPath: .status.phase name: Phase type: string - - jsonPath: .spec.replicas + - jsonPath: .status.desiredReplicas name: Desired type: string - jsonPath: .status.replicas @@ -4790,6 +4790,23 @@ spec: type: string type: object type: array + updateStrategy: + default: + rollingUpdate: + maxUnavailable: 25% + type: RollingUpdate + properties: + rollingUpdate: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object volumes: items: properties: @@ -5551,7 +5568,7 @@ spec: type: array currentHash: type: string - currentReplicas: + desiredReplicas: format: int32 type: integer lastScaledAt: @@ -5586,6 +5603,9 @@ spec: type: string updateHash: type: string + updatedReadyReplicas: + format: int32 + type: integer updatedReplicas: format: int32 type: integer diff --git a/config/base/crds/minimal/numaflow.numaproj.io_monovertices.yaml b/config/base/crds/minimal/numaflow.numaproj.io_monovertices.yaml index 65cb6b2652..0a3af26fbb 100644 --- a/config/base/crds/minimal/numaflow.numaproj.io_monovertices.yaml +++ b/config/base/crds/minimal/numaflow.numaproj.io_monovertices.yaml @@ -17,7 +17,7 @@ spec: - jsonPath: .status.phase name: Phase type: string - - jsonPath: .spec.replicas + - jsonPath: .status.desiredReplicas name: Desired type: string - jsonPath: .status.replicas diff --git a/config/install.yaml b/config/install.yaml index 8a84ffac83..ac272ddf19 100644 --- a/config/install.yaml +++ b/config/install.yaml @@ -2665,7 +2665,7 @@ spec: - jsonPath: .status.phase name: Phase type: string - - jsonPath: .spec.replicas + - jsonPath: .status.desiredReplicas name: Desired type: string - jsonPath: .status.replicas @@ -7434,6 +7434,23 @@ spec: type: string type: object type: array + updateStrategy: + default: + rollingUpdate: + maxUnavailable: 25% + type: RollingUpdate + properties: + rollingUpdate: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object volumes: items: properties: @@ -8195,7 +8212,7 @@ spec: type: array currentHash: type: string - currentReplicas: + desiredReplicas: format: int32 type: integer lastScaledAt: @@ -8230,6 +8247,9 @@ spec: type: string updateHash: type: string + updatedReadyReplicas: + format: int32 + type: integer updatedReplicas: format: int32 type: integer diff --git a/config/namespace-install.yaml b/config/namespace-install.yaml index c9301892de..12579dc36f 100644 --- a/config/namespace-install.yaml +++ b/config/namespace-install.yaml @@ -2665,7 +2665,7 @@ spec: - jsonPath: .status.phase name: Phase type: string - - jsonPath: .spec.replicas + - jsonPath: .status.desiredReplicas name: Desired type: string - jsonPath: .status.replicas @@ -7434,6 +7434,23 @@ spec: type: string type: object type: array + updateStrategy: + default: + rollingUpdate: + maxUnavailable: 25% + type: RollingUpdate + properties: + rollingUpdate: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object volumes: items: properties: @@ -8195,7 +8212,7 @@ spec: type: array currentHash: type: string - currentReplicas: + desiredReplicas: format: int32 type: integer lastScaledAt: @@ -8230,6 +8247,9 @@ spec: type: string updateHash: type: string + updatedReadyReplicas: + format: int32 + type: integer updatedReplicas: format: int32 type: integer diff --git a/docs/APIs.md b/docs/APIs.md index 97ddf96672..5fd26ad505 100644 --- a/docs/APIs.md +++ b/docs/APIs.md @@ -5791,6 +5791,27 @@ Template for the daemon service deployment. + + + + +updateStrategy
+ UpdateStrategy + + + + + +(Optional) +

+ +The strategy to use to replace existing pods with new ones. +

+ + + + + @@ -6159,6 +6180,27 @@ Template for the daemon service deployment. + + + + +updateStrategy
+ UpdateStrategy + + + + + +(Optional) +

+ +The strategy to use to replace existing pods with new ones. +

+ + + + + @@ -6259,6 +6301,25 @@ labels match the selector). +desiredReplicas
uint32 + + + + +(Optional) +

+ +The number of desired replicas. +

+ + + + + + + + + selector
string @@ -6376,7 +6437,7 @@ The number of pods targeted by this MonoVertex with a Ready Condition. -currentReplicas
uint32 +updatedReplicas
uint32 @@ -6384,7 +6445,7 @@ The number of pods targeted by this MonoVertex with a Ready Condition.

The number of Pods created by the controller from the MonoVertex version -indicated by currentHash. +indicated by updateHash.

@@ -6395,15 +6456,15 @@ indicated by currentHash. -updatedReplicas
uint32 +updatedReadyReplicas
uint32

-The number of Pods created by the controller from the MonoVertex version -indicated by updateHash. +The number of ready Pods created by the controller from the MonoVertex +version indicated by updateHash.

@@ -6421,8 +6482,8 @@ indicated by updateHash.

-If not empty, indicates the version of the MonoVertex used to generate -Pods in the sequence \[0,currentReplicas). +If not empty, indicates the current version of the MonoVertex used to +generate Pods.

@@ -6440,8 +6501,8 @@ Pods in the sequence \[0,currentReplicas).

-If not empty, indicates the version of the MonoVertx used to generate -Pods in the sequence \[replicas-updatedReplicas,replicas) +If not empty, indicates the updated version of the MonoVertex used to +generate Pods.

@@ -8418,6 +8479,81 @@ action is to retry. +

+ +RollingUpdateStrategy +

+ +

+ +(Appears on: +UpdateStrategy) +

+ +

+ +

+ +RollingUpdateStrategy is used to communicate parameter for +RollingUpdateStrategyType. +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + +Description +
+ +maxUnavailable
+k8s.io/apimachinery/pkg/util/intstr.IntOrString +
+ +(Optional) +

+ +The maximum number of pods that can be unavailable during the update. +Value can be an absolute number (ex: 5) or a percentage of desired pods +(ex: 10%). Absolute number is calculated from percentage by rounding +down. Defaults to 25%. Example: when this is set to 30%, the old pods +can be scaled down to 70% of desired pods immediately when the rolling +update starts. Once new pods are ready, old pods can be scaled down +further, followed by scaling up the new pods, ensuring that the total +number of pods available at all times during the update is at least 70% +of desired pods. +

+ +
+

SASL @@ -10659,6 +10795,120 @@ Description +

+ +UpdateStrategy +

+ +

+ +(Appears on: +MonoVertexSpec) +

+ +

+ +

+ +UpdateStrategy indicates the strategy that the controller will use to +perform updates for Vertex or MonoVertex. +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + +Description +
+ +type
+ +UpdateStrategyType +
+ +(Optional) +

+ +Type indicates the type of the StatefulSetUpdateStrategy. Default is +RollingUpdate. +

+ +
+ +rollingUpdate
+ +RollingUpdateStrategy +
+ +(Optional) +

+ +RollingUpdate is used to communicate parameters when Type is +RollingUpdateStrategy. +

+ +
+ +

+ +UpdateStrategyType (string alias) +

+ +

+ +

+ +(Appears on: +UpdateStrategy) +

+ +

+ +

+ +UpdateStrategyType is a string enumeration type that enumerates all +possible update strategies. +

+ +

+

Vertex diff --git a/docs/user-guide/reference/kustomize/numaflow-transformer-config.yaml b/docs/user-guide/reference/kustomize/numaflow-transformer-config.yaml index 39439f10da..37b74aba6e 100644 --- a/docs/user-guide/reference/kustomize/numaflow-transformer-config.yaml +++ b/docs/user-guide/reference/kustomize/numaflow-transformer-config.yaml @@ -435,6 +435,7 @@ varReference: - path: spec/source/udsource/container/command kind: MonoVertex - path: spec/source/udsource/container/env/value + kind: MonoVertex - path: spec/sink/udsink/container/args kind: MonoVertex - path: spec/sink/udsink/container/command diff --git a/pkg/apis/numaflow/v1alpha1/generated.pb.go b/pkg/apis/numaflow/v1alpha1/generated.pb.go index abf3a4e47a..5297014695 100644 --- a/pkg/apis/numaflow/v1alpha1/generated.pb.go +++ b/pkg/apis/numaflow/v1alpha1/generated.pb.go @@ -35,6 +35,8 @@ import ( math_bits "math/bits" reflect "reflect" strings "strings" + + intstr "k8s.io/apimachinery/pkg/util/intstr" ) // Reference imports to suppress errors if they are not otherwise used. @@ -1812,10 +1814,38 @@ func (m *RetryStrategy) XXX_DiscardUnknown() { var xxx_messageInfo_RetryStrategy proto.InternalMessageInfo +func (m *RollingUpdateStrategy) Reset() { *m = RollingUpdateStrategy{} } +func (*RollingUpdateStrategy) ProtoMessage() {} +func (*RollingUpdateStrategy) Descriptor() ([]byte, []int) { + return fileDescriptor_9d0d1b17d3865563, []int{63} +} +func (m *RollingUpdateStrategy) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RollingUpdateStrategy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *RollingUpdateStrategy) XXX_Merge(src proto.Message) { + xxx_messageInfo_RollingUpdateStrategy.Merge(m, src) +} +func (m *RollingUpdateStrategy) XXX_Size() int { + return m.Size() +} +func (m *RollingUpdateStrategy) XXX_DiscardUnknown() { + xxx_messageInfo_RollingUpdateStrategy.DiscardUnknown(m) +} + +var xxx_messageInfo_RollingUpdateStrategy proto.InternalMessageInfo + func (m *SASL) Reset() { *m = SASL{} } func (*SASL) ProtoMessage() {} func (*SASL) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{63} + return fileDescriptor_9d0d1b17d3865563, []int{64} } func (m *SASL) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1843,7 +1873,7 @@ var xxx_messageInfo_SASL proto.InternalMessageInfo func (m *SASLPlain) Reset() { *m = SASLPlain{} } func (*SASLPlain) ProtoMessage() {} func (*SASLPlain) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{64} + return fileDescriptor_9d0d1b17d3865563, []int{65} } func (m *SASLPlain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1871,7 +1901,7 @@ var xxx_messageInfo_SASLPlain proto.InternalMessageInfo func (m *Scale) Reset() { *m = Scale{} } func (*Scale) ProtoMessage() {} func (*Scale) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{65} + return fileDescriptor_9d0d1b17d3865563, []int{66} } func (m *Scale) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1899,7 +1929,7 @@ var xxx_messageInfo_Scale proto.InternalMessageInfo func (m *ServingSource) Reset() { *m = ServingSource{} } func (*ServingSource) ProtoMessage() {} func (*ServingSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{66} + return fileDescriptor_9d0d1b17d3865563, []int{67} } func (m *ServingSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1927,7 +1957,7 @@ var xxx_messageInfo_ServingSource proto.InternalMessageInfo func (m *ServingStore) Reset() { *m = ServingStore{} } func (*ServingStore) ProtoMessage() {} func (*ServingStore) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{67} + return fileDescriptor_9d0d1b17d3865563, []int{68} } func (m *ServingStore) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1955,7 +1985,7 @@ var xxx_messageInfo_ServingStore proto.InternalMessageInfo func (m *SessionWindow) Reset() { *m = SessionWindow{} } func (*SessionWindow) ProtoMessage() {} func (*SessionWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{68} + return fileDescriptor_9d0d1b17d3865563, []int{69} } func (m *SessionWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1983,7 +2013,7 @@ var xxx_messageInfo_SessionWindow proto.InternalMessageInfo func (m *SideInput) Reset() { *m = SideInput{} } func (*SideInput) ProtoMessage() {} func (*SideInput) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{69} + return fileDescriptor_9d0d1b17d3865563, []int{70} } func (m *SideInput) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2011,7 +2041,7 @@ var xxx_messageInfo_SideInput proto.InternalMessageInfo func (m *SideInputTrigger) Reset() { *m = SideInputTrigger{} } func (*SideInputTrigger) ProtoMessage() {} func (*SideInputTrigger) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{70} + return fileDescriptor_9d0d1b17d3865563, []int{71} } func (m *SideInputTrigger) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2039,7 +2069,7 @@ var xxx_messageInfo_SideInputTrigger proto.InternalMessageInfo func (m *SideInputsManagerTemplate) Reset() { *m = SideInputsManagerTemplate{} } func (*SideInputsManagerTemplate) ProtoMessage() {} func (*SideInputsManagerTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{71} + return fileDescriptor_9d0d1b17d3865563, []int{72} } func (m *SideInputsManagerTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2067,7 +2097,7 @@ var xxx_messageInfo_SideInputsManagerTemplate proto.InternalMessageInfo func (m *Sink) Reset() { *m = Sink{} } func (*Sink) ProtoMessage() {} func (*Sink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{72} + return fileDescriptor_9d0d1b17d3865563, []int{73} } func (m *Sink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2095,7 +2125,7 @@ var xxx_messageInfo_Sink proto.InternalMessageInfo func (m *SlidingWindow) Reset() { *m = SlidingWindow{} } func (*SlidingWindow) ProtoMessage() {} func (*SlidingWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{73} + return fileDescriptor_9d0d1b17d3865563, []int{74} } func (m *SlidingWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2123,7 +2153,7 @@ var xxx_messageInfo_SlidingWindow proto.InternalMessageInfo func (m *Source) Reset() { *m = Source{} } func (*Source) ProtoMessage() {} func (*Source) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{74} + return fileDescriptor_9d0d1b17d3865563, []int{75} } func (m *Source) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2151,7 +2181,7 @@ var xxx_messageInfo_Source proto.InternalMessageInfo func (m *Status) Reset() { *m = Status{} } func (*Status) ProtoMessage() {} func (*Status) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{75} + return fileDescriptor_9d0d1b17d3865563, []int{76} } func (m *Status) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2179,7 +2209,7 @@ var xxx_messageInfo_Status proto.InternalMessageInfo func (m *TLS) Reset() { *m = TLS{} } func (*TLS) ProtoMessage() {} func (*TLS) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{76} + return fileDescriptor_9d0d1b17d3865563, []int{77} } func (m *TLS) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2207,7 +2237,7 @@ var xxx_messageInfo_TLS proto.InternalMessageInfo func (m *TagConditions) Reset() { *m = TagConditions{} } func (*TagConditions) ProtoMessage() {} func (*TagConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{77} + return fileDescriptor_9d0d1b17d3865563, []int{78} } func (m *TagConditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2235,7 +2265,7 @@ var xxx_messageInfo_TagConditions proto.InternalMessageInfo func (m *Templates) Reset() { *m = Templates{} } func (*Templates) ProtoMessage() {} func (*Templates) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{78} + return fileDescriptor_9d0d1b17d3865563, []int{79} } func (m *Templates) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2263,7 +2293,7 @@ var xxx_messageInfo_Templates proto.InternalMessageInfo func (m *Transformer) Reset() { *m = Transformer{} } func (*Transformer) ProtoMessage() {} func (*Transformer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{79} + return fileDescriptor_9d0d1b17d3865563, []int{80} } func (m *Transformer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2291,7 +2321,7 @@ var xxx_messageInfo_Transformer proto.InternalMessageInfo func (m *UDF) Reset() { *m = UDF{} } func (*UDF) ProtoMessage() {} func (*UDF) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{80} + return fileDescriptor_9d0d1b17d3865563, []int{81} } func (m *UDF) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2319,7 +2349,7 @@ var xxx_messageInfo_UDF proto.InternalMessageInfo func (m *UDSink) Reset() { *m = UDSink{} } func (*UDSink) ProtoMessage() {} func (*UDSink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{81} + return fileDescriptor_9d0d1b17d3865563, []int{82} } func (m *UDSink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2347,7 +2377,7 @@ var xxx_messageInfo_UDSink proto.InternalMessageInfo func (m *UDSource) Reset() { *m = UDSource{} } func (*UDSource) ProtoMessage() {} func (*UDSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{82} + return fileDescriptor_9d0d1b17d3865563, []int{83} } func (m *UDSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2375,7 +2405,7 @@ var xxx_messageInfo_UDSource proto.InternalMessageInfo func (m *UDTransformer) Reset() { *m = UDTransformer{} } func (*UDTransformer) ProtoMessage() {} func (*UDTransformer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{83} + return fileDescriptor_9d0d1b17d3865563, []int{84} } func (m *UDTransformer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2400,10 +2430,38 @@ func (m *UDTransformer) XXX_DiscardUnknown() { var xxx_messageInfo_UDTransformer proto.InternalMessageInfo +func (m *UpdateStrategy) Reset() { *m = UpdateStrategy{} } +func (*UpdateStrategy) ProtoMessage() {} +func (*UpdateStrategy) Descriptor() ([]byte, []int) { + return fileDescriptor_9d0d1b17d3865563, []int{85} +} +func (m *UpdateStrategy) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UpdateStrategy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *UpdateStrategy) XXX_Merge(src proto.Message) { + xxx_messageInfo_UpdateStrategy.Merge(m, src) +} +func (m *UpdateStrategy) XXX_Size() int { + return m.Size() +} +func (m *UpdateStrategy) XXX_DiscardUnknown() { + xxx_messageInfo_UpdateStrategy.DiscardUnknown(m) +} + +var xxx_messageInfo_UpdateStrategy proto.InternalMessageInfo + func (m *Vertex) Reset() { *m = Vertex{} } func (*Vertex) ProtoMessage() {} func (*Vertex) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{84} + return fileDescriptor_9d0d1b17d3865563, []int{86} } func (m *Vertex) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2431,7 +2489,7 @@ var xxx_messageInfo_Vertex proto.InternalMessageInfo func (m *VertexInstance) Reset() { *m = VertexInstance{} } func (*VertexInstance) ProtoMessage() {} func (*VertexInstance) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{85} + return fileDescriptor_9d0d1b17d3865563, []int{87} } func (m *VertexInstance) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2459,7 +2517,7 @@ var xxx_messageInfo_VertexInstance proto.InternalMessageInfo func (m *VertexLimits) Reset() { *m = VertexLimits{} } func (*VertexLimits) ProtoMessage() {} func (*VertexLimits) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{86} + return fileDescriptor_9d0d1b17d3865563, []int{88} } func (m *VertexLimits) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2487,7 +2545,7 @@ var xxx_messageInfo_VertexLimits proto.InternalMessageInfo func (m *VertexList) Reset() { *m = VertexList{} } func (*VertexList) ProtoMessage() {} func (*VertexList) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{87} + return fileDescriptor_9d0d1b17d3865563, []int{89} } func (m *VertexList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2515,7 +2573,7 @@ var xxx_messageInfo_VertexList proto.InternalMessageInfo func (m *VertexSpec) Reset() { *m = VertexSpec{} } func (*VertexSpec) ProtoMessage() {} func (*VertexSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{88} + return fileDescriptor_9d0d1b17d3865563, []int{90} } func (m *VertexSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2543,7 +2601,7 @@ var xxx_messageInfo_VertexSpec proto.InternalMessageInfo func (m *VertexStatus) Reset() { *m = VertexStatus{} } func (*VertexStatus) ProtoMessage() {} func (*VertexStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{89} + return fileDescriptor_9d0d1b17d3865563, []int{91} } func (m *VertexStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2571,7 +2629,7 @@ var xxx_messageInfo_VertexStatus proto.InternalMessageInfo func (m *VertexTemplate) Reset() { *m = VertexTemplate{} } func (*VertexTemplate) ProtoMessage() {} func (*VertexTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{90} + return fileDescriptor_9d0d1b17d3865563, []int{92} } func (m *VertexTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2599,7 +2657,7 @@ var xxx_messageInfo_VertexTemplate proto.InternalMessageInfo func (m *Watermark) Reset() { *m = Watermark{} } func (*Watermark) ProtoMessage() {} func (*Watermark) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{91} + return fileDescriptor_9d0d1b17d3865563, []int{93} } func (m *Watermark) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2627,7 +2685,7 @@ var xxx_messageInfo_Watermark proto.InternalMessageInfo func (m *Window) Reset() { *m = Window{} } func (*Window) ProtoMessage() {} func (*Window) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{92} + return fileDescriptor_9d0d1b17d3865563, []int{94} } func (m *Window) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2724,6 +2782,7 @@ func init() { proto.RegisterType((*RedisConfig)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisConfig") proto.RegisterType((*RedisSettings)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisSettings") proto.RegisterType((*RetryStrategy)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RetryStrategy") + proto.RegisterType((*RollingUpdateStrategy)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RollingUpdateStrategy") proto.RegisterType((*SASL)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.SASL") proto.RegisterType((*SASLPlain)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.SASLPlain") proto.RegisterType((*Scale)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Scale") @@ -2746,6 +2805,7 @@ func init() { proto.RegisterType((*UDSink)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.UDSink") proto.RegisterType((*UDSource)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.UDSource") proto.RegisterType((*UDTransformer)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.UDTransformer") + proto.RegisterType((*UpdateStrategy)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.UpdateStrategy") proto.RegisterType((*Vertex)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Vertex") proto.RegisterType((*VertexInstance)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.VertexInstance") proto.RegisterType((*VertexLimits)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.VertexLimits") @@ -2762,490 +2822,502 @@ func init() { } var fileDescriptor_9d0d1b17d3865563 = []byte{ - // 7719 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x24, 0xd7, - 0x95, 0x9e, 0xfa, 0xbf, 0xfb, 0x34, 0xc9, 0xe1, 0xdc, 0x19, 0x8d, 0x38, 0xa3, 0xd1, 0x70, 0xb6, - 0xb4, 0xd2, 0xce, 0x66, 0xbd, 0x64, 0xc4, 0xe8, 0xcf, 0xfb, 0x63, 0x89, 0x4d, 0x0e, 0x39, 0x9c, - 0x21, 0x67, 0xe8, 0xd3, 0xe4, 0x48, 0x5e, 0x65, 0xad, 0x14, 0xab, 0x2e, 0x9b, 0x25, 0x56, 0x57, - 0xb5, 0xaa, 0xaa, 0x39, 0x43, 0x6d, 0x02, 0xef, 0xae, 0x02, 0x48, 0x41, 0x10, 0x24, 0xd8, 0x27, - 0x03, 0x81, 0x13, 0x24, 0x48, 0xe0, 0x07, 0xc3, 0x79, 0x08, 0xe0, 0x3c, 0x18, 0x48, 0x1c, 0x07, - 0x41, 0xe2, 0x04, 0xf9, 0xf1, 0x43, 0x80, 0x28, 0x2f, 0x44, 0xcc, 0x20, 0x0f, 0x09, 0x10, 0xc3, - 0x88, 0x91, 0xc4, 0x1e, 0x18, 0x71, 0x70, 0xff, 0xea, 0xaf, 0xab, 0x67, 0xc8, 0x2e, 0x72, 0x34, - 0xca, 0xea, 0xad, 0xea, 0x9e, 0x73, 0xbf, 0x73, 0xeb, 0xd6, 0xfd, 0x39, 0xf7, 0x9c, 0x73, 0xef, - 0x85, 0xe5, 0x8e, 0x15, 0xec, 0xf4, 0xb7, 0x66, 0x0c, 0xb7, 0x3b, 0xeb, 0xf4, 0xbb, 0x7a, 0xcf, - 0x73, 0xdf, 0xe3, 0x0f, 0xdb, 0xb6, 0x7b, 0x6f, 0xb6, 0xb7, 0xdb, 0x99, 0xd5, 0x7b, 0x96, 0x1f, - 0xa5, 0xec, 0xbd, 0xa4, 0xdb, 0xbd, 0x1d, 0xfd, 0xa5, 0xd9, 0x0e, 0x75, 0xa8, 0xa7, 0x07, 0xd4, - 0x9c, 0xe9, 0x79, 0x6e, 0xe0, 0x92, 0xd7, 0x22, 0xa0, 0x19, 0x05, 0x34, 0xa3, 0xb2, 0xcd, 0xf4, - 0x76, 0x3b, 0x33, 0x0c, 0x28, 0x4a, 0x51, 0x40, 0x97, 0x7e, 0x33, 0x56, 0x82, 0x8e, 0xdb, 0x71, - 0x67, 0x39, 0xde, 0x56, 0x7f, 0x9b, 0xbf, 0xf1, 0x17, 0xfe, 0x24, 0xe4, 0x5c, 0xd2, 0x76, 0x5f, - 0xf7, 0x67, 0x2c, 0x97, 0x15, 0x6b, 0xd6, 0x70, 0x3d, 0x3a, 0xbb, 0x37, 0x50, 0x96, 0x4b, 0x2f, - 0x47, 0x3c, 0x5d, 0xdd, 0xd8, 0xb1, 0x1c, 0xea, 0xed, 0xab, 0x6f, 0x99, 0xf5, 0xa8, 0xef, 0xf6, - 0x3d, 0x83, 0x1e, 0x2b, 0x97, 0x3f, 0xdb, 0xa5, 0x81, 0x9e, 0x25, 0x6b, 0x76, 0x58, 0x2e, 0xaf, - 0xef, 0x04, 0x56, 0x77, 0x50, 0xcc, 0xab, 0x8f, 0xca, 0xe0, 0x1b, 0x3b, 0xb4, 0xab, 0xa7, 0xf3, - 0x69, 0xdf, 0x07, 0x38, 0x37, 0xbf, 0xe5, 0x07, 0x9e, 0x6e, 0x04, 0xeb, 0xae, 0xb9, 0x41, 0xbb, - 0x3d, 0x5b, 0x0f, 0x28, 0xd9, 0x85, 0x3a, 0x2b, 0x9b, 0xa9, 0x07, 0xfa, 0x54, 0xe1, 0x6a, 0xe1, - 0x5a, 0x73, 0x6e, 0x7e, 0x66, 0xc4, 0x7f, 0x31, 0xb3, 0x26, 0x81, 0x5a, 0x63, 0x87, 0x07, 0xd3, - 0x75, 0xf5, 0x86, 0xa1, 0x00, 0xf2, 0xf5, 0x02, 0x8c, 0x39, 0xae, 0x49, 0xdb, 0xd4, 0xa6, 0x46, - 0xe0, 0x7a, 0x53, 0xc5, 0xab, 0xa5, 0x6b, 0xcd, 0xb9, 0xaf, 0x8e, 0x2c, 0x31, 0xe3, 0x8b, 0x66, - 0x6e, 0xc7, 0x04, 0x5c, 0x77, 0x02, 0x6f, 0xbf, 0x75, 0xfe, 0x07, 0x07, 0xd3, 0x4f, 0x1d, 0x1e, - 0x4c, 0x8f, 0xc5, 0x49, 0x98, 0x28, 0x09, 0xd9, 0x84, 0x66, 0xe0, 0xda, 0xac, 0xca, 0x2c, 0xd7, - 0xf1, 0xa7, 0x4a, 0xbc, 0x60, 0x57, 0x66, 0x44, 0x6d, 0x33, 0xf1, 0x33, 0xac, 0xb9, 0xcc, 0xec, - 0xbd, 0x34, 0xb3, 0x11, 0xb2, 0xb5, 0xce, 0x49, 0xe0, 0x66, 0x94, 0xe6, 0x63, 0x1c, 0x87, 0x50, - 0x38, 0xe3, 0x53, 0xa3, 0xef, 0x59, 0xc1, 0xfe, 0x82, 0xeb, 0x04, 0xf4, 0x7e, 0x30, 0x55, 0xe6, - 0xb5, 0xfc, 0x62, 0x16, 0xf4, 0xba, 0x6b, 0xb6, 0x93, 0xdc, 0xad, 0x73, 0x87, 0x07, 0xd3, 0x67, - 0x52, 0x89, 0x98, 0xc6, 0x24, 0x0e, 0x4c, 0x5a, 0x5d, 0xbd, 0x43, 0xd7, 0xfb, 0xb6, 0xdd, 0xa6, - 0x86, 0x47, 0x03, 0x7f, 0xaa, 0xc2, 0x3f, 0xe1, 0x5a, 0x96, 0x9c, 0x55, 0xd7, 0xd0, 0xed, 0x3b, - 0x5b, 0xef, 0x51, 0x23, 0x40, 0xba, 0x4d, 0x3d, 0xea, 0x18, 0xb4, 0x35, 0x25, 0x3f, 0x66, 0x72, - 0x25, 0x85, 0x84, 0x03, 0xd8, 0x64, 0x19, 0xce, 0xf6, 0x3c, 0xcb, 0xe5, 0x45, 0xb0, 0x75, 0xdf, - 0xbf, 0xad, 0x77, 0xe9, 0x54, 0xf5, 0x6a, 0xe1, 0x5a, 0xa3, 0x75, 0x51, 0xc2, 0x9c, 0x5d, 0x4f, - 0x33, 0xe0, 0x60, 0x1e, 0x72, 0x0d, 0xea, 0x2a, 0x71, 0xaa, 0x76, 0xb5, 0x70, 0xad, 0x22, 0xda, - 0x8e, 0xca, 0x8b, 0x21, 0x95, 0x2c, 0x41, 0x5d, 0xdf, 0xde, 0xb6, 0x1c, 0xc6, 0x59, 0xe7, 0x55, - 0x78, 0x39, 0xeb, 0xd3, 0xe6, 0x25, 0x8f, 0xc0, 0x51, 0x6f, 0x18, 0xe6, 0x25, 0x37, 0x81, 0xf8, - 0xd4, 0xdb, 0xb3, 0x0c, 0x3a, 0x6f, 0x18, 0x6e, 0xdf, 0x09, 0x78, 0xd9, 0x1b, 0xbc, 0xec, 0x97, - 0x64, 0xd9, 0x49, 0x7b, 0x80, 0x03, 0x33, 0x72, 0x91, 0x37, 0x61, 0x52, 0x76, 0xbb, 0xa8, 0x16, - 0x80, 0x23, 0x9d, 0x67, 0x15, 0x89, 0x29, 0x1a, 0x0e, 0x70, 0x13, 0x13, 0x2e, 0xeb, 0xfd, 0xc0, - 0xed, 0x32, 0xc8, 0xa4, 0xd0, 0x0d, 0x77, 0x97, 0x3a, 0x53, 0xcd, 0xab, 0x85, 0x6b, 0xf5, 0xd6, - 0xd5, 0xc3, 0x83, 0xe9, 0xcb, 0xf3, 0x0f, 0xe1, 0xc3, 0x87, 0xa2, 0x90, 0x3b, 0xd0, 0x30, 0x1d, - 0x7f, 0xdd, 0xb5, 0x2d, 0x63, 0x7f, 0x6a, 0x8c, 0x17, 0xf0, 0x25, 0xf9, 0xa9, 0x8d, 0xc5, 0xdb, - 0x6d, 0x41, 0x78, 0x70, 0x30, 0x7d, 0x79, 0x70, 0x74, 0x9c, 0x09, 0xe9, 0x18, 0x61, 0x90, 0x35, - 0x0e, 0xb8, 0xe0, 0x3a, 0xdb, 0x56, 0x67, 0x6a, 0x9c, 0xff, 0x8d, 0xab, 0x43, 0x1a, 0xf4, 0xe2, - 0xed, 0xb6, 0xe0, 0x6b, 0x8d, 0x4b, 0x71, 0xe2, 0x15, 0x23, 0x04, 0x62, 0xc2, 0x84, 0x1a, 0x57, - 0x17, 0x6c, 0xdd, 0xea, 0xfa, 0x53, 0x13, 0xbc, 0xf1, 0xfe, 0xea, 0x10, 0x4c, 0x8c, 0x33, 0xb7, - 0x2e, 0xc8, 0x4f, 0x99, 0x48, 0x24, 0xfb, 0x98, 0xc2, 0xbc, 0xf4, 0x06, 0x9c, 0x1d, 0x18, 0x1b, - 0xc8, 0x24, 0x94, 0x76, 0xe9, 0x3e, 0x1f, 0xfa, 0x1a, 0xc8, 0x1e, 0xc9, 0x79, 0xa8, 0xec, 0xe9, - 0x76, 0x9f, 0x4e, 0x15, 0x79, 0x9a, 0x78, 0xf9, 0xad, 0xe2, 0xeb, 0x05, 0xed, 0xef, 0x96, 0x60, - 0x4c, 0x8d, 0x38, 0x6d, 0xcb, 0xd9, 0x25, 0x6f, 0x41, 0xc9, 0x76, 0x3b, 0x72, 0xdc, 0xfc, 0x9d, - 0x91, 0x47, 0xb1, 0x55, 0xb7, 0xd3, 0xaa, 0x1d, 0x1e, 0x4c, 0x97, 0x56, 0xdd, 0x0e, 0x32, 0x44, - 0x62, 0x40, 0x65, 0x57, 0xdf, 0xde, 0xd5, 0x79, 0x19, 0x9a, 0x73, 0xad, 0x91, 0xa1, 0x6f, 0x31, - 0x14, 0x56, 0xd6, 0x56, 0xe3, 0xf0, 0x60, 0xba, 0xc2, 0x5f, 0x51, 0x60, 0x13, 0x17, 0x1a, 0x5b, - 0xb6, 0x6e, 0xec, 0xee, 0xb8, 0x36, 0x9d, 0x2a, 0xe5, 0x14, 0xd4, 0x52, 0x48, 0xe2, 0x37, 0x87, - 0xaf, 0x18, 0xc9, 0x20, 0x06, 0x54, 0xfb, 0xa6, 0x6f, 0x39, 0xbb, 0x72, 0x0c, 0x7c, 0x63, 0x64, - 0x69, 0x9b, 0x8b, 0xfc, 0x9b, 0xe0, 0xf0, 0x60, 0xba, 0x2a, 0x9e, 0x51, 0x42, 0x6b, 0x3f, 0x6e, - 0xc2, 0x84, 0xfa, 0x49, 0x77, 0xa9, 0x17, 0xd0, 0xfb, 0xe4, 0x2a, 0x94, 0x1d, 0xd6, 0x35, 0xf9, - 0x4f, 0x6e, 0x8d, 0xc9, 0xe6, 0x52, 0xe6, 0x5d, 0x92, 0x53, 0x58, 0xc9, 0x44, 0x53, 0x91, 0x15, - 0x3e, 0x7a, 0xc9, 0xda, 0x1c, 0x46, 0x94, 0x4c, 0x3c, 0xa3, 0x84, 0x26, 0xef, 0x40, 0x99, 0x7f, - 0xbc, 0xa8, 0xea, 0xdf, 0x1d, 0x5d, 0x04, 0xfb, 0xf4, 0x3a, 0xfb, 0x02, 0xfe, 0xe1, 0x1c, 0x94, - 0x35, 0xc5, 0xbe, 0xb9, 0x2d, 0x2b, 0xf6, 0x77, 0x72, 0x54, 0xec, 0x92, 0x68, 0x8a, 0x9b, 0x8b, - 0x4b, 0xc8, 0x10, 0xc9, 0x5f, 0x2f, 0xc0, 0x59, 0xc3, 0x75, 0x02, 0x9d, 0xa9, 0x1a, 0x6a, 0x92, - 0x9d, 0xaa, 0x70, 0x39, 0x37, 0x47, 0x96, 0xb3, 0x90, 0x46, 0x6c, 0x3d, 0xcd, 0xe6, 0x8c, 0x81, - 0x64, 0x1c, 0x94, 0x4d, 0xfe, 0x66, 0x01, 0x9e, 0x66, 0x63, 0xf9, 0x00, 0x33, 0x9f, 0x81, 0x4e, - 0xb6, 0x54, 0x17, 0x0f, 0x0f, 0xa6, 0x9f, 0x5e, 0xc9, 0x12, 0x86, 0xd9, 0x65, 0x60, 0xa5, 0x3b, - 0xa7, 0x0f, 0xaa, 0x25, 0x7c, 0x76, 0x6b, 0xce, 0xad, 0x9e, 0xa4, 0xaa, 0xd3, 0x7a, 0x56, 0x36, - 0xe5, 0x2c, 0xcd, 0x0e, 0xb3, 0x4a, 0x41, 0xae, 0x43, 0x6d, 0xcf, 0xb5, 0xfb, 0x5d, 0xea, 0x4f, - 0xd5, 0xf9, 0x10, 0x7b, 0x29, 0x6b, 0x88, 0xbd, 0xcb, 0x59, 0x5a, 0x67, 0x24, 0x7c, 0x4d, 0xbc, - 0xfb, 0xa8, 0xf2, 0x12, 0x0b, 0xaa, 0xb6, 0xd5, 0xb5, 0x02, 0x9f, 0x4f, 0x9c, 0xcd, 0xb9, 0xeb, - 0x23, 0x7f, 0x96, 0xe8, 0xa2, 0xab, 0x1c, 0x4c, 0xf4, 0x1a, 0xf1, 0x8c, 0x52, 0x00, 0x1b, 0x0a, - 0x7d, 0x43, 0xb7, 0xc5, 0xc4, 0xda, 0x9c, 0xfb, 0xd2, 0xe8, 0xdd, 0x86, 0xa1, 0xb4, 0xc6, 0xe5, - 0x37, 0x55, 0xf8, 0x2b, 0x0a, 0x6c, 0xf2, 0xfb, 0x30, 0x91, 0xf8, 0x9b, 0xfe, 0x54, 0x93, 0xd7, - 0xce, 0x73, 0x59, 0xb5, 0x13, 0x72, 0x45, 0x33, 0x4f, 0xa2, 0x85, 0xf8, 0x98, 0x02, 0x23, 0xb7, - 0xa0, 0xee, 0x5b, 0x26, 0x35, 0x74, 0xcf, 0x9f, 0x1a, 0x3b, 0x0a, 0xf0, 0xa4, 0x04, 0xae, 0xb7, - 0x65, 0x36, 0x0c, 0x01, 0xc8, 0x0c, 0x40, 0x4f, 0xf7, 0x02, 0x4b, 0x28, 0xaa, 0xe3, 0x5c, 0x69, - 0x9a, 0x38, 0x3c, 0x98, 0x86, 0xf5, 0x30, 0x15, 0x63, 0x1c, 0x8c, 0x9f, 0xe5, 0x5d, 0x71, 0x7a, - 0xfd, 0x40, 0x4c, 0xac, 0x0d, 0xc1, 0xdf, 0x0e, 0x53, 0x31, 0xc6, 0x41, 0xbe, 0x5d, 0x80, 0x67, - 0xa3, 0xd7, 0xc1, 0x4e, 0x76, 0xe6, 0xc4, 0x3b, 0xd9, 0xf4, 0xe1, 0xc1, 0xf4, 0xb3, 0xed, 0xe1, - 0x22, 0xf1, 0x61, 0xe5, 0xd1, 0xde, 0x82, 0xf1, 0xf9, 0x7e, 0xb0, 0xe3, 0x7a, 0xd6, 0x07, 0x5c, - 0xe9, 0x26, 0x4b, 0x50, 0x09, 0xb8, 0xf2, 0x24, 0xe6, 0xe5, 0x17, 0xb2, 0xaa, 0x5a, 0x28, 0xb2, - 0xb7, 0xe8, 0xbe, 0xd2, 0x06, 0xc4, 0xfc, 0x28, 0x94, 0x29, 0x91, 0x5d, 0xfb, 0xcb, 0x05, 0xa8, - 0xb5, 0x74, 0x63, 0xd7, 0xdd, 0xde, 0x26, 0x6f, 0x43, 0xdd, 0x72, 0x02, 0xea, 0xed, 0xe9, 0xb6, - 0x84, 0x9d, 0x89, 0xc1, 0x86, 0x2b, 0xb1, 0xe8, 0xbb, 0xd9, 0x9a, 0x87, 0x09, 0x5a, 0xec, 0xcb, - 0xb5, 0x02, 0xd7, 0x47, 0x57, 0x24, 0x06, 0x86, 0x68, 0x64, 0x1a, 0x2a, 0x7e, 0x40, 0x7b, 0x3e, - 0x9f, 0x79, 0xc6, 0x45, 0x31, 0xda, 0x2c, 0x01, 0x45, 0xba, 0xf6, 0x77, 0x0a, 0xd0, 0x68, 0xe9, - 0xbe, 0x65, 0xb0, 0xaf, 0x24, 0x0b, 0x50, 0xee, 0xfb, 0xd4, 0x3b, 0xde, 0xb7, 0xf1, 0xc9, 0x62, - 0xd3, 0xa7, 0x1e, 0xf2, 0xcc, 0xe4, 0x0e, 0xd4, 0x7b, 0xba, 0xef, 0xdf, 0x73, 0x3d, 0x53, 0x4e, - 0x78, 0x47, 0x04, 0x12, 0xca, 0xb9, 0xcc, 0x8a, 0x21, 0x88, 0xd6, 0x84, 0x68, 0xc6, 0xd7, 0x7e, - 0x5a, 0x80, 0x73, 0xad, 0xfe, 0xf6, 0x36, 0xf5, 0xa4, 0x2e, 0x2a, 0xb5, 0x3c, 0x0a, 0x15, 0x8f, - 0x9a, 0x96, 0x2f, 0xcb, 0xbe, 0x38, 0x72, 0x0b, 0x42, 0x86, 0x22, 0x95, 0x4a, 0x5e, 0x5f, 0x3c, - 0x01, 0x05, 0x3a, 0xe9, 0x43, 0xe3, 0x3d, 0x1a, 0xf8, 0x81, 0x47, 0xf5, 0xae, 0xfc, 0xba, 0x1b, - 0x23, 0x8b, 0xba, 0x49, 0x83, 0x36, 0x47, 0x8a, 0xeb, 0xb0, 0x61, 0x22, 0x46, 0x92, 0xb4, 0xef, - 0x57, 0x60, 0x6c, 0xc1, 0xed, 0x6e, 0x59, 0x0e, 0x35, 0xaf, 0x9b, 0x1d, 0x4a, 0xde, 0x85, 0x32, - 0x35, 0x3b, 0x54, 0x7e, 0xed, 0xe8, 0xd3, 0x3d, 0x03, 0x8b, 0x94, 0x16, 0xf6, 0x86, 0x1c, 0x98, - 0xac, 0xc2, 0xc4, 0xb6, 0xe7, 0x76, 0xc5, 0x08, 0xba, 0xb1, 0xdf, 0x93, 0x1a, 0x6b, 0xeb, 0x57, - 0xd5, 0xa8, 0xb4, 0x94, 0xa0, 0x3e, 0x38, 0x98, 0x86, 0xe8, 0x0d, 0x53, 0x79, 0xc9, 0xdb, 0x30, - 0x15, 0xa5, 0x84, 0x43, 0xc9, 0x02, 0x5b, 0x44, 0x70, 0x8d, 0xa5, 0xd2, 0xba, 0x7c, 0x78, 0x30, - 0x3d, 0xb5, 0x34, 0x84, 0x07, 0x87, 0xe6, 0x26, 0x1f, 0x15, 0x60, 0x32, 0x22, 0x8a, 0xe1, 0x5d, - 0x2a, 0x2a, 0x27, 0x34, 0x6f, 0xf0, 0xd5, 0xd6, 0x52, 0x4a, 0x04, 0x0e, 0x08, 0x25, 0x4b, 0x30, - 0x16, 0xb8, 0xb1, 0xfa, 0xaa, 0xf0, 0xfa, 0xd2, 0x94, 0x79, 0x60, 0xc3, 0x1d, 0x5a, 0x5b, 0x89, - 0x7c, 0x04, 0xe1, 0x82, 0x7a, 0x4f, 0xd5, 0x54, 0x95, 0xd7, 0xd4, 0xa5, 0xc3, 0x83, 0xe9, 0x0b, - 0x1b, 0x99, 0x1c, 0x38, 0x24, 0x27, 0xf9, 0xa3, 0x02, 0x4c, 0x28, 0x92, 0xac, 0xa3, 0xda, 0x49, - 0xd6, 0x11, 0x61, 0x2d, 0x62, 0x23, 0x21, 0x00, 0x53, 0x02, 0xb5, 0x9f, 0x95, 0xa1, 0x11, 0x0e, - 0xb0, 0xe4, 0x79, 0xa8, 0xf0, 0x85, 0xbf, 0xd4, 0x9b, 0xc3, 0x99, 0x93, 0xdb, 0x07, 0x50, 0xd0, - 0xc8, 0x0b, 0x50, 0x33, 0xdc, 0x6e, 0x57, 0x77, 0x4c, 0x6e, 0xcc, 0x69, 0xb4, 0x9a, 0x4c, 0x61, - 0x58, 0x10, 0x49, 0xa8, 0x68, 0xe4, 0x32, 0x94, 0x75, 0xaf, 0x23, 0xec, 0x2a, 0x0d, 0x31, 0x1e, - 0xcd, 0x7b, 0x1d, 0x1f, 0x79, 0x2a, 0xf9, 0x22, 0x94, 0xa8, 0xb3, 0x37, 0x55, 0x1e, 0xae, 0x91, - 0x5c, 0x77, 0xf6, 0xee, 0xea, 0x5e, 0xab, 0x29, 0xcb, 0x50, 0xba, 0xee, 0xec, 0x21, 0xcb, 0x43, - 0x56, 0xa1, 0x46, 0x9d, 0x3d, 0xf6, 0xef, 0xa5, 0xc1, 0xe3, 0x57, 0x86, 0x64, 0x67, 0x2c, 0x52, - 0x39, 0x0f, 0xf5, 0x1a, 0x99, 0x8c, 0x0a, 0x82, 0x7c, 0x05, 0xc6, 0x84, 0x8a, 0xb3, 0xc6, 0xfe, - 0x89, 0x3f, 0x55, 0xe5, 0x90, 0xd3, 0xc3, 0x75, 0x24, 0xce, 0x17, 0x19, 0x98, 0x62, 0x89, 0x3e, - 0x26, 0xa0, 0xc8, 0x57, 0xa0, 0xa1, 0xd6, 0xa3, 0xea, 0xcf, 0x66, 0xda, 0x66, 0xd4, 0x22, 0x16, - 0xe9, 0xfb, 0x7d, 0xcb, 0xa3, 0x5d, 0xea, 0x04, 0x7e, 0xeb, 0xac, 0x5a, 0xad, 0x2b, 0xaa, 0x8f, - 0x11, 0x1a, 0xd9, 0x1a, 0x34, 0x32, 0x09, 0x0b, 0xc9, 0xf3, 0x43, 0x46, 0xf5, 0x11, 0x2c, 0x4c, - 0x5f, 0x85, 0x33, 0xa1, 0x15, 0x48, 0x1a, 0x12, 0x84, 0xcd, 0xe4, 0x65, 0x96, 0x7d, 0x25, 0x49, - 0x7a, 0x70, 0x30, 0xfd, 0x5c, 0x86, 0x29, 0x21, 0x62, 0xc0, 0x34, 0x98, 0xf6, 0xbd, 0x12, 0x0c, - 0x6a, 0xff, 0xc9, 0x4a, 0x2b, 0x9c, 0x74, 0xa5, 0xa5, 0x3f, 0x48, 0x0c, 0x9f, 0xaf, 0xcb, 0x6c, - 0xf9, 0x3f, 0x2a, 0xeb, 0xc7, 0x94, 0x4e, 0xfa, 0xc7, 0x3c, 0x29, 0x7d, 0x47, 0xfb, 0xb8, 0x0c, - 0x13, 0x8b, 0x3a, 0xed, 0xba, 0xce, 0x23, 0xd7, 0x42, 0x85, 0x27, 0x62, 0x2d, 0x74, 0x0d, 0xea, - 0x1e, 0xed, 0xd9, 0x96, 0xa1, 0x0b, 0xe5, 0x4b, 0xda, 0x1e, 0x51, 0xa6, 0x61, 0x48, 0x1d, 0xb2, - 0x06, 0x2e, 0x3d, 0x91, 0x6b, 0xe0, 0xf2, 0xa7, 0xbf, 0x06, 0xd6, 0xfe, 0xa8, 0x08, 0x5c, 0x51, - 0x21, 0x57, 0xa1, 0xcc, 0x26, 0xe1, 0xb4, 0xe5, 0x85, 0x37, 0x1c, 0x4e, 0x21, 0x97, 0xa0, 0x18, - 0xb8, 0xb2, 0xe7, 0x81, 0xa4, 0x17, 0x37, 0x5c, 0x2c, 0x06, 0x2e, 0xf9, 0x00, 0xc0, 0x70, 0x1d, - 0xd3, 0x52, 0x26, 0xf9, 0x7c, 0x1f, 0xb6, 0xe4, 0x7a, 0xf7, 0x74, 0xcf, 0x5c, 0x08, 0x11, 0xc5, - 0x2a, 0x28, 0x7a, 0xc7, 0x98, 0x34, 0xf2, 0x06, 0x54, 0x5d, 0x67, 0xa9, 0x6f, 0xdb, 0xbc, 0x42, - 0x1b, 0xad, 0x5f, 0x63, 0x4b, 0xd3, 0x3b, 0x3c, 0xe5, 0xc1, 0xc1, 0xf4, 0x45, 0xa1, 0xdf, 0xb2, - 0xb7, 0xb7, 0x3c, 0x2b, 0xb0, 0x9c, 0x4e, 0x3b, 0xf0, 0xf4, 0x80, 0x76, 0xf6, 0x51, 0x66, 0xd3, - 0xfe, 0xa4, 0x00, 0xcd, 0x25, 0xeb, 0x3e, 0x35, 0xdf, 0xb2, 0x1c, 0xd3, 0xbd, 0x47, 0x10, 0xaa, - 0x36, 0x75, 0x3a, 0xc1, 0xce, 0x88, 0xeb, 0x07, 0xb1, 0x36, 0xe6, 0x08, 0x28, 0x91, 0xc8, 0x2c, - 0x34, 0x84, 0xf6, 0x69, 0x39, 0x1d, 0x5e, 0x87, 0xf5, 0x68, 0xd0, 0x6b, 0x2b, 0x02, 0x46, 0x3c, - 0xda, 0x3e, 0x9c, 0x1d, 0xa8, 0x06, 0x62, 0x42, 0x39, 0xd0, 0x3b, 0x6a, 0x7c, 0x5d, 0x1a, 0xb9, - 0x82, 0x37, 0xf4, 0x4e, 0xac, 0x72, 0xf9, 0x1c, 0xbf, 0xa1, 0xb3, 0x39, 0x9e, 0xa1, 0x6b, 0xbf, - 0x28, 0x40, 0x7d, 0xa9, 0xef, 0x18, 0x7c, 0x89, 0xf6, 0x68, 0x8b, 0x9c, 0x52, 0x18, 0x8a, 0x99, - 0x0a, 0x43, 0x1f, 0xaa, 0xbb, 0xf7, 0x42, 0x85, 0xa2, 0x39, 0xb7, 0x36, 0x7a, 0xab, 0x90, 0x45, - 0x9a, 0xb9, 0xc5, 0xf1, 0x84, 0xc3, 0x68, 0x42, 0x16, 0xa8, 0x7a, 0xeb, 0x2d, 0x2e, 0x54, 0x0a, - 0xbb, 0xf4, 0x45, 0x68, 0xc6, 0xd8, 0x8e, 0x65, 0x3b, 0xfe, 0x47, 0x65, 0xa8, 0x2e, 0xb7, 0xdb, - 0xf3, 0xeb, 0x2b, 0xe4, 0x15, 0x68, 0x4a, 0x5f, 0xc2, 0xed, 0xa8, 0x0e, 0x42, 0x57, 0x52, 0x3b, - 0x22, 0x61, 0x9c, 0x8f, 0xa9, 0x63, 0x1e, 0xd5, 0xed, 0xae, 0xec, 0x2c, 0xa1, 0x3a, 0x86, 0x2c, - 0x11, 0x05, 0x8d, 0xe8, 0x30, 0xc1, 0x56, 0x78, 0xac, 0x0a, 0xc5, 0xea, 0x4d, 0x76, 0x9b, 0x23, - 0xae, 0xef, 0xb8, 0x92, 0xb8, 0x99, 0x00, 0xc0, 0x14, 0x20, 0x79, 0x1d, 0xea, 0x7a, 0x3f, 0xd8, - 0xe1, 0x0a, 0xb4, 0xe8, 0x1b, 0x97, 0xb9, 0xab, 0x45, 0xa6, 0x3d, 0x38, 0x98, 0x1e, 0xbb, 0x85, - 0xad, 0x57, 0xd4, 0x3b, 0x86, 0xdc, 0xac, 0x70, 0x6a, 0xc5, 0x28, 0x0b, 0x57, 0x39, 0x76, 0xe1, - 0xd6, 0x13, 0x00, 0x98, 0x02, 0x24, 0xef, 0xc0, 0xd8, 0x2e, 0xdd, 0x0f, 0xf4, 0x2d, 0x29, 0xa0, - 0x7a, 0x1c, 0x01, 0x93, 0x4c, 0x85, 0xbb, 0x15, 0xcb, 0x8e, 0x09, 0x30, 0xe2, 0xc3, 0xf9, 0x5d, - 0xea, 0x6d, 0x51, 0xcf, 0x95, 0xab, 0x4f, 0x29, 0xa4, 0x76, 0x1c, 0x21, 0x53, 0x87, 0x07, 0xd3, - 0xe7, 0x6f, 0x65, 0xc0, 0x60, 0x26, 0xb8, 0xf6, 0xf3, 0x22, 0x9c, 0x59, 0x16, 0xce, 0x5c, 0xd7, - 0x13, 0x93, 0x30, 0xb9, 0x08, 0x25, 0xaf, 0xd7, 0xe7, 0x2d, 0xa7, 0x24, 0xcc, 0xb5, 0xb8, 0xbe, - 0x89, 0x2c, 0x8d, 0xbc, 0x0d, 0x75, 0x53, 0x0e, 0x19, 0x72, 0xf1, 0x3b, 0x92, 0xa1, 0x42, 0xbd, - 0x61, 0x88, 0xc6, 0x34, 0xfd, 0xae, 0xdf, 0x69, 0x5b, 0x1f, 0x50, 0xb9, 0x1e, 0xe4, 0x9a, 0xfe, - 0x9a, 0x48, 0x42, 0x45, 0x63, 0xb3, 0xea, 0x2e, 0xdd, 0x17, 0xab, 0xa1, 0x72, 0x34, 0xab, 0xde, - 0x92, 0x69, 0x18, 0x52, 0xc9, 0xb4, 0xea, 0x2c, 0xac, 0x15, 0x94, 0xc5, 0x4a, 0xfe, 0x2e, 0x4b, - 0x90, 0xfd, 0x86, 0x0d, 0x99, 0xef, 0x59, 0x41, 0x40, 0x3d, 0xf9, 0x1b, 0x47, 0x1a, 0x32, 0x6f, - 0x72, 0x04, 0x94, 0x48, 0xe4, 0x37, 0xa0, 0xc1, 0xc1, 0x5b, 0xb6, 0xbb, 0xc5, 0x7f, 0x5c, 0x43, - 0xac, 0xe9, 0xef, 0xaa, 0x44, 0x8c, 0xe8, 0xda, 0x2f, 0x8b, 0x70, 0x61, 0x99, 0x06, 0x42, 0xab, - 0x59, 0xa4, 0x3d, 0xdb, 0xdd, 0x67, 0xaa, 0x25, 0xd2, 0xf7, 0xc9, 0x9b, 0x00, 0x96, 0xbf, 0xd5, - 0xde, 0x33, 0x78, 0x3f, 0x10, 0x7d, 0xf8, 0xaa, 0xec, 0x92, 0xb0, 0xd2, 0x6e, 0x49, 0xca, 0x83, - 0xc4, 0x1b, 0xc6, 0xf2, 0x44, 0xcb, 0xab, 0xe2, 0x43, 0x96, 0x57, 0x6d, 0x80, 0x5e, 0xa4, 0xa0, - 0x96, 0x38, 0xe7, 0x9f, 0x53, 0x62, 0x8e, 0xa3, 0x9b, 0xc6, 0x60, 0xf2, 0xa8, 0x8c, 0x0e, 0x4c, - 0x9a, 0x74, 0x5b, 0xef, 0xdb, 0x41, 0xa8, 0x54, 0xcb, 0x4e, 0x7c, 0x74, 0xbd, 0x3c, 0x74, 0x34, - 0x2f, 0xa6, 0x90, 0x70, 0x00, 0x5b, 0xfb, 0x6e, 0x09, 0x2e, 0x2d, 0xd3, 0x20, 0xb4, 0xb8, 0xc8, - 0xd1, 0xb1, 0xdd, 0xa3, 0x06, 0xfb, 0x0b, 0x1f, 0x15, 0xa0, 0x6a, 0xeb, 0x5b, 0xd4, 0x66, 0xb3, - 0x17, 0xfb, 0x9a, 0x77, 0x47, 0x9e, 0x08, 0x86, 0x4b, 0x99, 0x59, 0xe5, 0x12, 0x52, 0x53, 0x83, - 0x48, 0x44, 0x29, 0x9e, 0x0d, 0xea, 0x86, 0xdd, 0xf7, 0x03, 0xea, 0xad, 0xbb, 0x5e, 0x20, 0xf5, - 0xc9, 0x70, 0x50, 0x5f, 0x88, 0x48, 0x18, 0xe7, 0x23, 0x73, 0x00, 0x86, 0x6d, 0x51, 0x27, 0xe0, - 0xb9, 0x44, 0xbf, 0x22, 0xea, 0xff, 0x2e, 0x84, 0x14, 0x8c, 0x71, 0x31, 0x51, 0x5d, 0xd7, 0xb1, - 0x02, 0x57, 0x88, 0x2a, 0x27, 0x45, 0xad, 0x45, 0x24, 0x8c, 0xf3, 0xf1, 0x6c, 0x34, 0xf0, 0x2c, - 0xc3, 0xe7, 0xd9, 0x2a, 0xa9, 0x6c, 0x11, 0x09, 0xe3, 0x7c, 0x6c, 0xce, 0x8b, 0x7d, 0xff, 0xb1, - 0xe6, 0xbc, 0x6f, 0x35, 0xe0, 0x4a, 0xa2, 0x5a, 0x03, 0x3d, 0xa0, 0xdb, 0x7d, 0xbb, 0x4d, 0x03, - 0xf5, 0x03, 0x47, 0x9c, 0x0b, 0xff, 0x6a, 0xf4, 0xdf, 0x45, 0x08, 0x89, 0x71, 0x32, 0xff, 0x7d, - 0xa0, 0x80, 0x47, 0xfa, 0xf7, 0xb3, 0xd0, 0x70, 0xf4, 0xc0, 0xe7, 0x1d, 0x57, 0xf6, 0xd1, 0x50, - 0x0d, 0xbb, 0xad, 0x08, 0x18, 0xf1, 0x90, 0x75, 0x38, 0x2f, 0xab, 0xf8, 0xfa, 0xfd, 0x9e, 0xeb, - 0x05, 0xd4, 0x13, 0x79, 0xe5, 0x74, 0x2a, 0xf3, 0x9e, 0x5f, 0xcb, 0xe0, 0xc1, 0xcc, 0x9c, 0x64, - 0x0d, 0xce, 0x19, 0xc2, 0xad, 0x4e, 0x6d, 0x57, 0x37, 0x15, 0xa0, 0x30, 0x70, 0x85, 0x4b, 0xa3, - 0x85, 0x41, 0x16, 0xcc, 0xca, 0x97, 0x6e, 0xcd, 0xd5, 0x91, 0x5a, 0x73, 0x6d, 0x94, 0xd6, 0x5c, - 0x1f, 0xad, 0x35, 0x37, 0x8e, 0xd6, 0x9a, 0x59, 0xcd, 0xb3, 0x76, 0x44, 0x3d, 0xa6, 0x9e, 0x88, - 0x19, 0x36, 0x16, 0xb5, 0x11, 0xd6, 0x7c, 0x3b, 0x83, 0x07, 0x33, 0x73, 0x92, 0x2d, 0xb8, 0x24, - 0xd2, 0xaf, 0x3b, 0x86, 0xb7, 0xdf, 0x63, 0x13, 0x4f, 0x0c, 0xb7, 0x99, 0xb0, 0x30, 0x5e, 0x6a, - 0x0f, 0xe5, 0xc4, 0x87, 0xa0, 0x90, 0xdf, 0x86, 0x71, 0xf1, 0x97, 0xd6, 0xf4, 0x1e, 0x87, 0x15, - 0x31, 0x1c, 0x4f, 0x4b, 0xd8, 0xf1, 0x85, 0x38, 0x11, 0x93, 0xbc, 0x64, 0x1e, 0xce, 0xf4, 0xf6, - 0x0c, 0xf6, 0xb8, 0xb2, 0x7d, 0x9b, 0x52, 0x93, 0x9a, 0xdc, 0x69, 0xd4, 0x68, 0x3d, 0xa3, 0x0c, - 0x1d, 0xeb, 0x49, 0x32, 0xa6, 0xf9, 0xc9, 0xeb, 0x30, 0xe6, 0x07, 0xba, 0x17, 0x48, 0xb3, 0xde, - 0xd4, 0x84, 0x88, 0x71, 0x51, 0x56, 0xaf, 0x76, 0x8c, 0x86, 0x09, 0xce, 0xcc, 0xf9, 0xe2, 0xcc, - 0xe9, 0xcd, 0x17, 0x79, 0x46, 0xab, 0x7f, 0x59, 0x84, 0xab, 0xcb, 0x34, 0x58, 0x73, 0x1d, 0x69, - 0x14, 0xcd, 0x9a, 0xf6, 0x8f, 0x64, 0x13, 0x4d, 0x4e, 0xda, 0xc5, 0x13, 0x9d, 0xb4, 0x4b, 0x27, - 0x34, 0x69, 0x97, 0x4f, 0x71, 0xd2, 0xfe, 0x27, 0x45, 0x78, 0x26, 0x51, 0x93, 0xeb, 0xae, 0xa9, - 0x06, 0xfc, 0xcf, 0x2b, 0xf0, 0x08, 0x15, 0xf8, 0x40, 0xe8, 0x9d, 0xdc, 0xad, 0x95, 0xd2, 0x78, - 0x3e, 0x4c, 0x6b, 0x3c, 0xef, 0xe4, 0x99, 0xf9, 0x32, 0x24, 0x1c, 0x69, 0xc6, 0xbb, 0x09, 0xc4, - 0x93, 0x4e, 0x38, 0x61, 0xfa, 0x89, 0x29, 0x3d, 0x61, 0x10, 0x1d, 0x0e, 0x70, 0x60, 0x46, 0x2e, - 0xd2, 0x86, 0xa7, 0x7d, 0xea, 0x04, 0x96, 0x43, 0xed, 0x24, 0x9c, 0xd0, 0x86, 0x9e, 0x93, 0x70, - 0x4f, 0xb7, 0xb3, 0x98, 0x30, 0x3b, 0x6f, 0x9e, 0x71, 0xe0, 0xdf, 0x00, 0x57, 0x39, 0x45, 0xd5, - 0x9c, 0x98, 0xc6, 0xf2, 0x51, 0x5a, 0x63, 0x79, 0x37, 0xff, 0x7f, 0x1b, 0x4d, 0x5b, 0x99, 0x03, - 0xe0, 0x7f, 0x21, 0xae, 0xae, 0x84, 0x93, 0x34, 0x86, 0x14, 0x8c, 0x71, 0xb1, 0x09, 0x48, 0xd5, - 0x73, 0x5c, 0x53, 0x09, 0x27, 0xa0, 0x76, 0x9c, 0x88, 0x49, 0xde, 0xa1, 0xda, 0x4e, 0x65, 0x64, - 0x6d, 0xe7, 0x26, 0x90, 0x84, 0xe1, 0x51, 0xe0, 0x55, 0x93, 0x31, 0x9c, 0x2b, 0x03, 0x1c, 0x98, - 0x91, 0x6b, 0x48, 0x53, 0xae, 0x9d, 0x6c, 0x53, 0xae, 0x8f, 0xde, 0x94, 0xc9, 0xbb, 0x70, 0x91, - 0x8b, 0x92, 0xf5, 0x93, 0x04, 0x16, 0x7a, 0xcf, 0xaf, 0x48, 0xe0, 0x8b, 0x38, 0x8c, 0x11, 0x87, - 0x63, 0xb0, 0xff, 0x63, 0x78, 0xd4, 0x64, 0xc2, 0x75, 0x7b, 0xb8, 0x4e, 0xb4, 0x90, 0xc1, 0x83, - 0x99, 0x39, 0x59, 0x13, 0x0b, 0x58, 0x33, 0xd4, 0xb7, 0x6c, 0x6a, 0xca, 0x18, 0xd6, 0xb0, 0x89, - 0x6d, 0xac, 0xb6, 0x25, 0x05, 0x63, 0x5c, 0x59, 0x6a, 0xca, 0xd8, 0x31, 0xd5, 0x94, 0x65, 0x6e, - 0xa5, 0xdf, 0x4e, 0x68, 0x43, 0x52, 0xd7, 0x09, 0xa3, 0x92, 0x17, 0xd2, 0x0c, 0x38, 0x98, 0x87, - 0x6b, 0x89, 0x86, 0x67, 0xf5, 0x02, 0x3f, 0x89, 0x35, 0x91, 0xd2, 0x12, 0x33, 0x78, 0x30, 0x33, - 0x27, 0xd3, 0xcf, 0x77, 0xa8, 0x6e, 0x07, 0x3b, 0x49, 0xc0, 0x33, 0x49, 0xfd, 0xfc, 0xc6, 0x20, - 0x0b, 0x66, 0xe5, 0xcb, 0x9c, 0x90, 0x26, 0x9f, 0x4c, 0xb5, 0xea, 0x8f, 0x4b, 0x70, 0x71, 0x99, - 0x06, 0x61, 0x78, 0xcf, 0xe7, 0x66, 0x94, 0x4f, 0xc1, 0x8c, 0xf2, 0xcd, 0x0a, 0x9c, 0x5b, 0xa6, - 0xc1, 0x80, 0x36, 0xf6, 0xa7, 0xb4, 0xfa, 0xd7, 0xe0, 0x5c, 0x14, 0x51, 0xd6, 0x0e, 0x5c, 0x4f, - 0xcc, 0xe5, 0xa9, 0xd5, 0x72, 0x7b, 0x90, 0x05, 0xb3, 0xf2, 0x91, 0xaf, 0xc0, 0x33, 0x7c, 0xaa, - 0x77, 0x3a, 0xc2, 0x3e, 0x2b, 0x8c, 0x09, 0xb1, 0x3d, 0x11, 0xd3, 0x12, 0xf2, 0x99, 0x76, 0x36, - 0x1b, 0x0e, 0xcb, 0x4f, 0xbe, 0x06, 0x63, 0x3d, 0xab, 0x47, 0x6d, 0xcb, 0xe1, 0xfa, 0x59, 0xee, - 0x90, 0x90, 0xf5, 0x18, 0x58, 0xb4, 0x80, 0x8b, 0xa7, 0x62, 0x42, 0x60, 0x66, 0x4b, 0xad, 0x9f, - 0x62, 0x4b, 0xfd, 0x9f, 0x45, 0xa8, 0x2d, 0x7b, 0x6e, 0xbf, 0xd7, 0xda, 0x27, 0x1d, 0xa8, 0xde, - 0xe3, 0xce, 0x33, 0xe9, 0x9a, 0x1a, 0x3d, 0x2a, 0x5b, 0xf8, 0xe0, 0x22, 0x95, 0x48, 0xbc, 0xa3, - 0x84, 0x67, 0x8d, 0x78, 0x97, 0xee, 0x53, 0x53, 0xfa, 0xd0, 0xc2, 0x46, 0x7c, 0x8b, 0x25, 0xa2, - 0xa0, 0x91, 0x2e, 0x9c, 0xd1, 0x6d, 0xdb, 0xbd, 0x47, 0xcd, 0x55, 0x3d, 0xa0, 0x0e, 0xf5, 0x95, - 0x4b, 0xf2, 0xb8, 0x66, 0x69, 0xee, 0xd7, 0x9f, 0x4f, 0x42, 0x61, 0x1a, 0x9b, 0xbc, 0x07, 0x35, - 0x3f, 0x70, 0x3d, 0xa5, 0x6c, 0x35, 0xe7, 0x16, 0x46, 0xff, 0xe9, 0xad, 0x2f, 0xb7, 0x05, 0x94, - 0xb0, 0xd9, 0xcb, 0x17, 0x54, 0x02, 0xb4, 0x6f, 0x14, 0x00, 0x6e, 0x6c, 0x6c, 0xac, 0x4b, 0xf7, - 0x82, 0x09, 0x65, 0xbd, 0x1f, 0x3a, 0x2a, 0x47, 0x77, 0x08, 0x26, 0xc2, 0x32, 0xa5, 0x0f, 0xaf, - 0x1f, 0xec, 0x20, 0x47, 0x27, 0xbf, 0x0e, 0x35, 0xa9, 0x20, 0xcb, 0x6a, 0x0f, 0x43, 0x0b, 0xa4, - 0x12, 0x8d, 0x8a, 0xae, 0xfd, 0xc3, 0x22, 0xc0, 0x8a, 0x69, 0xd3, 0xb6, 0x0a, 0xa4, 0x6f, 0x04, - 0x3b, 0x1e, 0xf5, 0x77, 0x5c, 0xdb, 0x1c, 0xd1, 0x9b, 0xca, 0x6d, 0xfe, 0x1b, 0x0a, 0x04, 0x23, - 0x3c, 0x62, 0xc2, 0x98, 0x1f, 0xd0, 0x9e, 0x8a, 0xd4, 0x1c, 0xd1, 0x89, 0x32, 0x29, 0xec, 0x22, - 0x11, 0x0e, 0x26, 0x50, 0x89, 0x0e, 0x4d, 0xcb, 0x31, 0x44, 0x07, 0x69, 0xed, 0x8f, 0xd8, 0x90, - 0xce, 0xb0, 0x15, 0xc7, 0x4a, 0x04, 0x83, 0x71, 0x4c, 0xed, 0x27, 0x45, 0xb8, 0xc0, 0xe5, 0xb1, - 0x62, 0x24, 0xe2, 0x31, 0xc9, 0x5f, 0x18, 0xd8, 0xf4, 0xf7, 0x67, 0x8f, 0x26, 0x5a, 0xec, 0x19, - 0x5b, 0xa3, 0x81, 0x1e, 0xe9, 0x73, 0x51, 0x5a, 0x6c, 0xa7, 0x5f, 0x1f, 0xca, 0x3e, 0x1b, 0xaf, - 0x44, 0xed, 0xb5, 0x47, 0x6e, 0x42, 0xd9, 0x1f, 0xc0, 0x47, 0xaf, 0xd0, 0x6b, 0xcc, 0x47, 0x2d, - 0x2e, 0x8e, 0xfc, 0x25, 0xa8, 0xfa, 0x81, 0x1e, 0xf4, 0x55, 0xd7, 0xdc, 0x3c, 0x69, 0xc1, 0x1c, - 0x3c, 0x1a, 0x47, 0xc4, 0x3b, 0x4a, 0xa1, 0xda, 0x4f, 0x0a, 0x70, 0x29, 0x3b, 0xe3, 0xaa, 0xe5, - 0x07, 0xe4, 0xcf, 0x0f, 0x54, 0xfb, 0x11, 0xff, 0x38, 0xcb, 0xcd, 0x2b, 0x3d, 0x8c, 0x0b, 0x57, - 0x29, 0xb1, 0x2a, 0x0f, 0xa0, 0x62, 0x05, 0xb4, 0xab, 0xd6, 0x97, 0x77, 0x4e, 0xf8, 0xd3, 0x63, - 0x53, 0x3b, 0x93, 0x82, 0x42, 0x98, 0xf6, 0x71, 0x71, 0xd8, 0x27, 0xf3, 0xe9, 0xc3, 0x4e, 0xc6, - 0xfc, 0xde, 0xca, 0x17, 0xf3, 0x9b, 0x2c, 0xd0, 0x60, 0xe8, 0xef, 0x5f, 0x1c, 0x0c, 0xfd, 0xbd, - 0x93, 0x3f, 0xf4, 0x37, 0x55, 0x0d, 0x43, 0x23, 0x80, 0x3f, 0x29, 0xc1, 0xe5, 0x87, 0x35, 0x1b, - 0x36, 0x9f, 0xc9, 0xd6, 0x99, 0x77, 0x3e, 0x7b, 0x78, 0x3b, 0x24, 0x73, 0x50, 0xe9, 0xed, 0xe8, - 0xbe, 0x52, 0xca, 0xd4, 0x82, 0xa5, 0xb2, 0xce, 0x12, 0x1f, 0xb0, 0x41, 0x83, 0x2b, 0x73, 0xfc, - 0x15, 0x05, 0x2b, 0x1b, 0x8e, 0xbb, 0xd4, 0xf7, 0x23, 0x9b, 0x40, 0x38, 0x1c, 0xaf, 0x89, 0x64, - 0x54, 0x74, 0x12, 0x40, 0x55, 0x98, 0x98, 0xe5, 0xcc, 0x34, 0x7a, 0x20, 0x57, 0x46, 0x98, 0x78, - 0xf4, 0x51, 0xd2, 0x5b, 0x21, 0x65, 0x91, 0x19, 0x28, 0x07, 0x51, 0xd0, 0xae, 0x5a, 0x9a, 0x97, - 0x33, 0xf4, 0x53, 0xce, 0xc7, 0x16, 0xf6, 0xee, 0x16, 0x37, 0xaa, 0x9b, 0xd2, 0x7f, 0x6e, 0xb9, - 0x0e, 0x57, 0xc8, 0x4a, 0xd1, 0xc2, 0xfe, 0xce, 0x00, 0x07, 0x66, 0xe4, 0xd2, 0xfe, 0x7d, 0x1d, - 0x2e, 0x64, 0xb7, 0x07, 0x56, 0x6f, 0x7b, 0xd4, 0xf3, 0x19, 0x76, 0x21, 0x59, 0x6f, 0x77, 0x45, - 0x32, 0x2a, 0xfa, 0x67, 0x3a, 0xe0, 0xec, 0x9b, 0x05, 0xb8, 0xe8, 0x49, 0x1f, 0xd1, 0xe3, 0x08, - 0x3a, 0x7b, 0x4e, 0x98, 0x33, 0x86, 0x08, 0xc4, 0xe1, 0x65, 0x21, 0x7f, 0xaf, 0x00, 0x53, 0xdd, - 0x94, 0x9d, 0xe3, 0x14, 0xf7, 0xad, 0xf1, 0xa8, 0xf8, 0xb5, 0x21, 0xf2, 0x70, 0x68, 0x49, 0xc8, - 0xd7, 0xa0, 0xd9, 0x63, 0xed, 0xc2, 0x0f, 0xa8, 0x63, 0xa8, 0xad, 0x6b, 0xa3, 0xf7, 0xa4, 0xf5, - 0x08, 0x4b, 0x85, 0xa2, 0x09, 0xfd, 0x20, 0x46, 0xc0, 0xb8, 0xc4, 0x27, 0x7c, 0xa3, 0xda, 0x35, - 0xa8, 0xfb, 0x34, 0x08, 0x2c, 0xa7, 0x23, 0xd6, 0x1b, 0x0d, 0xd1, 0x57, 0xda, 0x32, 0x0d, 0x43, - 0x2a, 0xf9, 0x0d, 0x68, 0x70, 0x97, 0xd3, 0xbc, 0xd7, 0xf1, 0xa7, 0x1a, 0x3c, 0x5c, 0x6c, 0x5c, - 0x04, 0xc0, 0xc9, 0x44, 0x8c, 0xe8, 0xe4, 0x65, 0x18, 0xdb, 0xe2, 0xdd, 0x57, 0xee, 0x5d, 0x16, - 0x36, 0x2e, 0xae, 0xad, 0xb5, 0x62, 0xe9, 0x98, 0xe0, 0x22, 0x73, 0x00, 0x34, 0xf4, 0xcb, 0xa5, - 0xed, 0x59, 0x91, 0xc7, 0x0e, 0x63, 0x5c, 0xe4, 0x39, 0x28, 0x05, 0xb6, 0xcf, 0x6d, 0x58, 0xf5, - 0x68, 0x09, 0xba, 0xb1, 0xda, 0x46, 0x96, 0xae, 0xfd, 0xb2, 0x00, 0x67, 0x52, 0x9b, 0x4b, 0x58, - 0x96, 0xbe, 0x67, 0xcb, 0x61, 0x24, 0xcc, 0xb2, 0x89, 0xab, 0xc8, 0xd2, 0xc9, 0xbb, 0x52, 0x2d, - 0x2f, 0xe6, 0x3c, 0xa6, 0xe1, 0xb6, 0x1e, 0xf8, 0x4c, 0x0f, 0x1f, 0xd0, 0xc8, 0xb9, 0x9b, 0x2f, - 0x2a, 0x8f, 0x9c, 0x07, 0x62, 0x6e, 0xbe, 0x88, 0x86, 0x09, 0xce, 0x94, 0xc1, 0xaf, 0x7c, 0x14, - 0x83, 0x9f, 0xf6, 0x27, 0xc5, 0x58, 0x0d, 0x48, 0xcd, 0xfe, 0x11, 0x35, 0xf0, 0x22, 0x9b, 0x40, - 0xc3, 0xc9, 0xbd, 0x11, 0x9f, 0xff, 0xf8, 0x64, 0x2c, 0xa9, 0xe4, 0x2d, 0x51, 0xf7, 0xa5, 0x9c, - 0x9b, 0x61, 0x37, 0x56, 0xdb, 0x22, 0xba, 0x4a, 0xfd, 0xb5, 0xf0, 0x17, 0x94, 0x4f, 0xe9, 0x17, - 0x68, 0xff, 0xba, 0x04, 0xcd, 0x9b, 0xee, 0xd6, 0x67, 0x24, 0x82, 0x3a, 0x7b, 0x9a, 0x2a, 0x7e, - 0x8a, 0xd3, 0xd4, 0x26, 0x3c, 0x13, 0x04, 0x76, 0x9b, 0x1a, 0xae, 0x63, 0xfa, 0xf3, 0xdb, 0x01, - 0xf5, 0x96, 0x2c, 0xc7, 0xf2, 0x77, 0xa8, 0x29, 0xdd, 0x49, 0xcf, 0x1e, 0x1e, 0x4c, 0x3f, 0xb3, - 0xb1, 0xb1, 0x9a, 0xc5, 0x82, 0xc3, 0xf2, 0xf2, 0x61, 0x43, 0xec, 0x04, 0xe4, 0x3b, 0x65, 0x64, - 0xcc, 0x8d, 0x18, 0x36, 0x62, 0xe9, 0x98, 0xe0, 0xd2, 0xbe, 0x53, 0x84, 0x46, 0xb8, 0x01, 0x9f, - 0xbc, 0x00, 0xb5, 0x2d, 0xcf, 0xdd, 0xa5, 0x9e, 0xf0, 0xdc, 0xc9, 0x9d, 0x32, 0x2d, 0x91, 0x84, - 0x8a, 0x46, 0x9e, 0x87, 0x4a, 0xe0, 0xf6, 0x2c, 0x23, 0x6d, 0x50, 0xdb, 0x60, 0x89, 0x28, 0x68, - 0xa7, 0xd7, 0xc0, 0x5f, 0x4c, 0xa8, 0x76, 0x8d, 0xa1, 0xca, 0xd8, 0x3b, 0x50, 0xf6, 0x75, 0xdf, - 0x96, 0xf3, 0x69, 0x8e, 0xbd, 0xec, 0xf3, 0xed, 0x55, 0xb9, 0x97, 0x7d, 0xbe, 0xbd, 0x8a, 0x1c, - 0x54, 0xfb, 0x59, 0x11, 0x9a, 0xa2, 0xde, 0xc4, 0xa8, 0x70, 0x92, 0x35, 0xf7, 0x06, 0x0f, 0xa5, - 0xf0, 0xfb, 0x5d, 0xea, 0x71, 0x33, 0x93, 0x1c, 0xe4, 0xe2, 0xfe, 0x81, 0x88, 0x18, 0x86, 0x53, - 0x44, 0x49, 0xaa, 0xea, 0xcb, 0xa7, 0x58, 0xf5, 0x95, 0x23, 0x55, 0x7d, 0xf5, 0x34, 0xaa, 0xfe, - 0xa3, 0x22, 0x34, 0x56, 0xad, 0x6d, 0x6a, 0xec, 0x1b, 0x36, 0xdf, 0x13, 0x68, 0x52, 0x9b, 0x06, - 0x74, 0xd9, 0xd3, 0x0d, 0xba, 0x4e, 0x3d, 0x8b, 0x1f, 0x50, 0xc3, 0xfa, 0x07, 0x1f, 0x81, 0xe4, - 0x9e, 0xc0, 0xc5, 0x21, 0x3c, 0x38, 0x34, 0x37, 0x59, 0x81, 0x31, 0x93, 0xfa, 0x96, 0x47, 0xcd, - 0xf5, 0xd8, 0x42, 0xe5, 0x05, 0x35, 0xd5, 0x2c, 0xc6, 0x68, 0x0f, 0x0e, 0xa6, 0xc7, 0x95, 0x81, - 0x52, 0xac, 0x58, 0x12, 0x59, 0x59, 0x97, 0xef, 0xe9, 0x7d, 0x3f, 0xab, 0x8c, 0xb1, 0x2e, 0xbf, - 0x9e, 0xcd, 0x82, 0xc3, 0xf2, 0x6a, 0x15, 0x28, 0xad, 0xba, 0x1d, 0xed, 0xe3, 0x12, 0x84, 0x27, - 0x19, 0x91, 0xbf, 0x52, 0x80, 0xa6, 0xee, 0x38, 0x6e, 0x20, 0x4f, 0x09, 0x12, 0x1e, 0x78, 0xcc, - 0x7d, 0x60, 0xd2, 0xcc, 0x7c, 0x04, 0x2a, 0x9c, 0xb7, 0xa1, 0x43, 0x39, 0x46, 0xc1, 0xb8, 0x6c, - 0xd2, 0x4f, 0xf9, 0x93, 0xd7, 0xf2, 0x97, 0xe2, 0x08, 0xde, 0xe3, 0x4b, 0x5f, 0x82, 0xc9, 0x74, - 0x61, 0x8f, 0xe3, 0x0e, 0xca, 0xe5, 0x98, 0x2f, 0x02, 0x44, 0x31, 0x25, 0x8f, 0xc1, 0x88, 0x65, - 0x25, 0x8c, 0x58, 0xcb, 0xa3, 0x57, 0x70, 0x58, 0xe8, 0xa1, 0x86, 0xab, 0xf7, 0x53, 0x86, 0xab, - 0x95, 0x93, 0x10, 0xf6, 0x70, 0x63, 0xd5, 0x3f, 0x28, 0xc0, 0x64, 0xc4, 0x2c, 0x77, 0xc8, 0xbe, - 0x06, 0xe3, 0x1e, 0xd5, 0xcd, 0x96, 0x1e, 0x18, 0x3b, 0x3c, 0xd4, 0xbb, 0xc0, 0x63, 0xb3, 0xcf, - 0x1e, 0x1e, 0x4c, 0x8f, 0x63, 0x9c, 0x80, 0x49, 0x3e, 0xa2, 0x43, 0x93, 0x25, 0x6c, 0x58, 0x5d, - 0xea, 0xf6, 0x83, 0x11, 0xad, 0xa6, 0x7c, 0xc1, 0x82, 0x11, 0x0c, 0xc6, 0x31, 0xb5, 0x4f, 0x0a, - 0x30, 0x11, 0x2f, 0xf0, 0xa9, 0x5b, 0xd4, 0x76, 0x92, 0x16, 0xb5, 0x85, 0x13, 0xf8, 0x27, 0x43, - 0xac, 0x68, 0x3f, 0xaf, 0xc7, 0x3f, 0x8d, 0x5b, 0xce, 0xe2, 0xc6, 0x82, 0xc2, 0x43, 0x8d, 0x05, - 0x9f, 0xfd, 0xc3, 0x6b, 0x86, 0x69, 0xb9, 0xe5, 0x27, 0x58, 0xcb, 0xfd, 0x34, 0x4f, 0xc0, 0x89, - 0x9d, 0xe2, 0x52, 0xcd, 0x71, 0x8a, 0x4b, 0x37, 0x3c, 0xc5, 0xa5, 0x76, 0x62, 0x83, 0xce, 0x51, - 0x4e, 0x72, 0xa9, 0x3f, 0xd6, 0x93, 0x5c, 0x1a, 0xa7, 0x75, 0x92, 0x0b, 0xe4, 0x3d, 0xc9, 0xe5, - 0xc3, 0x02, 0x4c, 0x98, 0x89, 0x1d, 0xb3, 0xdc, 0xb6, 0x90, 0x67, 0xaa, 0x49, 0x6e, 0xc0, 0x15, - 0x5b, 0xa6, 0x92, 0x69, 0x98, 0x12, 0xa9, 0xfd, 0xfd, 0x5a, 0x7c, 0x1e, 0x78, 0xdc, 0xa6, 0xea, - 0x57, 0x93, 0xa6, 0xea, 0xab, 0x69, 0x53, 0xf5, 0x99, 0x58, 0x14, 0x69, 0xdc, 0x5c, 0xfd, 0x85, - 0xd8, 0xf0, 0x58, 0xe2, 0x27, 0xa7, 0x84, 0x35, 0x9d, 0x31, 0x44, 0x7e, 0x01, 0xea, 0xbe, 0x3a, - 0x73, 0x52, 0x2c, 0x6c, 0xa2, 0xff, 0xa2, 0xce, 0x83, 0x0c, 0x39, 0x98, 0x26, 0xee, 0x51, 0xdd, - 0x77, 0x9d, 0xb4, 0x26, 0x8e, 0x3c, 0x15, 0x25, 0x35, 0x6e, 0x32, 0xaf, 0x3e, 0xc2, 0x64, 0xae, - 0x43, 0xd3, 0xd6, 0xfd, 0x60, 0xb3, 0x67, 0xea, 0x01, 0x35, 0x65, 0x7f, 0xfb, 0x33, 0x47, 0x9b, - 0xab, 0xd8, 0xfc, 0x17, 0x29, 0x84, 0xab, 0x11, 0x0c, 0xc6, 0x31, 0x89, 0x09, 0x63, 0xec, 0x95, - 0xf7, 0x06, 0x73, 0x5e, 0x1d, 0x01, 0x70, 0x1c, 0x19, 0xa1, 0xa5, 0x67, 0x35, 0x86, 0x83, 0x09, - 0xd4, 0x21, 0x56, 0xf5, 0xc6, 0x28, 0x56, 0x75, 0xf2, 0xdb, 0x42, 0xd9, 0xd8, 0x57, 0x3f, 0x8c, - 0x5b, 0xe3, 0xc6, 0xa3, 0xa8, 0x42, 0x8c, 0x13, 0x31, 0xc9, 0x4b, 0xe6, 0xe1, 0x8c, 0xd1, 0xf7, - 0x3c, 0x1e, 0x47, 0x24, 0xb3, 0x37, 0x79, 0xf6, 0x30, 0x5e, 0x6c, 0x21, 0x49, 0xc6, 0x34, 0x3f, - 0x83, 0xe8, 0xcb, 0x9a, 0x54, 0x10, 0x63, 0x49, 0x88, 0xcd, 0x24, 0x19, 0xd3, 0xfc, 0x7c, 0xa3, - 0x84, 0x40, 0xbd, 0xa1, 0xfb, 0x3b, 0x32, 0xd8, 0x2c, 0xda, 0x28, 0x11, 0x91, 0x30, 0xce, 0x47, - 0xe6, 0x00, 0x04, 0x12, 0xcf, 0x35, 0x91, 0x8c, 0xc1, 0xdc, 0x0c, 0x29, 0x18, 0xe3, 0xd2, 0x3e, - 0x6c, 0x40, 0xf3, 0xb6, 0x1e, 0x58, 0x7b, 0x94, 0xfb, 0xbc, 0x4e, 0xc7, 0xf1, 0xf0, 0xb7, 0x0a, - 0x70, 0x21, 0x19, 0xd8, 0x78, 0x8a, 0xde, 0x07, 0x7e, 0x4c, 0x0a, 0x66, 0x4a, 0xc3, 0x21, 0xa5, - 0xe0, 0x7e, 0x88, 0x81, 0x38, 0xc9, 0xd3, 0xf6, 0x43, 0xb4, 0x87, 0x09, 0xc4, 0xe1, 0x65, 0xf9, - 0xac, 0xf8, 0x21, 0x9e, 0xec, 0xd3, 0xf4, 0x52, 0x5e, 0x92, 0xda, 0x13, 0xe3, 0x25, 0xa9, 0x3f, - 0x11, 0xaa, 0x69, 0x2f, 0xe6, 0x25, 0x69, 0xe4, 0x8c, 0xd6, 0x91, 0x7b, 0x01, 0x04, 0xda, 0x30, - 0x6f, 0x0b, 0xdf, 0xc6, 0xaf, 0xac, 0xd7, 0x4c, 0xa3, 0xdb, 0xd2, 0x7d, 0xcb, 0x90, 0x4a, 0x42, - 0x8e, 0xd3, 0x43, 0xd5, 0xf9, 0x66, 0xc2, 0xa9, 0xcf, 0x5f, 0x51, 0x60, 0x47, 0xc7, 0xb9, 0x15, - 0x73, 0x1d, 0xe7, 0x46, 0x16, 0xa0, 0xec, 0xec, 0xd2, 0xfd, 0xe3, 0x6d, 0x88, 0xe7, 0x2b, 0x95, - 0xdb, 0xb7, 0xe8, 0x3e, 0xf2, 0xcc, 0xda, 0x77, 0x8a, 0x00, 0xec, 0xf3, 0x8f, 0xe6, 0xaf, 0xf8, - 0x75, 0xa8, 0xf9, 0x7d, 0x6e, 0x59, 0x90, 0xea, 0x4d, 0x14, 0xe2, 0x24, 0x92, 0x51, 0xd1, 0xc9, - 0xf3, 0x50, 0x79, 0xbf, 0x4f, 0xfb, 0xca, 0xf9, 0x1e, 0x2a, 0xb7, 0x5f, 0x66, 0x89, 0x28, 0x68, - 0xa7, 0x67, 0x7b, 0x54, 0x7e, 0x8d, 0xca, 0x69, 0xf9, 0x35, 0x1a, 0x50, 0xbb, 0xed, 0xf2, 0x88, - 0x49, 0xed, 0xbf, 0x17, 0x01, 0xa2, 0x88, 0x34, 0xf2, 0x8d, 0x02, 0x3c, 0x1d, 0x76, 0xb8, 0x40, - 0xac, 0x51, 0xf8, 0x81, 0xbd, 0xb9, 0x7d, 0x1c, 0x59, 0x9d, 0x9d, 0x8f, 0x40, 0xeb, 0x59, 0xe2, - 0x30, 0xbb, 0x14, 0x04, 0xa1, 0x4e, 0xbb, 0xbd, 0x60, 0x7f, 0xd1, 0xf2, 0x64, 0x0b, 0xcc, 0x0c, - 0x7c, 0xbc, 0x2e, 0x79, 0x44, 0x56, 0xb9, 0x90, 0xe6, 0x9d, 0x48, 0x51, 0x30, 0xc4, 0x21, 0x3b, - 0x50, 0x77, 0xdc, 0x77, 0x7d, 0x56, 0x1d, 0xb2, 0x39, 0xbe, 0x39, 0x7a, 0x95, 0x8b, 0x6a, 0x15, - 0x36, 0x71, 0xf9, 0x82, 0x35, 0x47, 0x56, 0xf6, 0xd7, 0x8b, 0x70, 0x2e, 0xa3, 0x1e, 0xc8, 0x9b, - 0x30, 0x29, 0x83, 0xff, 0xa2, 0x93, 0xab, 0x0b, 0xd1, 0xc9, 0xd5, 0xed, 0x14, 0x0d, 0x07, 0xb8, - 0xc9, 0xbb, 0x00, 0xba, 0x61, 0x50, 0xdf, 0x5f, 0x73, 0x4d, 0xa5, 0xbd, 0xbf, 0xc1, 0xd4, 0x97, - 0xf9, 0x30, 0xf5, 0xc1, 0xc1, 0xf4, 0x6f, 0x66, 0xc5, 0xf3, 0xa6, 0xea, 0x39, 0xca, 0x80, 0x31, - 0x48, 0xf2, 0x55, 0x00, 0xb1, 0x50, 0x0d, 0x8f, 0x1c, 0x78, 0x84, 0x75, 0x67, 0x46, 0x1d, 0xee, - 0x34, 0xf3, 0xe5, 0xbe, 0xee, 0x04, 0x56, 0xb0, 0x2f, 0x4e, 0x78, 0xb9, 0x1b, 0xa2, 0x60, 0x0c, - 0x51, 0xfb, 0x17, 0x45, 0xa8, 0x2b, 0xbb, 0xf2, 0x63, 0x30, 0x26, 0x76, 0x12, 0xc6, 0xc4, 0x13, - 0x8a, 0xe0, 0xcd, 0x32, 0x25, 0xba, 0x29, 0x53, 0xe2, 0x72, 0x7e, 0x51, 0x0f, 0x37, 0x24, 0x7e, - 0xbb, 0x08, 0x13, 0x8a, 0x35, 0xaf, 0x19, 0xf1, 0x77, 0xe1, 0x8c, 0xf0, 0xbc, 0xaf, 0xe9, 0xf7, - 0xc5, 0x61, 0x37, 0xbc, 0xc2, 0xca, 0x22, 0x68, 0xb6, 0x95, 0x24, 0x61, 0x9a, 0x97, 0x35, 0x6b, - 0x91, 0xb4, 0xc9, 0x56, 0x5d, 0xc2, 0x57, 0x27, 0x56, 0x87, 0xbc, 0x59, 0xb7, 0x52, 0x34, 0x1c, - 0xe0, 0x4e, 0xdb, 0x31, 0xcb, 0xa7, 0x60, 0xc7, 0xfc, 0x0f, 0x05, 0x18, 0x8b, 0xea, 0xeb, 0xd4, - 0xad, 0x98, 0xdb, 0x49, 0x2b, 0xe6, 0x7c, 0xee, 0xe6, 0x30, 0xc4, 0x86, 0xf9, 0xd7, 0x6a, 0x90, - 0x08, 0x24, 0x27, 0x5b, 0x70, 0xc9, 0xca, 0x0c, 0x87, 0x8b, 0x8d, 0x36, 0xe1, 0xce, 0xe8, 0x95, - 0xa1, 0x9c, 0xf8, 0x10, 0x14, 0xd2, 0x87, 0xfa, 0x1e, 0xf5, 0x02, 0xcb, 0xa0, 0xea, 0xfb, 0x96, - 0x73, 0xab, 0x64, 0xd2, 0x52, 0x1b, 0xd6, 0xe9, 0x5d, 0x29, 0x00, 0x43, 0x51, 0x64, 0x0b, 0x2a, - 0xd4, 0xec, 0x50, 0x75, 0xfc, 0x50, 0xce, 0xc3, 0x3d, 0xc3, 0xfa, 0x64, 0x6f, 0x3e, 0x0a, 0x68, - 0xe2, 0x43, 0xc3, 0x56, 0x9e, 0x38, 0xd9, 0x0e, 0x47, 0x57, 0xb0, 0x42, 0x9f, 0x5e, 0x74, 0x32, - 0x41, 0x98, 0x84, 0x91, 0x1c, 0xb2, 0x1b, 0x9a, 0x04, 0x2b, 0x27, 0x34, 0x78, 0x3c, 0xc4, 0x20, - 0xe8, 0x43, 0xe3, 0x9e, 0x1e, 0x50, 0xaf, 0xab, 0x7b, 0xbb, 0x72, 0xb5, 0x31, 0xfa, 0x17, 0xbe, - 0xa5, 0x90, 0xa2, 0x2f, 0x0c, 0x93, 0x30, 0x92, 0x43, 0x5c, 0x68, 0x04, 0x52, 0x7d, 0x56, 0x76, - 0xcf, 0xd1, 0x85, 0x2a, 0x45, 0xdc, 0x97, 0x01, 0xe5, 0xea, 0x15, 0x23, 0x19, 0x64, 0x2f, 0x71, - 0xfe, 0xb2, 0x38, 0x75, 0xbb, 0x95, 0xc3, 0x7e, 0x2e, 0xa1, 0xa2, 0xe9, 0x26, 0xfb, 0x1c, 0x67, - 0xed, 0x7f, 0x55, 0xa2, 0x61, 0xf9, 0x71, 0x5b, 0xf5, 0x5e, 0x4e, 0x5a, 0xf5, 0xae, 0xa4, 0xad, - 0x7a, 0x29, 0x87, 0xee, 0xf1, 0x43, 0x50, 0x53, 0xf6, 0xb4, 0xf2, 0x29, 0xd8, 0xd3, 0x5e, 0x82, - 0xe6, 0x1e, 0x1f, 0x09, 0xc4, 0x59, 0x46, 0x15, 0x3e, 0x8d, 0xf0, 0x91, 0xfd, 0x6e, 0x94, 0x8c, - 0x71, 0x1e, 0x96, 0x45, 0xde, 0x38, 0x11, 0x1e, 0x06, 0x2b, 0xb3, 0xb4, 0xa3, 0x64, 0x8c, 0xf3, - 0xf0, 0xe8, 0x35, 0xcb, 0xd9, 0x15, 0x19, 0x6a, 0x3c, 0x83, 0x88, 0x5e, 0x53, 0x89, 0x18, 0xd1, - 0xc9, 0x35, 0xa8, 0xf7, 0xcd, 0x6d, 0xc1, 0x5b, 0xe7, 0xbc, 0x5c, 0xc3, 0xdc, 0x5c, 0x5c, 0x92, - 0x67, 0x2b, 0x29, 0x2a, 0x2b, 0x49, 0x57, 0xef, 0x29, 0x02, 0x5f, 0x1b, 0xca, 0x92, 0xac, 0x45, - 0xc9, 0x18, 0xe7, 0x21, 0xbf, 0x05, 0x13, 0x1e, 0x35, 0xfb, 0x06, 0x0d, 0x73, 0x09, 0x73, 0x1c, - 0x11, 0x57, 0x6b, 0xc4, 0x29, 0x98, 0xe2, 0x1c, 0x62, 0x15, 0x6c, 0x8e, 0x64, 0x15, 0xfc, 0x12, - 0x4c, 0x98, 0x9e, 0x6e, 0x39, 0xd4, 0xbc, 0xe3, 0x70, 0xaf, 0xbd, 0x8c, 0xa1, 0x0b, 0x4d, 0xf4, - 0x8b, 0x09, 0x2a, 0xa6, 0xb8, 0xb5, 0x1f, 0x17, 0x80, 0x0c, 0x46, 0x8b, 0x93, 0x1d, 0xa8, 0x3a, - 0xdc, 0x7a, 0x96, 0xfb, 0xf8, 0xe9, 0x98, 0x11, 0x4e, 0x0c, 0x6b, 0x32, 0x41, 0xe2, 0x13, 0x07, - 0xea, 0xf4, 0x7e, 0x40, 0x3d, 0x27, 0xdc, 0x3d, 0x72, 0x32, 0x47, 0x5d, 0x8b, 0xd5, 0x84, 0x44, - 0xc6, 0x50, 0x86, 0xf6, 0xd3, 0x22, 0x34, 0x63, 0x7c, 0x8f, 0x5a, 0x94, 0xf2, 0x0d, 0xec, 0xc2, - 0x68, 0xb5, 0xe9, 0xd9, 0xb2, 0x87, 0xc6, 0x36, 0xb0, 0x4b, 0x12, 0xae, 0x62, 0x9c, 0x8f, 0xcc, - 0x01, 0x74, 0x75, 0x3f, 0xa0, 0x1e, 0x9f, 0xbd, 0x53, 0xdb, 0xc6, 0xd7, 0x42, 0x0a, 0xc6, 0xb8, - 0xc8, 0x55, 0x79, 0x58, 0x79, 0x39, 0x79, 0xcc, 0xdf, 0x90, 0x93, 0xc8, 0x2b, 0x27, 0x70, 0x12, - 0x39, 0xe9, 0xc0, 0xa4, 0x2a, 0xb5, 0xa2, 0x1e, 0xef, 0x10, 0x38, 0xb1, 0xfe, 0x49, 0x41, 0xe0, - 0x00, 0xa8, 0xf6, 0x9d, 0x02, 0x8c, 0x27, 0x4c, 0x26, 0xe2, 0x80, 0x3e, 0xb5, 0xd7, 0x21, 0x71, - 0x40, 0x5f, 0x6c, 0x8b, 0xc2, 0x8b, 0x50, 0x15, 0x15, 0x94, 0x0e, 0x61, 0x14, 0x55, 0x88, 0x92, - 0xca, 0xc6, 0x42, 0x69, 0x94, 0x4d, 0x8f, 0x85, 0xd2, 0x6a, 0x8b, 0x8a, 0x2e, 0x9c, 0x1b, 0xa2, - 0x74, 0x83, 0xce, 0x0d, 0x91, 0x8e, 0x21, 0x87, 0xf6, 0x3d, 0x5e, 0xee, 0xc0, 0xdb, 0x0f, 0xd7, - 0x82, 0x1d, 0xa8, 0xc9, 0xb0, 0x35, 0xd9, 0x35, 0xde, 0xcc, 0x61, 0xc7, 0xe1, 0x38, 0x32, 0x40, - 0x4b, 0x37, 0x76, 0xef, 0x6c, 0x6f, 0xa3, 0x42, 0x27, 0xd7, 0xa1, 0xe1, 0x3a, 0x4b, 0xba, 0x65, - 0xf7, 0x3d, 0x35, 0x33, 0xfc, 0x1a, 0x1b, 0xeb, 0xee, 0xa8, 0xc4, 0x07, 0x07, 0xd3, 0x17, 0xc2, - 0x97, 0x44, 0x21, 0x31, 0xca, 0xa9, 0xfd, 0x9f, 0x12, 0xf0, 0x90, 0x25, 0xf2, 0x1a, 0x34, 0xba, - 0xd4, 0xd8, 0xd1, 0x1d, 0xcb, 0x57, 0x47, 0x8c, 0xb2, 0xf5, 0x7d, 0x63, 0x4d, 0x25, 0x3e, 0x60, - 0x55, 0x30, 0xdf, 0x5e, 0xe5, 0xbb, 0x02, 0x22, 0x5e, 0x62, 0x40, 0xb5, 0xe3, 0xfb, 0x7a, 0xcf, - 0xca, 0xed, 0x31, 0x17, 0x47, 0x3a, 0x8a, 0x61, 0x40, 0x3c, 0xa3, 0x84, 0x26, 0x06, 0x54, 0x7a, - 0xb6, 0x6e, 0x39, 0xb9, 0xaf, 0xd6, 0x61, 0x5f, 0xb0, 0xce, 0x90, 0x84, 0x51, 0x8b, 0x3f, 0xa2, - 0xc0, 0x26, 0x7d, 0x68, 0xfa, 0x86, 0xa7, 0x77, 0xfd, 0x1d, 0x7d, 0xee, 0x95, 0x57, 0x73, 0xab, - 0x89, 0x91, 0x28, 0x31, 0x6b, 0x2d, 0xe0, 0xfc, 0x5a, 0xfb, 0xc6, 0xfc, 0xdc, 0x2b, 0xaf, 0x62, - 0x5c, 0x4e, 0x5c, 0xec, 0x2b, 0x2f, 0xcd, 0xc9, 0x9e, 0x7b, 0xe2, 0x62, 0x5f, 0x79, 0x69, 0x0e, - 0xe3, 0x72, 0xb4, 0xff, 0x5d, 0x80, 0x46, 0xc8, 0x4b, 0x36, 0x01, 0xd8, 0x18, 0x22, 0x0f, 0x61, - 0x3c, 0xd6, 0x85, 0x08, 0xdc, 0x2e, 0xb0, 0x19, 0x66, 0xc6, 0x18, 0x50, 0xc6, 0x29, 0x95, 0xc5, - 0x93, 0x3e, 0xa5, 0x72, 0x16, 0x1a, 0x3b, 0xba, 0x63, 0xfa, 0x3b, 0xfa, 0xae, 0x18, 0x4a, 0x63, - 0xe7, 0xb6, 0xde, 0x50, 0x04, 0x8c, 0x78, 0xb4, 0x7f, 0x56, 0x05, 0xe1, 0xe6, 0x66, 0x9d, 0xdd, - 0xb4, 0x7c, 0x11, 0x67, 0x5d, 0xe0, 0x39, 0xc3, 0xce, 0xbe, 0x28, 0xd3, 0x31, 0xe4, 0x20, 0x17, - 0xa1, 0xd4, 0xb5, 0x1c, 0xe9, 0xf3, 0xe1, 0x26, 0xbf, 0x35, 0xcb, 0x41, 0x96, 0xc6, 0x49, 0xfa, - 0x7d, 0x19, 0x22, 0x27, 0x48, 0xfa, 0x7d, 0x64, 0x69, 0x6c, 0x11, 0x6e, 0xbb, 0xee, 0x2e, 0xeb, - 0xb6, 0x2a, 0x92, 0xae, 0xcc, 0x55, 0x01, 0xbe, 0x08, 0x5f, 0x4d, 0x92, 0x30, 0xcd, 0x4b, 0x36, - 0xe1, 0x99, 0x0f, 0xa8, 0xe7, 0xca, 0x71, 0xaa, 0x6d, 0x53, 0xda, 0x53, 0x30, 0x42, 0x89, 0xe2, - 0x01, 0x79, 0xbf, 0x97, 0xcd, 0x82, 0xc3, 0xf2, 0xf2, 0xd0, 0x5e, 0xdd, 0xeb, 0xd0, 0x60, 0xdd, - 0x73, 0x0d, 0xea, 0xfb, 0x96, 0xd3, 0x51, 0xb0, 0xd5, 0x08, 0x76, 0x23, 0x9b, 0x05, 0x87, 0xe5, - 0x25, 0x6f, 0xc3, 0x94, 0x20, 0x09, 0x75, 0x61, 0x7e, 0x4f, 0xb7, 0x6c, 0x7d, 0xcb, 0xb2, 0xd5, - 0x8d, 0x74, 0xe3, 0xc2, 0xb3, 0xb2, 0x31, 0x84, 0x07, 0x87, 0xe6, 0x26, 0x37, 0x61, 0x52, 0xf9, - 0xd5, 0xd6, 0xa9, 0xd7, 0x0e, 0x43, 0x1f, 0xc6, 0x5b, 0x57, 0xd8, 0x8a, 0x77, 0x91, 0xf6, 0x3c, - 0x6a, 0xc4, 0xbd, 0x89, 0x8a, 0x0b, 0x07, 0xf2, 0x11, 0x84, 0x0b, 0x3c, 0xbe, 0x61, 0xb3, 0xb7, - 0xe0, 0xba, 0xb6, 0xe9, 0xde, 0x73, 0xd4, 0xb7, 0x0b, 0xd5, 0x8e, 0xbb, 0xd2, 0xda, 0x99, 0x1c, - 0x38, 0x24, 0x27, 0xfb, 0x72, 0x4e, 0x59, 0x74, 0xef, 0x39, 0x69, 0x54, 0x88, 0xbe, 0xbc, 0x3d, - 0x84, 0x07, 0x87, 0xe6, 0x26, 0x4b, 0x40, 0xd2, 0x5f, 0xb0, 0xd9, 0x93, 0xee, 0xd9, 0x0b, 0xe2, - 0x3c, 0x95, 0x34, 0x15, 0x33, 0x72, 0x90, 0x55, 0x38, 0x9f, 0x4e, 0x65, 0xe2, 0xa4, 0x97, 0x96, - 0x9f, 0xa4, 0x8a, 0x19, 0x74, 0xcc, 0xcc, 0xa5, 0xfd, 0xf3, 0x22, 0x8c, 0x27, 0x36, 0xe0, 0x3f, - 0x71, 0x1b, 0x9d, 0x99, 0x0e, 0xde, 0xf5, 0x3b, 0x2b, 0x8b, 0x37, 0xa8, 0x6e, 0x52, 0xef, 0x16, - 0x55, 0x87, 0x25, 0xf0, 0x41, 0x65, 0x2d, 0x41, 0xc1, 0x14, 0x27, 0xd9, 0x86, 0x8a, 0xb0, 0x28, - 0xe7, 0xbd, 0x5a, 0x43, 0xd5, 0x11, 0x37, 0x2b, 0xcb, 0xfb, 0x68, 0x5c, 0x8f, 0xa2, 0x80, 0xd7, - 0x02, 0x18, 0x8b, 0x73, 0xb0, 0x81, 0x24, 0x52, 0x37, 0x6b, 0x09, 0x55, 0x73, 0x05, 0x4a, 0x41, - 0x30, 0xea, 0x16, 0x6a, 0xe1, 0xa1, 0xd8, 0x58, 0x45, 0x86, 0xa1, 0x6d, 0xb3, 0x7f, 0xe7, 0xfb, - 0x96, 0xeb, 0xc8, 0xf3, 0xb4, 0x37, 0xa1, 0x16, 0x48, 0x23, 0xdd, 0x68, 0x5b, 0xc0, 0xb9, 0x8e, - 0xa2, 0x0c, 0x74, 0x0a, 0x4b, 0xfb, 0x8f, 0x45, 0x68, 0x84, 0x0b, 0xea, 0x23, 0x9c, 0x53, 0xed, - 0x42, 0x23, 0x8c, 0xcf, 0xca, 0x7d, 0x5b, 0x5f, 0x14, 0x36, 0xc4, 0xd7, 0x80, 0xe1, 0x2b, 0x46, - 0x32, 0xe2, 0xb1, 0x5f, 0xa5, 0x1c, 0xb1, 0x5f, 0x3d, 0xa8, 0x05, 0x9e, 0xd5, 0xe9, 0x48, 0xed, - 0x3c, 0x4f, 0xf0, 0x57, 0x58, 0x5d, 0x1b, 0x02, 0x50, 0xd6, 0xac, 0x78, 0x41, 0x25, 0x46, 0x7b, - 0x0f, 0x26, 0xd3, 0x9c, 0x5c, 0x75, 0x35, 0x76, 0xa8, 0xd9, 0xb7, 0x55, 0x1d, 0x47, 0xaa, 0xab, - 0x4c, 0xc7, 0x90, 0x83, 0x2d, 0x7f, 0xd9, 0x6f, 0xfa, 0xc0, 0x75, 0x94, 0xfa, 0xc8, 0x57, 0x01, - 0x1b, 0x32, 0x0d, 0x43, 0xaa, 0xf6, 0xdf, 0x4a, 0x70, 0x31, 0x32, 0x8b, 0xac, 0xe9, 0x8e, 0xde, - 0x39, 0xc2, 0x15, 0x6d, 0x9f, 0x6f, 0xaa, 0x39, 0xee, 0x65, 0x03, 0xa5, 0x27, 0xe0, 0xb2, 0x81, - 0xff, 0x5b, 0x04, 0x1e, 0x4b, 0x4a, 0xbe, 0x06, 0x63, 0x7a, 0xec, 0x76, 0x4e, 0xf9, 0x3b, 0xaf, - 0xe7, 0xfe, 0x9d, 0x3c, 0x64, 0x35, 0x8c, 0x8d, 0x8a, 0xa7, 0x62, 0x42, 0x20, 0x71, 0xa1, 0xbe, - 0xad, 0xdb, 0x36, 0xd3, 0x85, 0x72, 0xbb, 0x79, 0x12, 0xc2, 0x79, 0x33, 0x5f, 0x92, 0xd0, 0x18, - 0x0a, 0x21, 0x1f, 0x16, 0x60, 0xdc, 0x8b, 0x2f, 0x93, 0xe4, 0x0f, 0xc9, 0x13, 0x04, 0x10, 0x43, - 0x8b, 0x47, 0x62, 0xc5, 0xd7, 0x62, 0x49, 0x99, 0xda, 0x7f, 0x2d, 0xc0, 0x78, 0xdb, 0xb6, 0x4c, - 0xcb, 0xe9, 0x9c, 0xe2, 0x5d, 0x07, 0x77, 0xa0, 0xe2, 0xdb, 0x96, 0x49, 0x47, 0x9c, 0x4d, 0xc4, - 0x3c, 0xc6, 0x00, 0x50, 0xe0, 0x24, 0x2f, 0x4f, 0x28, 0x1d, 0xe1, 0xf2, 0x84, 0x5f, 0x54, 0x41, - 0x46, 0x45, 0x93, 0x3e, 0x34, 0x3a, 0xea, 0x4c, 0x76, 0xf9, 0x8d, 0x37, 0x72, 0x9c, 0xe7, 0x97, - 0x38, 0xdd, 0x5d, 0x8c, 0xfd, 0x61, 0x22, 0x46, 0x92, 0x08, 0x4d, 0x5e, 0x0b, 0xbb, 0x98, 0xf3, - 0x5a, 0x58, 0x21, 0x6e, 0xf0, 0x62, 0x58, 0x1d, 0xca, 0x3b, 0x41, 0xd0, 0x93, 0x8d, 0x69, 0xf4, - 0xb0, 0xf7, 0xe8, 0x48, 0x19, 0xa1, 0x13, 0xb1, 0x77, 0xe4, 0xd0, 0x4c, 0x84, 0xa3, 0x87, 0xd7, - 0x80, 0x2d, 0xe4, 0x0a, 0x38, 0x88, 0x8b, 0x60, 0xef, 0xc8, 0xa1, 0xc9, 0x1f, 0x40, 0x33, 0xf0, - 0x74, 0xc7, 0xdf, 0x76, 0xbd, 0x2e, 0xf5, 0xe4, 0x1a, 0x75, 0x29, 0xc7, 0xcd, 0xa8, 0x1b, 0x11, - 0x9a, 0xf0, 0x64, 0x26, 0x92, 0x30, 0x2e, 0x8d, 0xec, 0x42, 0xbd, 0x6f, 0x8a, 0x82, 0x49, 0xf3, - 0xd3, 0x7c, 0x9e, 0xcb, 0x6e, 0x63, 0xe1, 0x04, 0xea, 0x0d, 0x43, 0x01, 0xc9, 0x1b, 0xef, 0x6a, - 0x27, 0x75, 0xe3, 0x5d, 0xbc, 0x35, 0x66, 0x9d, 0x77, 0x41, 0xba, 0x52, 0xaf, 0x75, 0x3a, 0x32, - 0x1a, 0x6a, 0x29, 0xb7, 0xca, 0x29, 0x44, 0x36, 0x43, 0xdd, 0xd8, 0xe9, 0xa0, 0x92, 0xa1, 0x75, - 0x41, 0x7a, 0x19, 0x88, 0x91, 0xb8, 0x17, 0x46, 0x6c, 0xc2, 0x9a, 0x3d, 0xda, 0x78, 0x10, 0x5e, - 0x50, 0x12, 0x3b, 0x97, 0x3a, 0xf3, 0x02, 0x18, 0xed, 0x3f, 0x15, 0xa1, 0xb4, 0xb1, 0xda, 0x16, - 0x67, 0x4d, 0xf2, 0x4b, 0x97, 0x68, 0x7b, 0xd7, 0xea, 0xdd, 0xa5, 0x9e, 0xb5, 0xbd, 0x2f, 0x97, - 0xde, 0xb1, 0xb3, 0x26, 0xd3, 0x1c, 0x98, 0x91, 0x8b, 0xbc, 0x03, 0x63, 0x86, 0xbe, 0x40, 0xbd, - 0x60, 0x14, 0xc3, 0x02, 0xdf, 0x6d, 0xba, 0x30, 0x1f, 0x65, 0xc7, 0x04, 0x18, 0xd9, 0x04, 0x30, - 0x22, 0xe8, 0xd2, 0xb1, 0xcd, 0x21, 0x31, 0xe0, 0x18, 0x10, 0x41, 0x68, 0xec, 0x32, 0x56, 0x8e, - 0x5a, 0x3e, 0x0e, 0x2a, 0x6f, 0x39, 0xb7, 0x54, 0x5e, 0x8c, 0x60, 0x34, 0x07, 0xc6, 0x13, 0x97, - 0xc5, 0x90, 0x2f, 0x42, 0xdd, 0xed, 0xc5, 0x86, 0xd3, 0x06, 0x8f, 0xbb, 0xac, 0xdf, 0x91, 0x69, - 0x0f, 0x0e, 0xa6, 0xc7, 0x57, 0xdd, 0x8e, 0x65, 0xa8, 0x04, 0x0c, 0xd9, 0x89, 0x06, 0x55, 0xbe, - 0x45, 0x4c, 0x5d, 0x15, 0xc3, 0xe7, 0x0e, 0x7e, 0x9b, 0x83, 0x8f, 0x92, 0xa2, 0xfd, 0x61, 0x19, - 0x22, 0xdf, 0x1c, 0xf1, 0xa1, 0x2a, 0x42, 0xe0, 0xe5, 0xc8, 0x7d, 0xaa, 0xd1, 0xf6, 0x52, 0x14, - 0xe9, 0x40, 0xe9, 0x3d, 0x77, 0x2b, 0xf7, 0xc0, 0x1d, 0xdb, 0x1b, 0x2e, 0x6c, 0x65, 0xb1, 0x04, - 0x64, 0x12, 0xc8, 0xdf, 0x2e, 0xc0, 0x59, 0x3f, 0xad, 0xfa, 0xca, 0xe6, 0x80, 0xf9, 0x75, 0xfc, - 0xb4, 0x32, 0x2d, 0x03, 0x64, 0x87, 0x91, 0x71, 0xb0, 0x2c, 0xac, 0xfe, 0x85, 0xd3, 0x4c, 0x36, - 0xa7, 0xe5, 0x9c, 0x17, 0x1c, 0x26, 0xeb, 0x3f, 0x99, 0x86, 0x52, 0x94, 0xf6, 0xc7, 0x45, 0x68, - 0xc6, 0x46, 0xeb, 0xdc, 0x37, 0x10, 0xdd, 0x4f, 0xdd, 0x40, 0xb4, 0x3e, 0xba, 0x0f, 0x39, 0x2a, - 0xd5, 0x69, 0x5f, 0x42, 0xf4, 0xaf, 0x8a, 0x50, 0xda, 0x5c, 0x5c, 0x4a, 0x2e, 0x5a, 0x0b, 0x8f, - 0x61, 0xd1, 0xba, 0x03, 0xb5, 0xad, 0xbe, 0x65, 0x07, 0x96, 0x93, 0xfb, 0xf4, 0x0a, 0x75, 0x61, - 0x93, 0xf4, 0x31, 0x08, 0x54, 0x54, 0xf0, 0xa4, 0x03, 0xb5, 0x8e, 0x38, 0x3e, 0x30, 0x77, 0x64, - 0x9d, 0x3c, 0x86, 0x50, 0x08, 0x92, 0x2f, 0xa8, 0xd0, 0xb5, 0x7d, 0x90, 0x37, 0xcf, 0x3f, 0xf6, - 0xda, 0xd4, 0xfe, 0x00, 0x42, 0x2d, 0xe0, 0xf1, 0x0b, 0xff, 0x1f, 0x05, 0x48, 0x2a, 0x3e, 0x8f, - 0xbf, 0x35, 0xed, 0xa6, 0x5b, 0xd3, 0xe2, 0x49, 0x74, 0xbe, 0xec, 0x06, 0xa5, 0xfd, 0xd3, 0x22, - 0x54, 0x1f, 0xdb, 0x8e, 0x63, 0x9a, 0x08, 0x12, 0x5c, 0xc8, 0x39, 0x30, 0x0e, 0x0d, 0x11, 0xec, - 0xa6, 0x42, 0x04, 0xf3, 0x5e, 0x31, 0xfb, 0x88, 0x00, 0xc1, 0x7f, 0x57, 0x00, 0x39, 0x2c, 0xaf, - 0x38, 0x7e, 0xa0, 0x3b, 0x06, 0x25, 0x46, 0x38, 0x07, 0xe4, 0x8d, 0x44, 0x91, 0xd1, 0x5a, 0x62, - 0xda, 0xe7, 0xcf, 0x6a, 0xcc, 0x27, 0x5f, 0x80, 0xfa, 0x8e, 0xeb, 0x07, 0x7c, 0x9c, 0x2f, 0x26, - 0xad, 0x4b, 0x37, 0x64, 0x3a, 0x86, 0x1c, 0x69, 0x8f, 0x6b, 0x65, 0xb8, 0xc7, 0x55, 0xfb, 0x56, - 0x11, 0xc6, 0x3e, 0x2b, 0xdb, 0xa6, 0xb3, 0x42, 0x2a, 0x4b, 0x39, 0x43, 0x2a, 0xcb, 0xc7, 0x09, - 0xa9, 0xd4, 0x7e, 0x58, 0x00, 0x78, 0x6c, 0x7b, 0xb6, 0xcd, 0x64, 0xb4, 0x63, 0xee, 0x76, 0x95, - 0x1d, 0xeb, 0xf8, 0x8f, 0x2b, 0xea, 0x93, 0x78, 0xa4, 0xe3, 0x47, 0x05, 0x98, 0xd0, 0x13, 0xd1, - 0x83, 0xb9, 0x55, 0xcb, 0x54, 0x30, 0x62, 0x18, 0xfc, 0x92, 0x4c, 0xc7, 0x94, 0x58, 0xf2, 0x7a, - 0x74, 0x5e, 0xf0, 0xed, 0xa8, 0xd9, 0x0f, 0x1c, 0xf4, 0xcb, 0xd5, 0x9c, 0x04, 0xe7, 0x23, 0xa2, - 0x35, 0x4b, 0x27, 0x12, 0xad, 0x19, 0xdf, 0x87, 0x56, 0x7e, 0xe8, 0x3e, 0xb4, 0x3d, 0x68, 0x6c, - 0x7b, 0x6e, 0x97, 0x07, 0x44, 0xca, 0xcb, 0x69, 0xaf, 0xe7, 0x98, 0x53, 0xa2, 0x6b, 0xd9, 0x23, - 0x1b, 0xcf, 0x92, 0xc2, 0xc7, 0x48, 0x14, 0x37, 0x8b, 0xbb, 0x42, 0x6a, 0xf5, 0x24, 0xa5, 0x86, - 0x63, 0xc9, 0x86, 0x40, 0x47, 0x25, 0x26, 0x19, 0x04, 0x59, 0x7b, 0x3c, 0x41, 0x90, 0xda, 0x77, - 0xab, 0x6a, 0x00, 0x7b, 0xe2, 0x8e, 0xa6, 0xfc, 0xec, 0xef, 0xf5, 0x4d, 0x6f, 0xc4, 0xad, 0x3d, - 0xc6, 0x8d, 0xb8, 0xf5, 0x93, 0xd9, 0x88, 0xdb, 0xc8, 0xb7, 0x11, 0x17, 0xf2, 0x6f, 0xc4, 0x6d, - 0xe6, 0xdb, 0x88, 0x3b, 0x36, 0xd2, 0x46, 0xdc, 0xf1, 0x23, 0x6d, 0xc4, 0x3d, 0x28, 0x41, 0x6a, - 0x95, 0xf9, 0xb9, 0x47, 0xe9, 0xff, 0x2b, 0x8f, 0xd2, 0xc7, 0x45, 0x88, 0x86, 0xcd, 0x63, 0x46, - 0xdc, 0xbc, 0x0d, 0xf5, 0xae, 0x7e, 0x7f, 0x91, 0xda, 0xfa, 0x7e, 0x9e, 0xfb, 0x57, 0xd7, 0x24, - 0x06, 0x86, 0x68, 0xc4, 0x07, 0xb0, 0xc2, 0x33, 0xd0, 0x73, 0xdb, 0xe6, 0xa3, 0xe3, 0xd4, 0x85, - 0xf5, 0x2f, 0x7a, 0xc7, 0x98, 0x18, 0xed, 0xdf, 0x16, 0x41, 0x1e, 0x96, 0x4f, 0x28, 0x54, 0xb6, - 0xad, 0xfb, 0xd4, 0xcc, 0x1d, 0x3f, 0x1b, 0xbb, 0x15, 0x5b, 0x38, 0x1f, 0x78, 0x02, 0x0a, 0x74, - 0x6e, 0x55, 0x16, 0xce, 0x24, 0x59, 0x7f, 0x39, 0xac, 0xca, 0x71, 0xa7, 0x94, 0xb4, 0x2a, 0x8b, - 0x24, 0x54, 0x32, 0x84, 0x11, 0x9b, 0xc7, 0x15, 0xe4, 0xf6, 0x9d, 0x25, 0xe2, 0x13, 0x94, 0x11, - 0xdb, 0x17, 0x3b, 0xf1, 0xa5, 0x8c, 0xd6, 0xef, 0xff, 0xe0, 0x47, 0x57, 0x9e, 0xfa, 0xe1, 0x8f, - 0xae, 0x3c, 0xf5, 0xc9, 0x8f, 0xae, 0x3c, 0xf5, 0x87, 0x87, 0x57, 0x0a, 0x3f, 0x38, 0xbc, 0x52, - 0xf8, 0xe1, 0xe1, 0x95, 0xc2, 0x27, 0x87, 0x57, 0x0a, 0xff, 0xf9, 0xf0, 0x4a, 0xe1, 0x6f, 0xfc, - 0x97, 0x2b, 0x4f, 0xfd, 0xde, 0x6b, 0x51, 0x11, 0x66, 0x55, 0x11, 0x66, 0x95, 0xc0, 0xd9, 0xde, - 0x6e, 0x67, 0x96, 0x15, 0x21, 0x4a, 0x51, 0x45, 0xf8, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6c, - 0x98, 0x3b, 0x47, 0x90, 0x97, 0x00, 0x00, + // 7907 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x25, 0x47, + 0x76, 0x9e, 0xee, 0xff, 0xbd, 0xe7, 0xf2, 0x6f, 0x6a, 0x7e, 0xc4, 0x19, 0x8d, 0x86, 0xe3, 0x96, + 0x25, 0x8f, 0x63, 0x9b, 0x8c, 0x68, 0xfd, 0xad, 0xed, 0x5d, 0x89, 0x97, 0x1c, 0x72, 0x38, 0x43, + 0xce, 0x70, 0xcf, 0x25, 0x47, 0x5a, 0x2b, 0x5e, 0xa5, 0xd9, 0x5d, 0xbc, 0x6c, 0xb1, 0x6f, 0xf7, + 0x55, 0x77, 0x5f, 0xce, 0x50, 0x4e, 0xb0, 0xb6, 0x95, 0x40, 0x0a, 0x82, 0x20, 0x81, 0x9f, 0x0c, + 0x04, 0x4e, 0x90, 0x20, 0x80, 0x1f, 0x0c, 0xe7, 0x21, 0xc0, 0xe6, 0xc1, 0x40, 0xe2, 0x38, 0x08, + 0x92, 0x4d, 0x90, 0x9f, 0x45, 0x10, 0x20, 0xca, 0x0b, 0x91, 0x65, 0x90, 0x87, 0x04, 0x88, 0x61, + 0xc4, 0x48, 0xec, 0x0c, 0x16, 0xd9, 0xa0, 0xfe, 0xfa, 0xef, 0xf6, 0x9d, 0x21, 0x6f, 0x93, 0xa3, + 0x51, 0xac, 0xb7, 0xee, 0x3a, 0xa7, 0xbe, 0x53, 0x55, 0x5d, 0x5d, 0x75, 0xea, 0x9c, 0x53, 0x55, + 0xb0, 0xd2, 0xb1, 0x82, 0xdd, 0xfe, 0xf6, 0xac, 0xe1, 0x76, 0xe7, 0x9c, 0x7e, 0x57, 0xef, 0x79, + 0xee, 0x87, 0xfc, 0x61, 0xc7, 0x76, 0x1f, 0xcc, 0xf5, 0xf6, 0x3a, 0x73, 0x7a, 0xcf, 0xf2, 0xa3, + 0x94, 0xfd, 0x57, 0x75, 0xbb, 0xb7, 0xab, 0xbf, 0x3a, 0xd7, 0xa1, 0x0e, 0xf5, 0xf4, 0x80, 0x9a, + 0xb3, 0x3d, 0xcf, 0x0d, 0x5c, 0xf2, 0x66, 0x04, 0x34, 0xab, 0x80, 0x66, 0x55, 0xb6, 0xd9, 0xde, + 0x5e, 0x67, 0x96, 0x01, 0x45, 0x29, 0x0a, 0xe8, 0xca, 0xcf, 0xc4, 0x4a, 0xd0, 0x71, 0x3b, 0xee, + 0x1c, 0xc7, 0xdb, 0xee, 0xef, 0xf0, 0x37, 0xfe, 0xc2, 0x9f, 0x84, 0x9c, 0x2b, 0xda, 0xde, 0x5b, + 0xfe, 0xac, 0xe5, 0xb2, 0x62, 0xcd, 0x19, 0xae, 0x47, 0xe7, 0xf6, 0x07, 0xca, 0x72, 0xe5, 0xb5, + 0x88, 0xa7, 0xab, 0x1b, 0xbb, 0x96, 0x43, 0xbd, 0x03, 0x55, 0x97, 0x39, 0x8f, 0xfa, 0x6e, 0xdf, + 0x33, 0xe8, 0x89, 0x72, 0xf9, 0x73, 0x5d, 0x1a, 0xe8, 0x59, 0xb2, 0xe6, 0x86, 0xe5, 0xf2, 0xfa, + 0x4e, 0x60, 0x75, 0x07, 0xc5, 0xbc, 0xf1, 0xa4, 0x0c, 0xbe, 0xb1, 0x4b, 0xbb, 0xfa, 0x40, 0xbe, + 0x9f, 0x1d, 0x96, 0xaf, 0x1f, 0x58, 0xf6, 0x9c, 0xe5, 0x04, 0x7e, 0xe0, 0xa5, 0x33, 0x69, 0xbf, + 0x0f, 0x70, 0x7e, 0x61, 0xdb, 0x0f, 0x3c, 0xdd, 0x08, 0x36, 0x5c, 0x73, 0x93, 0x76, 0x7b, 0xb6, + 0x1e, 0x50, 0xb2, 0x07, 0x75, 0x56, 0x21, 0x53, 0x0f, 0xf4, 0xe9, 0xc2, 0xf5, 0xc2, 0x8d, 0xe6, + 0xfc, 0xc2, 0xec, 0x88, 0x1f, 0x70, 0x76, 0x5d, 0x02, 0xb5, 0xc6, 0x8e, 0x0e, 0x67, 0xea, 0xea, + 0x0d, 0x43, 0x01, 0xe4, 0x37, 0x0a, 0x30, 0xe6, 0xb8, 0x26, 0x6d, 0x53, 0x9b, 0x1a, 0x81, 0xeb, + 0x4d, 0x17, 0xaf, 0x97, 0x6e, 0x34, 0xe7, 0xbf, 0x3d, 0xb2, 0xc4, 0x8c, 0x1a, 0xcd, 0xde, 0x8d, + 0x09, 0xb8, 0xe9, 0x04, 0xde, 0x41, 0xeb, 0xc2, 0xf7, 0x0e, 0x67, 0x9e, 0x3b, 0x3a, 0x9c, 0x19, + 0x8b, 0x93, 0x30, 0x51, 0x12, 0xb2, 0x05, 0xcd, 0xc0, 0xb5, 0x59, 0x93, 0x59, 0xae, 0xe3, 0x4f, + 0x97, 0x78, 0xc1, 0xae, 0xcd, 0x8a, 0xa6, 0x66, 0xe2, 0x67, 0x59, 0x1f, 0x9b, 0xdd, 0x7f, 0x75, + 0x76, 0x33, 0x64, 0x6b, 0x9d, 0x97, 0xc0, 0xcd, 0x28, 0xcd, 0xc7, 0x38, 0x0e, 0xa1, 0x30, 0xe9, + 0x53, 0xa3, 0xef, 0x59, 0xc1, 0xc1, 0xa2, 0xeb, 0x04, 0xf4, 0x61, 0x30, 0x5d, 0xe6, 0xad, 0xfc, + 0x4a, 0x16, 0xf4, 0x86, 0x6b, 0xb6, 0x93, 0xdc, 0xad, 0xf3, 0x47, 0x87, 0x33, 0x93, 0xa9, 0x44, + 0x4c, 0x63, 0x12, 0x07, 0xa6, 0xac, 0xae, 0xde, 0xa1, 0x1b, 0x7d, 0xdb, 0x6e, 0x53, 0xc3, 0xa3, + 0x81, 0x3f, 0x5d, 0xe1, 0x55, 0xb8, 0x91, 0x25, 0x67, 0xcd, 0x35, 0x74, 0xfb, 0xde, 0xf6, 0x87, + 0xd4, 0x08, 0x90, 0xee, 0x50, 0x8f, 0x3a, 0x06, 0x6d, 0x4d, 0xcb, 0xca, 0x4c, 0xad, 0xa6, 0x90, + 0x70, 0x00, 0x9b, 0xac, 0xc0, 0xb9, 0x9e, 0x67, 0xb9, 0xbc, 0x08, 0xb6, 0xee, 0xfb, 0x77, 0xf5, + 0x2e, 0x9d, 0xae, 0x5e, 0x2f, 0xdc, 0x68, 0xb4, 0x2e, 0x4b, 0x98, 0x73, 0x1b, 0x69, 0x06, 0x1c, + 0xcc, 0x43, 0x6e, 0x40, 0x5d, 0x25, 0x4e, 0xd7, 0xae, 0x17, 0x6e, 0x54, 0x44, 0xdf, 0x51, 0x79, + 0x31, 0xa4, 0x92, 0x65, 0xa8, 0xeb, 0x3b, 0x3b, 0x96, 0xc3, 0x38, 0xeb, 0xbc, 0x09, 0xaf, 0x66, + 0x55, 0x6d, 0x41, 0xf2, 0x08, 0x1c, 0xf5, 0x86, 0x61, 0x5e, 0x72, 0x1b, 0x88, 0x4f, 0xbd, 0x7d, + 0xcb, 0xa0, 0x0b, 0x86, 0xe1, 0xf6, 0x9d, 0x80, 0x97, 0xbd, 0xc1, 0xcb, 0x7e, 0x45, 0x96, 0x9d, + 0xb4, 0x07, 0x38, 0x30, 0x23, 0x17, 0x79, 0x07, 0xa6, 0xe4, 0xbf, 0x1a, 0xb5, 0x02, 0x70, 0xa4, + 0x0b, 0xac, 0x21, 0x31, 0x45, 0xc3, 0x01, 0x6e, 0x62, 0xc2, 0x55, 0xbd, 0x1f, 0xb8, 0x5d, 0x06, + 0x99, 0x14, 0xba, 0xe9, 0xee, 0x51, 0x67, 0xba, 0x79, 0xbd, 0x70, 0xa3, 0xde, 0xba, 0x7e, 0x74, + 0x38, 0x73, 0x75, 0xe1, 0x31, 0x7c, 0xf8, 0x58, 0x14, 0x72, 0x0f, 0x1a, 0xa6, 0xe3, 0x6f, 0xb8, + 0xb6, 0x65, 0x1c, 0x4c, 0x8f, 0xf1, 0x02, 0xbe, 0x2a, 0xab, 0xda, 0x58, 0xba, 0xdb, 0x16, 0x84, + 0x47, 0x87, 0x33, 0x57, 0x07, 0x87, 0xd4, 0xd9, 0x90, 0x8e, 0x11, 0x06, 0x59, 0xe7, 0x80, 0x8b, + 0xae, 0xb3, 0x63, 0x75, 0xa6, 0xc7, 0xf9, 0xd7, 0xb8, 0x3e, 0xa4, 0x43, 0x2f, 0xdd, 0x6d, 0x0b, + 0xbe, 0xd6, 0xb8, 0x14, 0x27, 0x5e, 0x31, 0x42, 0x20, 0x26, 0x4c, 0xa8, 0xc1, 0x78, 0xd1, 0xd6, + 0xad, 0xae, 0x3f, 0x3d, 0xc1, 0x3b, 0xef, 0x8f, 0x0f, 0xc1, 0xc4, 0x38, 0x73, 0xeb, 0x92, 0xac, + 0xca, 0x44, 0x22, 0xd9, 0xc7, 0x14, 0xe6, 0x95, 0xb7, 0xe1, 0xdc, 0xc0, 0xd8, 0x40, 0xa6, 0xa0, + 0xb4, 0x47, 0x0f, 0xf8, 0xd0, 0xd7, 0x40, 0xf6, 0x48, 0x2e, 0x40, 0x65, 0x5f, 0xb7, 0xfb, 0x74, + 0xba, 0xc8, 0xd3, 0xc4, 0xcb, 0xcf, 0x15, 0xdf, 0x2a, 0x68, 0x7f, 0xb7, 0x04, 0x63, 0x6a, 0xc4, + 0x69, 0x5b, 0xce, 0x1e, 0x79, 0x17, 0x4a, 0xb6, 0xdb, 0x91, 0xe3, 0xe6, 0x2f, 0x8c, 0x3c, 0x8a, + 0xad, 0xb9, 0x9d, 0x56, 0xed, 0xe8, 0x70, 0xa6, 0xb4, 0xe6, 0x76, 0x90, 0x21, 0x12, 0x03, 0x2a, + 0x7b, 0xfa, 0xce, 0x9e, 0xce, 0xcb, 0xd0, 0x9c, 0x6f, 0x8d, 0x0c, 0x7d, 0x87, 0xa1, 0xb0, 0xb2, + 0xb6, 0x1a, 0x47, 0x87, 0x33, 0x15, 0xfe, 0x8a, 0x02, 0x9b, 0xb8, 0xd0, 0xd8, 0xb6, 0x75, 0x63, + 0x6f, 0xd7, 0xb5, 0xe9, 0x74, 0x29, 0xa7, 0xa0, 0x96, 0x42, 0x12, 0x9f, 0x39, 0x7c, 0xc5, 0x48, + 0x06, 0x31, 0xa0, 0xda, 0x37, 0x7d, 0xcb, 0xd9, 0x93, 0x63, 0xe0, 0xdb, 0x23, 0x4b, 0xdb, 0x5a, + 0xe2, 0x75, 0x82, 0xa3, 0xc3, 0x99, 0xaa, 0x78, 0x46, 0x09, 0xad, 0xfd, 0x41, 0x13, 0x26, 0xd4, + 0x47, 0xba, 0x4f, 0xbd, 0x80, 0x3e, 0x24, 0xd7, 0xa1, 0xec, 0xb0, 0x5f, 0x93, 0x7f, 0xe4, 0xd6, + 0x98, 0xec, 0x2e, 0x65, 0xfe, 0x4b, 0x72, 0x0a, 0x2b, 0x99, 0xe8, 0x2a, 0xb2, 0xc1, 0x47, 0x2f, + 0x59, 0x9b, 0xc3, 0x88, 0x92, 0x89, 0x67, 0x94, 0xd0, 0xe4, 0x7d, 0x28, 0xf3, 0xca, 0x8b, 0xa6, + 0xfe, 0xfa, 0xe8, 0x22, 0x58, 0xd5, 0xeb, 0xac, 0x06, 0xbc, 0xe2, 0x1c, 0x94, 0x75, 0xc5, 0xbe, + 0xb9, 0x23, 0x1b, 0xf6, 0x17, 0x72, 0x34, 0xec, 0xb2, 0xe8, 0x8a, 0x5b, 0x4b, 0xcb, 0xc8, 0x10, + 0xc9, 0x5f, 0x2f, 0xc0, 0x39, 0xc3, 0x75, 0x02, 0x9d, 0xe9, 0x19, 0x6a, 0x92, 0x9d, 0xae, 0x70, + 0x39, 0xb7, 0x47, 0x96, 0xb3, 0x98, 0x46, 0x6c, 0x5d, 0x64, 0x73, 0xc6, 0x40, 0x32, 0x0e, 0xca, + 0x26, 0x7f, 0xb3, 0x00, 0x17, 0xd9, 0x58, 0x3e, 0xc0, 0xcc, 0x67, 0xa0, 0xd3, 0x2d, 0xd5, 0xe5, + 0xa3, 0xc3, 0x99, 0x8b, 0xab, 0x59, 0xc2, 0x30, 0xbb, 0x0c, 0xac, 0x74, 0xe7, 0xf5, 0x41, 0xb5, + 0x84, 0xcf, 0x6e, 0xcd, 0xf9, 0xb5, 0xd3, 0x54, 0x75, 0x5a, 0x2f, 0xc8, 0xae, 0x9c, 0xa5, 0xd9, + 0x61, 0x56, 0x29, 0xc8, 0x4d, 0xa8, 0xed, 0xbb, 0x76, 0xbf, 0x4b, 0xfd, 0xe9, 0x3a, 0x1f, 0x62, + 0xaf, 0x64, 0x0d, 0xb1, 0xf7, 0x39, 0x4b, 0x6b, 0x52, 0xc2, 0xd7, 0xc4, 0xbb, 0x8f, 0x2a, 0x2f, + 0xb1, 0xa0, 0x6a, 0x5b, 0x5d, 0x2b, 0xf0, 0xf9, 0xc4, 0xd9, 0x9c, 0xbf, 0x39, 0x72, 0xb5, 0xc4, + 0x2f, 0xba, 0xc6, 0xc1, 0xc4, 0x5f, 0x23, 0x9e, 0x51, 0x0a, 0x60, 0x43, 0xa1, 0x6f, 0xe8, 0xb6, + 0x98, 0x58, 0x9b, 0xf3, 0xdf, 0x18, 0xfd, 0xb7, 0x61, 0x28, 0xad, 0x71, 0x59, 0xa7, 0x0a, 0x7f, + 0x45, 0x81, 0x4d, 0x7e, 0x09, 0x26, 0x12, 0x5f, 0xd3, 0x9f, 0x6e, 0xf2, 0xd6, 0x79, 0x31, 0xab, + 0x75, 0x42, 0xae, 0x68, 0xe6, 0x49, 0xf4, 0x10, 0x1f, 0x53, 0x60, 0xe4, 0x0e, 0xd4, 0x7d, 0xcb, + 0xa4, 0x86, 0xee, 0xf9, 0xd3, 0x63, 0xc7, 0x01, 0x9e, 0x92, 0xc0, 0xf5, 0xb6, 0xcc, 0x86, 0x21, + 0x00, 0x99, 0x05, 0xe8, 0xe9, 0x5e, 0x60, 0x09, 0x45, 0x75, 0x9c, 0x2b, 0x4d, 0x13, 0x47, 0x87, + 0x33, 0xb0, 0x11, 0xa6, 0x62, 0x8c, 0x83, 0xf1, 0xb3, 0xbc, 0xab, 0x4e, 0xaf, 0x1f, 0x88, 0x89, + 0xb5, 0x21, 0xf8, 0xdb, 0x61, 0x2a, 0xc6, 0x38, 0xc8, 0xef, 0x14, 0xe0, 0x85, 0xe8, 0x75, 0xf0, + 0x27, 0x9b, 0x3c, 0xf5, 0x9f, 0x6c, 0xe6, 0xe8, 0x70, 0xe6, 0x85, 0xf6, 0x70, 0x91, 0xf8, 0xb8, + 0xf2, 0x68, 0xef, 0xc2, 0xf8, 0x42, 0x3f, 0xd8, 0x75, 0x3d, 0xeb, 0x63, 0xae, 0x74, 0x93, 0x65, + 0xa8, 0x04, 0x5c, 0x79, 0x12, 0xf3, 0xf2, 0xcb, 0x59, 0x4d, 0x2d, 0x14, 0xd9, 0x3b, 0xf4, 0x40, + 0x69, 0x03, 0x62, 0x7e, 0x14, 0xca, 0x94, 0xc8, 0xae, 0xfd, 0xa5, 0x02, 0xd4, 0x5a, 0xba, 0xb1, + 0xe7, 0xee, 0xec, 0x90, 0xf7, 0xa0, 0x6e, 0x39, 0x01, 0xf5, 0xf6, 0x75, 0x5b, 0xc2, 0xce, 0xc6, + 0x60, 0xc3, 0x65, 0x58, 0x54, 0x6f, 0xb6, 0xe6, 0x61, 0x82, 0x96, 0xfa, 0x72, 0xad, 0xc0, 0xf5, + 0xd1, 0x55, 0x89, 0x81, 0x21, 0x1a, 0x99, 0x81, 0x8a, 0x1f, 0xd0, 0x9e, 0xcf, 0x67, 0x9e, 0x71, + 0x51, 0x8c, 0x36, 0x4b, 0x40, 0x91, 0xae, 0xfd, 0x9d, 0x02, 0x34, 0x5a, 0xba, 0x6f, 0x19, 0xac, + 0x96, 0x64, 0x11, 0xca, 0x7d, 0x9f, 0x7a, 0x27, 0xab, 0x1b, 0x9f, 0x2c, 0xb6, 0x7c, 0xea, 0x21, + 0xcf, 0x4c, 0xee, 0x41, 0xbd, 0xa7, 0xfb, 0xfe, 0x03, 0xd7, 0x33, 0xe5, 0x84, 0x77, 0x4c, 0x20, + 0xa1, 0x9c, 0xcb, 0xac, 0x18, 0x82, 0x68, 0x4d, 0x88, 0x66, 0x7c, 0xed, 0x8f, 0x0a, 0x70, 0xbe, + 0xd5, 0xdf, 0xd9, 0xa1, 0x9e, 0xd4, 0x45, 0xa5, 0x96, 0x47, 0xa1, 0xe2, 0x51, 0xd3, 0xf2, 0x65, + 0xd9, 0x97, 0x46, 0xee, 0x41, 0xc8, 0x50, 0xa4, 0x52, 0xc9, 0xdb, 0x8b, 0x27, 0xa0, 0x40, 0x27, + 0x7d, 0x68, 0x7c, 0x48, 0xd9, 0x1a, 0x98, 0xea, 0x5d, 0x59, 0xbb, 0x5b, 0x23, 0x8b, 0xba, 0x4d, + 0x83, 0x36, 0x47, 0x8a, 0xeb, 0xb0, 0x61, 0x22, 0x46, 0x92, 0xb4, 0xdf, 0xaf, 0xc0, 0xd8, 0xa2, + 0xdb, 0xdd, 0xb6, 0x1c, 0x6a, 0xde, 0x34, 0x3b, 0x94, 0x7c, 0x00, 0x65, 0x6a, 0x76, 0xa8, 0xac, + 0xed, 0xe8, 0xd3, 0x3d, 0x03, 0x8b, 0x94, 0x16, 0xf6, 0x86, 0x1c, 0x98, 0xac, 0xc1, 0xc4, 0x8e, + 0xe7, 0x76, 0xc5, 0x08, 0xba, 0x79, 0xd0, 0x93, 0x1a, 0x6b, 0xeb, 0xc7, 0xd5, 0xa8, 0xb4, 0x9c, + 0xa0, 0x3e, 0x3a, 0x9c, 0x81, 0xe8, 0x0d, 0x53, 0x79, 0xc9, 0x7b, 0x30, 0x1d, 0xa5, 0x84, 0x43, + 0xc9, 0x22, 0x5b, 0x44, 0x70, 0x8d, 0xa5, 0xd2, 0xba, 0x7a, 0x74, 0x38, 0x33, 0xbd, 0x3c, 0x84, + 0x07, 0x87, 0xe6, 0x26, 0x9f, 0x16, 0x60, 0x2a, 0x22, 0x8a, 0xe1, 0x5d, 0x2a, 0x2a, 0xa7, 0x34, + 0x6f, 0xf0, 0xd5, 0xd6, 0x72, 0x4a, 0x04, 0x0e, 0x08, 0x25, 0xcb, 0x30, 0x16, 0xb8, 0xb1, 0xf6, + 0xaa, 0xf0, 0xf6, 0xd2, 0x94, 0x79, 0x60, 0xd3, 0x1d, 0xda, 0x5a, 0x89, 0x7c, 0x04, 0xe1, 0x92, + 0x7a, 0x4f, 0xb5, 0x54, 0x95, 0xb7, 0xd4, 0x95, 0xa3, 0xc3, 0x99, 0x4b, 0x9b, 0x99, 0x1c, 0x38, + 0x24, 0x27, 0xf9, 0xd5, 0x02, 0x4c, 0x28, 0x92, 0x6c, 0xa3, 0xda, 0x69, 0xb6, 0x11, 0x61, 0x3d, + 0x62, 0x33, 0x21, 0x00, 0x53, 0x02, 0xb5, 0x3f, 0x29, 0x43, 0x23, 0x1c, 0x60, 0xc9, 0x4b, 0x50, + 0xe1, 0x0b, 0x7f, 0xa9, 0x37, 0x87, 0x33, 0x27, 0xb7, 0x0f, 0xa0, 0xa0, 0x91, 0x97, 0xa1, 0x66, + 0xb8, 0xdd, 0xae, 0xee, 0x98, 0xdc, 0x98, 0xd3, 0x68, 0x35, 0x99, 0xc2, 0xb0, 0x28, 0x92, 0x50, + 0xd1, 0xc8, 0x55, 0x28, 0xeb, 0x5e, 0x47, 0xd8, 0x55, 0x1a, 0x62, 0x3c, 0x5a, 0xf0, 0x3a, 0x3e, + 0xf2, 0x54, 0xf2, 0x35, 0x28, 0x51, 0x67, 0x7f, 0xba, 0x3c, 0x5c, 0x23, 0xb9, 0xe9, 0xec, 0xdf, + 0xd7, 0xbd, 0x56, 0x53, 0x96, 0xa1, 0x74, 0xd3, 0xd9, 0x47, 0x96, 0x87, 0xac, 0x41, 0x8d, 0x3a, + 0xfb, 0xec, 0xdb, 0x4b, 0x83, 0xc7, 0x8f, 0x0d, 0xc9, 0xce, 0x58, 0xa4, 0x72, 0x1e, 0xea, 0x35, + 0x32, 0x19, 0x15, 0x04, 0xf9, 0x16, 0x8c, 0x09, 0x15, 0x67, 0x9d, 0x7d, 0x13, 0x7f, 0xba, 0xca, + 0x21, 0x67, 0x86, 0xeb, 0x48, 0x9c, 0x2f, 0x32, 0x30, 0xc5, 0x12, 0x7d, 0x4c, 0x40, 0x91, 0x6f, + 0x41, 0x43, 0xad, 0x47, 0xd5, 0x97, 0xcd, 0xb4, 0xcd, 0xa8, 0x45, 0x2c, 0xd2, 0x8f, 0xfa, 0x96, + 0x47, 0xbb, 0xd4, 0x09, 0xfc, 0xd6, 0x39, 0xb5, 0x5a, 0x57, 0x54, 0x1f, 0x23, 0x34, 0xb2, 0x3d, + 0x68, 0x64, 0x12, 0x16, 0x92, 0x97, 0x86, 0x8c, 0xea, 0x23, 0x58, 0x98, 0xbe, 0x0d, 0x93, 0xa1, + 0x15, 0x48, 0x1a, 0x12, 0x84, 0xcd, 0xe4, 0x35, 0x96, 0x7d, 0x35, 0x49, 0x7a, 0x74, 0x38, 0xf3, + 0x62, 0x86, 0x29, 0x21, 0x62, 0xc0, 0x34, 0x98, 0xf6, 0x7b, 0x25, 0x18, 0xd4, 0xfe, 0x93, 0x8d, + 0x56, 0x38, 0xed, 0x46, 0x4b, 0x57, 0x48, 0x0c, 0x9f, 0x6f, 0xc9, 0x6c, 0xf9, 0x2b, 0x95, 0xf5, + 0x61, 0x4a, 0xa7, 0xfd, 0x61, 0x9e, 0x95, 0x7f, 0x47, 0xfb, 0xac, 0x0c, 0x13, 0x4b, 0x3a, 0xed, + 0xba, 0xce, 0x13, 0xd7, 0x42, 0x85, 0x67, 0x62, 0x2d, 0x74, 0x03, 0xea, 0x1e, 0xed, 0xd9, 0x96, + 0xa1, 0x0b, 0xe5, 0x4b, 0xda, 0x1e, 0x51, 0xa6, 0x61, 0x48, 0x1d, 0xb2, 0x06, 0x2e, 0x3d, 0x93, + 0x6b, 0xe0, 0xf2, 0x17, 0xbf, 0x06, 0xd6, 0x7e, 0xb5, 0x08, 0x5c, 0x51, 0x21, 0xd7, 0xa1, 0xcc, + 0x26, 0xe1, 0xb4, 0xe5, 0x85, 0x77, 0x1c, 0x4e, 0x21, 0x57, 0xa0, 0x18, 0xb8, 0xf2, 0xcf, 0x03, + 0x49, 0x2f, 0x6e, 0xba, 0x58, 0x0c, 0x5c, 0xf2, 0x31, 0x80, 0xe1, 0x3a, 0xa6, 0xa5, 0x4c, 0xf2, + 0xf9, 0x2a, 0xb6, 0xec, 0x7a, 0x0f, 0x74, 0xcf, 0x5c, 0x0c, 0x11, 0xc5, 0x2a, 0x28, 0x7a, 0xc7, + 0x98, 0x34, 0xf2, 0x36, 0x54, 0x5d, 0x67, 0xb9, 0x6f, 0xdb, 0xbc, 0x41, 0x1b, 0xad, 0x9f, 0x60, + 0x4b, 0xd3, 0x7b, 0x3c, 0xe5, 0xd1, 0xe1, 0xcc, 0x65, 0xa1, 0xdf, 0xb2, 0xb7, 0x77, 0x3d, 0x2b, + 0xb0, 0x9c, 0x4e, 0x3b, 0xf0, 0xf4, 0x80, 0x76, 0x0e, 0x50, 0x66, 0xd3, 0x7e, 0xbd, 0x00, 0xcd, + 0x65, 0xeb, 0x21, 0x35, 0xdf, 0xb5, 0x1c, 0xd3, 0x7d, 0x40, 0x10, 0xaa, 0x36, 0x75, 0x3a, 0xc1, + 0xee, 0x88, 0xeb, 0x07, 0xb1, 0x36, 0xe6, 0x08, 0x28, 0x91, 0xc8, 0x1c, 0x34, 0x84, 0xf6, 0x69, + 0x39, 0x1d, 0xde, 0x86, 0xf5, 0x68, 0xd0, 0x6b, 0x2b, 0x02, 0x46, 0x3c, 0xda, 0x01, 0x9c, 0x1b, + 0x68, 0x06, 0x62, 0x42, 0x39, 0xd0, 0x3b, 0x6a, 0x7c, 0x5d, 0x1e, 0xb9, 0x81, 0x37, 0xf5, 0x4e, + 0xac, 0x71, 0xf9, 0x1c, 0xbf, 0xa9, 0xb3, 0x39, 0x9e, 0xa1, 0x6b, 0x3f, 0x2c, 0x40, 0x7d, 0xb9, + 0xef, 0x18, 0x7c, 0x89, 0xf6, 0x64, 0x8b, 0x9c, 0x52, 0x18, 0x8a, 0x99, 0x0a, 0x43, 0x1f, 0xaa, + 0x7b, 0x0f, 0x42, 0x85, 0xa2, 0x39, 0xbf, 0x3e, 0x7a, 0xaf, 0x90, 0x45, 0x9a, 0xbd, 0xc3, 0xf1, + 0x84, 0xc3, 0x68, 0x42, 0x16, 0xa8, 0x7a, 0xe7, 0x5d, 0x2e, 0x54, 0x0a, 0xbb, 0xf2, 0x35, 0x68, + 0xc6, 0xd8, 0x4e, 0x64, 0x3b, 0xfe, 0x87, 0x65, 0xa8, 0xae, 0xb4, 0xdb, 0x0b, 0x1b, 0xab, 0xe4, + 0x75, 0x68, 0x4a, 0x5f, 0xc2, 0xdd, 0xa8, 0x0d, 0x42, 0x57, 0x52, 0x3b, 0x22, 0x61, 0x9c, 0x8f, + 0xa9, 0x63, 0x1e, 0xd5, 0xed, 0xae, 0xfc, 0x59, 0x42, 0x75, 0x0c, 0x59, 0x22, 0x0a, 0x1a, 0xd1, + 0x61, 0x82, 0xad, 0xf0, 0x58, 0x13, 0x8a, 0xd5, 0x9b, 0xfc, 0x6d, 0x8e, 0xb9, 0xbe, 0xe3, 0x4a, + 0xe2, 0x56, 0x02, 0x00, 0x53, 0x80, 0xe4, 0x2d, 0xa8, 0xeb, 0xfd, 0x60, 0x97, 0x2b, 0xd0, 0xe2, + 0xdf, 0xb8, 0xca, 0x5d, 0x2d, 0x32, 0xed, 0xd1, 0xe1, 0xcc, 0xd8, 0x1d, 0x6c, 0xbd, 0xae, 0xde, + 0x31, 0xe4, 0x66, 0x85, 0x53, 0x2b, 0x46, 0x59, 0xb8, 0xca, 0x89, 0x0b, 0xb7, 0x91, 0x00, 0xc0, + 0x14, 0x20, 0x79, 0x1f, 0xc6, 0xf6, 0xe8, 0x41, 0xa0, 0x6f, 0x4b, 0x01, 0xd5, 0x93, 0x08, 0x98, + 0x62, 0x2a, 0xdc, 0x9d, 0x58, 0x76, 0x4c, 0x80, 0x11, 0x1f, 0x2e, 0xec, 0x51, 0x6f, 0x9b, 0x7a, + 0xae, 0x5c, 0x7d, 0x4a, 0x21, 0xb5, 0x93, 0x08, 0x99, 0x3e, 0x3a, 0x9c, 0xb9, 0x70, 0x27, 0x03, + 0x06, 0x33, 0xc1, 0xb5, 0xff, 0x53, 0x84, 0xc9, 0x15, 0xe1, 0xcc, 0x75, 0x3d, 0x31, 0x09, 0x93, + 0xcb, 0x50, 0xf2, 0x7a, 0x7d, 0xde, 0x73, 0x4a, 0xc2, 0x5c, 0x8b, 0x1b, 0x5b, 0xc8, 0xd2, 0xc8, + 0x7b, 0x50, 0x37, 0xe5, 0x90, 0x21, 0x17, 0xbf, 0x23, 0x19, 0x2a, 0xd4, 0x1b, 0x86, 0x68, 0x4c, + 0xd3, 0xef, 0xfa, 0x9d, 0xb6, 0xf5, 0x31, 0x95, 0xeb, 0x41, 0xae, 0xe9, 0xaf, 0x8b, 0x24, 0x54, + 0x34, 0x36, 0xab, 0xee, 0xd1, 0x03, 0xb1, 0x1a, 0x2a, 0x47, 0xb3, 0xea, 0x1d, 0x99, 0x86, 0x21, + 0x95, 0xcc, 0xa8, 0x9f, 0x85, 0xf5, 0x82, 0xb2, 0x58, 0xc9, 0xdf, 0x67, 0x09, 0xf2, 0xbf, 0x61, + 0x43, 0xe6, 0x87, 0x56, 0x10, 0x50, 0x4f, 0x7e, 0xc6, 0x91, 0x86, 0xcc, 0xdb, 0x1c, 0x01, 0x25, + 0x12, 0xf9, 0x29, 0x68, 0x70, 0xf0, 0x96, 0xed, 0x6e, 0xf3, 0x0f, 0xd7, 0x10, 0x6b, 0xfa, 0xfb, + 0x2a, 0x11, 0x23, 0xba, 0xf6, 0xa3, 0x22, 0x5c, 0x5a, 0xa1, 0x81, 0xd0, 0x6a, 0x96, 0x68, 0xcf, + 0x76, 0x0f, 0x98, 0x6a, 0x89, 0xf4, 0x23, 0xf2, 0x0e, 0x80, 0xe5, 0x6f, 0xb7, 0xf7, 0x0d, 0xfe, + 0x1f, 0x88, 0x7f, 0xf8, 0xba, 0xfc, 0x25, 0x61, 0xb5, 0xdd, 0x92, 0x94, 0x47, 0x89, 0x37, 0x8c, + 0xe5, 0x89, 0x96, 0x57, 0xc5, 0xc7, 0x2c, 0xaf, 0xda, 0x00, 0xbd, 0x48, 0x41, 0x2d, 0x71, 0xce, + 0x9f, 0x55, 0x62, 0x4e, 0xa2, 0x9b, 0xc6, 0x60, 0xf2, 0xa8, 0x8c, 0x0e, 0x4c, 0x99, 0x74, 0x47, + 0xef, 0xdb, 0x41, 0xa8, 0x54, 0xcb, 0x9f, 0xf8, 0xf8, 0x7a, 0x79, 0xe8, 0x68, 0x5e, 0x4a, 0x21, + 0xe1, 0x00, 0xb6, 0xf6, 0xbb, 0x25, 0xb8, 0xb2, 0x42, 0x83, 0xd0, 0xe2, 0x22, 0x47, 0xc7, 0x76, + 0x8f, 0x1a, 0xec, 0x2b, 0x7c, 0x5a, 0x80, 0xaa, 0xad, 0x6f, 0x53, 0x9b, 0xcd, 0x5e, 0xac, 0x36, + 0x1f, 0x8c, 0x3c, 0x11, 0x0c, 0x97, 0x32, 0xbb, 0xc6, 0x25, 0xa4, 0xa6, 0x06, 0x91, 0x88, 0x52, + 0x3c, 0x1b, 0xd4, 0x0d, 0xbb, 0xef, 0x07, 0xd4, 0xdb, 0x70, 0xbd, 0x40, 0xea, 0x93, 0xe1, 0xa0, + 0xbe, 0x18, 0x91, 0x30, 0xce, 0x47, 0xe6, 0x01, 0x0c, 0xdb, 0xa2, 0x4e, 0xc0, 0x73, 0x89, 0xff, + 0x8a, 0xa8, 0xef, 0xbb, 0x18, 0x52, 0x30, 0xc6, 0xc5, 0x44, 0x75, 0x5d, 0xc7, 0x0a, 0x5c, 0x21, + 0xaa, 0x9c, 0x14, 0xb5, 0x1e, 0x91, 0x30, 0xce, 0xc7, 0xb3, 0xd1, 0xc0, 0xb3, 0x0c, 0x9f, 0x67, + 0xab, 0xa4, 0xb2, 0x45, 0x24, 0x8c, 0xf3, 0xb1, 0x39, 0x2f, 0x56, 0xff, 0x13, 0xcd, 0x79, 0xbf, + 0xdd, 0x80, 0x6b, 0x89, 0x66, 0x0d, 0xf4, 0x80, 0xee, 0xf4, 0xed, 0x36, 0x0d, 0xd4, 0x07, 0x1c, + 0x71, 0x2e, 0xfc, 0xab, 0xd1, 0x77, 0x17, 0x21, 0x24, 0xc6, 0xe9, 0x7c, 0xf7, 0x81, 0x02, 0x1e, + 0xeb, 0xdb, 0xcf, 0x41, 0xc3, 0xd1, 0x03, 0x9f, 0xff, 0xb8, 0xf2, 0x1f, 0x0d, 0xd5, 0xb0, 0xbb, + 0x8a, 0x80, 0x11, 0x0f, 0xd9, 0x80, 0x0b, 0xb2, 0x89, 0x6f, 0x3e, 0xec, 0xb9, 0x5e, 0x40, 0x3d, + 0x91, 0x57, 0x4e, 0xa7, 0x32, 0xef, 0x85, 0xf5, 0x0c, 0x1e, 0xcc, 0xcc, 0x49, 0xd6, 0xe1, 0xbc, + 0x21, 0xdc, 0xea, 0xd4, 0x76, 0x75, 0x53, 0x01, 0x0a, 0x03, 0x57, 0xb8, 0x34, 0x5a, 0x1c, 0x64, + 0xc1, 0xac, 0x7c, 0xe9, 0xde, 0x5c, 0x1d, 0xa9, 0x37, 0xd7, 0x46, 0xe9, 0xcd, 0xf5, 0xd1, 0x7a, + 0x73, 0xe3, 0x78, 0xbd, 0x99, 0xb5, 0x3c, 0xeb, 0x47, 0xd4, 0x63, 0xea, 0x89, 0x98, 0x61, 0x63, + 0x51, 0x1b, 0x61, 0xcb, 0xb7, 0x33, 0x78, 0x30, 0x33, 0x27, 0xd9, 0x86, 0x2b, 0x22, 0xfd, 0xa6, + 0x63, 0x78, 0x07, 0x3d, 0x36, 0xf1, 0xc4, 0x70, 0x9b, 0x09, 0x0b, 0xe3, 0x95, 0xf6, 0x50, 0x4e, + 0x7c, 0x0c, 0x0a, 0xf9, 0x79, 0x18, 0x17, 0x5f, 0x69, 0x5d, 0xef, 0x71, 0x58, 0x11, 0xc3, 0x71, + 0x51, 0xc2, 0x8e, 0x2f, 0xc6, 0x89, 0x98, 0xe4, 0x25, 0x0b, 0x30, 0xd9, 0xdb, 0x37, 0xd8, 0xe3, + 0xea, 0xce, 0x5d, 0x4a, 0x4d, 0x6a, 0x72, 0xa7, 0x51, 0xa3, 0xf5, 0xbc, 0x32, 0x74, 0x6c, 0x24, + 0xc9, 0x98, 0xe6, 0x27, 0x6f, 0xc1, 0x98, 0x1f, 0xe8, 0x5e, 0x20, 0xcd, 0x7a, 0xd3, 0x13, 0x22, + 0xc6, 0x45, 0x59, 0xbd, 0xda, 0x31, 0x1a, 0x26, 0x38, 0x33, 0xe7, 0x8b, 0xc9, 0xb3, 0x9b, 0x2f, + 0xf2, 0x8c, 0x56, 0xff, 0xa2, 0x08, 0xd7, 0x57, 0x68, 0xb0, 0xee, 0x3a, 0xd2, 0x28, 0x9a, 0x35, + 0xed, 0x1f, 0xcb, 0x26, 0x9a, 0x9c, 0xb4, 0x8b, 0xa7, 0x3a, 0x69, 0x97, 0x4e, 0x69, 0xd2, 0x2e, + 0x9f, 0xe1, 0xa4, 0xfd, 0x8f, 0x8b, 0xf0, 0x7c, 0xa2, 0x25, 0x37, 0x5c, 0x53, 0x0d, 0xf8, 0x5f, + 0x35, 0xe0, 0x31, 0x1a, 0xf0, 0x91, 0xd0, 0x3b, 0xb9, 0x5b, 0x2b, 0xa5, 0xf1, 0x7c, 0x92, 0xd6, + 0x78, 0xde, 0xcf, 0x33, 0xf3, 0x65, 0x48, 0x38, 0xd6, 0x8c, 0x77, 0x1b, 0x88, 0x27, 0x9d, 0x70, + 0xc2, 0xf4, 0x13, 0x53, 0x7a, 0xc2, 0x20, 0x3a, 0x1c, 0xe0, 0xc0, 0x8c, 0x5c, 0xa4, 0x0d, 0x17, + 0x7d, 0xea, 0x04, 0x96, 0x43, 0xed, 0x24, 0x9c, 0xd0, 0x86, 0x5e, 0x94, 0x70, 0x17, 0xdb, 0x59, + 0x4c, 0x98, 0x9d, 0x37, 0xcf, 0x38, 0xf0, 0xaf, 0x81, 0xab, 0x9c, 0xa2, 0x69, 0x4e, 0x4d, 0x63, + 0xf9, 0x34, 0xad, 0xb1, 0x7c, 0x90, 0xff, 0xbb, 0x8d, 0xa6, 0xad, 0xcc, 0x03, 0xf0, 0xaf, 0x10, + 0x57, 0x57, 0xc2, 0x49, 0x1a, 0x43, 0x0a, 0xc6, 0xb8, 0xd8, 0x04, 0xa4, 0xda, 0x39, 0xae, 0xa9, + 0x84, 0x13, 0x50, 0x3b, 0x4e, 0xc4, 0x24, 0xef, 0x50, 0x6d, 0xa7, 0x32, 0xb2, 0xb6, 0x73, 0x1b, + 0x48, 0xc2, 0xf0, 0x28, 0xf0, 0xaa, 0xc9, 0x18, 0xce, 0xd5, 0x01, 0x0e, 0xcc, 0xc8, 0x35, 0xa4, + 0x2b, 0xd7, 0x4e, 0xb7, 0x2b, 0xd7, 0x47, 0xef, 0xca, 0xe4, 0x03, 0xb8, 0xcc, 0x45, 0xc9, 0xf6, + 0x49, 0x02, 0x0b, 0xbd, 0xe7, 0xc7, 0x24, 0xf0, 0x65, 0x1c, 0xc6, 0x88, 0xc3, 0x31, 0xd8, 0xf7, + 0x31, 0x3c, 0x6a, 0x32, 0xe1, 0xba, 0x3d, 0x5c, 0x27, 0x5a, 0xcc, 0xe0, 0xc1, 0xcc, 0x9c, 0xac, + 0x8b, 0x05, 0xac, 0x1b, 0xea, 0xdb, 0x36, 0x35, 0x65, 0x0c, 0x6b, 0xd8, 0xc5, 0x36, 0xd7, 0xda, + 0x92, 0x82, 0x31, 0xae, 0x2c, 0x35, 0x65, 0xec, 0x84, 0x6a, 0xca, 0x0a, 0xb7, 0xd2, 0xef, 0x24, + 0xb4, 0x21, 0xa9, 0xeb, 0x84, 0x51, 0xc9, 0x8b, 0x69, 0x06, 0x1c, 0xcc, 0xc3, 0xb5, 0x44, 0xc3, + 0xb3, 0x7a, 0x81, 0x9f, 0xc4, 0x9a, 0x48, 0x69, 0x89, 0x19, 0x3c, 0x98, 0x99, 0x93, 0xe9, 0xe7, + 0xbb, 0x54, 0xb7, 0x83, 0xdd, 0x24, 0xe0, 0x64, 0x52, 0x3f, 0xbf, 0x35, 0xc8, 0x82, 0x59, 0xf9, + 0x32, 0x27, 0xa4, 0xa9, 0x67, 0x53, 0xad, 0xfa, 0xb5, 0x12, 0x5c, 0x5e, 0xa1, 0x41, 0x18, 0xde, + 0xf3, 0x95, 0x19, 0xe5, 0x0b, 0x30, 0xa3, 0xfc, 0x56, 0x05, 0xce, 0xaf, 0xd0, 0x60, 0x40, 0x1b, + 0xfb, 0x53, 0xda, 0xfc, 0xeb, 0x70, 0x3e, 0x8a, 0x28, 0x6b, 0x07, 0xae, 0x27, 0xe6, 0xf2, 0xd4, + 0x6a, 0xb9, 0x3d, 0xc8, 0x82, 0x59, 0xf9, 0xc8, 0xb7, 0xe0, 0x79, 0x3e, 0xd5, 0x3b, 0x1d, 0x61, + 0x9f, 0x15, 0xc6, 0x84, 0xd8, 0x9e, 0x88, 0x19, 0x09, 0xf9, 0x7c, 0x3b, 0x9b, 0x0d, 0x87, 0xe5, + 0x27, 0xdf, 0x81, 0xb1, 0x9e, 0xd5, 0xa3, 0xb6, 0xe5, 0x70, 0xfd, 0x2c, 0x77, 0x48, 0xc8, 0x46, + 0x0c, 0x2c, 0x5a, 0xc0, 0xc5, 0x53, 0x31, 0x21, 0x30, 0xb3, 0xa7, 0xd6, 0xcf, 0xb0, 0xa7, 0xfe, + 0xcf, 0x22, 0xd4, 0x56, 0x3c, 0xb7, 0xdf, 0x6b, 0x1d, 0x90, 0x0e, 0x54, 0x1f, 0x70, 0xe7, 0x99, + 0x74, 0x4d, 0x8d, 0x1e, 0x95, 0x2d, 0x7c, 0x70, 0x91, 0x4a, 0x24, 0xde, 0x51, 0xc2, 0xb3, 0x4e, + 0xbc, 0x47, 0x0f, 0xa8, 0x29, 0x7d, 0x68, 0x61, 0x27, 0xbe, 0xc3, 0x12, 0x51, 0xd0, 0x48, 0x17, + 0x26, 0x75, 0xdb, 0x76, 0x1f, 0x50, 0x73, 0x4d, 0x0f, 0xa8, 0x43, 0x7d, 0xe5, 0x92, 0x3c, 0xa9, + 0x59, 0x9a, 0xfb, 0xf5, 0x17, 0x92, 0x50, 0x98, 0xc6, 0x26, 0x1f, 0x42, 0xcd, 0x0f, 0x5c, 0x4f, + 0x29, 0x5b, 0xcd, 0xf9, 0xc5, 0xd1, 0x3f, 0x7a, 0xeb, 0x9b, 0x6d, 0x01, 0x25, 0x6c, 0xf6, 0xf2, + 0x05, 0x95, 0x00, 0xed, 0x37, 0x0b, 0x00, 0xb7, 0x36, 0x37, 0x37, 0xa4, 0x7b, 0xc1, 0x84, 0xb2, + 0xde, 0x0f, 0x1d, 0x95, 0xa3, 0x3b, 0x04, 0x13, 0x61, 0x99, 0xd2, 0x87, 0xd7, 0x0f, 0x76, 0x91, + 0xa3, 0x93, 0x9f, 0x84, 0x9a, 0x54, 0x90, 0x65, 0xb3, 0x87, 0xa1, 0x05, 0x52, 0x89, 0x46, 0x45, + 0xd7, 0xfe, 0x41, 0x11, 0x60, 0xd5, 0xb4, 0x69, 0x5b, 0x05, 0xd2, 0x37, 0x82, 0x5d, 0x8f, 0xfa, + 0xbb, 0xae, 0x6d, 0x8e, 0xe8, 0x4d, 0xe5, 0x36, 0xff, 0x4d, 0x05, 0x82, 0x11, 0x1e, 0x31, 0x61, + 0xcc, 0x0f, 0x68, 0x4f, 0x45, 0x6a, 0x8e, 0xe8, 0x44, 0x99, 0x12, 0x76, 0x91, 0x08, 0x07, 0x13, + 0xa8, 0x44, 0x87, 0xa6, 0xe5, 0x18, 0xe2, 0x07, 0x69, 0x1d, 0x8c, 0xd8, 0x91, 0x26, 0xd9, 0x8a, + 0x63, 0x35, 0x82, 0xc1, 0x38, 0xa6, 0xf6, 0x87, 0x45, 0xb8, 0xc4, 0xe5, 0xb1, 0x62, 0x24, 0xe2, + 0x31, 0xc9, 0x9f, 0x1f, 0xd8, 0xf4, 0xf7, 0x67, 0x8f, 0x27, 0x5a, 0xec, 0x19, 0x5b, 0xa7, 0x81, + 0x1e, 0xe9, 0x73, 0x51, 0x5a, 0x6c, 0xa7, 0x5f, 0x1f, 0xca, 0x3e, 0x1b, 0xaf, 0x44, 0xeb, 0xb5, + 0x47, 0xee, 0x42, 0xd9, 0x15, 0xe0, 0xa3, 0x57, 0xe8, 0x35, 0xe6, 0xa3, 0x16, 0x17, 0x47, 0xfe, + 0x22, 0x54, 0xfd, 0x40, 0x0f, 0xfa, 0xea, 0xd7, 0xdc, 0x3a, 0x6d, 0xc1, 0x1c, 0x3c, 0x1a, 0x47, + 0xc4, 0x3b, 0x4a, 0xa1, 0xda, 0x1f, 0x16, 0xe0, 0x4a, 0x76, 0xc6, 0x35, 0xcb, 0x0f, 0xc8, 0x9f, + 0x1b, 0x68, 0xf6, 0x63, 0x7e, 0x71, 0x96, 0x9b, 0x37, 0x7a, 0x18, 0x17, 0xae, 0x52, 0x62, 0x4d, + 0x1e, 0x40, 0xc5, 0x0a, 0x68, 0x57, 0xad, 0x2f, 0xef, 0x9d, 0x72, 0xd5, 0x63, 0x53, 0x3b, 0x93, + 0x82, 0x42, 0x98, 0xf6, 0x59, 0x71, 0x58, 0x95, 0xf9, 0xf4, 0x61, 0x27, 0x63, 0x7e, 0xef, 0xe4, + 0x8b, 0xf9, 0x4d, 0x16, 0x68, 0x30, 0xf4, 0xf7, 0x2f, 0x0c, 0x86, 0xfe, 0xde, 0xcb, 0x1f, 0xfa, + 0x9b, 0x6a, 0x86, 0xa1, 0x11, 0xc0, 0x9f, 0x97, 0xe0, 0xea, 0xe3, 0xba, 0x0d, 0x9b, 0xcf, 0x64, + 0xef, 0xcc, 0x3b, 0x9f, 0x3d, 0xbe, 0x1f, 0x92, 0x79, 0xa8, 0xf4, 0x76, 0x75, 0x5f, 0x29, 0x65, + 0x6a, 0xc1, 0x52, 0xd9, 0x60, 0x89, 0x8f, 0xd8, 0xa0, 0xc1, 0x95, 0x39, 0xfe, 0x8a, 0x82, 0x95, + 0x0d, 0xc7, 0x5d, 0xea, 0xfb, 0x91, 0x4d, 0x20, 0x1c, 0x8e, 0xd7, 0x45, 0x32, 0x2a, 0x3a, 0x09, + 0xa0, 0x2a, 0x4c, 0xcc, 0x72, 0x66, 0x1a, 0x3d, 0x90, 0x2b, 0x23, 0x4c, 0x3c, 0xaa, 0x94, 0xf4, + 0x56, 0x48, 0x59, 0x64, 0x16, 0xca, 0x41, 0x14, 0xb4, 0xab, 0x96, 0xe6, 0xe5, 0x0c, 0xfd, 0x94, + 0xf3, 0xb1, 0x85, 0xbd, 0xbb, 0xcd, 0x8d, 0xea, 0xa6, 0xf4, 0x9f, 0x5b, 0xae, 0xc3, 0x15, 0xb2, + 0x52, 0xb4, 0xb0, 0xbf, 0x37, 0xc0, 0x81, 0x19, 0xb9, 0xb4, 0x7f, 0x57, 0x87, 0x4b, 0xd9, 0xfd, + 0x81, 0xb5, 0xdb, 0x3e, 0xf5, 0x7c, 0x86, 0x5d, 0x48, 0xb6, 0xdb, 0x7d, 0x91, 0x8c, 0x8a, 0xfe, + 0xa5, 0x0e, 0x38, 0xfb, 0xad, 0x02, 0x5c, 0xf6, 0xa4, 0x8f, 0xe8, 0x69, 0x04, 0x9d, 0xbd, 0x28, + 0xcc, 0x19, 0x43, 0x04, 0xe2, 0xf0, 0xb2, 0x90, 0xbf, 0x57, 0x80, 0xe9, 0x6e, 0xca, 0xce, 0x71, + 0x86, 0xfb, 0xd6, 0x78, 0x54, 0xfc, 0xfa, 0x10, 0x79, 0x38, 0xb4, 0x24, 0xe4, 0x3b, 0xd0, 0xec, + 0xb1, 0x7e, 0xe1, 0x07, 0xd4, 0x31, 0xd4, 0xd6, 0xb5, 0xd1, 0xff, 0xa4, 0x8d, 0x08, 0x4b, 0x85, + 0xa2, 0x09, 0xfd, 0x20, 0x46, 0xc0, 0xb8, 0xc4, 0x67, 0x7c, 0xa3, 0xda, 0x0d, 0xa8, 0xfb, 0x34, + 0x08, 0x2c, 0xa7, 0x23, 0xd6, 0x1b, 0x0d, 0xf1, 0xaf, 0xb4, 0x65, 0x1a, 0x86, 0x54, 0xf2, 0x53, + 0xd0, 0xe0, 0x2e, 0xa7, 0x05, 0xaf, 0xe3, 0x4f, 0x37, 0x78, 0xb8, 0xd8, 0xb8, 0x08, 0x80, 0x93, + 0x89, 0x18, 0xd1, 0xc9, 0x6b, 0x30, 0xb6, 0xcd, 0x7f, 0x5f, 0xb9, 0x77, 0x59, 0xd8, 0xb8, 0xb8, + 0xb6, 0xd6, 0x8a, 0xa5, 0x63, 0x82, 0x8b, 0xcc, 0x03, 0xd0, 0xd0, 0x2f, 0x97, 0xb6, 0x67, 0x45, + 0x1e, 0x3b, 0x8c, 0x71, 0x91, 0x17, 0xa1, 0x14, 0xd8, 0x3e, 0xb7, 0x61, 0xd5, 0xa3, 0x25, 0xe8, + 0xe6, 0x5a, 0x1b, 0x59, 0xba, 0xf6, 0xa3, 0x02, 0x4c, 0xa6, 0x36, 0x97, 0xb0, 0x2c, 0x7d, 0xcf, + 0x96, 0xc3, 0x48, 0x98, 0x65, 0x0b, 0xd7, 0x90, 0xa5, 0x93, 0x0f, 0xa4, 0x5a, 0x5e, 0xcc, 0x79, + 0x4c, 0xc3, 0x5d, 0x3d, 0xf0, 0x99, 0x1e, 0x3e, 0xa0, 0x91, 0x73, 0x37, 0x5f, 0x54, 0x1e, 0x39, + 0x0f, 0xc4, 0xdc, 0x7c, 0x11, 0x0d, 0x13, 0x9c, 0x29, 0x83, 0x5f, 0xf9, 0x38, 0x06, 0x3f, 0xed, + 0xd7, 0x8b, 0xb1, 0x16, 0x90, 0x9a, 0xfd, 0x13, 0x5a, 0xe0, 0x15, 0x36, 0x81, 0x86, 0x93, 0x7b, + 0x23, 0x3e, 0xff, 0xf1, 0xc9, 0x58, 0x52, 0xc9, 0xbb, 0xa2, 0xed, 0x4b, 0x39, 0x37, 0xc3, 0x6e, + 0xae, 0xb5, 0x45, 0x74, 0x95, 0xfa, 0x6a, 0xe1, 0x27, 0x28, 0x9f, 0xd1, 0x27, 0xd0, 0xfe, 0x55, + 0x09, 0x9a, 0xb7, 0xdd, 0xed, 0x2f, 0x49, 0x04, 0x75, 0xf6, 0x34, 0x55, 0xfc, 0x02, 0xa7, 0xa9, + 0x2d, 0x78, 0x3e, 0x08, 0xec, 0x36, 0x35, 0x5c, 0xc7, 0xf4, 0x17, 0x76, 0x02, 0xea, 0x2d, 0x5b, + 0x8e, 0xe5, 0xef, 0x52, 0x53, 0xba, 0x93, 0x5e, 0x38, 0x3a, 0x9c, 0x79, 0x7e, 0x73, 0x73, 0x2d, + 0x8b, 0x05, 0x87, 0xe5, 0xe5, 0xc3, 0x86, 0xd8, 0x09, 0xc8, 0x77, 0xca, 0xc8, 0x98, 0x1b, 0x31, + 0x6c, 0xc4, 0xd2, 0x31, 0xc1, 0xa5, 0x7d, 0xb7, 0x08, 0x8d, 0x70, 0x03, 0x3e, 0x79, 0x19, 0x6a, + 0xdb, 0x9e, 0xbb, 0x47, 0x3d, 0xe1, 0xb9, 0x93, 0x3b, 0x65, 0x5a, 0x22, 0x09, 0x15, 0x8d, 0xbc, + 0x04, 0x95, 0xc0, 0xed, 0x59, 0x46, 0xda, 0xa0, 0xb6, 0xc9, 0x12, 0x51, 0xd0, 0xce, 0xae, 0x83, + 0xbf, 0x92, 0x50, 0xed, 0x1a, 0x43, 0x95, 0xb1, 0xf7, 0xa1, 0xec, 0xeb, 0xbe, 0x2d, 0xe7, 0xd3, + 0x1c, 0x7b, 0xd9, 0x17, 0xda, 0x6b, 0x72, 0x2f, 0xfb, 0x42, 0x7b, 0x0d, 0x39, 0xa8, 0xf6, 0x27, + 0x45, 0x68, 0x8a, 0x76, 0x13, 0xa3, 0xc2, 0x69, 0xb6, 0xdc, 0xdb, 0x3c, 0x94, 0xc2, 0xef, 0x77, + 0xa9, 0xc7, 0xcd, 0x4c, 0x72, 0x90, 0x8b, 0xfb, 0x07, 0x22, 0x62, 0x18, 0x4e, 0x11, 0x25, 0xa9, + 0xa6, 0x2f, 0x9f, 0x61, 0xd3, 0x57, 0x8e, 0xd5, 0xf4, 0xd5, 0xb3, 0x68, 0xfa, 0x4f, 0x8b, 0xd0, + 0x58, 0xb3, 0x76, 0xa8, 0x71, 0x60, 0xd8, 0x7c, 0x4f, 0xa0, 0x49, 0x6d, 0x1a, 0xd0, 0x15, 0x4f, + 0x37, 0xe8, 0x06, 0xf5, 0x2c, 0x7e, 0x40, 0x0d, 0xfb, 0x3f, 0xf8, 0x08, 0x24, 0xf7, 0x04, 0x2e, + 0x0d, 0xe1, 0xc1, 0xa1, 0xb9, 0xc9, 0x2a, 0x8c, 0x99, 0xd4, 0xb7, 0x3c, 0x6a, 0x6e, 0xc4, 0x16, + 0x2a, 0x2f, 0xab, 0xa9, 0x66, 0x29, 0x46, 0x7b, 0x74, 0x38, 0x33, 0xae, 0x0c, 0x94, 0x62, 0xc5, + 0x92, 0xc8, 0xca, 0x7e, 0xf9, 0x9e, 0xde, 0xf7, 0xb3, 0xca, 0x18, 0xfb, 0xe5, 0x37, 0xb2, 0x59, + 0x70, 0x58, 0x5e, 0xad, 0x02, 0xa5, 0x35, 0xb7, 0xa3, 0x7d, 0x56, 0x82, 0xf0, 0x24, 0x23, 0xf2, + 0x57, 0x0a, 0xd0, 0xd4, 0x1d, 0xc7, 0x0d, 0xe4, 0x29, 0x41, 0xc2, 0x03, 0x8f, 0xb9, 0x0f, 0x4c, + 0x9a, 0x5d, 0x88, 0x40, 0x85, 0xf3, 0x36, 0x74, 0x28, 0xc7, 0x28, 0x18, 0x97, 0x4d, 0xfa, 0x29, + 0x7f, 0xf2, 0x7a, 0xfe, 0x52, 0x1c, 0xc3, 0x7b, 0x7c, 0xe5, 0x1b, 0x30, 0x95, 0x2e, 0xec, 0x49, + 0xdc, 0x41, 0xb9, 0x1c, 0xf3, 0x45, 0x80, 0x28, 0xa6, 0xe4, 0x29, 0x18, 0xb1, 0xac, 0x84, 0x11, + 0x6b, 0x65, 0xf4, 0x06, 0x0e, 0x0b, 0x3d, 0xd4, 0x70, 0xf5, 0x51, 0xca, 0x70, 0xb5, 0x7a, 0x1a, + 0xc2, 0x1e, 0x6f, 0xac, 0xfa, 0xfb, 0x05, 0x98, 0x8a, 0x98, 0xe5, 0x0e, 0xd9, 0x37, 0x61, 0xdc, + 0xa3, 0xba, 0xd9, 0xd2, 0x03, 0x63, 0x97, 0x87, 0x7a, 0x17, 0x78, 0x6c, 0xf6, 0xb9, 0xa3, 0xc3, + 0x99, 0x71, 0x8c, 0x13, 0x30, 0xc9, 0x47, 0x74, 0x68, 0xb2, 0x84, 0x4d, 0xab, 0x4b, 0xdd, 0x7e, + 0x30, 0xa2, 0xd5, 0x94, 0x2f, 0x58, 0x30, 0x82, 0xc1, 0x38, 0xa6, 0xf6, 0x79, 0x01, 0x26, 0xe2, + 0x05, 0x3e, 0x73, 0x8b, 0xda, 0x6e, 0xd2, 0xa2, 0xb6, 0x78, 0x0a, 0xdf, 0x64, 0x88, 0x15, 0xed, + 0x13, 0x88, 0x57, 0x8d, 0x5b, 0xce, 0xe2, 0xc6, 0x82, 0xc2, 0x63, 0x8d, 0x05, 0x5f, 0xfe, 0xc3, + 0x6b, 0x86, 0x69, 0xb9, 0xe5, 0x67, 0x58, 0xcb, 0xfd, 0x22, 0x4f, 0xc0, 0x89, 0x9d, 0xe2, 0x52, + 0xcd, 0x71, 0x8a, 0x4b, 0x37, 0x3c, 0xc5, 0xa5, 0x76, 0x6a, 0x83, 0xce, 0x71, 0x4e, 0x72, 0xa9, + 0x3f, 0xd5, 0x93, 0x5c, 0x1a, 0x67, 0x75, 0x92, 0x0b, 0xe4, 0x3d, 0xc9, 0xe5, 0x93, 0x02, 0x4c, + 0x98, 0x89, 0x1d, 0xb3, 0xdc, 0xb6, 0x90, 0x67, 0xaa, 0x49, 0x6e, 0xc0, 0x15, 0x5b, 0xa6, 0x92, + 0x69, 0x98, 0x12, 0x49, 0x3e, 0x2d, 0xc0, 0x44, 0xbf, 0x67, 0xea, 0x41, 0x68, 0x38, 0xe2, 0x46, + 0x8b, 0x3c, 0xa5, 0xd8, 0x4a, 0xc0, 0x45, 0x8d, 0x9b, 0x4c, 0xc7, 0x94, 0x58, 0xed, 0x8f, 0x6b, + 0xf1, 0x19, 0xe9, 0x69, 0x1b, 0xcd, 0xdf, 0x48, 0x1a, 0xcd, 0xaf, 0xa7, 0x8d, 0xe6, 0x93, 0xb1, + 0x78, 0xd6, 0xb8, 0xe1, 0xfc, 0xa7, 0x63, 0x03, 0x75, 0x89, 0x9f, 0xe1, 0x12, 0x7e, 0xf3, 0x8c, + 0xc1, 0x7a, 0x01, 0x26, 0xa5, 0xf6, 0xaa, 0x88, 0x7c, 0x94, 0x1b, 0x8f, 0xc2, 0x9c, 0x96, 0x92, + 0x64, 0x4c, 0xf3, 0x33, 0x81, 0xbe, 0x3a, 0x40, 0x53, 0x2c, 0x15, 0xa2, 0x4e, 0xa6, 0x0e, 0xb7, + 0x0c, 0x39, 0xd8, 0xb2, 0xc2, 0xa3, 0xba, 0x2f, 0x4d, 0xdf, 0xb1, 0x65, 0x05, 0xf2, 0x54, 0x94, + 0xd4, 0xb8, 0xfd, 0xbf, 0xf6, 0x04, 0xfb, 0xbf, 0x0e, 0x4d, 0x5b, 0xf7, 0x03, 0xf1, 0x35, 0x4d, + 0xf9, 0x3b, 0xff, 0x99, 0xe3, 0x4d, 0xbc, 0x6c, 0x32, 0x8f, 0xb4, 0xdb, 0xb5, 0x08, 0x06, 0xe3, + 0x98, 0xc4, 0x84, 0x31, 0xf6, 0xca, 0x7f, 0x6d, 0x73, 0x21, 0x90, 0xc7, 0x4c, 0x9d, 0x44, 0x46, + 0x68, 0xb6, 0x5a, 0x8b, 0xe1, 0x60, 0x02, 0x75, 0x88, 0x8b, 0x00, 0x46, 0x71, 0x11, 0x90, 0x9f, + 0x17, 0x9a, 0xd3, 0x41, 0xf8, 0x59, 0x9b, 0xfc, 0xb3, 0x86, 0x21, 0x92, 0x18, 0x27, 0x62, 0x92, + 0x97, 0xf5, 0x8a, 0xbe, 0x6c, 0x06, 0x95, 0x7d, 0x2c, 0xd9, 0x2b, 0xb6, 0x92, 0x64, 0x4c, 0xf3, + 0x93, 0x0d, 0xb8, 0x10, 0x26, 0xc5, 0x8b, 0x31, 0xce, 0x71, 0xc2, 0x98, 0xb5, 0xad, 0x0c, 0x1e, + 0xcc, 0xcc, 0xc9, 0x37, 0x81, 0xf4, 0x3d, 0x8f, 0x3a, 0xc1, 0x2d, 0xdd, 0xdf, 0x95, 0xc1, 0x6f, + 0xd1, 0x26, 0x90, 0x88, 0x84, 0x71, 0x3e, 0x32, 0x0f, 0x20, 0xe0, 0x78, 0xae, 0xc9, 0x64, 0x7c, + 0xe9, 0x56, 0x48, 0xc1, 0x18, 0x97, 0xf6, 0x49, 0x03, 0x9a, 0x77, 0xf5, 0xc0, 0xda, 0xa7, 0xdc, + 0x9f, 0x77, 0x36, 0x4e, 0x95, 0xbf, 0x55, 0x80, 0x4b, 0xc9, 0xa0, 0xcd, 0x33, 0xf4, 0xac, 0xf0, + 0x23, 0x60, 0x30, 0x53, 0x1a, 0x0e, 0x29, 0x05, 0xf7, 0xb1, 0x0c, 0xc4, 0x80, 0x9e, 0xb5, 0x8f, + 0xa5, 0x3d, 0x4c, 0x20, 0x0e, 0x2f, 0xcb, 0x97, 0xc5, 0xc7, 0xf2, 0x6c, 0x9f, 0x14, 0x98, 0xf2, + 0x00, 0xd5, 0x9e, 0x19, 0x0f, 0x50, 0xfd, 0x99, 0x50, 0xbb, 0x7b, 0x31, 0x0f, 0x50, 0x23, 0x67, + 0x24, 0x92, 0xdc, 0xe7, 0x20, 0xd0, 0x86, 0x79, 0x92, 0xf8, 0x11, 0x05, 0xca, 0x32, 0xcf, 0xb4, + 0xd5, 0x6d, 0xdd, 0xb7, 0x0c, 0xa9, 0x76, 0xe4, 0x38, 0x19, 0x55, 0x9d, 0xdd, 0x26, 0x02, 0x16, + 0xf8, 0x2b, 0x0a, 0xec, 0xe8, 0xa8, 0xba, 0x62, 0xae, 0xa3, 0xea, 0xc8, 0x22, 0x94, 0x9d, 0x3d, + 0x7a, 0x70, 0xb2, 0xcd, 0xfe, 0x7c, 0x15, 0x76, 0xf7, 0x0e, 0x3d, 0x40, 0x9e, 0x59, 0xfb, 0x6e, + 0x11, 0x80, 0x55, 0xff, 0x78, 0xbe, 0x98, 0x9f, 0x84, 0x9a, 0xdf, 0xe7, 0x56, 0x13, 0xa9, 0x30, + 0x45, 0xe1, 0x5b, 0x22, 0x19, 0x15, 0x9d, 0xbc, 0x04, 0x95, 0x8f, 0xfa, 0xb4, 0xaf, 0x02, 0x0b, + 0x42, 0xc5, 0xfd, 0x9b, 0x2c, 0x11, 0x05, 0xed, 0xec, 0xec, 0xaa, 0xca, 0x67, 0x53, 0x39, 0x2b, + 0x9f, 0x4d, 0x03, 0x6a, 0x77, 0x5d, 0x1e, 0x0d, 0xaa, 0xfd, 0xf7, 0x22, 0x40, 0x14, 0x6d, 0x47, + 0x7e, 0xb3, 0x00, 0x17, 0xc3, 0x1f, 0x2e, 0x10, 0xeb, 0x2f, 0x7e, 0x18, 0x71, 0x6e, 0xff, 0x4d, + 0xd6, 0xcf, 0xce, 0x47, 0xa0, 0x8d, 0x2c, 0x71, 0x98, 0x5d, 0x0a, 0x82, 0x50, 0xa7, 0xdd, 0x5e, + 0x70, 0xb0, 0x64, 0x79, 0xb2, 0x07, 0x66, 0x06, 0x75, 0xde, 0x94, 0x3c, 0x22, 0xab, 0x34, 0x12, + 0xf0, 0x9f, 0x48, 0x51, 0x30, 0xc4, 0x21, 0xbb, 0x50, 0x77, 0xdc, 0x0f, 0x7c, 0xd6, 0x1c, 0xb2, + 0x3b, 0xbe, 0x33, 0x7a, 0x93, 0x8b, 0x66, 0x15, 0xf6, 0x7e, 0xf9, 0x82, 0x35, 0x47, 0x36, 0xf6, + 0x6f, 0x14, 0xe1, 0x7c, 0x46, 0x3b, 0x90, 0x77, 0x60, 0x4a, 0x06, 0x36, 0x46, 0xa7, 0x72, 0x17, + 0xa2, 0x53, 0xb9, 0xdb, 0x29, 0x1a, 0x0e, 0x70, 0x93, 0x0f, 0x00, 0x74, 0xc3, 0xa0, 0xbe, 0xbf, + 0xee, 0x9a, 0x6a, 0x3d, 0xf0, 0x36, 0x53, 0x5f, 0x16, 0xc2, 0xd4, 0x47, 0x87, 0x33, 0x3f, 0x93, + 0x15, 0xab, 0x9c, 0x6a, 0xe7, 0x28, 0x03, 0xc6, 0x20, 0xc9, 0xb7, 0x01, 0xc4, 0x22, 0x3c, 0x3c, + 0x4e, 0xe1, 0x09, 0x96, 0xab, 0x59, 0x75, 0x70, 0xd5, 0xec, 0x37, 0xfb, 0xba, 0x13, 0x58, 0xc1, + 0x81, 0x38, 0xbd, 0xe6, 0x7e, 0x88, 0x82, 0x31, 0x44, 0xed, 0x9f, 0x17, 0xa1, 0xae, 0x6c, 0xe6, + 0x4f, 0xc1, 0x50, 0xda, 0x49, 0x18, 0x4a, 0x4f, 0x29, 0x3a, 0x39, 0xcb, 0x4c, 0xea, 0xa6, 0xcc, + 0xa4, 0x2b, 0xf9, 0x45, 0x3d, 0xde, 0x48, 0xfa, 0x3b, 0x45, 0x98, 0x50, 0xac, 0x79, 0x4d, 0xa4, + 0x5f, 0x87, 0x49, 0x11, 0x55, 0xb0, 0xae, 0x3f, 0x14, 0x07, 0xf9, 0xf0, 0x06, 0x2b, 0x8b, 0x80, + 0xe0, 0x56, 0x92, 0x84, 0x69, 0x5e, 0xd6, 0xad, 0x45, 0xd2, 0x16, 0x5b, 0x84, 0x09, 0x3f, 0xa4, + 0x58, 0x6f, 0xf2, 0x6e, 0xdd, 0x4a, 0xd1, 0x70, 0x80, 0x3b, 0x6d, 0xa3, 0x2d, 0x9f, 0x81, 0x8d, + 0xf6, 0x3f, 0x14, 0x60, 0x2c, 0x6a, 0xaf, 0x33, 0xb7, 0xd0, 0xee, 0x24, 0x2d, 0xb4, 0x0b, 0xb9, + 0xbb, 0xc3, 0x10, 0xfb, 0xec, 0x5f, 0xab, 0x41, 0x22, 0x48, 0x9e, 0x6c, 0xc3, 0x15, 0x2b, 0x33, + 0xd4, 0x2f, 0x36, 0xda, 0x84, 0xbb, 0xbe, 0x57, 0x87, 0x72, 0xe2, 0x63, 0x50, 0x48, 0x1f, 0xea, + 0xfb, 0xd4, 0x0b, 0x2c, 0x83, 0xaa, 0xfa, 0xad, 0xe4, 0x56, 0xc9, 0xa4, 0x15, 0x3a, 0x6c, 0xd3, + 0xfb, 0x52, 0x00, 0x86, 0xa2, 0xc8, 0x36, 0x54, 0xa8, 0xd9, 0xa1, 0xea, 0x68, 0xa5, 0x9c, 0x07, + 0x97, 0x86, 0xed, 0xc9, 0xde, 0x7c, 0x14, 0xd0, 0xc4, 0x87, 0x86, 0xad, 0xbc, 0x8c, 0xb2, 0x1f, + 0x8e, 0xae, 0x60, 0x85, 0xfe, 0xca, 0xe8, 0xd4, 0x85, 0x30, 0x09, 0x23, 0x39, 0x64, 0x2f, 0x34, + 0x77, 0x56, 0x4e, 0x69, 0xf0, 0x78, 0x8c, 0xb1, 0xd3, 0x87, 0xc6, 0x03, 0x3d, 0xa0, 0x5e, 0x57, + 0xf7, 0xf6, 0xe4, 0x6a, 0x63, 0xf4, 0x1a, 0xbe, 0xab, 0x90, 0xa2, 0x1a, 0x86, 0x49, 0x18, 0xc9, + 0x21, 0x2e, 0x34, 0x02, 0xa9, 0x3e, 0x2b, 0x9b, 0xee, 0xe8, 0x42, 0x95, 0x22, 0xee, 0xcb, 0x60, + 0x79, 0xf5, 0x8a, 0x91, 0x0c, 0xb2, 0x9f, 0x38, 0x5b, 0x5a, 0x9c, 0x28, 0xde, 0xca, 0xe1, 0x1b, + 0x90, 0x50, 0xd1, 0x74, 0x93, 0x7d, 0x46, 0xb5, 0xf6, 0xbf, 0x2a, 0xd1, 0xb0, 0xfc, 0xb4, 0xed, + 0x84, 0xaf, 0x25, 0xed, 0x84, 0xd7, 0xd2, 0x76, 0xc2, 0x94, 0xb3, 0xfa, 0xe4, 0xe1, 0xb5, 0x29, + 0xf3, 0x5a, 0xf9, 0x0c, 0xcc, 0x6b, 0xaf, 0x42, 0x73, 0x9f, 0x8f, 0x04, 0xe2, 0x9c, 0xa6, 0x0a, + 0x9f, 0x46, 0xf8, 0xc8, 0x7e, 0x3f, 0x4a, 0xc6, 0x38, 0x0f, 0xcb, 0x22, 0x6f, 0xd3, 0x08, 0x0f, + 0xba, 0x95, 0x59, 0xda, 0x51, 0x32, 0xc6, 0x79, 0x78, 0x64, 0x9e, 0xe5, 0xec, 0x89, 0x0c, 0x35, + 0x9e, 0x41, 0x44, 0xe6, 0xa9, 0x44, 0x8c, 0xe8, 0xe4, 0x06, 0xd4, 0xfb, 0xe6, 0x8e, 0xe0, 0xad, + 0x73, 0x5e, 0xae, 0x61, 0x6e, 0x2d, 0x2d, 0xcb, 0x73, 0xa3, 0x14, 0x95, 0x95, 0xa4, 0xab, 0xf7, + 0x14, 0x81, 0xaf, 0x0d, 0x65, 0x49, 0xd6, 0xa3, 0x64, 0x8c, 0xf3, 0x90, 0x9f, 0x83, 0x09, 0x8f, + 0x9a, 0x7d, 0x83, 0x86, 0xb9, 0x80, 0xe7, 0x22, 0xe2, 0xda, 0x90, 0x38, 0x05, 0x53, 0x9c, 0x43, + 0x8c, 0x84, 0xcd, 0x91, 0x8c, 0x84, 0xdf, 0x80, 0x09, 0xd3, 0xd3, 0x2d, 0x87, 0x9a, 0xf7, 0x1c, + 0x1e, 0x91, 0x20, 0xe3, 0x03, 0x43, 0x0b, 0xf9, 0x52, 0x82, 0x8a, 0x29, 0x6e, 0xed, 0x0f, 0x0a, + 0x40, 0x06, 0x23, 0xe1, 0xc9, 0x2e, 0x54, 0x1d, 0x6e, 0x3d, 0xcb, 0x7d, 0xb4, 0x76, 0xcc, 0x08, + 0x27, 0x86, 0x35, 0x99, 0x20, 0xf1, 0x89, 0x03, 0x75, 0xfa, 0x30, 0xa0, 0x9e, 0x13, 0xee, 0x8c, + 0x39, 0x9d, 0x63, 0xbc, 0xc5, 0x6a, 0x42, 0x22, 0x63, 0x28, 0x43, 0xfb, 0xa3, 0x22, 0x34, 0x63, + 0x7c, 0x4f, 0x5a, 0x94, 0xf2, 0xcd, 0xf9, 0xc2, 0x68, 0xb5, 0xe5, 0xd9, 0xf2, 0x0f, 0x8d, 0x6d, + 0xce, 0x97, 0x24, 0x5c, 0xc3, 0x38, 0x1f, 0x99, 0x07, 0xe8, 0xea, 0x7e, 0x40, 0x3d, 0x3e, 0x7b, + 0xa7, 0xb6, 0xc4, 0xaf, 0x87, 0x14, 0x8c, 0x71, 0x91, 0xeb, 0xf2, 0x20, 0xf6, 0x72, 0xf2, 0x08, + 0xc3, 0x21, 0xa7, 0xac, 0x57, 0x4e, 0xe1, 0x94, 0x75, 0xd2, 0x81, 0x29, 0x55, 0x6a, 0x45, 0x3d, + 0xd9, 0x01, 0x77, 0x62, 0xfd, 0x93, 0x82, 0xc0, 0x01, 0x50, 0xed, 0xbb, 0x05, 0x18, 0x4f, 0x98, + 0x4c, 0xc4, 0xe1, 0x83, 0x6a, 0x1f, 0x47, 0xe2, 0xf0, 0xc1, 0xd8, 0xf6, 0x8b, 0x57, 0xa0, 0x2a, + 0x1a, 0x28, 0x1d, 0x9e, 0x29, 0x9a, 0x10, 0x25, 0x95, 0x8d, 0x85, 0xd2, 0x28, 0x9b, 0x1e, 0x0b, + 0xa5, 0xd5, 0x16, 0x15, 0x5d, 0xf8, 0x3a, 0x44, 0xe9, 0x64, 0x4b, 0xc7, 0x7c, 0x1d, 0x22, 0x1d, + 0x43, 0x0e, 0xed, 0xf7, 0x78, 0xb9, 0x03, 0xef, 0x20, 0x5c, 0x0b, 0x76, 0xa0, 0x26, 0x43, 0xf2, + 0xe4, 0xaf, 0xf1, 0x4e, 0x0e, 0x3b, 0x0e, 0xc7, 0x91, 0xc1, 0x67, 0xba, 0xb1, 0x77, 0x6f, 0x67, + 0x07, 0x15, 0x3a, 0xb9, 0x09, 0x0d, 0xd7, 0x59, 0xd6, 0x2d, 0xbb, 0xef, 0xa9, 0x99, 0xe1, 0x27, + 0xd8, 0x58, 0x77, 0x4f, 0x25, 0x3e, 0x3a, 0x9c, 0xb9, 0x14, 0xbe, 0x24, 0x0a, 0x89, 0x51, 0x4e, + 0xed, 0x2f, 0x17, 0xe0, 0x22, 0xba, 0xb6, 0x6d, 0x39, 0x9d, 0xa4, 0xb3, 0x8c, 0xd8, 0x30, 0xd1, + 0xd5, 0x1f, 0x6e, 0x39, 0xfa, 0xbe, 0x6e, 0xd9, 0xfa, 0xb6, 0x4d, 0x9f, 0xb8, 0x96, 0xeb, 0x07, + 0x96, 0x3d, 0x2b, 0xae, 0x83, 0x9b, 0x5d, 0x75, 0x82, 0x7b, 0x5e, 0x3b, 0xf0, 0x2c, 0xa7, 0x23, + 0x06, 0xbd, 0xf5, 0x04, 0x16, 0xa6, 0xb0, 0xb5, 0x3f, 0x2e, 0x01, 0x0f, 0x0b, 0x23, 0x6f, 0x42, + 0xa3, 0x4b, 0x8d, 0x5d, 0xdd, 0xb1, 0x7c, 0x75, 0x8c, 0xeb, 0x65, 0x56, 0xaf, 0x75, 0x95, 0xf8, + 0x88, 0x7d, 0x8a, 0x85, 0xf6, 0x1a, 0xdf, 0x79, 0x11, 0xf1, 0x12, 0x03, 0xaa, 0x1d, 0xdf, 0xd7, + 0x7b, 0x56, 0xee, 0xa8, 0x04, 0x71, 0x6c, 0xa6, 0x18, 0x8e, 0xc4, 0x33, 0x4a, 0x68, 0x62, 0x40, + 0xa5, 0x67, 0xeb, 0x96, 0x93, 0xfb, 0xfa, 0x22, 0x56, 0x83, 0x0d, 0x86, 0x24, 0x8c, 0x6b, 0xfc, + 0x11, 0x05, 0x36, 0xe9, 0x43, 0xd3, 0x37, 0x3c, 0xbd, 0xeb, 0xef, 0xea, 0xf3, 0xaf, 0xbf, 0x91, + 0x5b, 0x5d, 0x8d, 0x44, 0x89, 0xd9, 0x73, 0x11, 0x17, 0xd6, 0xdb, 0xb7, 0x16, 0xe6, 0x5f, 0x7f, + 0x03, 0xe3, 0x72, 0xe2, 0x62, 0x5f, 0x7f, 0x75, 0x5e, 0x8e, 0x20, 0xa7, 0x2e, 0xf6, 0xf5, 0x57, + 0xe7, 0x31, 0x2e, 0x47, 0xfb, 0xdf, 0x05, 0x68, 0x84, 0xbc, 0x64, 0x0b, 0x80, 0x8d, 0x65, 0xf2, + 0xa0, 0xcb, 0x13, 0x5d, 0x3a, 0xc1, 0xed, 0x13, 0x5b, 0x61, 0x66, 0x8c, 0x01, 0x65, 0x9c, 0x04, + 0x5a, 0x3c, 0xed, 0x93, 0x40, 0xe7, 0xa0, 0xb1, 0xab, 0x3b, 0xa6, 0xbf, 0xab, 0xef, 0x89, 0x21, + 0x3d, 0x76, 0x36, 0xee, 0x2d, 0x45, 0xc0, 0x88, 0x47, 0xfb, 0xa7, 0x55, 0x10, 0xa1, 0x04, 0x6c, + 0xd0, 0x31, 0x2d, 0x5f, 0xc4, 0xb2, 0x17, 0x78, 0xce, 0x70, 0xd0, 0x59, 0x92, 0xe9, 0x18, 0x72, + 0x90, 0xcb, 0x50, 0xea, 0x5a, 0x8e, 0xf4, 0x3d, 0x71, 0xd3, 0xe3, 0xba, 0xe5, 0x20, 0x4b, 0xe3, + 0x24, 0xfd, 0xa1, 0x0c, 0x43, 0x14, 0x24, 0xfd, 0x21, 0xb2, 0x34, 0xf2, 0x75, 0x98, 0xb4, 0x5d, + 0x77, 0x8f, 0x0d, 0x1f, 0x2a, 0x5a, 0x51, 0xf8, 0x81, 0xb9, 0x31, 0x60, 0x2d, 0x49, 0xc2, 0x34, + 0x2f, 0xd9, 0x82, 0xe7, 0x3f, 0xa6, 0x9e, 0x2b, 0xc7, 0xcb, 0xb6, 0x4d, 0x69, 0x4f, 0xc1, 0x08, + 0x65, 0x8e, 0x07, 0x3d, 0xfe, 0x62, 0x36, 0x0b, 0x0e, 0xcb, 0xcb, 0xc3, 0xa7, 0x75, 0xaf, 0x43, + 0x83, 0x0d, 0xcf, 0x35, 0xa8, 0xef, 0x5b, 0x4e, 0x47, 0xc1, 0x56, 0x23, 0xd8, 0xcd, 0x6c, 0x16, + 0x1c, 0x96, 0x97, 0xbc, 0x07, 0xd3, 0x82, 0x24, 0xd4, 0x96, 0x05, 0x31, 0xcc, 0x58, 0xb6, 0xba, + 0xf5, 0x6f, 0x5c, 0x78, 0x78, 0x36, 0x87, 0xf0, 0xe0, 0xd0, 0xdc, 0xe4, 0x36, 0x4c, 0x29, 0xff, + 0xde, 0x06, 0xf5, 0xda, 0x61, 0x78, 0xc9, 0x78, 0xeb, 0x1a, 0x5b, 0x79, 0x2f, 0xd1, 0x9e, 0x47, + 0x8d, 0xb8, 0x9f, 0x54, 0x71, 0xe1, 0x40, 0x3e, 0x82, 0x70, 0x89, 0xc7, 0x90, 0x6c, 0xf5, 0x16, + 0x5d, 0xd7, 0x36, 0xdd, 0x07, 0x8e, 0xaa, 0xbb, 0x50, 0x31, 0xb9, 0x4b, 0xaf, 0x9d, 0xc9, 0x81, + 0x43, 0x72, 0xb2, 0x9a, 0x73, 0xca, 0x92, 0xfb, 0xc0, 0x49, 0xa3, 0x42, 0x54, 0xf3, 0xf6, 0x10, + 0x1e, 0x1c, 0x9a, 0x9b, 0x2c, 0x03, 0x49, 0xd7, 0x60, 0xab, 0x27, 0x9d, 0xce, 0x97, 0xc4, 0x99, + 0x35, 0x69, 0x2a, 0x66, 0xe4, 0x20, 0x6b, 0x70, 0x21, 0x9d, 0xca, 0xc4, 0x49, 0xff, 0x33, 0x3f, + 0xad, 0x16, 0x33, 0xe8, 0x98, 0x99, 0x4b, 0xfb, 0x67, 0x45, 0x18, 0x4f, 0x1c, 0x72, 0xf0, 0xcc, + 0x6d, 0x26, 0x67, 0x6b, 0x81, 0xae, 0xdf, 0x59, 0x5d, 0xba, 0x45, 0x75, 0x93, 0x7a, 0x77, 0xa8, + 0x3a, 0x90, 0x42, 0x4c, 0x8b, 0x09, 0x0a, 0xa6, 0x38, 0xc9, 0x0e, 0x54, 0x84, 0x65, 0x3b, 0xef, + 0xf5, 0x25, 0xaa, 0x8d, 0xb8, 0x79, 0x5b, 0xde, 0xf9, 0xe3, 0x7a, 0x14, 0x05, 0xbc, 0x16, 0xc0, + 0x58, 0x9c, 0x83, 0x0d, 0x24, 0x91, 0xda, 0x5b, 0x4b, 0xa8, 0xbc, 0xab, 0x50, 0x0a, 0x82, 0x51, + 0xb7, 0xa9, 0x0b, 0x4f, 0xc9, 0xe6, 0x1a, 0x32, 0x0c, 0x6d, 0x87, 0x7d, 0x3b, 0xdf, 0xb7, 0x5c, + 0x47, 0x9e, 0x59, 0xbe, 0x05, 0xb5, 0x40, 0x1a, 0x0b, 0x47, 0xdb, 0x66, 0xcf, 0x75, 0x25, 0x65, + 0x28, 0x54, 0x58, 0xda, 0x7f, 0x2c, 0x42, 0x23, 0x5c, 0xd8, 0x1f, 0xe3, 0x2c, 0x70, 0x17, 0x1a, + 0x61, 0x0c, 0x5c, 0xee, 0x1b, 0x11, 0xa3, 0xd0, 0x2c, 0xbe, 0x16, 0x0d, 0x5f, 0x31, 0x92, 0x11, + 0x8f, 0xaf, 0x2b, 0xe5, 0x88, 0xaf, 0xeb, 0x41, 0x2d, 0xf0, 0xac, 0x4e, 0x47, 0xae, 0x12, 0xf2, + 0x04, 0xd8, 0x85, 0xcd, 0xb5, 0x29, 0x00, 0x65, 0xcb, 0x8a, 0x17, 0x54, 0x62, 0xb4, 0x0f, 0x61, + 0x2a, 0xcd, 0xc9, 0x55, 0x68, 0x63, 0x97, 0x9a, 0x7d, 0x5b, 0xb5, 0x71, 0xa4, 0x42, 0xcb, 0x74, + 0x0c, 0x39, 0xd8, 0x32, 0x9c, 0x7d, 0xa6, 0x8f, 0x5d, 0x47, 0xa9, 0xb1, 0x7c, 0x35, 0xb2, 0x29, + 0xd3, 0x30, 0xa4, 0x6a, 0xff, 0xad, 0x04, 0x97, 0x23, 0xf3, 0xcc, 0xba, 0xee, 0xe8, 0x9d, 0x63, + 0x5c, 0x83, 0xf7, 0xd5, 0xc6, 0xa5, 0x93, 0x5e, 0xe8, 0x50, 0x7a, 0x06, 0x2e, 0x74, 0xf8, 0xbf, + 0x45, 0xe0, 0xf1, 0xba, 0xe4, 0x3b, 0x30, 0xa6, 0xc7, 0x6e, 0x40, 0x95, 0x9f, 0xf3, 0x66, 0xee, + 0xcf, 0xc9, 0xc3, 0x82, 0xc3, 0x90, 0xad, 0x78, 0x2a, 0x26, 0x04, 0x12, 0x17, 0xea, 0x3b, 0xba, + 0x6d, 0x33, 0x5d, 0x28, 0xb7, 0xbb, 0x29, 0x21, 0x9c, 0x77, 0xf3, 0x65, 0x09, 0x8d, 0xa1, 0x10, + 0xf2, 0x49, 0x01, 0xc6, 0xbd, 0xf8, 0x72, 0x4d, 0x7e, 0x90, 0x3c, 0xc1, 0x08, 0x31, 0xb4, 0x78, + 0x80, 0x58, 0x7c, 0x4d, 0x98, 0x94, 0xa9, 0xfd, 0xd7, 0x02, 0x8c, 0xb7, 0x6d, 0xcb, 0xb4, 0x9c, + 0xce, 0x19, 0xde, 0x27, 0x71, 0x0f, 0x2a, 0xbe, 0x6d, 0x99, 0x74, 0xc4, 0xd9, 0x44, 0xcc, 0x63, + 0x0c, 0x00, 0x05, 0x4e, 0xf2, 0x82, 0x8a, 0xd2, 0x31, 0x2e, 0xa8, 0xf8, 0x61, 0x15, 0x64, 0xe4, + 0x39, 0xe9, 0x43, 0xa3, 0xa3, 0xce, 0xbd, 0x97, 0x75, 0xbc, 0x95, 0xe3, 0xcc, 0xc4, 0xc4, 0x09, + 0xfa, 0x62, 0xec, 0x0f, 0x13, 0x31, 0x92, 0x44, 0x68, 0xf2, 0xea, 0xdd, 0xa5, 0x9c, 0x57, 0xef, + 0x0a, 0x71, 0x83, 0x97, 0xef, 0xea, 0x50, 0xde, 0x0d, 0x82, 0x9e, 0xec, 0x4c, 0xa3, 0x6f, 0x2d, + 0x88, 0x8e, 0xed, 0x11, 0x3a, 0x11, 0x7b, 0x47, 0x0e, 0xcd, 0x44, 0x38, 0x7a, 0x78, 0xd5, 0xda, + 0x62, 0xae, 0xc0, 0x87, 0xb8, 0x08, 0xf6, 0x8e, 0x1c, 0x9a, 0xfc, 0x32, 0x34, 0x03, 0x4f, 0x77, + 0xfc, 0x1d, 0xd7, 0xeb, 0x52, 0x4f, 0xae, 0x51, 0x97, 0x73, 0xdc, 0x3e, 0xbb, 0x19, 0xa1, 0x09, + 0x8f, 0x6a, 0x22, 0x09, 0xe3, 0xd2, 0xc8, 0x1e, 0xd4, 0xfb, 0xa6, 0x28, 0x98, 0x34, 0x83, 0x2d, + 0xe4, 0xb9, 0x50, 0x38, 0x16, 0xd6, 0xa0, 0xde, 0x30, 0x14, 0x90, 0xbc, 0x55, 0xb0, 0x76, 0x5a, + 0xb7, 0x0a, 0xc6, 0x7b, 0x63, 0xd6, 0x99, 0x22, 0xa4, 0x2b, 0xf5, 0x5a, 0xa7, 0x23, 0xa3, 0xb2, + 0x96, 0x73, 0xab, 0x9c, 0x42, 0x64, 0x33, 0xd4, 0x8d, 0x9d, 0x0e, 0x2a, 0x19, 0x5a, 0x17, 0xa4, + 0xb7, 0x83, 0x18, 0x89, 0xbb, 0x77, 0xc4, 0x46, 0xb7, 0xb9, 0xe3, 0x8d, 0x07, 0xe1, 0x25, 0x30, + 0xb1, 0xb3, 0xbf, 0x33, 0x2f, 0xd9, 0xd1, 0xfe, 0x53, 0x11, 0x4a, 0x9b, 0x6b, 0x6d, 0x71, 0x9e, + 0x27, 0xbf, 0xd8, 0x8a, 0xb6, 0xf7, 0xac, 0xde, 0x7d, 0xea, 0x59, 0x3b, 0x07, 0x72, 0xe9, 0x1d, + 0x3b, 0xcf, 0x33, 0xcd, 0x81, 0x19, 0xb9, 0xc8, 0xfb, 0x30, 0x66, 0xe8, 0x8b, 0xd4, 0x0b, 0x46, + 0x31, 0x2c, 0xf0, 0x1d, 0xbd, 0x8b, 0x0b, 0x51, 0x76, 0x4c, 0x80, 0x91, 0x2d, 0x00, 0x23, 0x82, + 0x2e, 0x9d, 0xd8, 0x1c, 0x12, 0x03, 0x8e, 0x01, 0x11, 0x84, 0xc6, 0x1e, 0x63, 0xe5, 0xa8, 0xe5, + 0x93, 0xa0, 0xf2, 0x9e, 0x73, 0x47, 0xe5, 0xc5, 0x08, 0x46, 0x73, 0x60, 0x3c, 0x71, 0x21, 0x0f, + 0xf9, 0x1a, 0xd4, 0xdd, 0x5e, 0x6c, 0x38, 0x6d, 0xf0, 0xf8, 0xcf, 0xfa, 0x3d, 0x99, 0xf6, 0xe8, + 0x70, 0x66, 0x7c, 0xcd, 0xed, 0x58, 0x86, 0x4a, 0xc0, 0x90, 0x9d, 0x68, 0x50, 0xe5, 0xdb, 0xf0, + 0xd4, 0x75, 0x3c, 0x7c, 0xee, 0xe0, 0x37, 0x66, 0xf8, 0x28, 0x29, 0xda, 0xaf, 0x94, 0x21, 0xf2, + 0x11, 0x12, 0x1f, 0xaa, 0x62, 0x9b, 0x81, 0x1c, 0xb9, 0xcf, 0x74, 0x47, 0x83, 0x14, 0x45, 0x3a, + 0x50, 0xfa, 0xd0, 0xdd, 0xce, 0x3d, 0x70, 0xc7, 0xf6, 0xdf, 0x0b, 0x5b, 0x59, 0x2c, 0x01, 0x99, + 0x04, 0xf2, 0xb7, 0x0b, 0x70, 0xce, 0x4f, 0xab, 0xbe, 0xb2, 0x3b, 0x60, 0x7e, 0x1d, 0x3f, 0xad, + 0x4c, 0xcb, 0x40, 0xdd, 0x61, 0x64, 0x1c, 0x2c, 0x0b, 0x6b, 0x7f, 0xe1, 0xbc, 0x93, 0xdd, 0x69, + 0x25, 0xe7, 0x25, 0x92, 0xc9, 0xf6, 0x4f, 0xa6, 0xa1, 0x14, 0xa5, 0xfd, 0x5a, 0x11, 0x9a, 0xb1, + 0xd1, 0x3a, 0xf7, 0x2d, 0x4f, 0x0f, 0x53, 0xb7, 0x3c, 0x6d, 0x8c, 0xee, 0xcb, 0x8e, 0x4a, 0x75, + 0xd6, 0x17, 0x3d, 0xfd, 0xcb, 0x22, 0x94, 0xb6, 0x96, 0x96, 0x93, 0x8b, 0xd6, 0xc2, 0x53, 0x58, + 0xb4, 0xee, 0x42, 0x6d, 0xbb, 0x6f, 0xd9, 0x81, 0xe5, 0xe4, 0x3e, 0x21, 0x44, 0x5d, 0x8a, 0x25, + 0x7d, 0x1d, 0x02, 0x15, 0x15, 0x3c, 0xe9, 0x40, 0xad, 0x23, 0x8e, 0x68, 0xcc, 0x1d, 0xe1, 0x27, + 0x8f, 0x7a, 0x14, 0x82, 0xe4, 0x0b, 0x2a, 0x74, 0xed, 0x00, 0xe4, 0xed, 0xfe, 0x4f, 0xbd, 0x35, + 0xb5, 0x5f, 0x86, 0x50, 0x0b, 0x78, 0xfa, 0xc2, 0xff, 0x47, 0x01, 0x92, 0x8a, 0xcf, 0xd3, 0xef, + 0x4d, 0x7b, 0xe9, 0xde, 0xb4, 0x74, 0x1a, 0x3f, 0x5f, 0x76, 0x87, 0xd2, 0xfe, 0x7d, 0x01, 0x52, + 0x7b, 0xc3, 0xc8, 0x1b, 0xf2, 0xb4, 0xaf, 0x64, 0x28, 0x95, 0x3a, 0xed, 0x8b, 0x24, 0xb9, 0x63, + 0xa7, 0x7e, 0x7d, 0xca, 0x96, 0x6b, 0x71, 0x07, 0x9a, 0x2c, 0xfe, 0xdd, 0xd1, 0x97, 0x6b, 0x59, + 0xee, 0x38, 0x19, 0xee, 0x17, 0x27, 0x61, 0x52, 0xae, 0xf6, 0x4f, 0x8a, 0x50, 0x7d, 0x6a, 0x5b, + 0xd5, 0x69, 0x22, 0x02, 0x73, 0x31, 0xe7, 0x68, 0x3f, 0x34, 0xfe, 0xb2, 0x9b, 0x8a, 0xbf, 0xcc, + 0x7b, 0x37, 0xf1, 0x13, 0xa2, 0x2f, 0xff, 0x6d, 0x01, 0xe4, 0x5c, 0xb3, 0xea, 0xf8, 0x81, 0xee, + 0x18, 0x94, 0x18, 0xe1, 0xc4, 0x96, 0x37, 0xcc, 0x47, 0x86, 0xc2, 0x09, 0x5d, 0x86, 0x3f, 0xab, + 0x89, 0x8c, 0xfc, 0x34, 0xd4, 0x77, 0x5d, 0x3f, 0xe0, 0x93, 0x57, 0x31, 0x69, 0x32, 0xbb, 0x25, + 0xd3, 0x31, 0xe4, 0x48, 0xbb, 0xb3, 0x2b, 0xc3, 0xdd, 0xd9, 0xda, 0x6f, 0x17, 0x61, 0xec, 0xcb, + 0xb2, 0xdf, 0x3e, 0x2b, 0x5e, 0xb5, 0x94, 0x33, 0x5e, 0xb5, 0x7c, 0x92, 0x78, 0x55, 0xed, 0xfb, + 0x05, 0x80, 0xa7, 0xb6, 0xd9, 0xdf, 0x4c, 0x86, 0x92, 0xe6, 0xee, 0x57, 0xd9, 0x81, 0xa4, 0xff, + 0xa8, 0xa2, 0xaa, 0xc4, 0xc3, 0x48, 0x3f, 0x2d, 0xc0, 0x84, 0x9e, 0x08, 0xcd, 0xcc, 0xad, 0x2f, + 0xa7, 0x22, 0x3d, 0xc3, 0xc8, 0xa2, 0x64, 0x3a, 0xa6, 0xc4, 0x92, 0xb7, 0xa2, 0x83, 0xa6, 0xef, + 0x46, 0xdd, 0x7e, 0xe0, 0x84, 0x68, 0xae, 0xbb, 0x25, 0x38, 0x9f, 0x10, 0x0a, 0x5b, 0x3a, 0x95, + 0x50, 0xd8, 0xf8, 0x26, 0xbf, 0xf2, 0x63, 0x37, 0xf9, 0xed, 0x43, 0x63, 0xc7, 0x73, 0xbb, 0x3c, + 0xda, 0x54, 0xde, 0x6a, 0x7c, 0x33, 0xc7, 0x44, 0x19, 0xdd, 0xe7, 0x1f, 0x19, 0xae, 0x96, 0x15, + 0x3e, 0x46, 0xa2, 0xb8, 0xad, 0xdf, 0x15, 0x52, 0xab, 0xa7, 0x29, 0x35, 0x1c, 0x4b, 0x36, 0x05, + 0x3a, 0x2a, 0x31, 0xc9, 0x08, 0xd3, 0xda, 0xd3, 0x89, 0x30, 0xd5, 0x7e, 0xb7, 0xaa, 0x06, 0xb0, + 0x67, 0xee, 0x4c, 0xd3, 0xdc, 0x5b, 0xb3, 0xe3, 0xfb, 0xaa, 0xcb, 0x27, 0xd8, 0x57, 0x5d, 0x39, + 0xee, 0xbe, 0xea, 0xea, 0x13, 0x02, 0x3f, 0xd3, 0x9b, 0x9e, 0x6b, 0x4f, 0x71, 0xd3, 0x73, 0xfd, + 0x74, 0x36, 0x3d, 0x37, 0x4e, 0xb6, 0xe9, 0x59, 0xee, 0x1b, 0x0e, 0xb3, 0x43, 0x72, 0xd3, 0xf3, + 0x62, 0x92, 0x8c, 0x69, 0xfe, 0xac, 0x7d, 0xd3, 0xcd, 0x13, 0xee, 0x9b, 0x4e, 0xed, 0x72, 0x1e, + 0x1b, 0x69, 0x97, 0xf3, 0xf8, 0xb1, 0x76, 0x39, 0x1f, 0x96, 0x20, 0xb5, 0x74, 0xfe, 0xca, 0x4d, + 0xf6, 0xff, 0x95, 0x9b, 0xec, 0xb3, 0x22, 0x44, 0xc3, 0xe6, 0x09, 0xc3, 0x88, 0xde, 0x83, 0x7a, + 0x57, 0x7f, 0xb8, 0x44, 0x6d, 0xfd, 0x20, 0xcf, 0xc5, 0xbd, 0xeb, 0x12, 0x03, 0x43, 0x34, 0xe2, + 0x03, 0x58, 0xe1, 0xe1, 0xf9, 0xb9, 0x1d, 0x0e, 0xd1, 0x39, 0xfc, 0xc2, 0xa4, 0x19, 0xbd, 0x63, + 0x4c, 0x8c, 0xf6, 0x6f, 0x8a, 0x20, 0x6f, 0x59, 0x20, 0x14, 0x2a, 0x3b, 0xd6, 0x43, 0x6a, 0xe6, + 0x0e, 0x4e, 0x8e, 0x5d, 0xa7, 0x2e, 0x3c, 0x2a, 0x3c, 0x01, 0x05, 0x3a, 0x37, 0x95, 0x0b, 0x0f, + 0x99, 0x6c, 0xbf, 0x1c, 0xa6, 0xf2, 0xb8, 0xa7, 0x4d, 0x9a, 0xca, 0x45, 0x12, 0x2a, 0x19, 0xc2, + 0x32, 0xcf, 0x83, 0x25, 0x72, 0x3b, 0x04, 0x13, 0x41, 0x17, 0xca, 0x32, 0xef, 0x8b, 0x63, 0x0e, + 0xa4, 0x8c, 0xd6, 0x2f, 0x7d, 0xef, 0x07, 0xd7, 0x9e, 0xfb, 0xfe, 0x0f, 0xae, 0x3d, 0xf7, 0xf9, + 0x0f, 0xae, 0x3d, 0xf7, 0x2b, 0x47, 0xd7, 0x0a, 0xdf, 0x3b, 0xba, 0x56, 0xf8, 0xfe, 0xd1, 0xb5, + 0xc2, 0xe7, 0x47, 0xd7, 0x0a, 0xff, 0xf9, 0xe8, 0x5a, 0xe1, 0x6f, 0xfc, 0x97, 0x6b, 0xcf, 0xfd, + 0xe2, 0x9b, 0x51, 0x11, 0xe6, 0x54, 0x11, 0xe6, 0x94, 0xc0, 0xb9, 0xde, 0x5e, 0x67, 0x8e, 0x15, + 0x21, 0x4a, 0x51, 0x45, 0xf8, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x90, 0x35, 0xbe, 0x7d, 0xfe, + 0x99, 0x00, 0x00, } func (m *AbstractPodTemplate) Marshal() (dAtA []byte, err error) { @@ -6331,6 +6403,16 @@ func (m *MonoVertexSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.UpdateStrategy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 if m.DaemonTemplate != nil { { size, err := m.DaemonTemplate.MarshalToSizedBuffer(dAtA[:i]) @@ -6485,24 +6567,24 @@ func (m *MonoVertexStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.UpdateHash) i = encodeVarintGenerated(dAtA, i, uint64(len(m.UpdateHash))) i-- - dAtA[i] = 0x72 + dAtA[i] = 0x7a i -= len(m.CurrentHash) copy(dAtA[i:], m.CurrentHash) i = encodeVarintGenerated(dAtA, i, uint64(len(m.CurrentHash))) i-- - dAtA[i] = 0x6a + dAtA[i] = 0x72 + i = encodeVarintGenerated(dAtA, i, uint64(m.UpdatedReadyReplicas)) + i-- + dAtA[i] = 0x68 i = encodeVarintGenerated(dAtA, i, uint64(m.UpdatedReplicas)) i-- dAtA[i] = 0x60 - i = encodeVarintGenerated(dAtA, i, uint64(m.CurrentReplicas)) - i-- - dAtA[i] = 0x58 i = encodeVarintGenerated(dAtA, i, uint64(m.ReadyReplicas)) i-- - dAtA[i] = 0x50 + dAtA[i] = 0x58 i = encodeVarintGenerated(dAtA, i, uint64(m.ObservedGeneration)) i-- - dAtA[i] = 0x48 + dAtA[i] = 0x50 { size, err := m.LastScaledAt.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -6512,7 +6594,7 @@ func (m *MonoVertexStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x42 + dAtA[i] = 0x4a { size, err := m.LastUpdated.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -6522,22 +6604,25 @@ func (m *MonoVertexStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x3a + dAtA[i] = 0x42 i -= len(m.Message) copy(dAtA[i:], m.Message) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message))) i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a i -= len(m.Reason) copy(dAtA[i:], m.Reason) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) i-- - dAtA[i] = 0x2a + dAtA[i] = 0x32 i -= len(m.Selector) copy(dAtA[i:], m.Selector) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Selector))) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x2a + i = encodeVarintGenerated(dAtA, i, uint64(m.DesiredReplicas)) + i-- + dAtA[i] = 0x20 i = encodeVarintGenerated(dAtA, i, uint64(m.Replicas)) i-- dAtA[i] = 0x18 @@ -7483,6 +7568,41 @@ func (m *RetryStrategy) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *RollingUpdateStrategy) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RollingUpdateStrategy) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RollingUpdateStrategy) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxUnavailable != nil { + { + size, err := m.MaxUnavailable.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *SASL) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -8679,6 +8799,46 @@ func (m *UDTransformer) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *UpdateStrategy) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UpdateStrategy) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UpdateStrategy) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.RollingUpdate != nil { + { + size, err := m.RollingUpdate.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + i -= len(m.Type) + copy(dAtA[i:], m.Type) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *Vertex) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10411,6 +10571,8 @@ func (m *MonoVertexSpec) Size() (n int) { l = m.DaemonTemplate.Size() n += 1 + l + sovGenerated(uint64(l)) } + l = m.UpdateStrategy.Size() + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -10425,6 +10587,7 @@ func (m *MonoVertexStatus) Size() (n int) { l = len(m.Phase) n += 1 + l + sovGenerated(uint64(l)) n += 1 + sovGenerated(uint64(m.Replicas)) + n += 1 + sovGenerated(uint64(m.DesiredReplicas)) l = len(m.Selector) n += 1 + l + sovGenerated(uint64(l)) l = len(m.Reason) @@ -10437,8 +10600,8 @@ func (m *MonoVertexStatus) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) n += 1 + sovGenerated(uint64(m.ObservedGeneration)) n += 1 + sovGenerated(uint64(m.ReadyReplicas)) - n += 1 + sovGenerated(uint64(m.CurrentReplicas)) n += 1 + sovGenerated(uint64(m.UpdatedReplicas)) + n += 1 + sovGenerated(uint64(m.UpdatedReadyReplicas)) l = len(m.CurrentHash) n += 1 + l + sovGenerated(uint64(l)) l = len(m.UpdateHash) @@ -10789,6 +10952,19 @@ func (m *RetryStrategy) Size() (n int) { return n } +func (m *RollingUpdateStrategy) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxUnavailable != nil { + l = m.MaxUnavailable.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *SASL) Size() (n int) { if m == nil { return 0 @@ -11236,6 +11412,21 @@ func (m *UDTransformer) Size() (n int) { return n } +func (m *UpdateStrategy) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Type) + n += 1 + l + sovGenerated(uint64(l)) + if m.RollingUpdate != nil { + l = m.RollingUpdate.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *Vertex) Size() (n int) { if m == nil { return 0 @@ -12270,6 +12461,7 @@ func (this *MonoVertexSpec) String() string { `InitContainers:` + repeatedStringForInitContainers + `,`, `Sidecars:` + repeatedStringForSidecars + `,`, `DaemonTemplate:` + strings.Replace(this.DaemonTemplate.String(), "DaemonTemplate", "DaemonTemplate", 1) + `,`, + `UpdateStrategy:` + strings.Replace(strings.Replace(this.UpdateStrategy.String(), "UpdateStrategy", "UpdateStrategy", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -12282,6 +12474,7 @@ func (this *MonoVertexStatus) String() string { `Status:` + strings.Replace(strings.Replace(this.Status.String(), "Status", "Status", 1), `&`, ``, 1) + `,`, `Phase:` + fmt.Sprintf("%v", this.Phase) + `,`, `Replicas:` + fmt.Sprintf("%v", this.Replicas) + `,`, + `DesiredReplicas:` + fmt.Sprintf("%v", this.DesiredReplicas) + `,`, `Selector:` + fmt.Sprintf("%v", this.Selector) + `,`, `Reason:` + fmt.Sprintf("%v", this.Reason) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`, @@ -12289,8 +12482,8 @@ func (this *MonoVertexStatus) String() string { `LastScaledAt:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.LastScaledAt), "Time", "v11.Time", 1), `&`, ``, 1) + `,`, `ObservedGeneration:` + fmt.Sprintf("%v", this.ObservedGeneration) + `,`, `ReadyReplicas:` + fmt.Sprintf("%v", this.ReadyReplicas) + `,`, - `CurrentReplicas:` + fmt.Sprintf("%v", this.CurrentReplicas) + `,`, `UpdatedReplicas:` + fmt.Sprintf("%v", this.UpdatedReplicas) + `,`, + `UpdatedReadyReplicas:` + fmt.Sprintf("%v", this.UpdatedReadyReplicas) + `,`, `CurrentHash:` + fmt.Sprintf("%v", this.CurrentHash) + `,`, `UpdateHash:` + fmt.Sprintf("%v", this.UpdateHash) + `,`, `}`, @@ -12518,6 +12711,16 @@ func (this *RetryStrategy) String() string { }, "") return s } +func (this *RollingUpdateStrategy) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RollingUpdateStrategy{`, + `MaxUnavailable:` + strings.Replace(fmt.Sprintf("%v", this.MaxUnavailable), "IntOrString", "intstr.IntOrString", 1) + `,`, + `}`, + }, "") + return s +} func (this *SASL) String() string { if this == nil { return "nil" @@ -12798,6 +13001,17 @@ func (this *UDTransformer) String() string { }, "") return s } +func (this *UpdateStrategy) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&UpdateStrategy{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `RollingUpdate:` + strings.Replace(this.RollingUpdate.String(), "RollingUpdateStrategy", "RollingUpdateStrategy", 1) + `,`, + `}`, + }, "") + return s +} func (this *Vertex) String() string { if this == nil { return "nil" @@ -23365,6 +23579,39 @@ func (m *MonoVertexSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdateStrategy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.UpdateStrategy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -23500,6 +23747,25 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } } case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DesiredReplicas", wireType) + } + m.DesiredReplicas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DesiredReplicas |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Selector", wireType) } @@ -23531,7 +23797,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } m.Selector = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) } @@ -23563,7 +23829,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } m.Reason = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) } @@ -23595,7 +23861,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } m.Message = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 7: + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field LastUpdated", wireType) } @@ -23628,7 +23894,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 8: + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field LastScaledAt", wireType) } @@ -23661,7 +23927,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 9: + case 10: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field ObservedGeneration", wireType) } @@ -23680,7 +23946,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { break } } - case 10: + case 11: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field ReadyReplicas", wireType) } @@ -23699,11 +23965,11 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { break } } - case 11: + case 12: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CurrentReplicas", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedReplicas", wireType) } - m.CurrentReplicas = 0 + m.UpdatedReplicas = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -23713,16 +23979,16 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.CurrentReplicas |= uint32(b&0x7F) << shift + m.UpdatedReplicas |= uint32(b&0x7F) << shift if b < 0x80 { break } } - case 12: + case 13: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field UpdatedReplicas", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedReadyReplicas", wireType) } - m.UpdatedReplicas = 0 + m.UpdatedReadyReplicas = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -23732,12 +23998,12 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.UpdatedReplicas |= uint32(b&0x7F) << shift + m.UpdatedReadyReplicas |= uint32(b&0x7F) << shift if b < 0x80 { break } } - case 13: + case 14: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CurrentHash", wireType) } @@ -23769,7 +24035,7 @@ func (m *MonoVertexStatus) Unmarshal(dAtA []byte) error { } m.CurrentHash = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 14: + case 15: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field UpdateHash", wireType) } @@ -26651,6 +26917,92 @@ func (m *RetryStrategy) Unmarshal(dAtA []byte) error { } return nil } +func (m *RollingUpdateStrategy) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RollingUpdateStrategy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RollingUpdateStrategy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxUnavailable", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MaxUnavailable == nil { + m.MaxUnavailable = &intstr.IntOrString{} + } + if err := m.MaxUnavailable.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *SASL) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -30044,6 +30396,124 @@ func (m *UDTransformer) Unmarshal(dAtA []byte) error { } return nil } +func (m *UpdateStrategy) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UpdateStrategy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UpdateStrategy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = UpdateStrategyType(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RollingUpdate", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RollingUpdate == nil { + m.RollingUpdate = &RollingUpdateStrategy{} + } + if err := m.RollingUpdate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Vertex) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/pkg/apis/numaflow/v1alpha1/generated.proto b/pkg/apis/numaflow/v1alpha1/generated.proto index 55940285e3..1e6e6bd35a 100644 --- a/pkg/apis/numaflow/v1alpha1/generated.proto +++ b/pkg/apis/numaflow/v1alpha1/generated.proto @@ -26,6 +26,7 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; +import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1"; @@ -864,7 +865,7 @@ message Metadata { // +kubebuilder:subresource:status // +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector // +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` -// +kubebuilder:printcolumn:name="Desired",type=string,JSONPath=`.spec.replicas` +// +kubebuilder:printcolumn:name="Desired",type=string,JSONPath=`.status.desiredReplicas` // +kubebuilder:printcolumn:name="Current",type=string,JSONPath=`.status.replicas` // +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.readyReplicas` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` @@ -942,6 +943,11 @@ message MonoVertexSpec { // Template for the daemon service deployment. // +optional optional DaemonTemplate daemonTemplate = 11; + + // The strategy to use to replace existing pods with new ones. + // +kubebuilder:default={"type": "RollingUpdate", "rollingUpdate": {"maxUnavailable": "25%"}} + // +optional + optional UpdateStrategy updateStrategy = 12; } message MonoVertexStatus { @@ -954,41 +960,45 @@ message MonoVertexStatus { // +optional optional uint32 replicas = 3; + // The number of desired replicas. // +optional - optional string selector = 4; + optional uint32 desiredReplicas = 4; // +optional - optional string reason = 5; + optional string selector = 5; // +optional - optional string message = 6; + optional string reason = 6; + + // +optional + optional string message = 7; // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastUpdated = 7; + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastUpdated = 8; // Time of last scaling operation. // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScaledAt = 8; + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScaledAt = 9; // The generation observed by the MonoVertex controller. // +optional - optional int64 observedGeneration = 9; + optional int64 observedGeneration = 10; // The number of pods targeted by this MonoVertex with a Ready Condition. // +optional - optional uint32 readyReplicas = 10; - - // The number of Pods created by the controller from the MonoVertex version indicated by currentHash. - optional uint32 currentReplicas = 11; + optional uint32 readyReplicas = 11; // The number of Pods created by the controller from the MonoVertex version indicated by updateHash. optional uint32 updatedReplicas = 12; - // If not empty, indicates the version of the MonoVertex used to generate Pods in the sequence [0,currentReplicas). - optional string currentHash = 13; + // The number of ready Pods created by the controller from the MonoVertex version indicated by updateHash. + optional uint32 updatedReadyReplicas = 13; - // If not empty, indicates the version of the MonoVertx used to generate Pods in the sequence [replicas-updatedReplicas,replicas) - optional string updateHash = 14; + // If not empty, indicates the current version of the MonoVertex used to generate Pods. + optional string currentHash = 14; + + // If not empty, indicates the updated version of the MonoVertex used to generate Pods. + optional string updateHash = 15; } message NativeRedis { @@ -1291,6 +1301,21 @@ message RetryStrategy { optional string onFailure = 2; } +// RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType. +message RollingUpdateStrategy { + // The maximum number of pods that can be unavailable during the update. + // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + // Absolute number is calculated from percentage by rounding down. + // Defaults to 25%. + // Example: when this is set to 30%, the old pods can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old pods + // can be scaled down further, followed by scaling up the new pods, ensuring + // that the total number of pods available at all times during the update is at + // least 70% of desired pods. + // +optional + optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; +} + message SASL { // SASL mechanism to use optional string mechanism = 1; @@ -1599,6 +1624,19 @@ message UDTransformer { optional Transformer builtin = 2; } +// UpdateStrategy indicates the strategy that the +// controller will use to perform updates for Vertex or MonoVertex. +message UpdateStrategy { + // Type indicates the type of the StatefulSetUpdateStrategy. + // Default is RollingUpdate. + // +optional + optional string type = 1; + + // RollingUpdate is used to communicate parameters when Type is RollingUpdateStrategy. + // +optional + optional RollingUpdateStrategy rollingUpdate = 2; +} + // +genclient // +kubebuilder:object:root=true // +kubebuilder:resource:shortName=vtx diff --git a/pkg/apis/numaflow/v1alpha1/mono_vertex_types.go b/pkg/apis/numaflow/v1alpha1/mono_vertex_types.go index b05fd8c5f4..677ec4fc5c 100644 --- a/pkg/apis/numaflow/v1alpha1/mono_vertex_types.go +++ b/pkg/apis/numaflow/v1alpha1/mono_vertex_types.go @@ -54,7 +54,7 @@ const ( // +kubebuilder:subresource:status // +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector // +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` -// +kubebuilder:printcolumn:name="Desired",type=string,JSONPath=`.spec.replicas` +// +kubebuilder:printcolumn:name="Desired",type=string,JSONPath=`.status.desiredReplicas` // +kubebuilder:printcolumn:name="Current",type=string,JSONPath=`.status.replicas` // +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.readyReplicas` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` @@ -71,13 +71,28 @@ type MonoVertex struct { Status MonoVertexStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` } -func (mv MonoVertex) GetReplicas() int { +func (mv MonoVertex) getReplicas() int { if mv.Spec.Replicas == nil { return 1 } return int(*mv.Spec.Replicas) } +func (mv MonoVertex) CalculateReplicas() int { + desiredReplicas := mv.getReplicas() + // Don't allow replicas to be out of the range of min and max when auto scaling is enabled + if s := mv.Spec.Scale; !s.Disabled { + max := int(s.GetMaxReplicas()) + min := int(s.GetMinReplicas()) + if desiredReplicas < min { + desiredReplicas = min + } else if desiredReplicas > max { + desiredReplicas = max + } + } + return desiredReplicas +} + func (mv MonoVertex) GetHeadlessServiceName() string { return mv.Name + "-mv-headless" } @@ -291,6 +306,7 @@ func (mv MonoVertex) simpleCopy() MonoVertex { if m.Spec.Limits.ReadTimeout == nil { m.Spec.Limits.ReadTimeout = &metav1.Duration{Duration: DefaultReadTimeout} } + m.Spec.UpdateStrategy = UpdateStrategy{} // TODO: lifecycle // mvVtxCopy.Spec.Lifecycle = Lifecycle{} return m @@ -408,6 +424,10 @@ type MonoVertexSpec struct { // Template for the daemon service deployment. // +optional DaemonTemplate *DaemonTemplate `json:"daemonTemplate,omitempty" protobuf:"bytes,11,opt,name=daemonTemplate"` + // The strategy to use to replace existing pods with new ones. + // +kubebuilder:default={"type": "RollingUpdate", "rollingUpdate": {"maxUnavailable": "25%"}} + // +optional + UpdateStrategy UpdateStrategy `json:"updateStrategy,omitempty" protobuf:"bytes,12,opt,name=updateStrategy"` } func (mvspec MonoVertexSpec) DeepCopyWithoutReplicas() MonoVertexSpec { @@ -470,31 +490,34 @@ type MonoVertexStatus struct { // Total number of non-terminated pods targeted by this MonoVertex (their labels match the selector). // +optional Replicas uint32 `json:"replicas" protobuf:"varint,3,opt,name=replicas"` + // The number of desired replicas. + // +optional + DesiredReplicas uint32 `json:"desiredReplicas" protobuf:"varint,4,opt,name=desiredReplicas"` // +optional - Selector string `json:"selector,omitempty" protobuf:"bytes,4,opt,name=selector"` + Selector string `json:"selector,omitempty" protobuf:"bytes,5,opt,name=selector"` // +optional - Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"` + Reason string `json:"reason,omitempty" protobuf:"bytes,6,opt,name=reason"` // +optional - Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"` + Message string `json:"message,omitempty" protobuf:"bytes,7,opt,name=message"` // +optional - LastUpdated metav1.Time `json:"lastUpdated,omitempty" protobuf:"bytes,7,opt,name=lastUpdated"` + LastUpdated metav1.Time `json:"lastUpdated,omitempty" protobuf:"bytes,8,opt,name=lastUpdated"` // Time of last scaling operation. // +optional - LastScaledAt metav1.Time `json:"lastScaledAt,omitempty" protobuf:"bytes,8,opt,name=lastScaledAt"` + LastScaledAt metav1.Time `json:"lastScaledAt,omitempty" protobuf:"bytes,9,opt,name=lastScaledAt"` // The generation observed by the MonoVertex controller. // +optional - ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,9,opt,name=observedGeneration"` + ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,10,opt,name=observedGeneration"` // The number of pods targeted by this MonoVertex with a Ready Condition. // +optional - ReadyReplicas uint32 `json:"readyReplicas,omitempty" protobuf:"varint,10,opt,name=readyReplicas"` - // The number of Pods created by the controller from the MonoVertex version indicated by currentHash. - CurrentReplicas uint32 `json:"currentReplicas,omitempty" protobuf:"varint,11,opt,name=currentReplicas"` + ReadyReplicas uint32 `json:"readyReplicas,omitempty" protobuf:"varint,11,opt,name=readyReplicas"` // The number of Pods created by the controller from the MonoVertex version indicated by updateHash. UpdatedReplicas uint32 `json:"updatedReplicas,omitempty" protobuf:"varint,12,opt,name=updatedReplicas"` - // If not empty, indicates the version of the MonoVertex used to generate Pods in the sequence [0,currentReplicas). - CurrentHash string `json:"currentHash,omitempty" protobuf:"bytes,13,opt,name=currentHash"` - // If not empty, indicates the version of the MonoVertx used to generate Pods in the sequence [replicas-updatedReplicas,replicas) - UpdateHash string `json:"updateHash,omitempty" protobuf:"bytes,14,opt,name=updateHash"` + // The number of ready Pods created by the controller from the MonoVertex version indicated by updateHash. + UpdatedReadyReplicas uint32 `json:"updatedReadyReplicas,omitempty" protobuf:"varint,13,opt,name=updatedReadyReplicas"` + // If not empty, indicates the current version of the MonoVertex used to generate Pods. + CurrentHash string `json:"currentHash,omitempty" protobuf:"bytes,14,opt,name=currentHash"` + // If not empty, indicates the updated version of the MonoVertex used to generate Pods. + UpdateHash string `json:"updateHash,omitempty" protobuf:"bytes,15,opt,name=updateHash"` } // SetObservedGeneration sets the Status ObservedGeneration diff --git a/pkg/apis/numaflow/v1alpha1/openapi_generated.go b/pkg/apis/numaflow/v1alpha1/openapi_generated.go index 0ed5471bc8..a339fdfb7a 100644 --- a/pkg/apis/numaflow/v1alpha1/openapi_generated.go +++ b/pkg/apis/numaflow/v1alpha1/openapi_generated.go @@ -93,6 +93,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisConfig": schema_pkg_apis_numaflow_v1alpha1_RedisConfig(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisSettings": schema_pkg_apis_numaflow_v1alpha1_RedisSettings(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RetryStrategy": schema_pkg_apis_numaflow_v1alpha1_RetryStrategy(ref), + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RollingUpdateStrategy": schema_pkg_apis_numaflow_v1alpha1_RollingUpdateStrategy(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.SASL": schema_pkg_apis_numaflow_v1alpha1_SASL(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.SASLPlain": schema_pkg_apis_numaflow_v1alpha1_SASLPlain(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Scale": schema_pkg_apis_numaflow_v1alpha1_Scale(ref), @@ -114,6 +115,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDSink": schema_pkg_apis_numaflow_v1alpha1_UDSink(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDSource": schema_pkg_apis_numaflow_v1alpha1_UDSource(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDTransformer": schema_pkg_apis_numaflow_v1alpha1_UDTransformer(ref), + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UpdateStrategy": schema_pkg_apis_numaflow_v1alpha1_UpdateStrategy(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Vertex": schema_pkg_apis_numaflow_v1alpha1_Vertex(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.VertexInstance": schema_pkg_apis_numaflow_v1alpha1_VertexInstance(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.VertexLimits": schema_pkg_apis_numaflow_v1alpha1_VertexLimits(ref), @@ -3332,11 +3334,18 @@ func schema_pkg_apis_numaflow_v1alpha1_MonoVertexSpec(ref common.ReferenceCallba Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.DaemonTemplate"), }, }, + "updateStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "The strategy to use to replace existing pods with new ones.", + Default: map[string]interface{}{}, + Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UpdateStrategy"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.ContainerTemplate", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.DaemonTemplate", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Metadata", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.MonoVertexLimits", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Scale", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Sink", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Source", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume"}, + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.ContainerTemplate", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.DaemonTemplate", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Metadata", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.MonoVertexLimits", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Scale", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Sink", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Source", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UpdateStrategy", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume"}, } } @@ -3380,6 +3389,14 @@ func schema_pkg_apis_numaflow_v1alpha1_MonoVertexStatus(ref common.ReferenceCall Format: "int64", }, }, + "desiredReplicas": { + SchemaProps: spec.SchemaProps{ + Description: "The number of desired replicas.", + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, "selector": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, @@ -3423,30 +3440,30 @@ func schema_pkg_apis_numaflow_v1alpha1_MonoVertexStatus(ref common.ReferenceCall Format: "int64", }, }, - "currentReplicas": { + "updatedReplicas": { SchemaProps: spec.SchemaProps{ - Description: "The number of Pods created by the controller from the MonoVertex version indicated by currentHash.", + Description: "The number of Pods created by the controller from the MonoVertex version indicated by updateHash.", Type: []string{"integer"}, Format: "int64", }, }, - "updatedReplicas": { + "updatedReadyReplicas": { SchemaProps: spec.SchemaProps{ - Description: "The number of Pods created by the controller from the MonoVertex version indicated by updateHash.", + Description: "The number of ready Pods created by the controller from the MonoVertex version indicated by updateHash.", Type: []string{"integer"}, Format: "int64", }, }, "currentHash": { SchemaProps: spec.SchemaProps{ - Description: "If not empty, indicates the version of the MonoVertex used to generate Pods in the sequence [0,currentReplicas).", + Description: "If not empty, indicates the current version of the MonoVertex used to generate Pods.", Type: []string{"string"}, Format: "", }, }, "updateHash": { SchemaProps: spec.SchemaProps{ - Description: "If not empty, indicates the version of the MonoVertx used to generate Pods in the sequence [replicas-updatedReplicas,replicas)", + Description: "If not empty, indicates the updated version of the MonoVertex used to generate Pods.", Type: []string{"string"}, Format: "", }, @@ -4295,6 +4312,27 @@ func schema_pkg_apis_numaflow_v1alpha1_RetryStrategy(ref common.ReferenceCallbac } } +func schema_pkg_apis_numaflow_v1alpha1_RollingUpdateStrategy(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "maxUnavailable": { + SchemaProps: spec.SchemaProps{ + Description: "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. Defaults to 25%. Example: when this is set to 30%, the old pods can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old pods can be scaled down further, followed by scaling up the new pods, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + Ref: ref("k8s.io/apimachinery/pkg/util/intstr.IntOrString"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/util/intstr.IntOrString"}, + } +} + func schema_pkg_apis_numaflow_v1alpha1_SASL(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -5232,6 +5270,35 @@ func schema_pkg_apis_numaflow_v1alpha1_UDTransformer(ref common.ReferenceCallbac } } +func schema_pkg_apis_numaflow_v1alpha1_UpdateStrategy(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "UpdateStrategy indicates the strategy that the controller will use to perform updates for Vertex or MonoVertex.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type indicates the type of the StatefulSetUpdateStrategy. Default is RollingUpdate.\n\nPossible enum values:\n - `\"RollingUpdate\"`", + Type: []string{"string"}, + Format: "", + Enum: []interface{}{"RollingUpdate"}, + }, + }, + "rollingUpdate": { + SchemaProps: spec.SchemaProps{ + Description: "RollingUpdate is used to communicate parameters when Type is RollingUpdateStrategy.", + Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RollingUpdateStrategy"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RollingUpdateStrategy"}, + } +} + func schema_pkg_apis_numaflow_v1alpha1_Vertex(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/numaflow/v1alpha1/update_strategy.go b/pkg/apis/numaflow/v1alpha1/update_strategy.go new file mode 100644 index 0000000000..5313d06725 --- /dev/null +++ b/pkg/apis/numaflow/v1alpha1/update_strategy.go @@ -0,0 +1,80 @@ +/* +Copyright 2022 The Numaproj Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/util/intstr" +) + +// UpdateStrategy indicates the strategy that the +// controller will use to perform updates for Vertex or MonoVertex. +type UpdateStrategy struct { + // Type indicates the type of the StatefulSetUpdateStrategy. + // Default is RollingUpdate. + // +optional + Type UpdateStrategyType `json:"type,omitempty" protobuf:"bytes,1,opt,name=type,casttype=UpdateStrategyType"` + // RollingUpdate is used to communicate parameters when Type is RollingUpdateStrategy. + // +optional + RollingUpdate *RollingUpdateStrategy `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"` +} + +func (us UpdateStrategy) GetUpdateStrategyType() UpdateStrategyType { + switch us.Type { + case RollingUpdateStrategyType: + return us.Type + default: + return RollingUpdateStrategyType // We only support RollingUpdateStrategyType for now. + } +} + +func (us UpdateStrategy) GetRollingUpdateStrategy() RollingUpdateStrategy { + if us.RollingUpdate == nil { + return RollingUpdateStrategy{} + } + return *us.RollingUpdate +} + +// UpdateStrategyType is a string enumeration type that enumerates +// all possible update strategies. +// +enum +type UpdateStrategyType string + +const ( + RollingUpdateStrategyType UpdateStrategyType = "RollingUpdate" +) + +// RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType. +type RollingUpdateStrategy struct { + // The maximum number of pods that can be unavailable during the update. + // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + // Absolute number is calculated from percentage by rounding down. + // Defaults to 25%. + // Example: when this is set to 30%, the old pods can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old pods + // can be scaled down further, followed by scaling up the new pods, ensuring + // that the total number of pods available at all times during the update is at + // least 70% of desired pods. + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` +} + +func (rus RollingUpdateStrategy) GetMaxUnavailable() intstr.IntOrString { + if rus.MaxUnavailable == nil { + return intstr.FromString("25%") // Default value is 25%. + } + return *rus.MaxUnavailable +} diff --git a/pkg/apis/numaflow/v1alpha1/update_strategy_test.go b/pkg/apis/numaflow/v1alpha1/update_strategy_test.go new file mode 100644 index 0000000000..e78cd34d95 --- /dev/null +++ b/pkg/apis/numaflow/v1alpha1/update_strategy_test.go @@ -0,0 +1,128 @@ +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + intstr "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" +) + +func TestUpdateStrategy_GetUpdateStrategyType(t *testing.T) { + tests := []struct { + name string + strategy UpdateStrategy + expected UpdateStrategyType + }{ + { + name: "RollingUpdateStrategyType", + strategy: UpdateStrategy{Type: RollingUpdateStrategyType}, + expected: RollingUpdateStrategyType, + }, + { + name: "EmptyType", + strategy: UpdateStrategy{}, + expected: RollingUpdateStrategyType, + }, + { + name: "UnsupportedType", + strategy: UpdateStrategy{Type: "UnsupportedType"}, + expected: RollingUpdateStrategyType, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.strategy.GetUpdateStrategyType() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestUpdateStrategy_GetRollingUpdateStrategy(t *testing.T) { + tests := []struct { + name string + strategy UpdateStrategy + expected RollingUpdateStrategy + }{ + { + name: "NilRollingUpdate", + strategy: UpdateStrategy{}, + expected: RollingUpdateStrategy{}, + }, + { + name: "NonNilRollingUpdate", + strategy: UpdateStrategy{ + RollingUpdate: &RollingUpdateStrategy{ + MaxUnavailable: ptr.To[intstr.IntOrString](intstr.FromString("2")), + }, + }, + expected: RollingUpdateStrategy{ + MaxUnavailable: ptr.To[intstr.IntOrString](intstr.FromString("2")), + }, + }, + { + name: "EmptyRollingUpdate", + strategy: UpdateStrategy{ + RollingUpdate: &RollingUpdateStrategy{}, + }, + expected: RollingUpdateStrategy{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.strategy.GetRollingUpdateStrategy() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestRollingUpdateStrategy_GetMaxUnavailable(t *testing.T) { + tests := []struct { + name string + strategy RollingUpdateStrategy + expected intstr.IntOrString + }{ + { + name: "NilMaxUnavailable", + strategy: RollingUpdateStrategy{}, + expected: intstr.FromString("25%"), + }, + { + name: "IntegerMaxUnavailable", + strategy: RollingUpdateStrategy{ + MaxUnavailable: ptr.To[intstr.IntOrString](intstr.FromInt(5)), + }, + expected: intstr.FromInt(5), + }, + { + name: "StringMaxUnavailable", + strategy: RollingUpdateStrategy{ + MaxUnavailable: ptr.To[intstr.IntOrString](intstr.FromString("50%")), + }, + expected: intstr.FromString("50%"), + }, + { + name: "ZeroIntegerMaxUnavailable", + strategy: RollingUpdateStrategy{ + MaxUnavailable: ptr.To[intstr.IntOrString](intstr.FromInt(0)), + }, + expected: intstr.FromInt(0), + }, + { + name: "ZeroPercentMaxUnavailable", + strategy: RollingUpdateStrategy{ + MaxUnavailable: ptr.To[intstr.IntOrString](intstr.FromString("0%")), + }, + expected: intstr.FromString("0%"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.strategy.GetMaxUnavailable() + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go index 6033c0302f..b6325ce920 100644 --- a/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -1502,6 +1503,7 @@ func (in *MonoVertexSpec) DeepCopyInto(out *MonoVertexSpec) { *out = new(DaemonTemplate) (*in).DeepCopyInto(*out) } + in.UpdateStrategy.DeepCopyInto(&out.UpdateStrategy) return } @@ -2009,6 +2011,27 @@ func (in *RetryStrategy) DeepCopy() *RetryStrategy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RollingUpdateStrategy) DeepCopyInto(out *RollingUpdateStrategy) { + *out = *in + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + *out = new(intstr.IntOrString) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RollingUpdateStrategy. +func (in *RollingUpdateStrategy) DeepCopy() *RollingUpdateStrategy { + if in == nil { + return nil + } + out := new(RollingUpdateStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SASL) DeepCopyInto(out *SASL) { *out = *in @@ -2654,6 +2677,27 @@ func (in *UDTransformer) DeepCopy() *UDTransformer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) { + *out = *in + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + *out = new(RollingUpdateStrategy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy. +func (in *UpdateStrategy) DeepCopy() *UpdateStrategy { + if in == nil { + return nil + } + out := new(UpdateStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Vertex) DeepCopyInto(out *Vertex) { *out = *in diff --git a/pkg/mvtxdaemon/server/service/health_status.go b/pkg/mvtxdaemon/server/service/health_status.go index 9942f7885c..b075555aff 100644 --- a/pkg/mvtxdaemon/server/service/health_status.go +++ b/pkg/mvtxdaemon/server/service/health_status.go @@ -132,20 +132,18 @@ func (hc *HealthChecker) setCurrentHealth(status *dataHealthResponse) { // Else we consider the data criticality as healthy. // // TODO(MonoVertex): Add the logic to determine the warning state based on more conditions. -func (hc *HealthChecker) getMonoVertexDataCriticality(ctx context.Context, mvtxMetrics *mvtxdaemon.MonoVertexMetrics) (*monoVtxState, error) { +func (hc *HealthChecker) getMonoVertexDataCriticality(_ context.Context, mvtxMetrics *mvtxdaemon.MonoVertexMetrics) (*monoVtxState, error) { // Get the desired replicas for the MonoVertex based on the metrics desiredReplicas, err := hc.getDesiredReplica(mvtxMetrics) if err != nil { return nil, err } - // Get the current state of the MonoVertex replicas - currentReplicas := hc.monoVertex.GetReplicas() maxReplicas := int(hc.monoVertex.Spec.Scale.GetMaxReplicas()) // default status is healthy status := v1alpha1.MonoVertexStatusHealthy - // If the current replicas are equal to the max replicas, and the desired replicas are more than the max replicas, + // If the desired replicas are more than the max replicas, // the data criticality is Critical. - if currentReplicas == maxReplicas && desiredReplicas > maxReplicas { + if desiredReplicas > maxReplicas { status = v1alpha1.MonoVertexStatusCritical } return newMonoVtxState(mvtxMetrics.MonoVertex, status), nil diff --git a/pkg/reconciler/monovertex/controller.go b/pkg/reconciler/monovertex/controller.go index 104b7d9728..a0de7e6d6a 100644 --- a/pkg/reconciler/monovertex/controller.go +++ b/pkg/reconciler/monovertex/controller.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -113,36 +114,19 @@ func (mr *monoVertexReconciler) reconcile(ctx context.Context, monoVtx *dfv1.Mon if monoVtx.Scalable() { mr.scaler.StartWatching(mVtxKey) } - // TODO: handle lifecycle changes - - // Regular mono vertex change - result, err := mr.reconcileNonLifecycleChanges(ctx, monoVtx) - if err != nil { - mr.recorder.Eventf(monoVtx, corev1.EventTypeWarning, "ReconcileMonoVertexFailed", "Failed to reconcile a mono vertex: %v", err.Error()) - } - return result, err -} -func (mr *monoVertexReconciler) reconcileNonLifecycleChanges(ctx context.Context, monoVtx *dfv1.MonoVertex) (ctrl.Result, error) { - // Create or update mono vtx services - if err := mr.createOrUpdateMonoVtxServices(ctx, monoVtx); err != nil { + if err := mr.orchestrateFixedResources(ctx, monoVtx); err != nil { + monoVtx.Status.MarkDeployFailed("OrchestrateFixedResourcesFailed", err.Error()) return ctrl.Result{}, err } - // Mono vtx daemon service - if err := mr.createOrUpdateDaemonService(ctx, monoVtx); err != nil { - return ctrl.Result{}, err - } + // TODO: handle lifecycle changes - // Mono vtx daemon deployment - if err := mr.createOrUpdateDaemonDeployment(ctx, monoVtx); err != nil { + if err := mr.orchestratePods(ctx, monoVtx); err != nil { + monoVtx.Status.MarkDeployFailed("OrchestratePodsFailed", err.Error()) return ctrl.Result{}, err } - // Create pods - if err := mr.reconcilePods(ctx, monoVtx); err != nil { - return ctrl.Result{}, err - } monoVtx.Status.MarkDeployed() // Mark it running before checking the status of the pods @@ -155,42 +139,197 @@ func (mr *monoVertexReconciler) reconcileNonLifecycleChanges(ctx context.Context return ctrl.Result{}, nil } -func (mr *monoVertexReconciler) reconcilePods(ctx context.Context, monoVtx *dfv1.MonoVertex) error { - desiredReplicas := monoVtx.GetReplicas() - // Don't allow replicas to be out of the range of min and max when auto scaling is enabled - if s := monoVtx.Spec.Scale; !s.Disabled { - max := int(s.GetMaxReplicas()) - min := int(s.GetMinReplicas()) - if desiredReplicas < min { - desiredReplicas = min - } else if desiredReplicas > max { - desiredReplicas = max - } +// orchestrateFixedResources orchestrates fixed resources such as daemon service related objects for a mono vertex. +func (mr *monoVertexReconciler) orchestrateFixedResources(ctx context.Context, monoVtx *dfv1.MonoVertex) error { + // Create or update mono vtx services + if err := mr.createOrUpdateMonoVtxServices(ctx, monoVtx); err != nil { + return fmt.Errorf("failed to orchestrate mono vtx services: %w", err) + } + + // Mono vtx daemon service + if err := mr.createOrUpdateDaemonService(ctx, monoVtx); err != nil { + return fmt.Errorf("failed to orchestrate mono vtx daemon service: %w", err) } + + // Mono vtx daemon deployment + if err := mr.createOrUpdateDaemonDeployment(ctx, monoVtx); err != nil { + return fmt.Errorf("failed to orchestrate mono vtx daemon deployment: %w", err) + } + return nil +} + +func (mr *monoVertexReconciler) orchestratePods(ctx context.Context, monoVtx *dfv1.MonoVertex) error { + log := logging.FromContext(ctx) + desiredReplicas := monoVtx.CalculateReplicas() + monoVtx.Status.DesiredReplicas = uint32(desiredReplicas) + // Set metrics defer func() { reconciler.MonoVertexDesiredReplicas.WithLabelValues(monoVtx.Namespace, monoVtx.Name).Set(float64(desiredReplicas)) reconciler.MonoVertexCurrentReplicas.WithLabelValues(monoVtx.Namespace, monoVtx.Name).Set(float64(monoVtx.Status.Replicas)) }() + podSpec, err := mr.buildPodSpec(monoVtx) + if err != nil { + return fmt.Errorf("failed to generate mono vertex pod spec: %w", err) + } + + hash := sharedutil.MustHash(podSpec) + if monoVtx.Status.UpdateHash != hash { // New spec, or still processing last update, while new update is coming + monoVtx.Status.UpdateHash = hash + monoVtx.Status.UpdatedReplicas = 0 + monoVtx.Status.UpdatedReadyReplicas = 0 + } + + // Manually or automatically scaled down + if currentReplicas := int(monoVtx.Status.Replicas); currentReplicas > desiredReplicas { + if err := mr.cleanUpPodsFromTo(ctx, monoVtx, desiredReplicas, currentReplicas); err != nil { + return fmt.Errorf("failed to clean up mono vertex pods [%v, %v): %w", desiredReplicas, currentReplicas, err) + } + monoVtx.Status.Replicas = uint32(desiredReplicas) + } + updatedReplicas := int(monoVtx.Status.UpdatedReplicas) + if updatedReplicas > desiredReplicas { + updatedReplicas = desiredReplicas + monoVtx.Status.UpdatedReplicas = uint32(updatedReplicas) + } + + if updatedReplicas > 0 { + // Make sure [0 - updatedReplicas] with hash are in place + if err := mr.orchestratePodsFromTo(ctx, monoVtx, *podSpec, 0, updatedReplicas, hash); err != nil { + return fmt.Errorf("failed to orchestrate mono vertex pods [0, %v): %w", updatedReplicas, err) + } + // Wait for the updated pods to be ready before moving on + if monoVtx.Status.UpdatedReadyReplicas != monoVtx.Status.UpdatedReplicas { + updatedReadyReplicas := 0 + existingPods, err := mr.findExistingPods(ctx, monoVtx, 0, updatedReplicas) + if err != nil { + return fmt.Errorf("failed to get pods of a mono vertex: %w", err) + } + for _, pod := range existingPods { + if pod.GetAnnotations()[dfv1.KeyHash] == monoVtx.Status.UpdateHash { + if reconciler.IsPodReady(pod) { + updatedReadyReplicas++ + } + } + } + monoVtx.Status.UpdatedReadyReplicas = uint32(updatedReadyReplicas) + if updatedReadyReplicas < updatedReplicas { + return nil + } + } + } + + if monoVtx.Status.UpdateHash == monoVtx.Status.CurrentHash || + monoVtx.Status.CurrentHash == "" { + // 1. Regular scaling operation 2. First time + // create (desiredReplicas-updatedReplicas) pods directly + if desiredReplicas > updatedReplicas { + if err := mr.orchestratePodsFromTo(ctx, monoVtx, *podSpec, updatedReplicas, desiredReplicas, hash); err != nil { + return fmt.Errorf("failed to orchestrate mono vertex pods [%v, %v): %w", updatedReplicas, desiredReplicas, err) + } + } + monoVtx.Status.UpdatedReplicas = uint32(desiredReplicas) + monoVtx.Status.CurrentHash = monoVtx.Status.UpdateHash + } else { // Update scenario + if updatedReplicas >= desiredReplicas { + return nil + } + + // Create more pods + if monoVtx.Spec.UpdateStrategy.GetUpdateStrategyType() != dfv1.RollingUpdateStrategyType { + // Revisit later, we only support rolling update for now + return nil + } + + // Calculate the to be updated replicas based on the max unavailable configuration + maxUnavailConf := monoVtx.Spec.UpdateStrategy.GetRollingUpdateStrategy().GetMaxUnavailable() + toBeUpdated, err := intstr.GetScaledValueFromIntOrPercent(&maxUnavailConf, desiredReplicas, true) + if err != nil { // This should never happen since we have validated the configuration + return fmt.Errorf("invalid max unavailable configuration in rollingUpdate: %w", err) + } + if updatedReplicas+toBeUpdated > desiredReplicas { + toBeUpdated = desiredReplicas - updatedReplicas + } + log.Infof("Rolling update %d replicas, [%d, %d)\n", toBeUpdated, updatedReplicas, updatedReplicas+toBeUpdated) + + // Create pods [updatedReplicas, updatedReplicas+toBeUpdated), and clean up any pods in that range that has a different hash + if err := mr.orchestratePodsFromTo(ctx, monoVtx, *podSpec, updatedReplicas, updatedReplicas+toBeUpdated, monoVtx.Status.UpdateHash); err != nil { + return fmt.Errorf("failed to orchestrate pods [%v, %v)]: %w", updatedReplicas, updatedReplicas+toBeUpdated, err) + } + monoVtx.Status.UpdatedReplicas = uint32(updatedReplicas + toBeUpdated) + if monoVtx.Status.UpdatedReplicas == uint32(desiredReplicas) { + monoVtx.Status.CurrentHash = monoVtx.Status.UpdateHash + } + } + + currentReplicas := int(monoVtx.Status.Replicas) + if currentReplicas != desiredReplicas { + log.Infow("MonoVertex replicas changed", "currentReplicas", currentReplicas, "desiredReplicas", desiredReplicas) + mr.recorder.Eventf(monoVtx, corev1.EventTypeNormal, "ReplicasScaled", "Replicas changed from %d to %d", currentReplicas, desiredReplicas) + monoVtx.Status.Replicas = uint32(desiredReplicas) + monoVtx.Status.LastScaledAt = metav1.Time{Time: time.Now()} + } + if monoVtx.Status.Selector == "" { + selector, _ := labels.Parse(dfv1.KeyComponent + "=" + dfv1.ComponentMonoVertex + "," + dfv1.KeyMonoVertexName + "=" + monoVtx.Name) + monoVtx.Status.Selector = selector.String() + } + + return nil +} + +func (mr *monoVertexReconciler) findExistingPods(ctx context.Context, monoVtx *dfv1.MonoVertex, fromReplica, toReplica int) (map[string]corev1.Pod, error) { + pods := &corev1.PodList{} + selector, _ := labels.Parse(dfv1.KeyComponent + "=" + dfv1.ComponentMonoVertex + "," + dfv1.KeyMonoVertexName + "=" + monoVtx.Name) + if err := mr.client.List(ctx, pods, &client.ListOptions{Namespace: monoVtx.Namespace, LabelSelector: selector}); err != nil { + return nil, fmt.Errorf("failed to list mono vertex pods: %w", err) + } + result := make(map[string]corev1.Pod) + for _, pod := range pods.Items { + if !pod.DeletionTimestamp.IsZero() { + // Ignore pods being deleted + continue + } + replicaStr := pod.GetAnnotations()[dfv1.KeyReplica] + replica, _ := strconv.Atoi(replicaStr) + if replica >= fromReplica && replica < toReplica { + result[pod.Name] = pod + } + } + return result, nil +} + +func (mr *monoVertexReconciler) cleanUpPodsFromTo(ctx context.Context, monoVtx *dfv1.MonoVertex, fromReplica, toReplica int) error { log := logging.FromContext(ctx) - existingPods, err := mr.findExistingPods(ctx, monoVtx) + existingPods, err := mr.findExistingPods(ctx, monoVtx, fromReplica, toReplica) if err != nil { - mr.markDeploymentFailedAndLogEvent(monoVtx, false, log, "FindExistingPodFailed", err.Error(), "Failed to find existing mono vertex pods", zap.Error(err)) - return err + return fmt.Errorf("failed to find existing pods: %w", err) } - for replica := 0; replica < desiredReplicas; replica++ { - podSpec, err := mr.buildPodSpec(monoVtx) - if err != nil { - mr.markDeploymentFailedAndLogEvent(monoVtx, false, log, "PodSpecGenFailed", err.Error(), "Failed to generate mono vertex pod spec", zap.Error(err)) - return err + + for _, pod := range existingPods { + if err := mr.client.Delete(ctx, &pod); err != nil { + return fmt.Errorf("failed to delete pod %s: %w", pod.Name, err) } - hash := sharedutil.MustHash(podSpec) + log.Infof("Deleted MonoVertx pod %s\n", pod.Name) + mr.recorder.Eventf(monoVtx, corev1.EventTypeNormal, "DeletePodSuccess", "Succeeded to delete a mono vertex pod %s", pod.Name) + } + return nil +} + +// orchestratePodsFromTo orchestrates pods [fromReplica, toReplica], and clean up any pods in that range that has a different hash +func (mr *monoVertexReconciler) orchestratePodsFromTo(ctx context.Context, monoVtx *dfv1.MonoVertex, podSpec corev1.PodSpec, fromReplica, toReplica int, newHash string) error { + log := logging.FromContext(ctx) + existingPods, err := mr.findExistingPods(ctx, monoVtx, fromReplica, toReplica) + if err != nil { + return fmt.Errorf("failed to find existing pods: %w", err) + } + // Create pods [fromReplica, toReplica) + for replica := fromReplica; replica < toReplica; replica++ { podNamePrefix := fmt.Sprintf("%s-mv-%d-", monoVtx.Name, replica) needToCreate := true for existingPodName, existingPod := range existingPods { if strings.HasPrefix(existingPodName, podNamePrefix) { - if existingPod.GetAnnotations()[dfv1.KeyHash] == hash && existingPod.Status.Phase != corev1.PodFailed { + if existingPod.GetAnnotations()[dfv1.KeyHash] == newHash && existingPod.Status.Phase != corev1.PodFailed { needToCreate = false delete(existingPods, existingPodName) } @@ -213,7 +352,7 @@ func (mr *monoVertexReconciler) reconcilePods(ctx context.Context, monoVtx *dfv1 podLabels[dfv1.KeyComponent] = dfv1.ComponentMonoVertex podLabels[dfv1.KeyAppName] = monoVtx.Name podLabels[dfv1.KeyMonoVertexName] = monoVtx.Name - annotations[dfv1.KeyHash] = hash + annotations[dfv1.KeyHash] = newHash annotations[dfv1.KeyReplica] = strconv.Itoa(replica) // Defaults to udf annotations[dfv1.KeyDefaultContainer] = dfv1.CtrMain @@ -225,12 +364,11 @@ func (mr *monoVertexReconciler) reconcilePods(ctx context.Context, monoVtx *dfv1 Annotations: annotations, OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(monoVtx.GetObjectMeta(), dfv1.MonoVertexGroupVersionKind)}, }, - Spec: *podSpec, + Spec: podSpec, } pod.Spec.Hostname = fmt.Sprintf("%s-mv-%d", monoVtx.Name, replica) if err := mr.client.Create(ctx, pod); err != nil { - mr.markDeploymentFailedAndLogEvent(monoVtx, true, log, "CreatePodFailed", err.Error(), "Failed to created a mono vertex pod", zap.Error(err)) - return err + return fmt.Errorf("failed to create a mono vertex pod: %w", err) } log.Infow("Succeeded to create a mono vertex pod", zap.String("pod", pod.Name)) mr.recorder.Eventf(monoVtx, corev1.EventTypeNormal, "CreatePodSuccess", "Succeeded to create a mono vertex pod %s", pod.Name) @@ -238,21 +376,9 @@ func (mr *monoVertexReconciler) reconcilePods(ctx context.Context, monoVtx *dfv1 } for _, v := range existingPods { if err := mr.client.Delete(ctx, &v); err != nil && !apierrors.IsNotFound(err) { - mr.markDeploymentFailedAndLogEvent(monoVtx, true, log, "DelPodFailed", err.Error(), "Failed to delete a mono vertex pod", zap.Error(err)) - return err + return fmt.Errorf("failed to delete pod %s: %w", v.Name, err) } } - - currentReplicas := int(monoVtx.Status.Replicas) - if currentReplicas != desiredReplicas || monoVtx.Status.Selector == "" { - log.Infow("MonoVertex replicas changed", "currentReplicas", currentReplicas, "desiredReplicas", desiredReplicas) - mr.recorder.Eventf(monoVtx, corev1.EventTypeNormal, "ReplicasScaled", "Replicas changed from %d to %d", currentReplicas, desiredReplicas) - monoVtx.Status.Replicas = uint32(desiredReplicas) - monoVtx.Status.LastScaledAt = metav1.Time{Time: time.Now()} - } - selector, _ := labels.Parse(dfv1.KeyComponent + "=" + dfv1.ComponentMonoVertex + "," + dfv1.KeyMonoVertexName + "=" + monoVtx.Name) - monoVtx.Status.Selector = selector.String() - return nil } @@ -404,23 +530,6 @@ func (mr *monoVertexReconciler) createOrUpdateDaemonDeployment(ctx context.Conte return nil } -func (mr *monoVertexReconciler) findExistingPods(ctx context.Context, monoVtx *dfv1.MonoVertex) (map[string]corev1.Pod, error) { - pods := &corev1.PodList{} - selector, _ := labels.Parse(dfv1.KeyComponent + "=" + dfv1.ComponentMonoVertex + "," + dfv1.KeyMonoVertexName + "=" + monoVtx.Name) - if err := mr.client.List(ctx, pods, &client.ListOptions{Namespace: monoVtx.Namespace, LabelSelector: selector}); err != nil { - return nil, fmt.Errorf("failed to list mono vertex pods: %w", err) - } - result := make(map[string]corev1.Pod) - for _, v := range pods.Items { - if !v.DeletionTimestamp.IsZero() { - // Ignore pods being deleted - continue - } - result[v.Name] = v - } - return result, nil -} - func (mr *monoVertexReconciler) buildPodSpec(monoVtx *dfv1.MonoVertex) (*corev1.PodSpec, error) { podSpec, err := monoVtx.GetPodSpec(dfv1.GetMonoVertexPodSpecReq{ Image: mr.image, @@ -482,7 +591,7 @@ func (mr *monoVertexReconciler) checkChildrenResourceStatus(ctx context.Context, var podList corev1.PodList if err := mr.client.List(ctx, &podList, &client.ListOptions{Namespace: monoVtx.GetNamespace(), LabelSelector: selector}); err != nil { monoVtx.Status.MarkPodNotHealthy("ListMonoVerticesPodsFailed", err.Error()) - return fmt.Errorf("failed to get pods of a vertex: %w", err) + return fmt.Errorf("failed to get pods of a mono vertex: %w", err) } readyPods := reconciler.NumOfReadyPods(podList) if readyPods > int(monoVtx.Status.Replicas) { // It might happen in some corner cases, such as during rollout diff --git a/pkg/reconciler/monovertex/controller_test.go b/pkg/reconciler/monovertex/controller_test.go index d84ddef68a..e9c4f9fdea 100644 --- a/pkg/reconciler/monovertex/controller_test.go +++ b/pkg/reconciler/monovertex/controller_test.go @@ -15,3 +15,302 @@ limitations under the License. */ package monovertex + +import ( + "context" + "strings" + "testing" + + "go.uber.org/zap/zaptest" + appv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + dfv1 "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1" + "github.com/numaproj/numaflow/pkg/reconciler" + "github.com/numaproj/numaflow/pkg/reconciler/monovertex/scaling" + "github.com/stretchr/testify/assert" +) + +const ( + testNamespace = "test-ns" + testMonoVtxName = "tmvtx" + testFlowImage = "test-d-iamge" +) + +var ( + testMonoVtx = &dfv1.MonoVertex{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: testNamespace, + Name: testMonoVtxName, + }, + Spec: dfv1.MonoVertexSpec{ + Scale: dfv1.Scale{ + Min: ptr.To[int32](2), + }, + Source: &dfv1.Source{ + UDSource: &dfv1.UDSource{ + Container: &dfv1.Container{ + Image: "test-source-image", + }, + }, + UDTransformer: &dfv1.UDTransformer{ + Container: &dfv1.Container{ + Image: "test-tf-image", + }, + }, + }, + Sink: &dfv1.Sink{ + AbstractSink: dfv1.AbstractSink{ + UDSink: &dfv1.UDSink{ + Container: &dfv1.Container{ + Image: "test-sink", + }, + }, + }, + Fallback: &dfv1.AbstractSink{ + UDSink: &dfv1.UDSink{ + Container: &dfv1.Container{ + Image: "test-fb-sink", + }, + }, + }, + }, + }, + } +) + +func init() { + _ = dfv1.AddToScheme(scheme.Scheme) + _ = appv1.AddToScheme(scheme.Scheme) + _ = corev1.AddToScheme(scheme.Scheme) +} + +func Test_NewReconciler(t *testing.T) { + cl := fake.NewClientBuilder().Build() + r := NewReconciler(cl, scheme.Scheme, reconciler.FakeGlobalConfig(t, nil), testFlowImage, scaling.NewScaler(cl), zaptest.NewLogger(t).Sugar(), record.NewFakeRecorder(64)) + _, ok := r.(*monoVertexReconciler) + assert.True(t, ok) +} + +func Test_BuildPodSpec(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + } + t.Run("test has everything", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + spec, err := r.buildPodSpec(testObj) + assert.NoError(t, err) + assert.Equal(t, 5, len(spec.Containers)) + assert.Equal(t, dfv1.CtrMain, spec.Containers[0].Name) + assert.Equal(t, dfv1.CtrUdsource, spec.Containers[1].Name) + assert.Equal(t, dfv1.CtrUdtransformer, spec.Containers[2].Name) + assert.Equal(t, dfv1.CtrUdsink, spec.Containers[3].Name) + assert.Equal(t, dfv1.CtrFallbackUdsink, spec.Containers[4].Name) + assert.Equal(t, 0, len(spec.InitContainers)) + }) + + t.Run("test no transformer, no fallback sink", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + testObj.Spec.Source.UDTransformer = nil + testObj.Spec.Sink.Fallback = nil + spec, err := r.buildPodSpec(testObj) + assert.NoError(t, err) + assert.Equal(t, 3, len(spec.Containers)) + assert.Equal(t, dfv1.CtrMain, spec.Containers[0].Name) + assert.Equal(t, dfv1.CtrUdsource, spec.Containers[1].Name) + assert.Equal(t, dfv1.CtrUdsink, spec.Containers[2].Name) + assert.Equal(t, 0, len(spec.InitContainers)) + }) +} + +func Test_createOrUpdateDaemonDeployment(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + } + + t.Run("test everything from scratch for daemon deployment", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + err := r.createOrUpdateDaemonDeployment(context.TODO(), testObj) + assert.NoError(t, err) + var daemonDeployment appv1.Deployment + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetDaemonDeploymentName()}, + &daemonDeployment) + assert.NoError(t, err) + assert.Equal(t, testObj.GetDaemonDeploymentName(), daemonDeployment.Name) + assert.Equal(t, 1, len(daemonDeployment.Spec.Template.Spec.Containers)) + assert.Equal(t, dfv1.CtrMain, daemonDeployment.Spec.Template.Spec.Containers[0].Name) + }) +} + +func Test_createOrUpdateDaemonService(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + } + + t.Run("test everything from scratch for daemon service", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + err := r.createOrUpdateDaemonService(context.TODO(), testObj) + assert.NoError(t, err) + var daemonSvc corev1.Service + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetDaemonServiceName()}, + &daemonSvc) + assert.NoError(t, err) + assert.Equal(t, testObj.GetDaemonServiceName(), daemonSvc.Name) + assert.Equal(t, 1, len(daemonSvc.Spec.Ports)) + assert.Equal(t, int32(dfv1.MonoVertexDaemonServicePort), daemonSvc.Spec.Ports[0].Port) + }) +} + +func Test_createOrUpdateMonoVtxServices(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + } + + t.Run("test everything from scratch for monovtx service", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + err := r.createOrUpdateMonoVtxServices(context.TODO(), testObj) + assert.NoError(t, err) + var svc corev1.Service + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetHeadlessServiceName()}, + &svc) + assert.NoError(t, err) + assert.Equal(t, testObj.GetHeadlessServiceName(), svc.Name) + assert.Equal(t, 1, len(svc.Spec.Ports)) + assert.Equal(t, int32(dfv1.MonoVertexMetricsPort), svc.Spec.Ports[0].Port) + m, err := r.findExistingMonoVtxServices(context.TODO(), testObj) + assert.NoError(t, err) + assert.Equal(t, 1, len(m)) + }) +} + +func Test_orchestratePods(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + } + t.Run("test orchestratePodsFromTo and cleanUpPodsFromTo", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + hash := "test-hasssssh" + podSpec, err := r.buildPodSpec(testObj) + assert.NoError(t, err) + err = r.orchestratePodsFromTo(context.TODO(), testObj, *podSpec, 2, 4, hash) + assert.NoError(t, err) + foundPods, err := r.findExistingPods(context.TODO(), testObj, 2, 4) + assert.NoError(t, err) + assert.Equal(t, 2, len(foundPods)) + for n, pod := range foundPods { + assert.Equal(t, hash, pod.Annotations[dfv1.KeyHash]) + assert.True(t, strings.HasPrefix(n, testObj.Name+"-mv-2") || strings.HasPrefix(n, testObj.Name+"-mv-3")) + } + err = r.cleanUpPodsFromTo(context.TODO(), testObj, 2, 4) + assert.NoError(t, err) + foundPods, err = r.findExistingPods(context.TODO(), testObj, 2, 4) + assert.NoError(t, err) + assert.Equal(t, 0, len(foundPods)) + }) + + t.Run("test orchestratePods", func(t *testing.T) { + testObj := testMonoVtx.DeepCopy() + err := r.orchestratePods(context.TODO(), testObj) + assert.NoError(t, err) + foundPods, err := r.findExistingPods(context.TODO(), testObj, 0, 4) + assert.NoError(t, err) + assert.Equal(t, 2, len(foundPods)) + for n := range foundPods { + assert.True(t, strings.HasPrefix(n, testObj.Name+"-mv-0") || strings.HasPrefix(n, testObj.Name+"-mv-1")) + } + }) +} + +func Test_orchestrateFixedResources(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + } + testObj := testMonoVtx.DeepCopy() + err := r.orchestrateFixedResources(context.TODO(), testObj) + assert.NoError(t, err) + var svc corev1.Service + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetHeadlessServiceName()}, + &svc) + assert.NoError(t, err) + assert.Equal(t, testObj.GetHeadlessServiceName(), svc.Name) + var daemonSvc corev1.Service + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetDaemonServiceName()}, + &daemonSvc) + assert.NoError(t, err) + assert.Equal(t, testObj.GetDaemonServiceName(), daemonSvc.Name) + var daemonDeployment appv1.Deployment + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetDaemonDeploymentName()}, + &daemonDeployment) + assert.NoError(t, err) + assert.Equal(t, testObj.GetDaemonDeploymentName(), daemonDeployment.Name) +} + +func Test_reconcile(t *testing.T) { + fakeConfig := reconciler.FakeGlobalConfig(t, nil) + cl := fake.NewClientBuilder().Build() + r := &monoVertexReconciler{ + client: cl, + scheme: scheme.Scheme, + config: fakeConfig, + image: testFlowImage, + logger: zaptest.NewLogger(t).Sugar(), + recorder: record.NewFakeRecorder(64), + scaler: scaling.NewScaler(cl), + } + testObj := testMonoVtx.DeepCopy() + _, err := r.reconcile(context.TODO(), testObj) + assert.NoError(t, err) + var daemonDeployment appv1.Deployment + err = r.client.Get(context.TODO(), client.ObjectKey{Namespace: testObj.GetNamespace(), Name: testObj.GetDaemonDeploymentName()}, + &daemonDeployment) + assert.NoError(t, err) + assert.Equal(t, testObj.GetDaemonDeploymentName(), daemonDeployment.Name) +} diff --git a/pkg/reconciler/monovertex/scaling/scaling.go b/pkg/reconciler/monovertex/scaling/scaling.go index fa085fc2b4..2ae99fcf1b 100644 --- a/pkg/reconciler/monovertex/scaling/scaling.go +++ b/pkg/reconciler/monovertex/scaling/scaling.go @@ -157,6 +157,10 @@ func (s *Scaler) scaleOneMonoVertex(ctx context.Context, key string, worker int) s.StopWatching(key) // Remove it in case it's watched. return nil } + if monoVtx.Status.UpdateHash != monoVtx.Status.CurrentHash && monoVtx.Status.UpdateHash != "" { + log.Info("MonoVertex is updating, skip scaling.") + return nil + } secondsSinceLastScale := time.Since(monoVtx.Status.LastScaledAt.Time).Seconds() scaleDownCooldown := float64(monoVtx.Spec.Scale.GetScaleDownCooldownSeconds()) scaleUpCooldown := float64(monoVtx.Spec.Scale.GetScaleUpCooldownSeconds()) @@ -174,7 +178,7 @@ func (s *Scaler) scaleOneMonoVertex(ctx context.Context, key string, worker int) // log.Info("MonoVertex is pausing, skip scaling.") // return nil // } - if int(monoVtx.Status.Replicas) != monoVtx.GetReplicas() { + if int(monoVtx.Status.Replicas) != monoVtx.CalculateReplicas() { log.Infof("MonoVertex %s might be under processing, replicas mismatch, skip scaling.", monoVtx.Name) return nil } @@ -235,7 +239,7 @@ func (s *Scaler) scaleOneMonoVertex(ctx context.Context, key string, worker int) desired = min log.Infof("Calculated desired replica number %d of MonoVertex %q is smaller than min, using min %d.", monoVtxName, desired, min) } - current := int32(monoVtx.GetReplicas()) + current := int32(monoVtx.Status.Replicas) if current > max || current < min { // Someone might have manually scaled up/down the MonoVertex return s.patchMonoVertexReplicas(ctx, monoVtx, desired) } diff --git a/pkg/reconciler/pipeline/controller.go b/pkg/reconciler/pipeline/controller.go index 0f5354b2c8..96d9fa2266 100644 --- a/pkg/reconciler/pipeline/controller.go +++ b/pkg/reconciler/pipeline/controller.go @@ -145,7 +145,7 @@ func (r *pipelineReconciler) reconcile(ctx context.Context, pl *dfv1.Pipeline) ( pl.Status.SetObservedGeneration(pl.Generation) // Regular pipeline change - // This should be happening in call cases to ensure a clean initialization regardless of the lifecycle phase + // This should be happening in all cases to ensure a clean initialization regardless of the lifecycle phase // Eg: even for a pipeline started with desiredPhase = Pause, we should still create the resources for the pipeline result, err := r.reconcileNonLifecycleChanges(ctx, pl) if err != nil { diff --git a/pkg/reconciler/util.go b/pkg/reconciler/util.go index 6d27a749bb..8edad6b1a8 100644 --- a/pkg/reconciler/util.go +++ b/pkg/reconciler/util.go @@ -63,20 +63,25 @@ func isPodHealthy(pod *corev1.Pod) (healthy bool, reason string) { func NumOfReadyPods(pods corev1.PodList) int { result := 0 for _, pod := range pods.Items { - ready := true - for _, s := range pod.Status.ContainerStatuses { - if !s.Ready { - ready = false - break - } - } - if ready { + if IsPodReady(pod) { result++ } } return result } +func IsPodReady(pod corev1.Pod) bool { + if pod.Status.Phase != corev1.PodRunning { + return false + } + for _, c := range pod.Status.ContainerStatuses { + if !c.Ready { + return false + } + } + return true +} + // CheckVertexStatus will calculate the status of the vertices and return the status and reason func CheckVertexStatus(vertices *dfv1.VertexList) (healthy bool, reason string, message string) { for _, vertex := range vertices.Items { diff --git a/pkg/reconciler/util_test.go b/pkg/reconciler/util_test.go index 51348f5a32..72a09da1bd 100644 --- a/pkg/reconciler/util_test.go +++ b/pkg/reconciler/util_test.go @@ -260,6 +260,7 @@ func TestNumOfReadyPods(t *testing.T) { Items: []corev1.Pod{ { Status: corev1.PodStatus{ + Phase: corev1.PodRunning, ContainerStatuses: []corev1.ContainerStatus{ { Ready: true, @@ -272,6 +273,7 @@ func TestNumOfReadyPods(t *testing.T) { }, { Status: corev1.PodStatus{ + Phase: corev1.PodRunning, ContainerStatuses: []corev1.ContainerStatus{ { Ready: false, @@ -284,6 +286,7 @@ func TestNumOfReadyPods(t *testing.T) { }, { Status: corev1.PodStatus{ + Phase: corev1.PodRunning, ContainerStatuses: []corev1.ContainerStatus{ { Ready: true, @@ -296,6 +299,7 @@ func TestNumOfReadyPods(t *testing.T) { }, { Status: corev1.PodStatus{ + Phase: corev1.PodRunning, ContainerStatuses: []corev1.ContainerStatus{ { Ready: true, @@ -311,6 +315,7 @@ func TestNumOfReadyPods(t *testing.T) { }, { Status: corev1.PodStatus{ + Phase: corev1.PodRunning, ContainerStatuses: []corev1.ContainerStatus{ { Ready: false, @@ -324,6 +329,22 @@ func TestNumOfReadyPods(t *testing.T) { }, }, }, + { + Status: corev1.PodStatus{ + Phase: corev1.PodFailed, + ContainerStatuses: []corev1.ContainerStatus{ + { + Ready: true, + }, + { + Ready: true, + }, + { + Ready: true, + }, + }, + }, + }, }, } assert.Equal(t, 2, NumOfReadyPods(pods)) diff --git a/rust/numaflow-models/Makefile b/rust/numaflow-models/Makefile index 3e38249cae..069179f746 100644 --- a/rust/numaflow-models/Makefile +++ b/rust/numaflow-models/Makefile @@ -19,6 +19,7 @@ generate: sed 's/io.k8s.api.core.v1./CoreV1/' | \ sed 's/io.k8s.apimachinery.pkg.apis.meta.v1./MetaV1/' | \ sed 's/io.k8s.apimachinery.pkg.api.resource.Quantity/ResourceQuantity/' | \ + sed 's/io.k8s.apimachinery.pkg.util.intstr.IntOrString/IntOrString/' | \ sed 's/io.numaproj.numaflow.v1alpha1.//' \ > ./dist/swagger.json $(DOCKER) openapitools/openapi-generator-cli:$(GENERATOR_VERSION) \ @@ -58,6 +59,7 @@ generate: --type-mappings MetaV1Time="k8s_openapi::apimachinery::pkg::apis::meta::v1::Time" \ --type-mappings MetaV1ObjectMeta="k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta" \ --type-mappings ResourceQuantity="k8s_openapi::apimachinery::pkg::api::resource::Quantity" \ + --type-mappings IntOrString="k8s_openapi::apimachinery::pkg::util::intstr::IntOrString" \ --generate-alias-as-model cargo add kube diff --git a/rust/numaflow-models/src/models/mod.rs b/rust/numaflow-models/src/models/mod.rs index bbb11ca261..29846575d2 100644 --- a/rust/numaflow-models/src/models/mod.rs +++ b/rust/numaflow-models/src/models/mod.rs @@ -128,6 +128,8 @@ pub mod redis_settings; pub use self::redis_settings::RedisSettings; pub mod retry_strategy; pub use self::retry_strategy::RetryStrategy; +pub mod rolling_update_strategy; +pub use self::rolling_update_strategy::RollingUpdateStrategy; pub mod sasl; pub use self::sasl::Sasl; pub mod sasl_plain; @@ -170,6 +172,8 @@ pub mod ud_transformer; pub use self::ud_transformer::UdTransformer; pub mod udf; pub use self::udf::Udf; +pub mod update_strategy; +pub use self::update_strategy::UpdateStrategy; pub mod vertex; pub use self::vertex::Vertex; pub mod vertex_instance; diff --git a/rust/numaflow-models/src/models/mono_vertex_spec.rs b/rust/numaflow-models/src/models/mono_vertex_spec.rs index 8eadbbdaab..6d4068bee7 100644 --- a/rust/numaflow-models/src/models/mono_vertex_spec.rs +++ b/rust/numaflow-models/src/models/mono_vertex_spec.rs @@ -79,6 +79,8 @@ pub struct MonoVertexSpec { /// If specified, the pod's tolerations. #[serde(rename = "tolerations", skip_serializing_if = "Option::is_none")] pub tolerations: Option>, + #[serde(rename = "updateStrategy", skip_serializing_if = "Option::is_none")] + pub update_strategy: Option>, #[serde(rename = "volumes", skip_serializing_if = "Option::is_none")] pub volumes: Option>, } @@ -109,6 +111,7 @@ impl MonoVertexSpec { sink: None, source: None, tolerations: None, + update_strategy: None, volumes: None, } } diff --git a/rust/numaflow-models/src/models/mono_vertex_status.rs b/rust/numaflow-models/src/models/mono_vertex_status.rs index bd2fdee807..16e2de5479 100644 --- a/rust/numaflow-models/src/models/mono_vertex_status.rs +++ b/rust/numaflow-models/src/models/mono_vertex_status.rs @@ -21,12 +21,12 @@ pub struct MonoVertexStatus { /// Conditions are the latest available observations of a resource's current state. #[serde(rename = "conditions", skip_serializing_if = "Option::is_none")] pub conditions: Option>, - /// If not empty, indicates the version of the MonoVertex used to generate Pods in the sequence [0,currentReplicas). + /// If not empty, indicates the current version of the MonoVertex used to generate Pods. #[serde(rename = "currentHash", skip_serializing_if = "Option::is_none")] pub current_hash: Option, - /// The number of Pods created by the controller from the MonoVertex version indicated by currentHash. - #[serde(rename = "currentReplicas", skip_serializing_if = "Option::is_none")] - pub current_replicas: Option, + /// The number of desired replicas. + #[serde(rename = "desiredReplicas", skip_serializing_if = "Option::is_none")] + pub desired_replicas: Option, #[serde(rename = "lastScaledAt", skip_serializing_if = "Option::is_none")] pub last_scaled_at: Option, #[serde(rename = "lastUpdated", skip_serializing_if = "Option::is_none")] @@ -48,9 +48,15 @@ pub struct MonoVertexStatus { pub replicas: Option, #[serde(rename = "selector", skip_serializing_if = "Option::is_none")] pub selector: Option, - /// If not empty, indicates the version of the MonoVertx used to generate Pods in the sequence [replicas-updatedReplicas,replicas) + /// If not empty, indicates the updated version of the MonoVertex used to generate Pods. #[serde(rename = "updateHash", skip_serializing_if = "Option::is_none")] pub update_hash: Option, + /// The number of ready Pods created by the controller from the MonoVertex version indicated by updateHash. + #[serde( + rename = "updatedReadyReplicas", + skip_serializing_if = "Option::is_none" + )] + pub updated_ready_replicas: Option, /// The number of Pods created by the controller from the MonoVertex version indicated by updateHash. #[serde(rename = "updatedReplicas", skip_serializing_if = "Option::is_none")] pub updated_replicas: Option, @@ -61,7 +67,7 @@ impl MonoVertexStatus { MonoVertexStatus { conditions: None, current_hash: None, - current_replicas: None, + desired_replicas: None, last_scaled_at: None, last_updated: None, message: None, @@ -72,6 +78,7 @@ impl MonoVertexStatus { replicas: None, selector: None, update_hash: None, + updated_ready_replicas: None, updated_replicas: None, } } diff --git a/rust/numaflow-models/src/models/rolling_update_strategy.rs b/rust/numaflow-models/src/models/rolling_update_strategy.rs new file mode 100644 index 0000000000..2712fea2b4 --- /dev/null +++ b/rust/numaflow-models/src/models/rolling_update_strategy.rs @@ -0,0 +1,34 @@ +/* +Copyright 2022 The Numaproj Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by Openapi Generator. DO NOT EDIT. + +/// RollingUpdateStrategy : RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType. + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct RollingUpdateStrategy { + #[serde(rename = "maxUnavailable", skip_serializing_if = "Option::is_none")] + pub max_unavailable: Option, +} + +impl RollingUpdateStrategy { + /// RollingUpdateStrategy is used to communicate parameter for RollingUpdateStrategyType. + pub fn new() -> RollingUpdateStrategy { + RollingUpdateStrategy { + max_unavailable: None, + } + } +} diff --git a/rust/numaflow-models/src/models/update_strategy.rs b/rust/numaflow-models/src/models/update_strategy.rs new file mode 100644 index 0000000000..96f1256351 --- /dev/null +++ b/rust/numaflow-models/src/models/update_strategy.rs @@ -0,0 +1,51 @@ +/* +Copyright 2022 The Numaproj Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by Openapi Generator. DO NOT EDIT. + +/// UpdateStrategy : UpdateStrategy indicates the strategy that the controller will use to perform updates for Vertex or MonoVertex. + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct UpdateStrategy { + #[serde(rename = "rollingUpdate", skip_serializing_if = "Option::is_none")] + pub rolling_update: Option>, + /// Type indicates the type of the StatefulSetUpdateStrategy. Default is RollingUpdate. Possible enum values: - `\"RollingUpdate\"` + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub r#type: Option, +} + +impl UpdateStrategy { + /// UpdateStrategy indicates the strategy that the controller will use to perform updates for Vertex or MonoVertex. + pub fn new() -> UpdateStrategy { + UpdateStrategy { + rolling_update: None, + r#type: None, + } + } +} + +/// Type indicates the type of the StatefulSetUpdateStrategy. Default is RollingUpdate. Possible enum values: - `\"RollingUpdate\"` +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum Type { + #[serde(rename = "RollingUpdate")] + RollingUpdate, +} + +impl Default for Type { + fn default() -> Type { + Self::RollingUpdate + } +} diff --git a/test/fixtures/util.go b/test/fixtures/util.go index 2c8c8a0ae1..c88d28d1af 100644 --- a/test/fixtures/util.go +++ b/test/fixtures/util.go @@ -278,7 +278,7 @@ func WaitForMonoVertexPodRunning(kubeClient kubernetes.Interface, monoVertexClie if err != nil { return fmt.Errorf("error getting monovertex pod list: %w", err) } - ok := len(podList.Items) > 0 && len(podList.Items) == monoVertex.GetReplicas() // pod number should equal to desired replicas + ok := len(podList.Items) > 0 && len(podList.Items) == monoVertex.CalculateReplicas() // pod number should equal to desired replicas for _, p := range podList.Items { ok = ok && p.Status.Phase == corev1.PodRunning }