From 38ba564c30af680c1754587429d41a40fc213faa Mon Sep 17 00:00:00 2001 From: daviszhen Date: Wed, 17 Jun 2026 16:09:35 +0800 Subject: [PATCH 01/17] update --- pkg/sql/plan/function/func_unary.go | 160 +++++++++++++++++++--- pkg/sql/plan/function/func_unary_test.go | 70 ++++++++++ pkg/sql/plan/function/function_id.go | 14 +- pkg/sql/plan/function/function_id_test.go | 6 +- pkg/sql/plan/function/function_test.go | 11 +- pkg/sql/plan/function/list_builtIn.go | 46 +++++++ 6 files changed, 276 insertions(+), 31 deletions(-) diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 8677701bd87f8..010b7b56a1508 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -6981,11 +6981,16 @@ type userLevelLockKey struct { var userLevelLocks = struct { sync.Mutex - counts map[userLevelLockKey]uint64 + //owner, lockname -> count + counts map[userLevelLockKey]uint64 + //owner -> lockername byOwner map[string]map[string]struct{} + //account:lockname -> connectionid + holders map[string]uint64 }{ counts: make(map[userLevelLockKey]uint64), byOwner: make(map[string]map[string]struct{}), + holders: make(map[string]uint64), } func userLevelLockOwner(proc *process.Process) string { @@ -7002,8 +7007,15 @@ func userLevelLockOwner(proc *process.Process) string { return fmt.Sprintf("%d", si.GetConnectionID()) } +func userLevelLockConnectionID(proc *process.Process) uint64 { + if proc == nil || proc.GetSessionInfo() == nil { + return 0 + } + return proc.GetSessionInfo().GetConnectionID() +} + // maxUserLevelLockNameLength is the MySQL-compatible maximum length for -// user-level lock names (GET_LOCK, RELEASE_LOCK, IS_FREE_LOCK). +// user-level lock names (GET_LOCK, RELEASE_LOCK, IS_FREE_LOCK, IS_USED_LOCK). const maxUserLevelLockNameLength = 64 // normalizeUserLevelLockName validates and normalizes a MySQL user-level lock name. @@ -7023,8 +7035,20 @@ func normalizeUserLevelLockName(name string) (string, error) { return normalized, nil } -func userLevelLockTxnID(owner, name string) []byte { - return []byte("mo-user-level-lock\x00" + owner + "\x00" + name) +func userLevelLockTxnID(owner string, connID uint64, name string) []byte { + return []byte(fmt.Sprintf("mo-user-level-lock\x00%s\x00%d\x00%s", owner, connID, name)) +} + +func userLevelLockConnectionIDFromTxnID(txnID []byte) (uint64, bool) { + parts := strings.SplitN(string(txnID), "\x00", 4) + if len(parts) != 4 || parts[0] != "mo-user-level-lock" { + return 0, false + } + connID, err := strconv.ParseUint(parts[2], 10, 64) + if err != nil { + return 0, false + } + return connID, true } func userLevelLockRow(proc *process.Process, name string) []byte { @@ -7035,6 +7059,10 @@ func userLevelLockRow(proc *process.Process, name string) []byte { return []byte(account + "\x00" + name) } +func userLevelLockStateKey(proc *process.Process, name string) string { + return string(userLevelLockRow(proc, name)) +} + func userLevelLockService(proc *process.Process) (lockservice.LockService, error) { if proc == nil || proc.GetLockService() == nil { return nil, moerr.NewInternalErrorNoCtx("GET_LOCK requires lock service") @@ -7071,7 +7099,7 @@ func userLevelLockConflictOrTimeout(err error) bool { errors.Is(err, context.DeadlineExceeded) } -func trackUserLevelLock(owner, name string) { +func trackUserLevelLock(owner, name, stateKey string, connID uint64) { key := userLevelLockKey{owner: owner, name: name} userLevelLocks.Lock() defer userLevelLocks.Unlock() @@ -7081,6 +7109,14 @@ func trackUserLevelLock(owner, name string) { userLevelLocks.byOwner[owner] = make(map[string]struct{}) } userLevelLocks.byOwner[owner][name] = struct{}{} + userLevelLocks.holders[stateKey] = connID +} + +func getUserLevelLockHolder(stateKey string) (uint64, bool) { + userLevelLocks.Lock() + defer userLevelLocks.Unlock() + connID, ok := userLevelLocks.holders[stateKey] + return connID, ok } func userLevelLockRefCount(owner, name string) uint64 { @@ -7089,7 +7125,7 @@ func userLevelLockRefCount(owner, name string) uint64 { return userLevelLocks.counts[userLevelLockKey{owner: owner, name: name}] } -func untrackUserLevelLock(owner, name string) (uint64, bool) { +func untrackUserLevelLock(owner, name, stateKey string) (uint64, bool) { key := userLevelLockKey{owner: owner, name: name} userLevelLocks.Lock() defer userLevelLocks.Unlock() @@ -7103,6 +7139,7 @@ func untrackUserLevelLock(owner, name string) (uint64, bool) { return count - 1, true } delete(userLevelLocks.counts, key) + delete(userLevelLocks.holders, stateKey) if names := userLevelLocks.byOwner[owner]; names != nil { delete(names, name) if len(names) == 0 { @@ -7136,9 +7173,18 @@ func getUserLevelLock(name string, timeout float64, proc *process.Process) (int6 if err != nil { return 0, err } + //owner = sessionid or serviceid:connectionid or connectionid owner := userLevelLockOwner(proc) + //connectionid + connID := userLevelLockConnectionID(proc) + //account:lockname + stateKey := userLevelLockStateKey(proc, name) + //owner+lockname -> count + //serviceid:connectionid + lockname -> count if userLevelLockRefCount(owner, name) > 0 { - trackUserLevelLock(owner, name) + //count++ + //owner -> lockname + trackUserLevelLock(owner, name, stateKey, connID) return 1, nil } @@ -7149,7 +7195,7 @@ func getUserLevelLock(name string, timeout float64, proc *process.Process) (int6 ctx, userLevelLockTableID, [][]byte{userLevelLockRow(proc, name)}, - userLevelLockTxnID(owner, name), + userLevelLockTxnID(owner, connID, name), userLevelLockOptions(policy)) if err != nil { if userLevelLockConflictOrTimeout(err) { @@ -7157,7 +7203,7 @@ func getUserLevelLock(name string, timeout float64, proc *process.Process) (int6 } return 0, err } - trackUserLevelLock(owner, name) + trackUserLevelLock(owner, name, stateKey, connID) return 1, nil } @@ -7176,6 +7222,8 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro return 0, false, err } owner := userLevelLockOwner(proc) + connID := userLevelLockConnectionID(proc) + stateKey := userLevelLockStateKey(proc, name) count := userLevelLockRefCount(owner, name) if count == 0 { // Probe the lockservice to distinguish "lock does not exist" (NULL) @@ -7185,7 +7233,7 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro proc.Ctx, userLevelLockTableID, [][]byte{userLevelLockRow(proc, name)}, - userLevelLockTxnID(probeOwner, name), + userLevelLockTxnID(probeOwner, connID, name), userLevelLockOptions(lockpb.WaitPolicy_FastFail)) if probeErr != nil { if userLevelLockConflictOrTimeout(probeErr) { @@ -7196,19 +7244,19 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro } // Lock did not exist — we acquired it via the probe. Release it and // return NULL to signal the lock was already free. - if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(probeOwner, name), timestamp.Timestamp{}); err != nil { + if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(probeOwner, connID, name), timestamp.Timestamp{}); err != nil { return 0, false, err } return 0, true, nil } if count > 1 { - untrackUserLevelLock(owner, name) + untrackUserLevelLock(owner, name, stateKey) return 1, false, nil } - if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(owner, name), timestamp.Timestamp{}); err != nil { + if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}); err != nil { return 0, false, err } - untrackUserLevelLock(owner, name) + untrackUserLevelLock(owner, name, stateKey) return 1, false, nil } @@ -7222,12 +7270,13 @@ func isUserLevelLockFree(name string, proc *process.Process) (int64, error) { return 0, err } owner := userLevelLockOwner(proc) + connID := userLevelLockConnectionID(proc) probeOwner := owner + "\x00probe\x00" + name _, err = ls.Lock( proc.Ctx, userLevelLockTableID, [][]byte{userLevelLockRow(proc, name)}, - userLevelLockTxnID(probeOwner, name), + userLevelLockTxnID(probeOwner, connID, name), userLevelLockOptions(lockpb.WaitPolicy_FastFail)) if err != nil { if userLevelLockConflictOrTimeout(err) { @@ -7235,29 +7284,71 @@ func isUserLevelLockFree(name string, proc *process.Process) (int64, error) { } return 0, err } - if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(probeOwner, name), timestamp.Timestamp{}); err != nil { + if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(probeOwner, connID, name), timestamp.Timestamp{}); err != nil { return 0, err } return 1, nil } -func ReleaseUserLevelLocks(proc *process.Process) { +func isUserLevelLockUsed(name string, proc *process.Process) (uint64, bool, error) { + name, err := normalizeUserLevelLockName(name) + if err != nil { + return 0, false, err + } + ls, err := userLevelLockService(proc) + if err != nil { + return 0, false, err + } + + stateKey := userLevelLockStateKey(proc, name) + if holderConnID, ok := getUserLevelLockHolder(stateKey); ok { + return holderConnID, false, nil + } + + row := userLevelLockRow(proc, name) + var holderConnID uint64 + ls.IterLocks(func(tableID uint64, keys [][]byte, lock lockservice.Lock) bool { + if tableID != userLevelLockTableID || len(keys) != 1 || !bytes.Equal(keys[0], row) { + return true + } + lock.IterHolders(func(holder lockpb.WaitTxn) bool { + holderConnID, _ = userLevelLockConnectionIDFromTxnID(holder.TxnID) + return false + }) + return false + }) + if holderConnID == 0 { + return 0, true, nil + } + return holderConnID, false, nil +} + +func releaseAllUserLevelLocks(proc *process.Process) int64 { if proc == nil || proc.GetLockService() == nil { - return + return 0 } owner := userLevelLockOwner(proc) + connID := userLevelLockConnectionID(proc) + var released int64 for _, name := range userLevelLocksForOwner(owner) { + stateKey := userLevelLockStateKey(proc, name) for { - count, held := untrackUserLevelLock(owner, name) + count, held := untrackUserLevelLock(owner, name, stateKey) if !held { break } + released++ if count == 0 { - _ = proc.GetLockService().Unlock(context.Background(), userLevelLockTxnID(owner, name), timestamp.Timestamp{}) + _ = proc.GetLockService().Unlock(context.Background(), userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}) break } } } + return released +} + +func ReleaseUserLevelLocks(proc *process.Process) { + _ = releaseAllUserLevelLocks(proc) } func GetLock(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, selectList *FunctionSelectList) error { @@ -7331,6 +7422,35 @@ func IsFreeLock(ivecs []*vector.Vector, result vector.FunctionResultWrapper, pro return nil } +func IsUsedLock(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, selectList *FunctionSelectList) error { + names := vector.GenerateFunctionStrParameter(ivecs[0]) + rs := vector.MustFunctionResult[uint64](result) + + for i := uint64(0); i < uint64(length); i++ { + name, null := names.GetStrValue(i) + if null { + if err := rs.Append(0, true); err != nil { + return err + } + continue + } + value, isNull, err := isUserLevelLockUsed(string(name), proc) + if err != nil { + return err + } + if err := rs.Append(value, isNull); err != nil { + return err + } + } + return nil +} + +func ReleaseAllLocks(_ []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, selectList *FunctionSelectList) error { + return opNoneParamToFixed[int64](result, proc, length, func() int64 { + return releaseAllUserLevelLocks(proc) + }) +} + func Version( _ []*vector.Vector, result vector.FunctionResultWrapper, diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index ec04a6b35ec59..cce48e5f1ffcd 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7157,6 +7157,7 @@ func resetUserLevelLocksForTest(t *testing.T) { userLevelLocks.Lock() userLevelLocks.counts = make(map[userLevelLockKey]uint64) userLevelLocks.byOwner = make(map[string]map[string]struct{}) + userLevelLocks.holders = make(map[string]uint64) userLevelLocks.Unlock() } @@ -7290,6 +7291,14 @@ func TestUserLevelLockFunctions(t *testing.T) { expect: NewFunctionTestResult(types.T_int64.ToType(), false, []int64{0}, []bool{false}), fn: IsFreeLock, }, + { + name: "used lock returns holder connection id", + inputs: []FunctionTestInput{ + NewFunctionTestInput(types.T_varchar.ToType(), []string{"prisma_migrate_lock"}, []bool{false}), + }, + expect: NewFunctionTestResult(types.T_uint64.ToType(), false, []uint64{proc.GetSessionInfo().ConnectionID}, []bool{false}), + fn: IsUsedLock, + }, { name: "release held lock", inputs: []FunctionTestInput{ @@ -7452,6 +7461,67 @@ func TestReleaseUserLevelLocksCleanup(t *testing.T) { }) } +func TestIsUsedLockReturnsHolderConnectionID(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc1 := newUserLevelLockTestProcess(t, services[0], "acc") + proc2 := newUserLevelLockTestProcess(t, services[1], "acc") + proc1.GetSessionInfo().ConnectionID = 1001 + proc2.GetSessionInfo().ConnectionID = 1002 + + v, err := getUserLevelLock("holder_lock", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + + holder, isNull, err := isUserLevelLockUsed("holder_lock", proc2) + require.NoError(t, err) + require.False(t, isNull) + require.Equal(t, uint64(1001), holder) + + holder, isNull, err = isUserLevelLockUsed("missing_holder_lock", proc2) + require.NoError(t, err) + require.True(t, isNull) + require.Equal(t, uint64(0), holder) + }) +} + +func TestReleaseAllUserLevelLocksReturnsReleasedCount(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc1 := newUserLevelLockTestProcess(t, services[0], "acc") + proc2 := newUserLevelLockTestProcess(t, services[1], "acc") + + v, err := getUserLevelLock("release_all_a", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + v, err = getUserLevelLock("release_all_a", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + v, err = getUserLevelLock("release_all_b", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + + released := releaseAllUserLevelLocks(proc1) + require.Equal(t, int64(3), released) + require.Equal(t, int64(0), releaseAllUserLevelLocks(proc1)) + + v, err = getUserLevelLock("release_all_a", 0, proc2) + require.NoError(t, err) + require.Equal(t, int64(1), v) + v, isNull, err := releaseUserLevelLock("release_all_a", proc2) + require.NoError(t, err) + require.False(t, isNull) + require.Equal(t, int64(1), v) + + fcTC := NewFunctionTestCase( + proc1, + nil, + NewFunctionTestResult(types.T_int64.ToType(), false, []int64{0}, []bool{false}), + ReleaseAllLocks, + ) + s, info := fcTC.Run() + require.True(t, s, info) + }) +} + func TestReleaseLockNeverCreatedReturnsNull(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") diff --git a/pkg/sql/plan/function/function_id.go b/pkg/sql/plan/function/function_id.go index adc8216cfd71b..db239d6d0ac9a 100644 --- a/pkg/sql/plan/function/function_id.go +++ b/pkg/sql/plan/function/function_id.go @@ -727,14 +727,16 @@ const ( UUID_TO_BIN = 516 BIN_TO_UUID = 517 - GET_LOCK = 518 - RELEASE_LOCK = 519 - IS_FREE_LOCK = 520 - NAME_CONST = 521 + GET_LOCK = 518 + RELEASE_LOCK = 519 + IS_FREE_LOCK = 520 + IS_USED_LOCK = 521 + RELEASE_ALL_LOCKS = 522 + NAME_CONST = 523 // FUNCTION_END_NUMBER is not a function, just a flag to record the max number of function. // TODO: every one should put the new function id in front of this one if you want to make a new function. - FUNCTION_END_NUMBER = 522 + FUNCTION_END_NUMBER = 524 ) // functionIdRegister is what function we have registered already. @@ -1080,6 +1082,8 @@ var functionIdRegister = map[string]int32{ "get_lock": GET_LOCK, "release_lock": RELEASE_LOCK, "is_free_lock": IS_FREE_LOCK, + "is_used_lock": IS_USED_LOCK, + "release_all_locks": RELEASE_ALL_LOCKS, "split_part": SPLIT_PART, "insert": INSERT, "instr": INSTR, diff --git a/pkg/sql/plan/function/function_id_test.go b/pkg/sql/plan/function/function_id_test.go index 6e3170a8e784a..ba09b0f8f0589 100644 --- a/pkg/sql/plan/function/function_id_test.go +++ b/pkg/sql/plan/function/function_id_test.go @@ -574,10 +574,12 @@ var predefinedFunids = map[int]int{ GET_LOCK: 518, RELEASE_LOCK: 519, IS_FREE_LOCK: 520, - NAME_CONST: 521, + IS_USED_LOCK: 521, + RELEASE_ALL_LOCKS: 522, + NAME_CONST: 523, // FUNCTION_END_NUMBER is not a function, just a flag to record the max number of function. // TODO: every one should put the new function id in front of this one if you want to make a new function. - FUNCTION_END_NUMBER: 522, + FUNCTION_END_NUMBER: 524, } func Test_funids(t *testing.T) { diff --git a/pkg/sql/plan/function/function_test.go b/pkg/sql/plan/function/function_test.go index 76e0c8a26e967..27118dd717845 100644 --- a/pkg/sql/plan/function/function_test.go +++ b/pkg/sql/plan/function/function_test.go @@ -295,10 +295,13 @@ func TestUserLevelLockBuiltinRegistration(t *testing.T) { name string id int args []types.T + ret types.Type }{ - {name: "get_lock", id: GET_LOCK, args: []types.T{types.T_varchar, types.T_float64}}, - {name: "release_lock", id: RELEASE_LOCK, args: []types.T{types.T_varchar}}, - {name: "is_free_lock", id: IS_FREE_LOCK, args: []types.T{types.T_varchar}}, + {name: "get_lock", id: GET_LOCK, args: []types.T{types.T_varchar, types.T_float64}, ret: types.T_int64.ToType()}, + {name: "release_lock", id: RELEASE_LOCK, args: []types.T{types.T_varchar}, ret: types.T_int64.ToType()}, + {name: "is_free_lock", id: IS_FREE_LOCK, args: []types.T{types.T_varchar}, ret: types.T_int64.ToType()}, + {name: "is_used_lock", id: IS_USED_LOCK, args: []types.T{types.T_varchar}, ret: types.T_uint64.ToType()}, + {name: "release_all_locks", id: RELEASE_ALL_LOCKS, args: []types.T{}, ret: types.T_int64.ToType()}, } for _, tc := range cases { @@ -319,7 +322,7 @@ func TestUserLevelLockBuiltinRegistration(t *testing.T) { require.Equal(t, tc.args, overload.args) require.True(t, overload.volatile) require.True(t, overload.realTimeRelated) - require.Equal(t, types.T_int64.ToType(), overload.retType(nil)) + require.Equal(t, tc.ret, overload.retType(nil)) require.NotNil(t, overload.newOp()) }) } diff --git a/pkg/sql/plan/function/list_builtIn.go b/pkg/sql/plan/function/list_builtIn.go index 602caa39ad004..91d35ee2b053d 100644 --- a/pkg/sql/plan/function/list_builtIn.go +++ b/pkg/sql/plan/function/list_builtIn.go @@ -10631,6 +10631,52 @@ var supportedControlBuiltIns = []FuncNew{ }, }, + // function `is_used_lock` + { + functionId: IS_USED_LOCK, + class: plan.Function_STRICT, + layout: STANDARD_FUNCTION, + checkFn: fixedTypeMatch, + + Overloads: []overload{ + { + overloadId: 0, + args: []types.T{types.T_varchar}, + volatile: true, + realTimeRelated: true, + retType: func(parameters []types.Type) types.Type { + return types.T_uint64.ToType() + }, + newOp: func() executeLogicOfOverload { + return IsUsedLock + }, + }, + }, + }, + + // function `release_all_locks` + { + functionId: RELEASE_ALL_LOCKS, + class: plan.Function_STRICT, + layout: STANDARD_FUNCTION, + checkFn: fixedTypeMatch, + + Overloads: []overload{ + { + overloadId: 0, + args: []types.T{}, + volatile: true, + realTimeRelated: true, + retType: func(parameters []types.Type) types.Type { + return types.T_int64.ToType() + }, + newOp: func() executeLogicOfOverload { + return ReleaseAllLocks + }, + }, + }, + }, + // function `trigger_fault_point` { functionId: TRIGGER_FAULT_POINT, From 271f1378656ae64ca4cc713da5481801212adb74 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Wed, 17 Jun 2026 17:36:39 +0800 Subject: [PATCH 02/17] add is_used_lock --- pkg/frontend/test/mock_lock/types.go | 16 +++++ pkg/incrservice/store_sql_test.go | 5 ++ pkg/lockservice/lock_table_remote.go | 7 ++- pkg/lockservice/lock_table_remote_test.go | 2 + pkg/lockservice/service_observability.go | 22 +++++++ pkg/lockservice/service_observability_test.go | 47 ++++++++++++++ pkg/lockservice/service_remote.go | 5 ++ pkg/lockservice/types.go | 2 + pkg/sql/plan/function/func_unary.go | 63 ++++++------------- pkg/sql/plan/function/func_unary_test.go | 11 +++- pkg/vm/engine/test/testutil/disttae_engine.go | 3 + proto/lock.proto | 4 +- 12 files changed, 140 insertions(+), 47 deletions(-) diff --git a/pkg/frontend/test/mock_lock/types.go b/pkg/frontend/test/mock_lock/types.go index 451518f3a0f78..f1a00b1ab4144 100644 --- a/pkg/frontend/test/mock_lock/types.go +++ b/pkg/frontend/test/mock_lock/types.go @@ -261,6 +261,22 @@ func (mr *MockLockServiceMockRecorder) GetLockTableBind(group, tableID any) *gom return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLockTableBind", reflect.TypeOf((*MockLockService)(nil).GetLockTableBind), group, tableID) } +// GetLockHolder mocks base method. +func (m *MockLockService) GetLockHolder(ctx context.Context, tableID uint64, row []byte, options lock.LockOptions) (lock.WaitTxn, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLockHolder", ctx, tableID, row, options) + ret0, _ := ret[0].(lock.WaitTxn) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetLockHolder indicates an expected call of GetLockHolder. +func (mr *MockLockServiceMockRecorder) GetLockHolder(ctx, tableID, row, options any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLockHolder", reflect.TypeOf((*MockLockService)(nil).GetLockHolder), ctx, tableID, row, options) +} + // GetServiceID mocks base method. func (m *MockLockService) GetServiceID() string { m.ctrl.T.Helper() diff --git a/pkg/incrservice/store_sql_test.go b/pkg/incrservice/store_sql_test.go index 25f05bb3fed80..44536a37f1733 100644 --- a/pkg/incrservice/store_sql_test.go +++ b/pkg/incrservice/store_sql_test.go @@ -138,6 +138,11 @@ func (tls *testLockService) GetWaitingList(ctx context.Context, txnID []byte) (b panic("implement me") } +func (tls *testLockService) GetLockHolder(ctx context.Context, tableID uint64, row []byte, options lock.LockOptions) (lock.WaitTxn, bool, error) { + //TODO implement me + panic("implement me") +} + func (tls *testLockService) ForceRefreshLockTableBinds(targets []uint64, matcher func(bind lock.LockTable) bool) { //TODO implement me panic("implement me") diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index 869c16deb2d74..1e43062fca1bc 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -301,6 +301,9 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err if err := l.maybeHandleBindChanged(resp); err != nil { return Lock{}, false, err } + if !resp.GetTxnLock.Found { + return Lock{}, false, nil + } wq := newWaiterQueue() wq.init(l.logger) @@ -309,7 +312,9 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err waiters: wq, value: byte(resp.GetTxnLock.Value), } - lock.holders.add(txn) + if len(resp.GetTxnLock.Holder.TxnID) > 0 { + lock.holders.add(resp.GetTxnLock.Holder) + } for _, v := range resp.GetTxnLock.WaitingList { w := acquireWaiter(v, "doGetLock", l.logger) lock.addWaiter(l.logger, w) diff --git a/pkg/lockservice/lock_table_remote_test.go b/pkg/lockservice/lock_table_remote_test.go index 85b7f03cd3631..ee277a24a5752 100644 --- a/pkg/lockservice/lock_table_remote_test.go +++ b/pkg/lockservice/lock_table_remote_test.go @@ -352,7 +352,9 @@ func TestGetLockRemoteWithRetry(t *testing.T) { writeResponse(getLogger(""), cancel, resp, moerr.NewRPCTimeout(ctx), cs) return } + resp.GetTxnLock.Found = true resp.GetTxnLock.Value = int32(pb.Granularity_Row) + resp.GetTxnLock.Holder = pb.WaitTxn{TxnID: []byte("txn1")} writeResponse(getLogger(""), cancel, resp, nil, cs) }, ) diff --git a/pkg/lockservice/service_observability.go b/pkg/lockservice/service_observability.go index 37c9061e6a1a0..1cc24ed948f9e 100644 --- a/pkg/lockservice/service_observability.go +++ b/pkg/lockservice/service_observability.go @@ -49,6 +49,28 @@ func (s *service) GetWaitingList( return true, waitingList, nil } +func (s *service) GetLockHolder( + ctx context.Context, + tableID uint64, + row []byte, + options pb.LockOptions) (pb.WaitTxn, bool, error) { + s.wait() + l, err := s.getLockTableWithCreate(options.Group, tableID, [][]byte{row}, options.Sharding) + if err != nil { + return pb.WaitTxn{}, false, err + } + var holder pb.WaitTxn + var found bool + l.getLock(row, pb.WaitTxn{}, func(lock Lock) { + lock.IterHolders(func(v pb.WaitTxn) bool { + holder = v + found = true + return false + }) + }) + return holder, found, nil +} + func (s *service) ForceRefreshLockTableBinds( targets []uint64, matcher func(bind pb.LockTable) bool) { diff --git a/pkg/lockservice/service_observability_test.go b/pkg/lockservice/service_observability_test.go index a3c4f412a779a..c6ce6fff7d6db 100644 --- a/pkg/lockservice/service_observability_test.go +++ b/pkg/lockservice/service_observability_test.go @@ -90,6 +90,53 @@ func TestGetWaitingList(t *testing.T) { ) } +func TestGetLockHolder(t *testing.T) { + runLockServiceTests( + t, + []string{"s1", "s2"}, + func(alloc *lockTableAllocator, s []*service) { + l1 := s[0] + l2 := s[1] + + ctx, cancel := context.WithTimeout( + context.Background(), + time.Second*10) + defer cancel() + + table := uint64(10) + row := []byte{1} + txnID := []byte("txn1") + option := pb.LockOptions{ + Granularity: pb.Granularity_Row, + Mode: pb.LockMode_Exclusive, + Policy: pb.WaitPolicy_Wait, + } + + _, err := l1.Lock( + ctx, + table, + [][]byte{row}, + txnID, + option) + require.NoError(t, err) + + holder, ok, err := l2.GetLockHolder(ctx, table, row, option) + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, txnID, holder.TxnID) + + _, ok, err = l2.GetLockHolder(ctx, table, []byte{2}, option) + require.NoError(t, err) + require.False(t, ok) + + require.NoError(t, l1.Unlock( + ctx, + txnID, + timestamp.Timestamp{PhysicalTime: 1})) + }, + ) +} + func TestForceRefreshLockTableBinds(t *testing.T) { runBindChangedTests( t, diff --git a/pkg/lockservice/service_remote.go b/pkg/lockservice/service_remote.go index beefd182b2c4a..1ee378730bda3 100644 --- a/pkg/lockservice/service_remote.go +++ b/pkg/lockservice/service_remote.go @@ -416,7 +416,12 @@ func (s *service) handleRemoteGetLock( req.GetTxnLock.Row, pb.WaitTxn{TxnID: req.GetTxnLock.TxnID}, func(lock Lock) { + resp.GetTxnLock.Found = true resp.GetTxnLock.Value = int32(lock.value) + lock.IterHolders(func(holder pb.WaitTxn) bool { + resp.GetTxnLock.Holder = holder + return false + }) values := make([]pb.WaitTxn, 0) lock.waiters.iter(func(w *waiter) bool { values = append(values, w.txn) diff --git a/pkg/lockservice/types.go b/pkg/lockservice/types.go index 3196c5c384464..260ee9dbe33ca 100644 --- a/pkg/lockservice/types.go +++ b/pkg/lockservice/types.go @@ -116,6 +116,8 @@ type LockService interface { // GetWaitingList get special txnID's waiting list GetWaitingList(ctx context.Context, txnID []byte) (bool, []pb.WaitTxn, error) + // GetLockHolder returns the current holder of a row lock if it exists. + GetLockHolder(ctx context.Context, tableID uint64, row []byte, options pb.LockOptions) (pb.WaitTxn, bool, error) // ForceRefreshLockTableBinds force refresh all lock tables binds ForceRefreshLockTableBinds(targets []uint64, matcher func(bind pb.LockTable) bool) // GetLockTableBind returns lock table bind diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 010b7b56a1508..9f30a7a1d9a03 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -6985,12 +6985,9 @@ var userLevelLocks = struct { counts map[userLevelLockKey]uint64 //owner -> lockername byOwner map[string]map[string]struct{} - //account:lockname -> connectionid - holders map[string]uint64 }{ counts: make(map[userLevelLockKey]uint64), byOwner: make(map[string]map[string]struct{}), - holders: make(map[string]uint64), } func userLevelLockOwner(proc *process.Process) string { @@ -7059,10 +7056,6 @@ func userLevelLockRow(proc *process.Process, name string) []byte { return []byte(account + "\x00" + name) } -func userLevelLockStateKey(proc *process.Process, name string) string { - return string(userLevelLockRow(proc, name)) -} - func userLevelLockService(proc *process.Process) (lockservice.LockService, error) { if proc == nil || proc.GetLockService() == nil { return nil, moerr.NewInternalErrorNoCtx("GET_LOCK requires lock service") @@ -7099,7 +7092,7 @@ func userLevelLockConflictOrTimeout(err error) bool { errors.Is(err, context.DeadlineExceeded) } -func trackUserLevelLock(owner, name, stateKey string, connID uint64) { +func trackUserLevelLock(owner, name string) { key := userLevelLockKey{owner: owner, name: name} userLevelLocks.Lock() defer userLevelLocks.Unlock() @@ -7109,14 +7102,6 @@ func trackUserLevelLock(owner, name, stateKey string, connID uint64) { userLevelLocks.byOwner[owner] = make(map[string]struct{}) } userLevelLocks.byOwner[owner][name] = struct{}{} - userLevelLocks.holders[stateKey] = connID -} - -func getUserLevelLockHolder(stateKey string) (uint64, bool) { - userLevelLocks.Lock() - defer userLevelLocks.Unlock() - connID, ok := userLevelLocks.holders[stateKey] - return connID, ok } func userLevelLockRefCount(owner, name string) uint64 { @@ -7125,7 +7110,7 @@ func userLevelLockRefCount(owner, name string) uint64 { return userLevelLocks.counts[userLevelLockKey{owner: owner, name: name}] } -func untrackUserLevelLock(owner, name, stateKey string) (uint64, bool) { +func untrackUserLevelLock(owner, name string) (uint64, bool) { key := userLevelLockKey{owner: owner, name: name} userLevelLocks.Lock() defer userLevelLocks.Unlock() @@ -7139,7 +7124,6 @@ func untrackUserLevelLock(owner, name, stateKey string) (uint64, bool) { return count - 1, true } delete(userLevelLocks.counts, key) - delete(userLevelLocks.holders, stateKey) if names := userLevelLocks.byOwner[owner]; names != nil { delete(names, name) if len(names) == 0 { @@ -7177,14 +7161,12 @@ func getUserLevelLock(name string, timeout float64, proc *process.Process) (int6 owner := userLevelLockOwner(proc) //connectionid connID := userLevelLockConnectionID(proc) - //account:lockname - stateKey := userLevelLockStateKey(proc, name) //owner+lockname -> count //serviceid:connectionid + lockname -> count if userLevelLockRefCount(owner, name) > 0 { //count++ //owner -> lockname - trackUserLevelLock(owner, name, stateKey, connID) + trackUserLevelLock(owner, name) return 1, nil } @@ -7203,7 +7185,7 @@ func getUserLevelLock(name string, timeout float64, proc *process.Process) (int6 } return 0, err } - trackUserLevelLock(owner, name, stateKey, connID) + trackUserLevelLock(owner, name) return 1, nil } @@ -7223,7 +7205,6 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro } owner := userLevelLockOwner(proc) connID := userLevelLockConnectionID(proc) - stateKey := userLevelLockStateKey(proc, name) count := userLevelLockRefCount(owner, name) if count == 0 { // Probe the lockservice to distinguish "lock does not exist" (NULL) @@ -7250,13 +7231,13 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro return 0, true, nil } if count > 1 { - untrackUserLevelLock(owner, name, stateKey) + untrackUserLevelLock(owner, name) return 1, false, nil } if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}); err != nil { return 0, false, err } - untrackUserLevelLock(owner, name, stateKey) + untrackUserLevelLock(owner, name) return 1, false, nil } @@ -7300,24 +7281,19 @@ func isUserLevelLockUsed(name string, proc *process.Process) (uint64, bool, erro return 0, false, err } - stateKey := userLevelLockStateKey(proc, name) - if holderConnID, ok := getUserLevelLockHolder(stateKey); ok { - return holderConnID, false, nil + holder, ok, err := ls.GetLockHolder( + proc.Ctx, + userLevelLockTableID, + userLevelLockRow(proc, name), + userLevelLockOptions(lockpb.WaitPolicy_FastFail)) + if err != nil { + return 0, false, err } - - row := userLevelLockRow(proc, name) - var holderConnID uint64 - ls.IterLocks(func(tableID uint64, keys [][]byte, lock lockservice.Lock) bool { - if tableID != userLevelLockTableID || len(keys) != 1 || !bytes.Equal(keys[0], row) { - return true - } - lock.IterHolders(func(holder lockpb.WaitTxn) bool { - holderConnID, _ = userLevelLockConnectionIDFromTxnID(holder.TxnID) - return false - }) - return false - }) - if holderConnID == 0 { + if !ok { + return 0, true, nil + } + holderConnID, ok := userLevelLockConnectionIDFromTxnID(holder.TxnID) + if !ok { return 0, true, nil } return holderConnID, false, nil @@ -7331,9 +7307,8 @@ func releaseAllUserLevelLocks(proc *process.Process) int64 { connID := userLevelLockConnectionID(proc) var released int64 for _, name := range userLevelLocksForOwner(owner) { - stateKey := userLevelLockStateKey(proc, name) for { - count, held := untrackUserLevelLock(owner, name, stateKey) + count, held := untrackUserLevelLock(owner, name) if !held { break } diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index cce48e5f1ffcd..acf92de1cffb4 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7157,7 +7157,6 @@ func resetUserLevelLocksForTest(t *testing.T) { userLevelLocks.Lock() userLevelLocks.counts = make(map[userLevelLockKey]uint64) userLevelLocks.byOwner = make(map[string]map[string]struct{}) - userLevelLocks.holders = make(map[string]uint64) userLevelLocks.Unlock() } @@ -7239,6 +7238,16 @@ func (s *userLevelLockTestService) GetWaitingList(ctx context.Context, txnID []b return false, nil, nil } +func (s *userLevelLockTestService) GetLockHolder(ctx context.Context, tableID uint64, row []byte, options lockpb.LockOptions) (lockpb.WaitTxn, bool, error) { + s.state.Lock() + defer s.state.Unlock() + holder := s.state.locks[string(row)] + if holder == "" { + return lockpb.WaitTxn{}, false, nil + } + return lockpb.WaitTxn{TxnID: []byte(holder)}, true, nil +} + func (s *userLevelLockTestService) ForceRefreshLockTableBinds(targets []uint64, matcher func(bind lockpb.LockTable) bool) { } diff --git a/pkg/vm/engine/test/testutil/disttae_engine.go b/pkg/vm/engine/test/testutil/disttae_engine.go index e2ab4cca4d420..785d933642bd9 100644 --- a/pkg/vm/engine/test/testutil/disttae_engine.go +++ b/pkg/vm/engine/test/testutil/disttae_engine.go @@ -597,6 +597,9 @@ func (ml *mockLockService) Close() error { func (ml *mockLockService) GetWaitingList(ctx context.Context, txnID []byte) (bool, []lock.WaitTxn, error) { return false, nil, nil } +func (ml *mockLockService) GetLockHolder(ctx context.Context, tableID uint64, row []byte, options lock.LockOptions) (lock.WaitTxn, bool, error) { + return lock.WaitTxn{}, false, nil +} func (ml *mockLockService) ForceRefreshLockTableBinds(targets []uint64, matcher func(bind lock.LockTable) bool) { } func (ml *mockLockService) GetLockTableBind(group uint32, tableID uint64) (lock.LockTable, error) { diff --git a/proto/lock.proto b/proto/lock.proto index 4e35d8aa5c678..53f9c887d7b39 100644 --- a/proto/lock.proto +++ b/proto/lock.proto @@ -206,6 +206,8 @@ message GetTxnLockRequest { message GetTxnLockResponse { int32 Value = 1; repeated WaitTxn WaitingList = 2 [(gogoproto.nullable) = false]; + WaitTxn Holder = 3 [(gogoproto.nullable) = false]; + bool Found = 4; } // GetWaitingListRequest get a waiting txn list on a specical txn request. CN -> CN @@ -397,4 +399,4 @@ message ResumeInvalidCNRequest { message ResumeInvalidCNResponse { -} \ No newline at end of file +} From 9dfbe1d6e673954c3e5690a7115946abd03b4bbd Mon Sep 17 00:00:00 2001 From: daviszhen Date: Wed, 17 Jun 2026 17:41:24 +0800 Subject: [PATCH 03/17] update pb --- pkg/pb/lock/lock.pb.go | 361 ++++++++++++++++++++++++++--------------- 1 file changed, 228 insertions(+), 133 deletions(-) diff --git a/pkg/pb/lock/lock.pb.go b/pkg/pb/lock/lock.pb.go index 2e30860a91c0b..136b6001128fd 100644 --- a/pkg/pb/lock/lock.pb.go +++ b/pkg/pb/lock/lock.pb.go @@ -1045,6 +1045,8 @@ func (m *GetTxnLockRequest) GetRow() []byte { type GetTxnLockResponse struct { Value int32 `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"` WaitingList []WaitTxn `protobuf:"bytes,2,rep,name=WaitingList,proto3" json:"WaitingList"` + Holder WaitTxn `protobuf:"bytes,3,opt,name=Holder,proto3" json:"Holder"` + Found bool `protobuf:"varint,4,opt,name=Found,proto3" json:"Found,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1097,6 +1099,20 @@ func (m *GetTxnLockResponse) GetWaitingList() []WaitTxn { return nil } +func (m *GetTxnLockResponse) GetHolder() WaitTxn { + if m != nil { + return m.Holder + } + return WaitTxn{} +} + +func (m *GetTxnLockResponse) GetFound() bool { + if m != nil { + return m.Found + } + return false +} + // GetWaitingListRequest get a waiting txn list on a specical txn request. CN -> CN type GetWaitingListRequest struct { Txn WaitTxn `protobuf:"bytes,1,opt,name=Txn,proto3" json:"Txn"` @@ -2881,139 +2897,140 @@ func init() { func init() { proto.RegisterFile("lock.proto", fileDescriptor_164ad2988c7acaf1) } var fileDescriptor_164ad2988c7acaf1 = []byte{ - // 2099 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0xcd, 0x72, 0x1b, 0xc7, - 0xf1, 0xe7, 0x02, 0x20, 0x3e, 0x1a, 0x00, 0xb9, 0x1c, 0x52, 0xd4, 0x92, 0x7f, 0x9b, 0xc2, 0x7f, - 0x43, 0x57, 0xc1, 0x74, 0x2c, 0x46, 0x54, 0x64, 0x3b, 0x72, 0xa2, 0x0a, 0x05, 0x8a, 0x34, 0x2d, - 0x51, 0x74, 0x06, 0x90, 0x52, 0x95, 0xdb, 0x12, 0x18, 0x91, 0x5b, 0x04, 0x77, 0x91, 0xc5, 0x82, - 0x04, 0x1f, 0x20, 0x55, 0xa9, 0xca, 0x3d, 0xe7, 0x1c, 0x7d, 0xc9, 0x7b, 0xf8, 0xe8, 0xaa, 0xdc, - 0xf3, 0xa1, 0xbc, 0x42, 0x1e, 0x20, 0xd5, 0x33, 0xb3, 0xd8, 0x99, 0xfd, 0x20, 0xec, 0xdc, 0x76, - 0xba, 0x7b, 0x7e, 0xdd, 0xd3, 0xdb, 0xf8, 0x4d, 0xf7, 0x02, 0x60, 0xe8, 0xf7, 0x2f, 0x1f, 0x8e, - 0x02, 0x3f, 0xf4, 0x49, 0x09, 0x9f, 0x37, 0x3f, 0x3d, 0x77, 0xc3, 0x8b, 0xc9, 0xd9, 0xc3, 0xbe, - 0x7f, 0xb5, 0x7b, 0xee, 0x9f, 0xfb, 0xbb, 0x5c, 0x79, 0x36, 0x79, 0xc7, 0x57, 0x7c, 0xc1, 0x9f, - 0xc4, 0xa6, 0xcd, 0xe5, 0xd0, 0xbd, 0x62, 0xe3, 0xd0, 0xb9, 0x1a, 0x09, 0x81, 0xfd, 0x9f, 0x02, - 0xd4, 0x5f, 0xf9, 0xfd, 0xcb, 0xd3, 0x51, 0xe8, 0xfa, 0xde, 0x98, 0x3c, 0x86, 0xfa, 0x51, 0xe0, - 0x78, 0x93, 0xa1, 0x13, 0xb8, 0xe1, 0xad, 0x65, 0xb4, 0x8c, 0xf6, 0xd2, 0xde, 0xca, 0x43, 0xee, - 0x57, 0x51, 0x50, 0xd5, 0x8a, 0xd8, 0x50, 0x3a, 0xf1, 0x07, 0xcc, 0x2a, 0x70, 0xeb, 0x25, 0x61, - 0x8d, 0xa8, 0x28, 0xa5, 0x5c, 0x47, 0xda, 0x50, 0xfe, 0xc6, 0x1f, 0xba, 0xfd, 0x5b, 0xab, 0xc8, - 0xad, 0x4c, 0x61, 0xf5, 0x5b, 0xc7, 0x0d, 0x85, 0x9c, 0x4a, 0x3d, 0xf9, 0x00, 0x6a, 0x87, 0x7e, - 0x70, 0xe3, 0x04, 0x83, 0x9e, 0x6f, 0x95, 0x5a, 0x46, 0xbb, 0x46, 0x63, 0x01, 0x69, 0xc3, 0x72, - 0xcf, 0x39, 0x1b, 0xb2, 0x03, 0xf6, 0xae, 0x73, 0xe1, 0x78, 0xe7, 0x6c, 0x60, 0x2d, 0xb6, 0x8c, - 0x76, 0x95, 0x26, 0xc5, 0x88, 0x43, 0x59, 0x18, 0xdc, 0xa2, 0x0b, 0xab, 0xdc, 0x32, 0xda, 0x45, - 0x1a, 0x0b, 0xc8, 0x1a, 0x2c, 0x1e, 0x05, 0xfe, 0x64, 0x64, 0x55, 0x5a, 0x46, 0xbb, 0x49, 0xc5, - 0x82, 0xec, 0x40, 0xb5, 0x7b, 0xe1, 0x04, 0x03, 0xd7, 0x3b, 0xb7, 0xaa, 0xea, 0x69, 0x22, 0x29, - 0x9d, 0xe9, 0xc9, 0x53, 0x80, 0xae, 0xe7, 0x8c, 0xba, 0x17, 0x7e, 0xd8, 0x1b, 0x5b, 0xb5, 0x96, - 0xd1, 0xae, 0xef, 0xad, 0x3d, 0x8c, 0x13, 0xdc, 0x8b, 0x9e, 0x9e, 0x97, 0xbe, 0xfb, 0xfb, 0x83, - 0x05, 0xaa, 0x58, 0xdb, 0x7f, 0x33, 0xa0, 0x86, 0x09, 0xe2, 0x31, 0x63, 0x2c, 0xfc, 0x81, 0xa7, - 0xbb, 0x44, 0xc5, 0x02, 0xe3, 0xef, 0xb2, 0xe0, 0xda, 0xed, 0xb3, 0xe3, 0x03, 0x9e, 0xda, 0x1a, - 0x8d, 0x05, 0xc4, 0x82, 0xca, 0x5b, 0x16, 0x8c, 0x5d, 0xdf, 0xe3, 0x09, 0x2d, 0xd1, 0x68, 0x89, - 0x68, 0x6f, 0x9d, 0xa1, 0x3b, 0xe0, 0xb9, 0xab, 0x52, 0xb1, 0x88, 0xcf, 0xbb, 0x98, 0x77, 0xde, - 0xf2, 0x9c, 0xf3, 0xb6, 0xa0, 0x7e, 0x1a, 0xb8, 0xe7, 0xae, 0x27, 0x62, 0xad, 0x70, 0xaf, 0xaa, - 0xc8, 0xfe, 0x13, 0x40, 0x85, 0xb2, 0xdf, 0x4f, 0xd8, 0x38, 0x14, 0xd9, 0xe7, 0x8f, 0xc7, 0x07, - 0xf2, 0x5c, 0xb1, 0x80, 0x3c, 0x56, 0x8e, 0xcf, 0xcf, 0x56, 0xdf, 0x5b, 0x8e, 0xcb, 0x86, 0x8b, - 0x65, 0xd6, 0x94, 0x34, 0x6d, 0x43, 0xf9, 0x84, 0x85, 0x17, 0xfe, 0x40, 0x96, 0x50, 0x43, 0xec, - 0x10, 0x32, 0x2a, 0x75, 0xe4, 0x13, 0x28, 0xe1, 0x16, 0x7e, 0xfa, 0x7a, 0x54, 0xba, 0x28, 0x91, - 0xde, 0x25, 0x2e, 0x37, 0x22, 0x8f, 0xa0, 0xfc, 0xc6, 0x43, 0x0b, 0x9e, 0x96, 0xfa, 0xde, 0xaa, - 0x30, 0x17, 0x32, 0x7d, 0x83, 0x34, 0x24, 0xbf, 0x02, 0x38, 0x62, 0x61, 0x6f, 0xea, 0x71, 0x2f, - 0x65, 0xbe, 0xed, 0xbe, 0xfc, 0x81, 0xcc, 0xe4, 0xfa, 0x56, 0x65, 0x03, 0x39, 0x86, 0xa5, 0x23, - 0x16, 0x62, 0x09, 0xba, 0xde, 0xf9, 0x2b, 0x77, 0x1c, 0xf2, 0x44, 0xd6, 0xf7, 0xfe, 0x6f, 0x06, - 0xa1, 0xe8, 0x74, 0x98, 0xc4, 0x46, 0xf2, 0x73, 0xa8, 0x1c, 0xb1, 0xf0, 0xb9, 0xeb, 0x0d, 0x78, - 0xad, 0x62, 0xf5, 0x45, 0x18, 0x28, 0xd4, 0x37, 0x47, 0xa6, 0x84, 0xc2, 0xca, 0x4b, 0xc6, 0x46, - 0x71, 0x9e, 0x71, 0xbf, 0xa8, 0xde, 0x2d, 0xb1, 0x3f, 0xa5, 0xd6, 0x91, 0xd2, 0xdb, 0xf1, 0x50, - 0x28, 0xa4, 0xec, 0xca, 0x0f, 0x19, 0xcf, 0x0b, 0xa8, 0x87, 0xd2, 0x75, 0x89, 0x43, 0xe9, 0x4a, - 0xf2, 0x0a, 0x96, 0x79, 0xc1, 0x3a, 0x21, 0x93, 0xc5, 0x6e, 0xd5, 0x39, 0xd6, 0x07, 0x02, 0x2b, - 0xa1, 0xd4, 0xc1, 0x92, 0x5b, 0x49, 0x07, 0x1a, 0x1d, 0xc7, 0xf3, 0xfc, 0xb0, 0xe3, 0x5f, 0x5d, - 0xb9, 0xa1, 0xd5, 0xe0, 0x50, 0x1b, 0x02, 0x4a, 0xd5, 0xe8, 0x38, 0xda, 0x26, 0x04, 0x39, 0x62, - 0xe1, 0x7e, 0x3f, 0x74, 0xaf, 0x59, 0x6f, 0xea, 0x59, 0x4d, 0x15, 0x44, 0xd5, 0x24, 0x40, 0x54, - 0x15, 0xa6, 0xbd, 0xcb, 0x42, 0x8a, 0x8c, 0x10, 0x84, 0xd1, 0xc9, 0x96, 0xd4, 0xb4, 0xa7, 0xd4, - 0x89, 0xb4, 0xa7, 0xf4, 0x88, 0xd9, 0x71, 0xbc, 0x04, 0xe6, 0xb2, 0x8a, 0x99, 0x52, 0x27, 0x30, - 0x53, 0x7a, 0xf2, 0x06, 0x08, 0x65, 0x57, 0x8e, 0xeb, 0xf5, 0xa6, 0xde, 0xb1, 0x17, 0x81, 0x9a, - 0x1c, 0xf4, 0x81, 0x00, 0x4d, 0xeb, 0x75, 0xd4, 0x0c, 0x00, 0xf2, 0x6b, 0xa8, 0x77, 0x2e, 0x58, - 0xff, 0xf2, 0x34, 0x18, 0x5d, 0x38, 0x9e, 0xb5, 0xc2, 0xf1, 0x2c, 0x19, 0x64, 0xac, 0xd0, 0x81, - 0xd4, 0x2d, 0x58, 0x18, 0x94, 0x8d, 0x27, 0x57, 0xec, 0xd8, 0xbb, 0xc6, 0xb7, 0xdc, 0x79, 0x6d, - 0x11, 0xb5, 0x30, 0x12, 0xca, 0x44, 0x61, 0x24, 0xb4, 0xc4, 0x81, 0xf5, 0xfd, 0x33, 0x3f, 0x08, - 0x45, 0xe5, 0x1d, 0x30, 0x67, 0x80, 0x20, 0xf8, 0x76, 0xd7, 0x38, 0xe8, 0x4f, 0x04, 0x68, 0xb6, - 0x8d, 0x8e, 0x9d, 0x03, 0x64, 0x7f, 0x0b, 0x50, 0xa5, 0x6c, 0x3c, 0xf2, 0xbd, 0x31, 0x9b, 0x43, - 0x87, 0x31, 0xb3, 0x15, 0xee, 0x60, 0xb6, 0x35, 0x58, 0x7c, 0x11, 0x04, 0x7e, 0xc0, 0xe9, 0xaf, - 0x41, 0xc5, 0x82, 0x7c, 0x0c, 0x95, 0xd7, 0xec, 0x86, 0xff, 0x8a, 0x4b, 0x99, 0x44, 0x4a, 0x23, - 0x3d, 0xf9, 0xa9, 0xa4, 0x46, 0xc1, 0x75, 0x44, 0xa5, 0x46, 0x11, 0xa6, 0xc6, 0x8d, 0x7b, 0x33, - 0x6e, 0x2c, 0xab, 0xec, 0x12, 0x71, 0xa3, 0xb6, 0x23, 0x22, 0xc7, 0x67, 0x1a, 0x39, 0x56, 0xd4, - 0xb7, 0xac, 0x92, 0xa3, 0xb6, 0x57, 0x65, 0xc7, 0xaf, 0x53, 0xec, 0x58, 0x55, 0xdf, 0x71, 0x92, - 0x1d, 0x35, 0x9c, 0x24, 0x3d, 0x3e, 0x89, 0xe9, 0x51, 0xd0, 0xdb, 0xbd, 0x04, 0x3d, 0x6a, 0xbb, - 0x67, 0xfc, 0xd8, 0xcd, 0xe2, 0x47, 0x50, 0xeb, 0x3f, 0x83, 0x1f, 0x35, 0xa8, 0x0c, 0x82, 0xfc, - 0x3a, 0x45, 0x90, 0x1a, 0xa9, 0x25, 0x09, 0x52, 0x3f, 0x57, 0x82, 0x21, 0x4f, 0xd2, 0x0c, 0x29, - 0x68, 0xed, 0xc3, 0x1c, 0x86, 0xd4, 0xd0, 0x52, 0x14, 0x79, 0x90, 0xa0, 0x48, 0xc1, 0x6e, 0x9b, - 0x59, 0x14, 0xa9, 0x01, 0xe9, 0x1c, 0x79, 0x90, 0xe0, 0xc8, 0x25, 0x15, 0x45, 0xe7, 0x48, 0x1d, - 0x45, 0x23, 0xc9, 0x6e, 0x16, 0x49, 0x2e, 0xab, 0xb9, 0xcf, 0x20, 0x49, 0x3d, 0xf7, 0x69, 0x96, - 0xec, 0x66, 0xb1, 0xa4, 0x46, 0x68, 0x19, 0x2c, 0xa9, 0x83, 0xa6, 0x69, 0xf2, 0x6d, 0x26, 0x4d, - 0x0a, 0x5a, 0x6b, 0xe5, 0xd3, 0xa4, 0x06, 0x9b, 0xc5, 0x93, 0xfb, 0x3a, 0x4f, 0x12, 0xed, 0xbe, - 0x52, 0x79, 0x52, 0x43, 0xd2, 0x88, 0xf2, 0x24, 0x4d, 0x94, 0xab, 0x6a, 0x7d, 0xa4, 0x88, 0x52, - 0xaf, 0x8f, 0x24, 0x53, 0x9e, 0xcd, 0x61, 0xca, 0xed, 0xbb, 0x99, 0x52, 0x03, 0xcf, 0xa3, 0xca, - 0x3f, 0x1a, 0x62, 0x0a, 0x89, 0x9a, 0x47, 0x6c, 0x88, 0xa7, 0x9e, 0x64, 0xca, 0x06, 0x15, 0x8b, - 0x39, 0x0d, 0x31, 0x81, 0x12, 0xf5, 0x6f, 0xc6, 0x56, 0xb1, 0x55, 0x6c, 0x37, 0x28, 0x7f, 0x26, - 0x8f, 0xa0, 0x22, 0x07, 0x9b, 0x74, 0x3b, 0x28, 0x15, 0xd1, 0xcf, 0x5f, 0x2e, 0xed, 0xa7, 0xd0, - 0x50, 0x7f, 0x83, 0x64, 0x07, 0xca, 0x98, 0x91, 0x61, 0xc8, 0x63, 0xa9, 0x47, 0xd4, 0x2c, 0x64, - 0x11, 0xfb, 0x89, 0x95, 0xfd, 0x25, 0xac, 0xa4, 0x5a, 0xc0, 0x9c, 0xb3, 0x98, 0x50, 0xa4, 0xfe, - 0x0d, 0x3f, 0x45, 0x83, 0xe2, 0xa3, 0xed, 0x00, 0x49, 0x53, 0xa4, 0x6c, 0xe6, 0x27, 0x62, 0x34, - 0x58, 0xa4, 0x62, 0x41, 0x9e, 0x40, 0x5d, 0xe5, 0xc8, 0x42, 0xab, 0xd8, 0xae, 0xef, 0x35, 0xe3, - 0x89, 0xaa, 0x37, 0xf5, 0xa2, 0xca, 0x50, 0xec, 0xec, 0x67, 0x70, 0x2f, 0xb3, 0xbf, 0x24, 0x1f, - 0x41, 0x11, 0x5f, 0xa8, 0x38, 0x61, 0x26, 0x0e, 0xea, 0xed, 0x53, 0x58, 0xcf, 0x66, 0xe0, 0x64, - 0x40, 0xc6, 0x0f, 0x0c, 0xa8, 0x0f, 0x15, 0xa9, 0xcd, 0x7f, 0xe5, 0x9d, 0x80, 0x39, 0x21, 0x1b, - 0x9c, 0x7a, 0xd1, 0x2b, 0x9f, 0x09, 0xc8, 0x36, 0x34, 0x71, 0x3b, 0x0b, 0xf6, 0x07, 0x83, 0x80, - 0x8d, 0xc7, 0xfc, 0x62, 0xac, 0x51, 0x5d, 0x68, 0xff, 0xd9, 0x80, 0xa6, 0xd6, 0xd0, 0xe7, 0xf8, - 0xfa, 0x0c, 0xaa, 0x82, 0xcc, 0x7a, 0x5d, 0x39, 0x92, 0xdc, 0x35, 0xcd, 0xcd, 0x6c, 0xc9, 0xe7, - 0x50, 0x3b, 0x99, 0x84, 0x8e, 0x28, 0xb3, 0x22, 0x3f, 0xb9, 0x1c, 0x23, 0x5e, 0x4c, 0xc3, 0xc0, - 0x89, 0x74, 0xd1, 0x3c, 0x33, 0xb3, 0xb5, 0x4d, 0x58, 0xd2, 0x2f, 0x53, 0xfb, 0x5b, 0x83, 0xdf, - 0x7f, 0x4a, 0xcf, 0xad, 0x17, 0xbd, 0x91, 0x2c, 0xfa, 0xd9, 0xe4, 0x58, 0x50, 0x27, 0xc7, 0xd9, - 0xac, 0x57, 0xcc, 0x9b, 0xf5, 0x4a, 0x3f, 0x6e, 0xd6, 0x5b, 0x4c, 0xcf, 0x7a, 0x87, 0xb0, 0x9c, - 0xb8, 0x48, 0xff, 0xa7, 0xa1, 0xce, 0xfe, 0xab, 0x01, 0x56, 0xde, 0xc0, 0x31, 0xe7, 0xf0, 0xdb, - 0x50, 0xee, 0x86, 0x4e, 0x38, 0x19, 0xeb, 0x5d, 0x93, 0x90, 0x51, 0xa9, 0x23, 0xeb, 0x50, 0xe6, - 0xef, 0x37, 0x62, 0x06, 0xb9, 0x22, 0x4f, 0x00, 0x66, 0x3e, 0x91, 0x1e, 0x8a, 0xf9, 0xe1, 0x2a, - 0x86, 0xf6, 0x6f, 0x60, 0x23, 0xf7, 0xfe, 0x27, 0x4b, 0x50, 0x38, 0x7d, 0xc9, 0x03, 0xad, 0xd2, - 0xc2, 0xe9, 0xcb, 0x1f, 0x16, 0xa1, 0xfd, 0x05, 0x58, 0x79, 0xbd, 0xff, 0xdd, 0x19, 0xb0, 0x3f, - 0x81, 0x8d, 0xdc, 0x0b, 0x31, 0x19, 0x0c, 0xba, 0xc9, 0x1b, 0x07, 0xe6, 0xbb, 0xc9, 0xbd, 0x22, - 0x53, 0x6e, 0x7e, 0x01, 0x1b, 0xb9, 0x03, 0xc2, 0x1c, 0x3f, 0x4f, 0x61, 0x33, 0xff, 0xd2, 0x14, - 0x2d, 0xb4, 0xd4, 0x4a, 0x3a, 0x8c, 0x05, 0xf6, 0x13, 0xb8, 0x97, 0x39, 0x66, 0xce, 0x71, 0xd9, - 0x86, 0xf5, 0xec, 0xe6, 0x2b, 0x75, 0xae, 0xcf, 0x60, 0x3d, 0x7b, 0xf6, 0x9c, 0xe3, 0xe1, 0x63, - 0xb8, 0x9f, 0xd3, 0x91, 0xa5, 0x5c, 0x1c, 0xc2, 0x87, 0x77, 0x0e, 0x1c, 0xc8, 0xd3, 0xe1, 0x1c, - 0x9e, 0x0e, 0xa7, 0x9e, 0xfd, 0x33, 0xd8, 0xba, 0xfb, 0x3a, 0x4e, 0x79, 0xa6, 0xb0, 0x9a, 0x31, - 0x0d, 0x93, 0x2f, 0xa1, 0x29, 0x9a, 0x0a, 0xbc, 0x96, 0x62, 0x62, 0x97, 0x3f, 0x93, 0x99, 0x4a, - 0xfa, 0xd6, 0x6d, 0xed, 0x5f, 0xc2, 0x5a, 0x56, 0xfb, 0x88, 0xac, 0x2d, 0x24, 0x78, 0x0d, 0x88, - 0x77, 0x89, 0xbf, 0x4b, 0x5d, 0x68, 0x3f, 0x86, 0xd5, 0x8c, 0xd1, 0x7a, 0x4e, 0xae, 0x9f, 0xc1, - 0x5a, 0x56, 0xaf, 0x19, 0x7f, 0x12, 0x33, 0xd4, 0x4f, 0x62, 0xa6, 0xb8, 0xf5, 0x0a, 0xdc, 0x3d, - 0xbf, 0xe0, 0x0e, 0x80, 0xa4, 0x87, 0xd1, 0x39, 0x2c, 0x34, 0x43, 0x31, 0x22, 0x94, 0x4f, 0x61, - 0x35, 0xa3, 0x55, 0x43, 0x22, 0x92, 0x5d, 0x9d, 0x88, 0x42, 0xae, 0xec, 0xcf, 0xa1, 0x36, 0x4b, - 0x1c, 0xb1, 0xa0, 0x12, 0x35, 0x93, 0xc2, 0x53, 0xb4, 0xcc, 0x88, 0xf6, 0x0f, 0xc5, 0xa8, 0x37, - 0x21, 0x8f, 0xa0, 0x8a, 0xc5, 0xcb, 0xaf, 0x49, 0xe3, 0x2e, 0xe6, 0x9d, 0x99, 0x21, 0xc5, 0x7f, - 0xe5, 0x8c, 0x3b, 0xbe, 0xf7, 0x6e, 0xe8, 0xf6, 0x43, 0x1e, 0x7f, 0x95, 0xaa, 0x22, 0x7c, 0x51, - 0x5f, 0x39, 0xe3, 0x6f, 0x02, 0x76, 0x2d, 0x47, 0x83, 0x22, 0xb7, 0xd1, 0x85, 0xe4, 0x0b, 0xa8, - 0xcd, 0xee, 0x46, 0xd9, 0x65, 0xdd, 0x75, 0x6f, 0xc6, 0xc6, 0x3f, 0xe2, 0x53, 0x6e, 0x0b, 0xea, - 0x51, 0x54, 0x2f, 0xd9, 0x2d, 0x9f, 0x47, 0x1b, 0x54, 0x15, 0xa9, 0x16, 0x98, 0xa5, 0x8a, 0x6e, - 0x81, 0x99, 0xdd, 0x02, 0xc0, 0xa8, 0x45, 0x6f, 0xc0, 0xc7, 0xca, 0x06, 0x55, 0x24, 0x98, 0x79, - 0xf1, 0x24, 0xbe, 0xe5, 0x36, 0x69, 0xb4, 0xc4, 0x9d, 0xaf, 0xd9, 0x0d, 0x26, 0x6e, 0x7f, 0x20, - 0x46, 0xc1, 0x2a, 0x55, 0x24, 0x76, 0x17, 0x9a, 0xda, 0x4d, 0x8f, 0xaf, 0xea, 0x92, 0xdd, 0xca, - 0xee, 0x02, 0x1f, 0xb1, 0x39, 0x1d, 0x5f, 0xba, 0x23, 0x99, 0x65, 0xfe, 0x8c, 0x65, 0x15, 0xb0, - 0xd1, 0xd0, 0xe9, 0xb3, 0x9e, 0x2f, 0x47, 0xfa, 0x58, 0x80, 0x74, 0x93, 0xfd, 0x45, 0x63, 0xce, - 0x4f, 0x60, 0x03, 0xee, 0xe7, 0x34, 0xf8, 0x3b, 0xff, 0xaf, 0x7d, 0xdb, 0x27, 0x15, 0xde, 0x82, - 0x9a, 0x0b, 0xa4, 0x06, 0x8b, 0x14, 0xf3, 0x6c, 0x1a, 0x3b, 0x1f, 0x89, 0x3a, 0xe2, 0x5f, 0xec, - 0x9b, 0x50, 0x7b, 0x31, 0xed, 0x0f, 0x27, 0x63, 0xf7, 0x9a, 0x99, 0x0b, 0x04, 0xa0, 0x8c, 0xed, - 0x01, 0x1b, 0x98, 0xc6, 0xce, 0x36, 0x40, 0xfc, 0xe1, 0x9e, 0x54, 0xa1, 0x84, 0x2b, 0x73, 0x81, - 0x34, 0xa0, 0x7a, 0xe8, 0x8c, 0xc3, 0x43, 0xc7, 0x1d, 0x9a, 0xc6, 0xce, 0x83, 0xb8, 0xe1, 0x40, - 0x9b, 0xd7, 0xbe, 0xc7, 0x84, 0xb7, 0xe7, 0xb7, 0xe8, 0xd8, 0xd8, 0xf9, 0x47, 0x21, 0xfa, 0xee, - 0x81, 0x7a, 0x74, 0x2c, 0xfc, 0x88, 0xae, 0xc8, 0x34, 0xc8, 0x92, 0xfa, 0x39, 0xc1, 0x2c, 0x10, - 0x92, 0xfc, 0x3c, 0x60, 0x16, 0x51, 0xa6, 0x33, 0xb8, 0x59, 0x22, 0xf5, 0xd9, 0xe8, 0x6f, 0x2e, - 0x92, 0x7b, 0x19, 0x03, 0xbd, 0x59, 0x26, 0xcb, 0x50, 0x97, 0xff, 0x2a, 0xf0, 0x4d, 0x15, 0xb2, - 0x02, 0x4d, 0x29, 0x90, 0xfe, 0xab, 0x64, 0x35, 0x35, 0x6a, 0x9b, 0x35, 0x62, 0xea, 0x03, 0xb3, - 0x09, 0x28, 0x51, 0x69, 0xc7, 0xac, 0xa3, 0xcf, 0xd4, 0xc5, 0x6c, 0x36, 0xc8, 0x7a, 0xd6, 0xd4, - 0x68, 0x36, 0xd1, 0x3c, 0x75, 0xc1, 0x9a, 0x4b, 0x18, 0xa2, 0x42, 0x24, 0xe6, 0x32, 0xc6, 0x93, - 0x78, 0xb9, 0xa6, 0x49, 0x36, 0xf3, 0x06, 0x34, 0x73, 0x65, 0x87, 0x45, 0x0d, 0x88, 0x88, 0x88, - 0x03, 0xe3, 0x71, 0x5f, 0x78, 0x98, 0x09, 0x73, 0x01, 0x23, 0x52, 0xc4, 0x32, 0xb3, 0xa6, 0xa1, - 0x98, 0xbf, 0xe1, 0xc9, 0xef, 0x4e, 0xfa, 0x7d, 0xb3, 0xa0, 0x88, 0xe3, 0x78, 0xcd, 0xe2, 0xf3, - 0xce, 0xf7, 0xff, 0xda, 0x32, 0xbe, 0x7b, 0xbf, 0x65, 0x7c, 0xff, 0x7e, 0xcb, 0xf8, 0xe7, 0xfb, - 0xad, 0x85, 0xbf, 0xfc, 0x7b, 0xcb, 0xf8, 0x9d, 0xfa, 0xdf, 0xd4, 0x95, 0x13, 0x06, 0xee, 0xd4, - 0xe7, 0x0d, 0x64, 0xb4, 0xf0, 0xd8, 0xee, 0xe8, 0xf2, 0x7c, 0x77, 0x74, 0xb6, 0x8b, 0x01, 0x9f, - 0x95, 0xf9, 0x3f, 0x52, 0x8f, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xd0, 0x34, 0x3d, 0xff, 0xe5, - 0x1a, 0x00, 0x00, + // 2124 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0xcd, 0x72, 0xdb, 0xc8, + 0x11, 0x16, 0x48, 0x8a, 0x3f, 0x4d, 0x52, 0x82, 0x46, 0xb2, 0x0c, 0x29, 0xbb, 0x32, 0x83, 0x68, + 0xab, 0xb8, 0x72, 0xd6, 0x8a, 0xe5, 0x78, 0x77, 0xe3, 0x4d, 0x5c, 0x91, 0x29, 0x4b, 0xd6, 0xda, + 0xb2, 0x36, 0x43, 0xda, 0xa9, 0xca, 0x0d, 0x22, 0xc7, 0x12, 0x4a, 0x14, 0xc0, 0x80, 0xa0, 0x7e, + 0x1e, 0x20, 0x55, 0xa9, 0xca, 0x3d, 0xe7, 0x1c, 0x72, 0xd8, 0x4b, 0xde, 0x63, 0x8f, 0x5b, 0x95, + 0x7b, 0x7e, 0x9c, 0x57, 0xc8, 0x03, 0xa4, 0x7a, 0x66, 0x40, 0xcc, 0xe0, 0x47, 0x5c, 0xe7, 0x86, + 0xe9, 0xee, 0xf9, 0x7a, 0xa6, 0xd1, 0xf8, 0xa6, 0x7b, 0x00, 0x30, 0xf4, 0xfb, 0xe7, 0x0f, 0x46, + 0x81, 0x1f, 0xfa, 0xa4, 0x84, 0xcf, 0xeb, 0x9f, 0x9d, 0xba, 0xe1, 0xd9, 0xe4, 0xe4, 0x41, 0xdf, + 0xbf, 0xd8, 0x3e, 0xf5, 0x4f, 0xfd, 0x6d, 0xae, 0x3c, 0x99, 0xbc, 0xe3, 0x23, 0x3e, 0xe0, 0x4f, + 0x62, 0xd2, 0xfa, 0x62, 0xe8, 0x5e, 0xb0, 0x71, 0xe8, 0x5c, 0x8c, 0x84, 0xc0, 0xfe, 0x6f, 0x01, + 0xea, 0xaf, 0xfc, 0xfe, 0xf9, 0xf1, 0x28, 0x74, 0x7d, 0x6f, 0x4c, 0x1e, 0x41, 0xfd, 0x20, 0x70, + 0xbc, 0xc9, 0xd0, 0x09, 0xdc, 0xf0, 0xc6, 0x32, 0x5a, 0x46, 0x7b, 0x61, 0x67, 0xe9, 0x01, 0xf7, + 0xab, 0x28, 0xa8, 0x6a, 0x45, 0x6c, 0x28, 0x1d, 0xf9, 0x03, 0x66, 0x15, 0xb8, 0xf5, 0x82, 0xb0, + 0x46, 0x54, 0x94, 0x52, 0xae, 0x23, 0x6d, 0x28, 0x7f, 0xe3, 0x0f, 0xdd, 0xfe, 0x8d, 0x55, 0xe4, + 0x56, 0xa6, 0xb0, 0xfa, 0xad, 0xe3, 0x86, 0x42, 0x4e, 0xa5, 0x9e, 0x7c, 0x04, 0xb5, 0x7d, 0x3f, + 0xb8, 0x72, 0x82, 0x41, 0xcf, 0xb7, 0x4a, 0x2d, 0xa3, 0x5d, 0xa3, 0xb1, 0x80, 0xb4, 0x61, 0xb1, + 0xe7, 0x9c, 0x0c, 0xd9, 0x1e, 0x7b, 0xd7, 0x39, 0x73, 0xbc, 0x53, 0x36, 0xb0, 0xe6, 0x5b, 0x46, + 0xbb, 0x4a, 0x93, 0x62, 0xc4, 0xa1, 0x2c, 0x0c, 0x6e, 0xd0, 0x85, 0x55, 0x6e, 0x19, 0xed, 0x22, + 0x8d, 0x05, 0x64, 0x05, 0xe6, 0x0f, 0x02, 0x7f, 0x32, 0xb2, 0x2a, 0x2d, 0xa3, 0xdd, 0xa4, 0x62, + 0x40, 0xb6, 0xa0, 0xda, 0x3d, 0x73, 0x82, 0x81, 0xeb, 0x9d, 0x5a, 0x55, 0x75, 0x37, 0x91, 0x94, + 0x4e, 0xf5, 0xe4, 0x09, 0x40, 0xd7, 0x73, 0x46, 0xdd, 0x33, 0x3f, 0xec, 0x8d, 0xad, 0x5a, 0xcb, + 0x68, 0xd7, 0x77, 0x56, 0x1e, 0xc4, 0x01, 0xee, 0x45, 0x4f, 0xcf, 0x4a, 0xdf, 0xfd, 0xe3, 0xde, + 0x1c, 0x55, 0xac, 0xed, 0xbf, 0x1b, 0x50, 0xc3, 0x00, 0xf1, 0x35, 0xe3, 0x5a, 0xf8, 0x03, 0x0f, + 0x77, 0x89, 0x8a, 0x01, 0xae, 0xbf, 0xcb, 0x82, 0x4b, 0xb7, 0xcf, 0x0e, 0xf7, 0x78, 0x68, 0x6b, + 0x34, 0x16, 0x10, 0x0b, 0x2a, 0x6f, 0x59, 0x30, 0x76, 0x7d, 0x8f, 0x07, 0xb4, 0x44, 0xa3, 0x21, + 0xa2, 0xbd, 0x75, 0x86, 0xee, 0x80, 0xc7, 0xae, 0x4a, 0xc5, 0x20, 0xde, 0xef, 0x7c, 0xde, 0x7e, + 0xcb, 0x33, 0xf6, 0xdb, 0x82, 0xfa, 0x71, 0xe0, 0x9e, 0xba, 0x9e, 0x58, 0x6b, 0x85, 0x7b, 0x55, + 0x45, 0xf6, 0x9f, 0x00, 0x2a, 0x94, 0xfd, 0x7e, 0xc2, 0xc6, 0xa1, 0x88, 0x3e, 0x7f, 0x3c, 0xdc, + 0x93, 0xfb, 0x8a, 0x05, 0xe4, 0x91, 0xb2, 0x7d, 0xbe, 0xb7, 0xfa, 0xce, 0x62, 0x9c, 0x36, 0x5c, + 0x2c, 0xa3, 0xa6, 0x84, 0x69, 0x13, 0xca, 0x47, 0x2c, 0x3c, 0xf3, 0x07, 0x32, 0x85, 0x1a, 0x62, + 0x86, 0x90, 0x51, 0xa9, 0x23, 0xf7, 0xa1, 0x84, 0x53, 0xf8, 0xee, 0xeb, 0x51, 0xea, 0xa2, 0x44, + 0x7a, 0x97, 0xb8, 0xdc, 0x88, 0x3c, 0x84, 0xf2, 0x1b, 0x0f, 0x2d, 0x78, 0x58, 0xea, 0x3b, 0xcb, + 0xc2, 0x5c, 0xc8, 0xf4, 0x09, 0xd2, 0x90, 0xfc, 0x0a, 0xe0, 0x80, 0x85, 0xbd, 0x6b, 0x8f, 0x7b, + 0x29, 0xf3, 0x69, 0x77, 0xe5, 0x07, 0x32, 0x95, 0xeb, 0x53, 0x95, 0x09, 0xe4, 0x10, 0x16, 0x0e, + 0x58, 0x88, 0x29, 0xe8, 0x7a, 0xa7, 0xaf, 0xdc, 0x71, 0xc8, 0x03, 0x59, 0xdf, 0xf9, 0xd1, 0x14, + 0x42, 0xd1, 0xe9, 0x30, 0x89, 0x89, 0xe4, 0xe7, 0x50, 0x39, 0x60, 0xe1, 0x33, 0xd7, 0x1b, 0xf0, + 0x5c, 0xc5, 0xec, 0x8b, 0x30, 0x50, 0xa8, 0x4f, 0x8e, 0x4c, 0x09, 0x85, 0xa5, 0x97, 0x8c, 0x8d, + 0xe2, 0x38, 0xe3, 0x7c, 0x91, 0xbd, 0x1b, 0x62, 0x7e, 0x4a, 0xad, 0x23, 0xa5, 0xa7, 0xe3, 0xa6, + 0x50, 0x48, 0xd9, 0x85, 0x1f, 0x32, 0x1e, 0x17, 0x50, 0x37, 0xa5, 0xeb, 0x12, 0x9b, 0xd2, 0x95, + 0xe4, 0x15, 0x2c, 0xf2, 0x84, 0x75, 0x42, 0x26, 0x93, 0xdd, 0xaa, 0x73, 0xac, 0x8f, 0x04, 0x56, + 0x42, 0xa9, 0x83, 0x25, 0xa7, 0x92, 0x0e, 0x34, 0x3a, 0x8e, 0xe7, 0xf9, 0x61, 0xc7, 0xbf, 0xb8, + 0x70, 0x43, 0xab, 0xc1, 0xa1, 0xd6, 0x04, 0x94, 0xaa, 0xd1, 0x71, 0xb4, 0x49, 0x08, 0x72, 0xc0, + 0xc2, 0xdd, 0x7e, 0xe8, 0x5e, 0xb2, 0xde, 0xb5, 0x67, 0x35, 0x55, 0x10, 0x55, 0x93, 0x00, 0x51, + 0x55, 0x18, 0xf6, 0x2e, 0x0b, 0x29, 0x32, 0x42, 0x10, 0x46, 0x3b, 0x5b, 0x50, 0xc3, 0x9e, 0x52, + 0x27, 0xc2, 0x9e, 0xd2, 0x23, 0x66, 0xc7, 0xf1, 0x12, 0x98, 0x8b, 0x2a, 0x66, 0x4a, 0x9d, 0xc0, + 0x4c, 0xe9, 0xc9, 0x1b, 0x20, 0x94, 0x5d, 0x38, 0xae, 0xd7, 0xbb, 0xf6, 0x0e, 0xbd, 0x08, 0xd4, + 0xe4, 0xa0, 0xf7, 0x04, 0x68, 0x5a, 0xaf, 0xa3, 0x66, 0x00, 0x90, 0x5f, 0x43, 0xbd, 0x73, 0xc6, + 0xfa, 0xe7, 0xc7, 0xc1, 0xe8, 0xcc, 0xf1, 0xac, 0x25, 0x8e, 0x67, 0xc9, 0x45, 0xc6, 0x0a, 0x1d, + 0x48, 0x9d, 0x82, 0x89, 0x41, 0xd9, 0x78, 0x72, 0xc1, 0x0e, 0xbd, 0x4b, 0x7c, 0xcb, 0x9d, 0xd7, + 0x16, 0x51, 0x13, 0x23, 0xa1, 0x4c, 0x24, 0x46, 0x42, 0x4b, 0x1c, 0x58, 0xdd, 0x3d, 0xf1, 0x83, + 0x50, 0x64, 0xde, 0x1e, 0x73, 0x06, 0x08, 0x82, 0x6f, 0x77, 0x85, 0x83, 0xfe, 0x44, 0x80, 0x66, + 0xdb, 0xe8, 0xd8, 0x39, 0x40, 0xf6, 0xb7, 0x00, 0x55, 0xca, 0xc6, 0x23, 0xdf, 0x1b, 0xb3, 0x19, + 0x74, 0x18, 0x33, 0x5b, 0xe1, 0x16, 0x66, 0x5b, 0x81, 0xf9, 0xe7, 0x41, 0xe0, 0x07, 0x9c, 0xfe, + 0x1a, 0x54, 0x0c, 0xc8, 0xa7, 0x50, 0x79, 0xcd, 0xae, 0xf8, 0x57, 0x5c, 0xca, 0x24, 0x52, 0x1a, + 0xe9, 0xc9, 0x4f, 0x25, 0x35, 0x0a, 0xae, 0x23, 0x2a, 0x35, 0x8a, 0x65, 0x6a, 0xdc, 0xb8, 0x33, + 0xe5, 0xc6, 0xb2, 0xca, 0x2e, 0x11, 0x37, 0x6a, 0x33, 0x22, 0x72, 0x7c, 0xaa, 0x91, 0x63, 0x45, + 0x7d, 0xcb, 0x2a, 0x39, 0x6a, 0x73, 0x55, 0x76, 0xfc, 0x3a, 0xc5, 0x8e, 0x55, 0xf5, 0x1d, 0x27, + 0xd9, 0x51, 0xc3, 0x49, 0xd2, 0xe3, 0xe3, 0x98, 0x1e, 0x05, 0xbd, 0xdd, 0x49, 0xd0, 0xa3, 0x36, + 0x7b, 0xca, 0x8f, 0xdd, 0x2c, 0x7e, 0x04, 0x35, 0xff, 0x33, 0xf8, 0x51, 0x83, 0xca, 0x20, 0xc8, + 0xaf, 0x53, 0x04, 0xa9, 0x91, 0x5a, 0x92, 0x20, 0xf5, 0x7d, 0x25, 0x18, 0xf2, 0x28, 0xcd, 0x90, + 0x82, 0xd6, 0x3e, 0xce, 0x61, 0x48, 0x0d, 0x2d, 0x45, 0x91, 0x7b, 0x09, 0x8a, 0x14, 0xec, 0xb6, + 0x9e, 0x45, 0x91, 0x1a, 0x90, 0xce, 0x91, 0x7b, 0x09, 0x8e, 0x5c, 0x50, 0x51, 0x74, 0x8e, 0xd4, + 0x51, 0x34, 0x92, 0xec, 0x66, 0x91, 0xe4, 0xa2, 0x1a, 0xfb, 0x0c, 0x92, 0xd4, 0x63, 0x9f, 0x66, + 0xc9, 0x6e, 0x16, 0x4b, 0x6a, 0x84, 0x96, 0xc1, 0x92, 0x3a, 0x68, 0x9a, 0x26, 0xdf, 0x66, 0xd2, + 0xa4, 0xa0, 0xb5, 0x56, 0x3e, 0x4d, 0x6a, 0xb0, 0x59, 0x3c, 0xb9, 0xab, 0xf3, 0x24, 0xd1, 0xce, + 0x2b, 0x95, 0x27, 0x35, 0x24, 0x8d, 0x28, 0x8f, 0xd2, 0x44, 0xb9, 0xac, 0xe6, 0x47, 0x8a, 0x28, + 0xf5, 0xfc, 0x48, 0x32, 0xe5, 0xc9, 0x0c, 0xa6, 0xdc, 0xbc, 0x9d, 0x29, 0x35, 0xf0, 0x3c, 0xaa, + 0xfc, 0xa3, 0x21, 0xba, 0x90, 0xa8, 0x78, 0xc4, 0x82, 0xf8, 0xda, 0x93, 0x4c, 0xd9, 0xa0, 0x62, + 0x30, 0xa3, 0x20, 0x26, 0x50, 0xa2, 0xfe, 0xd5, 0xd8, 0x2a, 0xb6, 0x8a, 0xed, 0x06, 0xe5, 0xcf, + 0xe4, 0x21, 0x54, 0x64, 0x63, 0x93, 0x2e, 0x07, 0xa5, 0x22, 0xfa, 0xfc, 0xe5, 0xd0, 0x7e, 0x02, + 0x0d, 0xf5, 0x1b, 0x24, 0x5b, 0x50, 0xc6, 0x88, 0x0c, 0x43, 0xbe, 0x96, 0x7a, 0x44, 0xcd, 0x42, + 0x16, 0xb1, 0x9f, 0x18, 0xd9, 0x5f, 0xc1, 0x52, 0xaa, 0x04, 0xcc, 0xd9, 0x8b, 0x09, 0x45, 0xea, + 0x5f, 0xf1, 0x5d, 0x34, 0x28, 0x3e, 0xda, 0x7f, 0x35, 0x80, 0xa4, 0x39, 0x52, 0x56, 0xf3, 0x13, + 0xd1, 0x1b, 0xcc, 0x53, 0x31, 0x20, 0x8f, 0xa1, 0xae, 0x92, 0x64, 0xa1, 0x55, 0x6c, 0xd7, 0x77, + 0x9a, 0x71, 0x4b, 0xd5, 0xbb, 0xf6, 0xa2, 0xd4, 0x50, 0x29, 0xf1, 0x3e, 0x94, 0x5f, 0xf8, 0xc3, + 0x01, 0x13, 0x47, 0x48, 0xce, 0x0c, 0x69, 0x82, 0x9e, 0xf7, 0xfd, 0x89, 0x37, 0xed, 0x23, 0xf8, + 0xc0, 0x7e, 0x0a, 0x77, 0x32, 0x6b, 0x54, 0xf2, 0x09, 0x14, 0x31, 0x29, 0x8c, 0x7c, 0x60, 0xd4, + 0xdb, 0xc7, 0xb0, 0x9a, 0xcd, 0xe2, 0xc9, 0x3d, 0x19, 0x3f, 0x6c, 0x4f, 0x76, 0x1f, 0x2a, 0x52, + 0x9b, 0x9f, 0x36, 0x9d, 0x80, 0x39, 0x21, 0x1b, 0x1c, 0x7b, 0x51, 0xda, 0x4c, 0x05, 0x64, 0x13, + 0x9a, 0x38, 0x9d, 0x05, 0xbb, 0x83, 0x41, 0xc0, 0xc6, 0x63, 0x1e, 0x99, 0x1a, 0xd5, 0x85, 0xf6, + 0x9f, 0x0d, 0x68, 0x6a, 0x4d, 0x41, 0x8e, 0xaf, 0xcf, 0xa1, 0x2a, 0x08, 0xb1, 0xd7, 0x95, 0x6d, + 0xcd, 0x6d, 0x1d, 0xe1, 0xd4, 0x96, 0x7c, 0x01, 0xb5, 0xa3, 0x49, 0xe8, 0x88, 0x54, 0x2d, 0xf2, + 0x9d, 0xcb, 0x56, 0xe4, 0xf9, 0x75, 0x18, 0x38, 0x91, 0x2e, 0xea, 0x89, 0xa6, 0xb6, 0xb6, 0x09, + 0x0b, 0xfa, 0x81, 0x6c, 0x7f, 0x6b, 0xf0, 0x33, 0x54, 0xa9, 0xdb, 0xf5, 0x0f, 0xc7, 0x48, 0x7e, + 0x38, 0xd3, 0xee, 0xb3, 0xa0, 0x76, 0x9f, 0xd3, 0x7e, 0xb1, 0x98, 0xd7, 0x2f, 0x96, 0x3e, 0xac, + 0x5f, 0x9c, 0x4f, 0xf7, 0x8b, 0xfb, 0xb0, 0x98, 0x38, 0x8c, 0xff, 0xaf, 0xc6, 0xd0, 0xfe, 0x9b, + 0x01, 0x56, 0x5e, 0xd3, 0x32, 0x63, 0xf3, 0x9b, 0x50, 0xee, 0x86, 0x4e, 0x38, 0x19, 0xeb, 0x95, + 0x97, 0x90, 0x51, 0xa9, 0x23, 0xab, 0x50, 0xe6, 0xef, 0x37, 0x62, 0x17, 0x39, 0x22, 0x8f, 0x01, + 0xa6, 0x3e, 0x91, 0x62, 0x8a, 0xf9, 0xcb, 0x55, 0x0c, 0xed, 0xdf, 0xc0, 0x5a, 0x6e, 0x0d, 0x41, + 0x16, 0xa0, 0x70, 0xfc, 0x92, 0x2f, 0xb4, 0x4a, 0x0b, 0xc7, 0x2f, 0x7f, 0xd8, 0x0a, 0xed, 0x2f, + 0xc1, 0xca, 0xeb, 0x1f, 0x6e, 0x8f, 0x80, 0x7d, 0x1f, 0xd6, 0x72, 0x0f, 0xd5, 0xe4, 0x62, 0xd0, + 0x4d, 0x5e, 0x4b, 0x31, 0xdb, 0x4d, 0xee, 0x31, 0x9b, 0x72, 0xf3, 0x0b, 0x58, 0xcb, 0x6d, 0x32, + 0x66, 0xf8, 0x79, 0x02, 0xeb, 0xf9, 0x07, 0xaf, 0x28, 0xc3, 0xa5, 0x56, 0x32, 0x6a, 0x2c, 0xb0, + 0x1f, 0xc3, 0x9d, 0xcc, 0x56, 0x75, 0x86, 0xcb, 0x36, 0xac, 0x66, 0x17, 0x70, 0xa9, 0x7d, 0x7d, + 0x0e, 0xab, 0xd9, 0xfd, 0xeb, 0x0c, 0x0f, 0x9f, 0xc2, 0xdd, 0x9c, 0xaa, 0x2e, 0xe5, 0x62, 0x1f, + 0x3e, 0xbe, 0xb5, 0x69, 0x41, 0x9e, 0x0e, 0x67, 0xf0, 0x74, 0x78, 0xed, 0xd9, 0x3f, 0x83, 0x8d, + 0xdb, 0x8f, 0xf4, 0x94, 0x67, 0x0a, 0xcb, 0x19, 0x1d, 0x35, 0xf9, 0x0a, 0x9a, 0xa2, 0x30, 0xc1, + 0x93, 0x2d, 0x26, 0x76, 0xf9, 0x99, 0x4c, 0x55, 0xd2, 0xb7, 0x6e, 0x6b, 0xff, 0x12, 0x56, 0xb2, + 0x4a, 0x50, 0x64, 0x6d, 0x21, 0xc1, 0x63, 0x40, 0xbc, 0x4b, 0xfc, 0x2e, 0x75, 0xa1, 0xfd, 0x08, + 0x96, 0x33, 0xda, 0xf3, 0x19, 0xb1, 0x7e, 0x0a, 0x2b, 0x59, 0xf5, 0x6a, 0x7c, 0xad, 0x66, 0xa8, + 0xd7, 0x6a, 0xa6, 0x38, 0xf5, 0x0a, 0xdc, 0x3d, 0x3f, 0xe0, 0xf6, 0x80, 0xa4, 0x1b, 0xda, 0x19, + 0x2c, 0x34, 0x45, 0x31, 0x22, 0x94, 0xcf, 0x60, 0x39, 0xa3, 0xdc, 0x43, 0x22, 0x92, 0x95, 0xa1, + 0x58, 0x85, 0x1c, 0xd9, 0x5f, 0x40, 0x6d, 0x1a, 0x38, 0x62, 0x41, 0x25, 0x2a, 0x48, 0x85, 0xa7, + 0x68, 0x98, 0xb1, 0xda, 0x3f, 0x14, 0xa3, 0xfa, 0x86, 0x3c, 0x84, 0x2a, 0x26, 0x2f, 0x3f, 0x26, + 0x8d, 0xdb, 0x98, 0x77, 0x6a, 0x86, 0x14, 0xff, 0xc2, 0x19, 0x77, 0x7c, 0xef, 0xdd, 0xd0, 0xed, + 0x87, 0x7c, 0xfd, 0x55, 0xaa, 0x8a, 0xf0, 0x45, 0xbd, 0x70, 0xc6, 0xdf, 0x04, 0xec, 0x52, 0xb6, + 0x17, 0x45, 0x6e, 0xa3, 0x0b, 0xc9, 0x97, 0x50, 0x9b, 0x9e, 0x8d, 0xb2, 0x52, 0xbb, 0xed, 0xdc, + 0x8c, 0x8d, 0x3f, 0xe0, 0x3a, 0xb8, 0x05, 0xf5, 0x68, 0x55, 0x2f, 0xd9, 0x0d, 0xef, 0x69, 0x1b, + 0x54, 0x15, 0xa9, 0x16, 0x18, 0xa5, 0x8a, 0x6e, 0x81, 0x91, 0xdd, 0x00, 0xc0, 0x55, 0x8b, 0xda, + 0x80, 0xb7, 0xa6, 0x0d, 0xaa, 0x48, 0x30, 0xf2, 0xe2, 0x49, 0xdc, 0x07, 0x37, 0x69, 0x34, 0xc4, + 0x99, 0xaf, 0xd9, 0x15, 0x06, 0x6e, 0x77, 0x20, 0xda, 0xc9, 0x2a, 0x55, 0x24, 0x76, 0x17, 0x9a, + 0xda, 0x49, 0x8f, 0xaf, 0xea, 0x9c, 0xdd, 0xc8, 0xea, 0x02, 0x1f, 0xb1, 0xc0, 0x1d, 0x9f, 0xbb, + 0x23, 0x19, 0x65, 0xfe, 0x8c, 0x69, 0x15, 0xb0, 0xd1, 0xd0, 0xe9, 0xb3, 0x9e, 0x2f, 0xaf, 0x05, + 0x62, 0x01, 0xd2, 0x4d, 0xf6, 0xad, 0xc8, 0x8c, 0x4f, 0x60, 0x0d, 0xee, 0xe6, 0x34, 0x09, 0x5b, + 0x3f, 0xd6, 0xfe, 0x0f, 0x90, 0x0a, 0x2f, 0x63, 0xcd, 0x39, 0x52, 0x83, 0x79, 0x8a, 0x71, 0x36, + 0x8d, 0xad, 0x4f, 0x44, 0x1e, 0xf1, 0x5b, 0xff, 0x26, 0xd4, 0x9e, 0x5f, 0xf7, 0x87, 0x93, 0xb1, + 0x7b, 0xc9, 0xcc, 0x39, 0x02, 0x50, 0xc6, 0xf2, 0x80, 0x0d, 0x4c, 0x63, 0x6b, 0x13, 0x20, 0xbe, + 0xfc, 0x27, 0x55, 0x28, 0xe1, 0xc8, 0x9c, 0x23, 0x0d, 0xa8, 0xee, 0x3b, 0xe3, 0x70, 0xdf, 0x71, + 0x87, 0xa6, 0xb1, 0x75, 0x2f, 0x2e, 0x38, 0xd0, 0xe6, 0xb5, 0xef, 0x31, 0xe1, 0xed, 0xd9, 0x0d, + 0x3a, 0x36, 0xb6, 0xfe, 0x59, 0x88, 0xee, 0x4e, 0x50, 0x8f, 0x8e, 0x85, 0x1f, 0x51, 0x15, 0x99, + 0x06, 0x59, 0x50, 0xaf, 0x24, 0xcc, 0x02, 0x21, 0xc9, 0x2b, 0x06, 0xb3, 0x88, 0x32, 0x9d, 0xc1, + 0xcd, 0x12, 0xa9, 0x4f, 0xaf, 0x0f, 0xcc, 0x79, 0x72, 0x27, 0xe3, 0x52, 0xc0, 0x2c, 0x93, 0x45, + 0xa8, 0xcb, 0x3f, 0x13, 0x7c, 0x52, 0x85, 0x2c, 0x41, 0x53, 0x0a, 0xa4, 0xff, 0x2a, 0x59, 0x4e, + 0xb5, 0xeb, 0x66, 0x8d, 0x98, 0x7a, 0xd3, 0x6d, 0x02, 0x4a, 0x54, 0xda, 0x31, 0xeb, 0xe8, 0x33, + 0x75, 0x30, 0x9b, 0x0d, 0xb2, 0x9a, 0xd5, 0x79, 0x9a, 0x4d, 0x34, 0x4f, 0x1d, 0xb0, 0xe6, 0x02, + 0x2e, 0x51, 0x21, 0x12, 0x73, 0x11, 0xd7, 0x93, 0x78, 0xb9, 0xa6, 0x49, 0xd6, 0xf3, 0x9a, 0x3c, + 0x73, 0x69, 0x8b, 0x45, 0x05, 0x88, 0x58, 0x11, 0x07, 0xc6, 0xed, 0x3e, 0xf7, 0x30, 0x12, 0xe6, + 0x1c, 0xae, 0x48, 0x11, 0xcb, 0xc8, 0x9a, 0x86, 0x62, 0xfe, 0x86, 0x07, 0xbf, 0x3b, 0xe9, 0xf7, + 0xcd, 0x82, 0x22, 0x8e, 0xd7, 0x6b, 0x16, 0x9f, 0x75, 0xbe, 0xff, 0xf7, 0x86, 0xf1, 0xdd, 0xfb, + 0x0d, 0xe3, 0xfb, 0xf7, 0x1b, 0xc6, 0xbf, 0xde, 0x6f, 0xcc, 0xfd, 0xe5, 0x3f, 0x1b, 0xc6, 0xef, + 0xd4, 0xff, 0x5b, 0x17, 0x4e, 0x18, 0xb8, 0xd7, 0x3e, 0x2f, 0x20, 0xa3, 0x81, 0xc7, 0xb6, 0x47, + 0xe7, 0xa7, 0xdb, 0xa3, 0x93, 0x6d, 0x5c, 0xf0, 0x49, 0x99, 0xff, 0xd5, 0x7a, 0xf4, 0xbf, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x25, 0xdb, 0xc2, 0x32, 0x29, 0x1b, 0x00, 0x00, } func (m *LockOptions) Marshal() (dAtA []byte, err error) { @@ -3772,6 +3789,26 @@ func (m *GetTxnLockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.Found { + i-- + if m.Found { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + { + size, err := m.Holder.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a if len(m.WaitingList) > 0 { for iNdEx := len(m.WaitingList) - 1; iNdEx >= 0; iNdEx-- { { @@ -5398,6 +5435,11 @@ func (m *GetTxnLockResponse) ProtoSize() (n int) { n += 1 + l + sovLock(uint64(l)) } } + l = m.Holder.ProtoSize() + n += 1 + l + sovLock(uint64(l)) + if m.Found { + n += 2 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -8253,6 +8295,59 @@ func (m *GetTxnLockResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Holder", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Holder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Found", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Found = bool(v != 0) default: iNdEx = preIndex skippy, err := skipLock(dAtA[iNdEx:]) From 1eeb08006ba817ddf81fcdd31d2425986e6287b5 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Wed, 17 Jun 2026 18:25:37 +0800 Subject: [PATCH 04/17] add bvt --- .../cases/function/user_lock.result | 70 +++++++++++++++++++ test/distributed/cases/function/user_lock.sql | 49 +++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 test/distributed/cases/function/user_lock.result create mode 100644 test/distributed/cases/function/user_lock.sql diff --git a/test/distributed/cases/function/user_lock.result b/test/distributed/cases/function/user_lock.result new file mode 100644 index 0000000000000..d640b2b43bedd --- /dev/null +++ b/test/distributed/cases/function/user_lock.result @@ -0,0 +1,70 @@ +drop database if exists user_lock_bvt_db; +create database user_lock_bvt_db; +use user_lock_bvt_db; +create table user_lock_bvt_holder (conn_id bigint unsigned); +select is_free_lock('user_lock_bvt_lock'); +➤ is_free_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +1 +select is_used_lock('user_lock_bvt_lock') is null; +➤ is_used_lock(user_lock_bvt_lock) is null[-7,1,0] 𝄀 +1 +select release_lock('user_lock_bvt_lock') is null; +➤ release_lock(user_lock_bvt_lock) is null[-7,1,0] 𝄀 +1 +use user_lock_bvt_db; +insert into user_lock_bvt_holder values (connection_id()); +select get_lock('user_lock_bvt_lock', 0); +➤ get_lock(user_lock_bvt_lock, 0)[-5,64,0] 𝄀 +1 +select get_lock('user_lock_bvt_lock', 0); +➤ get_lock(user_lock_bvt_lock, 0)[-5,64,0] 𝄀 +1 +select is_free_lock('user_lock_bvt_lock'); +➤ is_free_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +0 +select get_lock('user_lock_bvt_lock', 0); +➤ get_lock(user_lock_bvt_lock, 0)[-5,64,0] 𝄀 +0 +select is_used_lock('user_lock_bvt_lock') = (select conn_id from user_lock_bvt_holder); +➤ is_used_lock(user_lock_bvt_lock) = (select conn_id from user_lock_bvt_holder)[-7,1,0] 𝄀 +1 +select release_lock('user_lock_bvt_lock'); +➤ release_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +0 +use user_lock_bvt_db; +select is_used_lock('user_lock_bvt_lock') = (select conn_id from user_lock_bvt_holder); +➤ is_used_lock(user_lock_bvt_lock) = (select conn_id from user_lock_bvt_holder)[-7,1,0] 𝄀 +1 +select release_all_locks(); +➤ release_all_locks()[-5,64,0] 𝄀 +0 +use user_lock_bvt_db; +select is_free_lock('user_lock_bvt_lock'); +➤ is_free_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +0 +select release_lock('user_lock_bvt_lock'); +➤ release_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +1 +select is_free_lock('user_lock_bvt_lock'); +➤ is_free_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +0 +select release_all_locks(); +➤ release_all_locks()[-5,64,0] 𝄀 +1 +select is_free_lock('user_lock_bvt_lock'); +➤ is_free_lock(user_lock_bvt_lock)[-5,64,0] 𝄀 +1 +select is_used_lock('user_lock_bvt_lock') is null; +➤ is_used_lock(user_lock_bvt_lock) is null[-7,1,0] 𝄀 +1 +select get_lock('user_lock_bvt_lock', 0); +➤ get_lock(user_lock_bvt_lock, 0)[-5,64,0] 𝄀 +1 +select release_all_locks(); +➤ release_all_locks()[-5,64,0] 𝄀 +1 +select release_all_locks(); +➤ release_all_locks()[-5,64,0] 𝄀 +0 +drop table user_lock_bvt_holder; +drop database user_lock_bvt_db; diff --git a/test/distributed/cases/function/user_lock.sql b/test/distributed/cases/function/user_lock.sql new file mode 100644 index 0000000000000..8f6bee0efe43e --- /dev/null +++ b/test/distributed/cases/function/user_lock.sql @@ -0,0 +1,49 @@ +-- @suite +-- @case +-- @desc:test mysql-compatible user-level lock functions +-- @label:bvt + +drop database if exists user_lock_bvt_db; +create database user_lock_bvt_db; +use user_lock_bvt_db; + +create table user_lock_bvt_holder (conn_id bigint unsigned); + +select is_free_lock('user_lock_bvt_lock'); +select is_used_lock('user_lock_bvt_lock') is null; +select release_lock('user_lock_bvt_lock') is null; + +-- @session:id=1{ +use user_lock_bvt_db; +insert into user_lock_bvt_holder values (connection_id()); +select get_lock('user_lock_bvt_lock', 0); +select get_lock('user_lock_bvt_lock', 0); +-- @session} + +select is_free_lock('user_lock_bvt_lock'); +select get_lock('user_lock_bvt_lock', 0); +select is_used_lock('user_lock_bvt_lock') = (select conn_id from user_lock_bvt_holder); +select release_lock('user_lock_bvt_lock'); + +-- @session:id=2{ +use user_lock_bvt_db; +select is_used_lock('user_lock_bvt_lock') = (select conn_id from user_lock_bvt_holder); +select release_all_locks(); +-- @session} + +-- @session:id=1{ +use user_lock_bvt_db; +select is_free_lock('user_lock_bvt_lock'); +select release_lock('user_lock_bvt_lock'); +select is_free_lock('user_lock_bvt_lock'); +select release_all_locks(); +-- @session} + +select is_free_lock('user_lock_bvt_lock'); +select is_used_lock('user_lock_bvt_lock') is null; +select get_lock('user_lock_bvt_lock', 0); +select release_all_locks(); +select release_all_locks(); + +drop table user_lock_bvt_holder; +drop database user_lock_bvt_db; From 649df2c41bc7036762ab317518c9678d5cd7cb9c Mon Sep 17 00:00:00 2001 From: daviszhen Date: Wed, 17 Jun 2026 18:35:34 +0800 Subject: [PATCH 05/17] update --- pkg/sql/plan/function/func_unary_test.go | 61 ++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index acf92de1cffb4..a46026779f031 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7345,6 +7345,52 @@ func TestUserLevelLockFunctions(t *testing.T) { }) } +func TestUserLevelLockFunctionNullInputs(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc := newUserLevelLockTestProcess(t, services[0], "acc") + + cases := []struct { + name string + inputs []FunctionTestInput + expect FunctionTestResult + fn fEvalFn + }{ + { + name: "release lock returns null for null name", + inputs: []FunctionTestInput{ + NewFunctionTestInput(types.T_varchar.ToType(), []string{""}, []bool{true}), + }, + expect: NewFunctionTestResult(types.T_int64.ToType(), false, []int64{0}, []bool{true}), + fn: ReleaseLock, + }, + { + name: "is free lock returns null for null name", + inputs: []FunctionTestInput{ + NewFunctionTestInput(types.T_varchar.ToType(), []string{""}, []bool{true}), + }, + expect: NewFunctionTestResult(types.T_int64.ToType(), false, []int64{0}, []bool{true}), + fn: IsFreeLock, + }, + { + name: "is used lock returns null for null name", + inputs: []FunctionTestInput{ + NewFunctionTestInput(types.T_varchar.ToType(), []string{""}, []bool{true}), + }, + expect: NewFunctionTestResult(types.T_uint64.ToType(), false, []uint64{0}, []bool{true}), + fn: IsUsedLock, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + fcTC := NewFunctionTestCase(proc, tc.inputs, tc.expect, tc.fn) + s, info := fcTC.Run() + require.True(t, s, info) + }) + } + }) +} + func TestUserLevelLockContention(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7493,6 +7539,21 @@ func TestIsUsedLockReturnsHolderConnectionID(t *testing.T) { }) } +func TestIsUsedLockReturnsNullForMalformedHolderTxnID(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc := newUserLevelLockTestProcess(t, services[0], "acc") + state := services[0].(*userLevelLockTestService).state + state.Lock() + state.locks[string(userLevelLockRow(proc, "bad_holder"))] = "not-a-user-level-lock-txn" + state.Unlock() + + holder, isNull, err := isUserLevelLockUsed("bad_holder", proc) + require.NoError(t, err) + require.True(t, isNull) + require.Equal(t, uint64(0), holder) + }) +} + func TestReleaseAllUserLevelLocksReturnsReleasedCount(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") From 22e893d27795d8b91f8d00a9f5737df0a155d30f Mon Sep 17 00:00:00 2001 From: daviszhen Date: Wed, 17 Jun 2026 18:49:42 +0800 Subject: [PATCH 06/17] update --- pkg/lockservice/lock_table_remote.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index 1e43062fca1bc..d3d8623894e45 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -302,6 +302,8 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err return Lock{}, false, err } if !resp.GetTxnLock.Found { + // Keep the same semantics as localLockTable.getLock: no callback + // when the row lock does not exist on the lock table owner. return Lock{}, false, nil } @@ -312,6 +314,9 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err waiters: wq, value: byte(resp.GetTxnLock.Value), } + // Use the holder reported by the lock table owner. The txn argument is + // only the lookup context and may be empty, for example when IS_USED_LOCK + // probes the current holder. if len(resp.GetTxnLock.Holder.TxnID) > 0 { lock.holders.add(resp.GetTxnLock.Holder) } From 30beae4039fbe3b0076ca0db402d1b2216e45cf1 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 11:55:55 +0800 Subject: [PATCH 07/17] update --- pkg/sql/plan/function/func_unary.go | 13 ++++++++----- pkg/sql/plan/function/func_unary_test.go | 21 ++++++++++++++++++++- pkg/sql/plan/function/function_id.go | 6 +++--- pkg/sql/plan/function/function_id_test.go | 6 +++--- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 9f30a7a1d9a03..0134532877f26 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -7033,15 +7033,18 @@ func normalizeUserLevelLockName(name string) (string, error) { } func userLevelLockTxnID(owner string, connID uint64, name string) []byte { - return []byte(fmt.Sprintf("mo-user-level-lock\x00%s\x00%d\x00%s", owner, connID, name)) + return []byte(fmt.Sprintf("mo-user-level-lock\x00%s\x00%s\x00%d", owner, name, connID)) } func userLevelLockConnectionIDFromTxnID(txnID []byte) (uint64, bool) { - parts := strings.SplitN(string(txnID), "\x00", 4) - if len(parts) != 4 || parts[0] != "mo-user-level-lock" { + parts := strings.Split(string(txnID), "\x00") + if len(parts) < 3 || len(parts) > 4 || parts[0] != "mo-user-level-lock" { return 0, false } - connID, err := strconv.ParseUint(parts[2], 10, 64) + if len(parts) == 3 { + return 0, false + } + connID, err := strconv.ParseUint(parts[3], 10, 64) if err != nil { return 0, false } @@ -7307,12 +7310,12 @@ func releaseAllUserLevelLocks(proc *process.Process) int64 { connID := userLevelLockConnectionID(proc) var released int64 for _, name := range userLevelLocksForOwner(owner) { + released++ for { count, held := untrackUserLevelLock(owner, name) if !held { break } - released++ if count == 0 { _ = proc.GetLockService().Unlock(context.Background(), userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}) break diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index a46026779f031..8dec53be4dbfd 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7273,6 +7273,10 @@ func runUserLevelLockTest(t *testing.T, fn func([]lockservice.LockService)) { resetUserLevelLocksForTest(t) } +func userLevelLockTxnIDOld(owner, name string) []byte { + return []byte("mo-user-level-lock\x00" + owner + "\x00" + name) +} + func TestUserLevelLockFunctions(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7539,6 +7543,21 @@ func TestIsUsedLockReturnsHolderConnectionID(t *testing.T) { }) } +func TestIsUsedLockReturnsNullForLegacyHolderTxnID(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc := newUserLevelLockTestProcess(t, services[0], "acc") + state := services[0].(*userLevelLockTestService).state + state.Lock() + state.locks[string(userLevelLockRow(proc, "legacy_holder"))] = string(userLevelLockTxnIDOld(userLevelLockOwner(proc), "legacy_holder")) + state.Unlock() + + holder, isNull, err := isUserLevelLockUsed("legacy_holder", proc) + require.NoError(t, err) + require.True(t, isNull) + require.Equal(t, uint64(0), holder) + }) +} + func TestIsUsedLockReturnsNullForMalformedHolderTxnID(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7570,7 +7589,7 @@ func TestReleaseAllUserLevelLocksReturnsReleasedCount(t *testing.T) { require.Equal(t, int64(1), v) released := releaseAllUserLevelLocks(proc1) - require.Equal(t, int64(3), released) + require.Equal(t, int64(2), released) require.Equal(t, int64(0), releaseAllUserLevelLocks(proc1)) v, err = getUserLevelLock("release_all_a", 0, proc2) diff --git a/pkg/sql/plan/function/function_id.go b/pkg/sql/plan/function/function_id.go index db239d6d0ac9a..7182739cae87f 100644 --- a/pkg/sql/plan/function/function_id.go +++ b/pkg/sql/plan/function/function_id.go @@ -730,9 +730,9 @@ const ( GET_LOCK = 518 RELEASE_LOCK = 519 IS_FREE_LOCK = 520 - IS_USED_LOCK = 521 - RELEASE_ALL_LOCKS = 522 - NAME_CONST = 523 + NAME_CONST = 521 + IS_USED_LOCK = 522 + RELEASE_ALL_LOCKS = 523 // FUNCTION_END_NUMBER is not a function, just a flag to record the max number of function. // TODO: every one should put the new function id in front of this one if you want to make a new function. diff --git a/pkg/sql/plan/function/function_id_test.go b/pkg/sql/plan/function/function_id_test.go index ba09b0f8f0589..b712f382dacaa 100644 --- a/pkg/sql/plan/function/function_id_test.go +++ b/pkg/sql/plan/function/function_id_test.go @@ -574,9 +574,9 @@ var predefinedFunids = map[int]int{ GET_LOCK: 518, RELEASE_LOCK: 519, IS_FREE_LOCK: 520, - IS_USED_LOCK: 521, - RELEASE_ALL_LOCKS: 522, - NAME_CONST: 523, + NAME_CONST: 521, + IS_USED_LOCK: 522, + RELEASE_ALL_LOCKS: 523, // FUNCTION_END_NUMBER is not a function, just a flag to record the max number of function. // TODO: every one should put the new function id in front of this one if you want to make a new function. FUNCTION_END_NUMBER: 524, From 9a057e5ae5426b537219139584b232d2167f8a9a Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 12:44:18 +0800 Subject: [PATCH 08/17] update --- pkg/lockservice/lock_table_local.go | 20 ++ pkg/lockservice/lock_table_proxy.go | 4 + pkg/lockservice/lock_table_remote.go | 52 ++++- pkg/lockservice/rpc.go | 1 + pkg/lockservice/service_observability.go | 11 +- pkg/lockservice/service_remote.go | 23 ++ pkg/lockservice/types.go | 2 + pkg/pb/lock/lock.pb.go | 263 ++++++++++++----------- pkg/sql/plan/function/func_unary.go | 14 +- pkg/sql/plan/function/func_unary_test.go | 38 ++++ proto/lock.proto | 2 + 11 files changed, 278 insertions(+), 152 deletions(-) diff --git a/pkg/lockservice/lock_table_local.go b/pkg/lockservice/lock_table_local.go index dd537acced514..20d3cffd790d9 100644 --- a/pkg/lockservice/lock_table_local.go +++ b/pkg/lockservice/lock_table_local.go @@ -354,6 +354,26 @@ func (l *localLockTable) getLock( } } +func (l *localLockTable) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { + l.mu.RLock() + defer l.mu.RUnlock() + if l.mu.closed { + return pb.WaitTxn{}, false, nil + } + lock, ok := l.mu.store.Get(key) + if !ok { + return pb.WaitTxn{}, false, nil + } + var holder pb.WaitTxn + var found bool + lock.IterHolders(func(v pb.WaitTxn) bool { + holder = v + found = true + return false + }) + return holder, found, nil +} + func (l *localLockTable) getBind() pb.LockTable { return l.bind } diff --git a/pkg/lockservice/lock_table_proxy.go b/pkg/lockservice/lock_table_proxy.go index a694bcb918df0..e7b13aa2e8361 100644 --- a/pkg/lockservice/lock_table_proxy.go +++ b/pkg/lockservice/lock_table_proxy.go @@ -202,6 +202,10 @@ func (lp *localLockTableProxy) getLock( lp.remote.getLock(key, txn, fn) } +func (lp *localLockTableProxy) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { + return lp.remote.getLockHolder(key) +} + func (lp *localLockTableProxy) getBind() pb.LockTable { return lp.remote.getBind() } diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index d3d8623894e45..b991b4d351c9c 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -242,6 +242,21 @@ func (l *remoteLockTable) getLock( } } +func (l *remoteLockTable) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { + backoff := remoteRetryInitialBackoff + for { + holder, ok, err := l.doGetLockHolder(key) + if err == nil { + return holder, ok, nil + } + if err = l.handleError(err, false); err == nil { + return pb.WaitTxn{}, false, nil + } + waitRemoteRetryBackoff(backoff) + backoff = nextRemoteRetryBackoff(backoff) + } +} + func waitRemoteRetryBackoff(backoff time.Duration) { if backoff > 0 { time.Sleep(backoff) @@ -301,11 +316,6 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err if err := l.maybeHandleBindChanged(resp); err != nil { return Lock{}, false, err } - if !resp.GetTxnLock.Found { - // Keep the same semantics as localLockTable.getLock: no callback - // when the row lock does not exist on the lock table owner. - return Lock{}, false, nil - } wq := newWaiterQueue() wq.init(l.logger) @@ -314,12 +324,7 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err waiters: wq, value: byte(resp.GetTxnLock.Value), } - // Use the holder reported by the lock table owner. The txn argument is - // only the lookup context and may be empty, for example when IS_USED_LOCK - // probes the current holder. - if len(resp.GetTxnLock.Holder.TxnID) > 0 { - lock.holders.add(resp.GetTxnLock.Holder) - } + lock.holders.add(txn) for _, v := range resp.GetTxnLock.WaitingList { w := acquireWaiter(v, "doGetLock", l.logger) lock.addWaiter(l.logger, w) @@ -330,6 +335,31 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err return Lock{}, false, moerr.AttachCause(ctx, err) } +func (l *remoteLockTable) doGetLockHolder(key []byte) (pb.WaitTxn, bool, error) { + ctx, cancel := context.WithTimeoutCause(context.Background(), defaultRPCTimeout, moerr.CauseDoGetLock) + defer cancel() + + req := acquireRequest() + defer releaseRequest(req) + + req.Method = pb.Method_GetLockHolder + req.LockTable = l.bind + req.GetTxnLock.Row = key + + resp, err := l.client.Send(ctx, req) + if err == nil { + defer releaseResponse(resp) + if err := l.maybeHandleBindChanged(resp); err != nil { + return pb.WaitTxn{}, false, err + } + if !resp.GetTxnLock.Found { + return pb.WaitTxn{}, false, nil + } + return resp.GetTxnLock.Holder, true, nil + } + return pb.WaitTxn{}, false, moerr.AttachCause(ctx, err) +} + func (l *remoteLockTable) getBind() pb.LockTable { return l.bind } diff --git a/pkg/lockservice/rpc.go b/pkg/lockservice/rpc.go index 0b50f96446b3e..fdad2ce3dd50d 100644 --- a/pkg/lockservice/rpc.go +++ b/pkg/lockservice/rpc.go @@ -170,6 +170,7 @@ func (c *client) AsyncSend(ctx context.Context, request *pb.Request) (*morpc.Fut case pb.Method_Lock, pb.Method_Unlock, pb.Method_GetTxnLock, + pb.Method_GetLockHolder, pb.Method_KeepRemoteLock: sid = getUUIDFromServiceIdentifier(request.LockTable.ServiceID) c.cluster.GetCNServiceWithoutWorkingState( diff --git a/pkg/lockservice/service_observability.go b/pkg/lockservice/service_observability.go index 1cc24ed948f9e..b02b03343e66f 100644 --- a/pkg/lockservice/service_observability.go +++ b/pkg/lockservice/service_observability.go @@ -59,16 +59,7 @@ func (s *service) GetLockHolder( if err != nil { return pb.WaitTxn{}, false, err } - var holder pb.WaitTxn - var found bool - l.getLock(row, pb.WaitTxn{}, func(lock Lock) { - lock.IterHolders(func(v pb.WaitTxn) bool { - holder = v - found = true - return false - }) - }) - return holder, found, nil + return l.getLockHolder(row) } func (s *service) ForceRefreshLockTableBinds( diff --git a/pkg/lockservice/service_remote.go b/pkg/lockservice/service_remote.go index 1ee378730bda3..c249f3bafd1af 100644 --- a/pkg/lockservice/service_remote.go +++ b/pkg/lockservice/service_remote.go @@ -35,6 +35,7 @@ var methodVersions = map[pb.Method]int64{ pb.Method_ForwardLock: defines.MORPCVersion1, pb.Method_Unlock: defines.MORPCVersion1, pb.Method_GetTxnLock: defines.MORPCVersion1, + pb.Method_GetLockHolder: defines.MORPCVersion2, pb.Method_GetWaitingList: defines.MORPCVersion1, pb.Method_KeepRemoteLock: defines.MORPCVersion1, pb.Method_GetBind: defines.MORPCVersion1, @@ -166,6 +167,8 @@ func (s *service) initRemoteHandler() { s.handleRemoteUnlock) s.remote.server.RegisterMethodHandler(pb.Method_GetTxnLock, s.handleRemoteGetLock) + s.remote.server.RegisterMethodHandler(pb.Method_GetLockHolder, + s.handleRemoteGetLockHolder) s.remote.server.RegisterMethodHandler(pb.Method_GetWaitingList, s.handleRemoteGetWaitingList) s.remote.server.RegisterMethodHandler(pb.Method_KeepRemoteLock, @@ -432,6 +435,26 @@ func (s *service) handleRemoteGetLock( writeResponse(s.logger, cancel, resp, err, cs) } +func (s *service) handleRemoteGetLockHolder( + ctx context.Context, + cancel context.CancelFunc, + req *pb.Request, + resp *pb.Response, + cs morpc.ClientSession) { + l, err := s.getLocalLockTable(req, resp) + if err != nil || l == nil { + writeResponse(s.logger, cancel, resp, err, cs) + return + } + + holder, found, err := l.getLockHolder(req.GetTxnLock.Row) + if err == nil && found { + resp.GetTxnLock.Holder = holder + resp.GetTxnLock.Found = true + } + writeResponse(s.logger, cancel, resp, err, cs) +} + func (s *service) handleRemoteGetWaitingList( ctx context.Context, cancel context.CancelFunc, diff --git a/pkg/lockservice/types.go b/pkg/lockservice/types.go index 260ee9dbe33ca..8b2de393d8b29 100644 --- a/pkg/lockservice/types.go +++ b/pkg/lockservice/types.go @@ -158,6 +158,8 @@ type lockTable interface { unlock(txn *activeTxn, ls *cowSlice, commitTS timestamp.Timestamp, mutations ...pb.ExtraMutation) // getLock get a lock getLock(key []byte, txn pb.WaitTxn, fn func(Lock)) + // getLockHolder returns the current holder if the lock is actively held. + getLockHolder(key []byte) (pb.WaitTxn, bool, error) // getBind returns lock table binding getBind() pb.LockTable // close close the locktable diff --git a/pkg/pb/lock/lock.pb.go b/pkg/pb/lock/lock.pb.go index 136b6001128fd..ac426dad71d3c 100644 --- a/pkg/pb/lock/lock.pb.go +++ b/pkg/pb/lock/lock.pb.go @@ -170,6 +170,8 @@ const ( Method_ResumeInvalidCN Method = 16 // AbortRemoteDeadlockTxn abort remote txn for deadlock Method_AbortRemoteDeadlockTxn Method = 17 + // GetLockHolder get current holder on a special lock + Method_GetLockHolder Method = 18 ) var Method_name = map[int32]string{ @@ -191,6 +193,7 @@ var Method_name = map[int32]string{ 15: "CheckOrphan", 16: "ResumeInvalidCN", 17: "AbortRemoteDeadlockTxn", + 18: "GetLockHolder", } var Method_value = map[string]int32{ @@ -212,6 +215,7 @@ var Method_value = map[string]int32{ "CheckOrphan": 15, "ResumeInvalidCN": 16, "AbortRemoteDeadlockTxn": 17, + "GetLockHolder": 18, } func (x Method) String() string { @@ -2897,140 +2901,141 @@ func init() { func init() { proto.RegisterFile("lock.proto", fileDescriptor_164ad2988c7acaf1) } var fileDescriptor_164ad2988c7acaf1 = []byte{ - // 2124 bytes of a gzipped FileDescriptorProto + // 2135 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0xcd, 0x72, 0xdb, 0xc8, 0x11, 0x16, 0x48, 0x8a, 0x3f, 0x4d, 0x52, 0x82, 0x46, 0xb2, 0x0c, 0x29, 0xbb, 0x32, 0x83, 0x68, 0xab, 0xb8, 0x72, 0xd6, 0x8a, 0xe5, 0x78, 0x77, 0xe3, 0x4d, 0x5c, 0x91, 0x29, 0x4b, 0xd6, 0xda, 0xb2, 0x36, 0x43, 0xda, 0xa9, 0xca, 0x0d, 0x22, 0xc7, 0x12, 0x4a, 0x14, 0xc0, 0x80, 0xa0, 0x7e, 0x1e, 0x20, 0x55, 0xa9, 0xca, 0x3d, 0xe7, 0x1c, 0x72, 0xd8, 0x4b, 0xde, 0x63, 0x8f, 0x5b, 0x95, - 0x7b, 0x7e, 0x9c, 0x57, 0xc8, 0x03, 0xa4, 0x7a, 0x66, 0x40, 0xcc, 0xe0, 0x47, 0x5c, 0xe7, 0x86, - 0xe9, 0xee, 0xf9, 0x7a, 0xa6, 0xd1, 0xf8, 0xa6, 0x7b, 0x00, 0x30, 0xf4, 0xfb, 0xe7, 0x0f, 0x46, - 0x81, 0x1f, 0xfa, 0xa4, 0x84, 0xcf, 0xeb, 0x9f, 0x9d, 0xba, 0xe1, 0xd9, 0xe4, 0xe4, 0x41, 0xdf, - 0xbf, 0xd8, 0x3e, 0xf5, 0x4f, 0xfd, 0x6d, 0xae, 0x3c, 0x99, 0xbc, 0xe3, 0x23, 0x3e, 0xe0, 0x4f, - 0x62, 0xd2, 0xfa, 0x62, 0xe8, 0x5e, 0xb0, 0x71, 0xe8, 0x5c, 0x8c, 0x84, 0xc0, 0xfe, 0x6f, 0x01, - 0xea, 0xaf, 0xfc, 0xfe, 0xf9, 0xf1, 0x28, 0x74, 0x7d, 0x6f, 0x4c, 0x1e, 0x41, 0xfd, 0x20, 0x70, - 0xbc, 0xc9, 0xd0, 0x09, 0xdc, 0xf0, 0xc6, 0x32, 0x5a, 0x46, 0x7b, 0x61, 0x67, 0xe9, 0x01, 0xf7, - 0xab, 0x28, 0xa8, 0x6a, 0x45, 0x6c, 0x28, 0x1d, 0xf9, 0x03, 0x66, 0x15, 0xb8, 0xf5, 0x82, 0xb0, - 0x46, 0x54, 0x94, 0x52, 0xae, 0x23, 0x6d, 0x28, 0x7f, 0xe3, 0x0f, 0xdd, 0xfe, 0x8d, 0x55, 0xe4, - 0x56, 0xa6, 0xb0, 0xfa, 0xad, 0xe3, 0x86, 0x42, 0x4e, 0xa5, 0x9e, 0x7c, 0x04, 0xb5, 0x7d, 0x3f, - 0xb8, 0x72, 0x82, 0x41, 0xcf, 0xb7, 0x4a, 0x2d, 0xa3, 0x5d, 0xa3, 0xb1, 0x80, 0xb4, 0x61, 0xb1, - 0xe7, 0x9c, 0x0c, 0xd9, 0x1e, 0x7b, 0xd7, 0x39, 0x73, 0xbc, 0x53, 0x36, 0xb0, 0xe6, 0x5b, 0x46, - 0xbb, 0x4a, 0x93, 0x62, 0xc4, 0xa1, 0x2c, 0x0c, 0x6e, 0xd0, 0x85, 0x55, 0x6e, 0x19, 0xed, 0x22, - 0x8d, 0x05, 0x64, 0x05, 0xe6, 0x0f, 0x02, 0x7f, 0x32, 0xb2, 0x2a, 0x2d, 0xa3, 0xdd, 0xa4, 0x62, - 0x40, 0xb6, 0xa0, 0xda, 0x3d, 0x73, 0x82, 0x81, 0xeb, 0x9d, 0x5a, 0x55, 0x75, 0x37, 0x91, 0x94, - 0x4e, 0xf5, 0xe4, 0x09, 0x40, 0xd7, 0x73, 0x46, 0xdd, 0x33, 0x3f, 0xec, 0x8d, 0xad, 0x5a, 0xcb, - 0x68, 0xd7, 0x77, 0x56, 0x1e, 0xc4, 0x01, 0xee, 0x45, 0x4f, 0xcf, 0x4a, 0xdf, 0xfd, 0xe3, 0xde, - 0x1c, 0x55, 0xac, 0xed, 0xbf, 0x1b, 0x50, 0xc3, 0x00, 0xf1, 0x35, 0xe3, 0x5a, 0xf8, 0x03, 0x0f, - 0x77, 0x89, 0x8a, 0x01, 0xae, 0xbf, 0xcb, 0x82, 0x4b, 0xb7, 0xcf, 0x0e, 0xf7, 0x78, 0x68, 0x6b, - 0x34, 0x16, 0x10, 0x0b, 0x2a, 0x6f, 0x59, 0x30, 0x76, 0x7d, 0x8f, 0x07, 0xb4, 0x44, 0xa3, 0x21, - 0xa2, 0xbd, 0x75, 0x86, 0xee, 0x80, 0xc7, 0xae, 0x4a, 0xc5, 0x20, 0xde, 0xef, 0x7c, 0xde, 0x7e, - 0xcb, 0x33, 0xf6, 0xdb, 0x82, 0xfa, 0x71, 0xe0, 0x9e, 0xba, 0x9e, 0x58, 0x6b, 0x85, 0x7b, 0x55, - 0x45, 0xf6, 0x9f, 0x00, 0x2a, 0x94, 0xfd, 0x7e, 0xc2, 0xc6, 0xa1, 0x88, 0x3e, 0x7f, 0x3c, 0xdc, - 0x93, 0xfb, 0x8a, 0x05, 0xe4, 0x91, 0xb2, 0x7d, 0xbe, 0xb7, 0xfa, 0xce, 0x62, 0x9c, 0x36, 0x5c, - 0x2c, 0xa3, 0xa6, 0x84, 0x69, 0x13, 0xca, 0x47, 0x2c, 0x3c, 0xf3, 0x07, 0x32, 0x85, 0x1a, 0x62, - 0x86, 0x90, 0x51, 0xa9, 0x23, 0xf7, 0xa1, 0x84, 0x53, 0xf8, 0xee, 0xeb, 0x51, 0xea, 0xa2, 0x44, - 0x7a, 0x97, 0xb8, 0xdc, 0x88, 0x3c, 0x84, 0xf2, 0x1b, 0x0f, 0x2d, 0x78, 0x58, 0xea, 0x3b, 0xcb, - 0xc2, 0x5c, 0xc8, 0xf4, 0x09, 0xd2, 0x90, 0xfc, 0x0a, 0xe0, 0x80, 0x85, 0xbd, 0x6b, 0x8f, 0x7b, - 0x29, 0xf3, 0x69, 0x77, 0xe5, 0x07, 0x32, 0x95, 0xeb, 0x53, 0x95, 0x09, 0xe4, 0x10, 0x16, 0x0e, - 0x58, 0x88, 0x29, 0xe8, 0x7a, 0xa7, 0xaf, 0xdc, 0x71, 0xc8, 0x03, 0x59, 0xdf, 0xf9, 0xd1, 0x14, - 0x42, 0xd1, 0xe9, 0x30, 0x89, 0x89, 0xe4, 0xe7, 0x50, 0x39, 0x60, 0xe1, 0x33, 0xd7, 0x1b, 0xf0, - 0x5c, 0xc5, 0xec, 0x8b, 0x30, 0x50, 0xa8, 0x4f, 0x8e, 0x4c, 0x09, 0x85, 0xa5, 0x97, 0x8c, 0x8d, - 0xe2, 0x38, 0xe3, 0x7c, 0x91, 0xbd, 0x1b, 0x62, 0x7e, 0x4a, 0xad, 0x23, 0xa5, 0xa7, 0xe3, 0xa6, - 0x50, 0x48, 0xd9, 0x85, 0x1f, 0x32, 0x1e, 0x17, 0x50, 0x37, 0xa5, 0xeb, 0x12, 0x9b, 0xd2, 0x95, - 0xe4, 0x15, 0x2c, 0xf2, 0x84, 0x75, 0x42, 0x26, 0x93, 0xdd, 0xaa, 0x73, 0xac, 0x8f, 0x04, 0x56, - 0x42, 0xa9, 0x83, 0x25, 0xa7, 0x92, 0x0e, 0x34, 0x3a, 0x8e, 0xe7, 0xf9, 0x61, 0xc7, 0xbf, 0xb8, - 0x70, 0x43, 0xab, 0xc1, 0xa1, 0xd6, 0x04, 0x94, 0xaa, 0xd1, 0x71, 0xb4, 0x49, 0x08, 0x72, 0xc0, - 0xc2, 0xdd, 0x7e, 0xe8, 0x5e, 0xb2, 0xde, 0xb5, 0x67, 0x35, 0x55, 0x10, 0x55, 0x93, 0x00, 0x51, - 0x55, 0x18, 0xf6, 0x2e, 0x0b, 0x29, 0x32, 0x42, 0x10, 0x46, 0x3b, 0x5b, 0x50, 0xc3, 0x9e, 0x52, - 0x27, 0xc2, 0x9e, 0xd2, 0x23, 0x66, 0xc7, 0xf1, 0x12, 0x98, 0x8b, 0x2a, 0x66, 0x4a, 0x9d, 0xc0, - 0x4c, 0xe9, 0xc9, 0x1b, 0x20, 0x94, 0x5d, 0x38, 0xae, 0xd7, 0xbb, 0xf6, 0x0e, 0xbd, 0x08, 0xd4, - 0xe4, 0xa0, 0xf7, 0x04, 0x68, 0x5a, 0xaf, 0xa3, 0x66, 0x00, 0x90, 0x5f, 0x43, 0xbd, 0x73, 0xc6, - 0xfa, 0xe7, 0xc7, 0xc1, 0xe8, 0xcc, 0xf1, 0xac, 0x25, 0x8e, 0x67, 0xc9, 0x45, 0xc6, 0x0a, 0x1d, - 0x48, 0x9d, 0x82, 0x89, 0x41, 0xd9, 0x78, 0x72, 0xc1, 0x0e, 0xbd, 0x4b, 0x7c, 0xcb, 0x9d, 0xd7, - 0x16, 0x51, 0x13, 0x23, 0xa1, 0x4c, 0x24, 0x46, 0x42, 0x4b, 0x1c, 0x58, 0xdd, 0x3d, 0xf1, 0x83, - 0x50, 0x64, 0xde, 0x1e, 0x73, 0x06, 0x08, 0x82, 0x6f, 0x77, 0x85, 0x83, 0xfe, 0x44, 0x80, 0x66, - 0xdb, 0xe8, 0xd8, 0x39, 0x40, 0xf6, 0xb7, 0x00, 0x55, 0xca, 0xc6, 0x23, 0xdf, 0x1b, 0xb3, 0x19, - 0x74, 0x18, 0x33, 0x5b, 0xe1, 0x16, 0x66, 0x5b, 0x81, 0xf9, 0xe7, 0x41, 0xe0, 0x07, 0x9c, 0xfe, - 0x1a, 0x54, 0x0c, 0xc8, 0xa7, 0x50, 0x79, 0xcd, 0xae, 0xf8, 0x57, 0x5c, 0xca, 0x24, 0x52, 0x1a, - 0xe9, 0xc9, 0x4f, 0x25, 0x35, 0x0a, 0xae, 0x23, 0x2a, 0x35, 0x8a, 0x65, 0x6a, 0xdc, 0xb8, 0x33, - 0xe5, 0xc6, 0xb2, 0xca, 0x2e, 0x11, 0x37, 0x6a, 0x33, 0x22, 0x72, 0x7c, 0xaa, 0x91, 0x63, 0x45, - 0x7d, 0xcb, 0x2a, 0x39, 0x6a, 0x73, 0x55, 0x76, 0xfc, 0x3a, 0xc5, 0x8e, 0x55, 0xf5, 0x1d, 0x27, - 0xd9, 0x51, 0xc3, 0x49, 0xd2, 0xe3, 0xe3, 0x98, 0x1e, 0x05, 0xbd, 0xdd, 0x49, 0xd0, 0xa3, 0x36, - 0x7b, 0xca, 0x8f, 0xdd, 0x2c, 0x7e, 0x04, 0x35, 0xff, 0x33, 0xf8, 0x51, 0x83, 0xca, 0x20, 0xc8, - 0xaf, 0x53, 0x04, 0xa9, 0x91, 0x5a, 0x92, 0x20, 0xf5, 0x7d, 0x25, 0x18, 0xf2, 0x28, 0xcd, 0x90, - 0x82, 0xd6, 0x3e, 0xce, 0x61, 0x48, 0x0d, 0x2d, 0x45, 0x91, 0x7b, 0x09, 0x8a, 0x14, 0xec, 0xb6, - 0x9e, 0x45, 0x91, 0x1a, 0x90, 0xce, 0x91, 0x7b, 0x09, 0x8e, 0x5c, 0x50, 0x51, 0x74, 0x8e, 0xd4, - 0x51, 0x34, 0x92, 0xec, 0x66, 0x91, 0xe4, 0xa2, 0x1a, 0xfb, 0x0c, 0x92, 0xd4, 0x63, 0x9f, 0x66, - 0xc9, 0x6e, 0x16, 0x4b, 0x6a, 0x84, 0x96, 0xc1, 0x92, 0x3a, 0x68, 0x9a, 0x26, 0xdf, 0x66, 0xd2, - 0xa4, 0xa0, 0xb5, 0x56, 0x3e, 0x4d, 0x6a, 0xb0, 0x59, 0x3c, 0xb9, 0xab, 0xf3, 0x24, 0xd1, 0xce, - 0x2b, 0x95, 0x27, 0x35, 0x24, 0x8d, 0x28, 0x8f, 0xd2, 0x44, 0xb9, 0xac, 0xe6, 0x47, 0x8a, 0x28, - 0xf5, 0xfc, 0x48, 0x32, 0xe5, 0xc9, 0x0c, 0xa6, 0xdc, 0xbc, 0x9d, 0x29, 0x35, 0xf0, 0x3c, 0xaa, - 0xfc, 0xa3, 0x21, 0xba, 0x90, 0xa8, 0x78, 0xc4, 0x82, 0xf8, 0xda, 0x93, 0x4c, 0xd9, 0xa0, 0x62, - 0x30, 0xa3, 0x20, 0x26, 0x50, 0xa2, 0xfe, 0xd5, 0xd8, 0x2a, 0xb6, 0x8a, 0xed, 0x06, 0xe5, 0xcf, - 0xe4, 0x21, 0x54, 0x64, 0x63, 0x93, 0x2e, 0x07, 0xa5, 0x22, 0xfa, 0xfc, 0xe5, 0xd0, 0x7e, 0x02, - 0x0d, 0xf5, 0x1b, 0x24, 0x5b, 0x50, 0xc6, 0x88, 0x0c, 0x43, 0xbe, 0x96, 0x7a, 0x44, 0xcd, 0x42, - 0x16, 0xb1, 0x9f, 0x18, 0xd9, 0x5f, 0xc1, 0x52, 0xaa, 0x04, 0xcc, 0xd9, 0x8b, 0x09, 0x45, 0xea, - 0x5f, 0xf1, 0x5d, 0x34, 0x28, 0x3e, 0xda, 0x7f, 0x35, 0x80, 0xa4, 0x39, 0x52, 0x56, 0xf3, 0x13, - 0xd1, 0x1b, 0xcc, 0x53, 0x31, 0x20, 0x8f, 0xa1, 0xae, 0x92, 0x64, 0xa1, 0x55, 0x6c, 0xd7, 0x77, - 0x9a, 0x71, 0x4b, 0xd5, 0xbb, 0xf6, 0xa2, 0xd4, 0x50, 0x29, 0xf1, 0x3e, 0x94, 0x5f, 0xf8, 0xc3, - 0x01, 0x13, 0x47, 0x48, 0xce, 0x0c, 0x69, 0x82, 0x9e, 0xf7, 0xfd, 0x89, 0x37, 0xed, 0x23, 0xf8, - 0xc0, 0x7e, 0x0a, 0x77, 0x32, 0x6b, 0x54, 0xf2, 0x09, 0x14, 0x31, 0x29, 0x8c, 0x7c, 0x60, 0xd4, - 0xdb, 0xc7, 0xb0, 0x9a, 0xcd, 0xe2, 0xc9, 0x3d, 0x19, 0x3f, 0x6c, 0x4f, 0x76, 0x1f, 0x2a, 0x52, - 0x9b, 0x9f, 0x36, 0x9d, 0x80, 0x39, 0x21, 0x1b, 0x1c, 0x7b, 0x51, 0xda, 0x4c, 0x05, 0x64, 0x13, - 0x9a, 0x38, 0x9d, 0x05, 0xbb, 0x83, 0x41, 0xc0, 0xc6, 0x63, 0x1e, 0x99, 0x1a, 0xd5, 0x85, 0xf6, - 0x9f, 0x0d, 0x68, 0x6a, 0x4d, 0x41, 0x8e, 0xaf, 0xcf, 0xa1, 0x2a, 0x08, 0xb1, 0xd7, 0x95, 0x6d, - 0xcd, 0x6d, 0x1d, 0xe1, 0xd4, 0x96, 0x7c, 0x01, 0xb5, 0xa3, 0x49, 0xe8, 0x88, 0x54, 0x2d, 0xf2, - 0x9d, 0xcb, 0x56, 0xe4, 0xf9, 0x75, 0x18, 0x38, 0x91, 0x2e, 0xea, 0x89, 0xa6, 0xb6, 0xb6, 0x09, - 0x0b, 0xfa, 0x81, 0x6c, 0x7f, 0x6b, 0xf0, 0x33, 0x54, 0xa9, 0xdb, 0xf5, 0x0f, 0xc7, 0x48, 0x7e, - 0x38, 0xd3, 0xee, 0xb3, 0xa0, 0x76, 0x9f, 0xd3, 0x7e, 0xb1, 0x98, 0xd7, 0x2f, 0x96, 0x3e, 0xac, - 0x5f, 0x9c, 0x4f, 0xf7, 0x8b, 0xfb, 0xb0, 0x98, 0x38, 0x8c, 0xff, 0xaf, 0xc6, 0xd0, 0xfe, 0x9b, - 0x01, 0x56, 0x5e, 0xd3, 0x32, 0x63, 0xf3, 0x9b, 0x50, 0xee, 0x86, 0x4e, 0x38, 0x19, 0xeb, 0x95, - 0x97, 0x90, 0x51, 0xa9, 0x23, 0xab, 0x50, 0xe6, 0xef, 0x37, 0x62, 0x17, 0x39, 0x22, 0x8f, 0x01, - 0xa6, 0x3e, 0x91, 0x62, 0x8a, 0xf9, 0xcb, 0x55, 0x0c, 0xed, 0xdf, 0xc0, 0x5a, 0x6e, 0x0d, 0x41, - 0x16, 0xa0, 0x70, 0xfc, 0x92, 0x2f, 0xb4, 0x4a, 0x0b, 0xc7, 0x2f, 0x7f, 0xd8, 0x0a, 0xed, 0x2f, - 0xc1, 0xca, 0xeb, 0x1f, 0x6e, 0x8f, 0x80, 0x7d, 0x1f, 0xd6, 0x72, 0x0f, 0xd5, 0xe4, 0x62, 0xd0, - 0x4d, 0x5e, 0x4b, 0x31, 0xdb, 0x4d, 0xee, 0x31, 0x9b, 0x72, 0xf3, 0x0b, 0x58, 0xcb, 0x6d, 0x32, - 0x66, 0xf8, 0x79, 0x02, 0xeb, 0xf9, 0x07, 0xaf, 0x28, 0xc3, 0xa5, 0x56, 0x32, 0x6a, 0x2c, 0xb0, - 0x1f, 0xc3, 0x9d, 0xcc, 0x56, 0x75, 0x86, 0xcb, 0x36, 0xac, 0x66, 0x17, 0x70, 0xa9, 0x7d, 0x7d, - 0x0e, 0xab, 0xd9, 0xfd, 0xeb, 0x0c, 0x0f, 0x9f, 0xc2, 0xdd, 0x9c, 0xaa, 0x2e, 0xe5, 0x62, 0x1f, - 0x3e, 0xbe, 0xb5, 0x69, 0x41, 0x9e, 0x0e, 0x67, 0xf0, 0x74, 0x78, 0xed, 0xd9, 0x3f, 0x83, 0x8d, - 0xdb, 0x8f, 0xf4, 0x94, 0x67, 0x0a, 0xcb, 0x19, 0x1d, 0x35, 0xf9, 0x0a, 0x9a, 0xa2, 0x30, 0xc1, - 0x93, 0x2d, 0x26, 0x76, 0xf9, 0x99, 0x4c, 0x55, 0xd2, 0xb7, 0x6e, 0x6b, 0xff, 0x12, 0x56, 0xb2, - 0x4a, 0x50, 0x64, 0x6d, 0x21, 0xc1, 0x63, 0x40, 0xbc, 0x4b, 0xfc, 0x2e, 0x75, 0xa1, 0xfd, 0x08, - 0x96, 0x33, 0xda, 0xf3, 0x19, 0xb1, 0x7e, 0x0a, 0x2b, 0x59, 0xf5, 0x6a, 0x7c, 0xad, 0x66, 0xa8, - 0xd7, 0x6a, 0xa6, 0x38, 0xf5, 0x0a, 0xdc, 0x3d, 0x3f, 0xe0, 0xf6, 0x80, 0xa4, 0x1b, 0xda, 0x19, - 0x2c, 0x34, 0x45, 0x31, 0x22, 0x94, 0xcf, 0x60, 0x39, 0xa3, 0xdc, 0x43, 0x22, 0x92, 0x95, 0xa1, - 0x58, 0x85, 0x1c, 0xd9, 0x5f, 0x40, 0x6d, 0x1a, 0x38, 0x62, 0x41, 0x25, 0x2a, 0x48, 0x85, 0xa7, - 0x68, 0x98, 0xb1, 0xda, 0x3f, 0x14, 0xa3, 0xfa, 0x86, 0x3c, 0x84, 0x2a, 0x26, 0x2f, 0x3f, 0x26, - 0x8d, 0xdb, 0x98, 0x77, 0x6a, 0x86, 0x14, 0xff, 0xc2, 0x19, 0x77, 0x7c, 0xef, 0xdd, 0xd0, 0xed, - 0x87, 0x7c, 0xfd, 0x55, 0xaa, 0x8a, 0xf0, 0x45, 0xbd, 0x70, 0xc6, 0xdf, 0x04, 0xec, 0x52, 0xb6, - 0x17, 0x45, 0x6e, 0xa3, 0x0b, 0xc9, 0x97, 0x50, 0x9b, 0x9e, 0x8d, 0xb2, 0x52, 0xbb, 0xed, 0xdc, - 0x8c, 0x8d, 0x3f, 0xe0, 0x3a, 0xb8, 0x05, 0xf5, 0x68, 0x55, 0x2f, 0xd9, 0x0d, 0xef, 0x69, 0x1b, - 0x54, 0x15, 0xa9, 0x16, 0x18, 0xa5, 0x8a, 0x6e, 0x81, 0x91, 0xdd, 0x00, 0xc0, 0x55, 0x8b, 0xda, - 0x80, 0xb7, 0xa6, 0x0d, 0xaa, 0x48, 0x30, 0xf2, 0xe2, 0x49, 0xdc, 0x07, 0x37, 0x69, 0x34, 0xc4, - 0x99, 0xaf, 0xd9, 0x15, 0x06, 0x6e, 0x77, 0x20, 0xda, 0xc9, 0x2a, 0x55, 0x24, 0x76, 0x17, 0x9a, - 0xda, 0x49, 0x8f, 0xaf, 0xea, 0x9c, 0xdd, 0xc8, 0xea, 0x02, 0x1f, 0xb1, 0xc0, 0x1d, 0x9f, 0xbb, - 0x23, 0x19, 0x65, 0xfe, 0x8c, 0x69, 0x15, 0xb0, 0xd1, 0xd0, 0xe9, 0xb3, 0x9e, 0x2f, 0xaf, 0x05, - 0x62, 0x01, 0xd2, 0x4d, 0xf6, 0xad, 0xc8, 0x8c, 0x4f, 0x60, 0x0d, 0xee, 0xe6, 0x34, 0x09, 0x5b, - 0x3f, 0xd6, 0xfe, 0x0f, 0x90, 0x0a, 0x2f, 0x63, 0xcd, 0x39, 0x52, 0x83, 0x79, 0x8a, 0x71, 0x36, - 0x8d, 0xad, 0x4f, 0x44, 0x1e, 0xf1, 0x5b, 0xff, 0x26, 0xd4, 0x9e, 0x5f, 0xf7, 0x87, 0x93, 0xb1, - 0x7b, 0xc9, 0xcc, 0x39, 0x02, 0x50, 0xc6, 0xf2, 0x80, 0x0d, 0x4c, 0x63, 0x6b, 0x13, 0x20, 0xbe, - 0xfc, 0x27, 0x55, 0x28, 0xe1, 0xc8, 0x9c, 0x23, 0x0d, 0xa8, 0xee, 0x3b, 0xe3, 0x70, 0xdf, 0x71, - 0x87, 0xa6, 0xb1, 0x75, 0x2f, 0x2e, 0x38, 0xd0, 0xe6, 0xb5, 0xef, 0x31, 0xe1, 0xed, 0xd9, 0x0d, - 0x3a, 0x36, 0xb6, 0xfe, 0x59, 0x88, 0xee, 0x4e, 0x50, 0x8f, 0x8e, 0x85, 0x1f, 0x51, 0x15, 0x99, - 0x06, 0x59, 0x50, 0xaf, 0x24, 0xcc, 0x02, 0x21, 0xc9, 0x2b, 0x06, 0xb3, 0x88, 0x32, 0x9d, 0xc1, - 0xcd, 0x12, 0xa9, 0x4f, 0xaf, 0x0f, 0xcc, 0x79, 0x72, 0x27, 0xe3, 0x52, 0xc0, 0x2c, 0x93, 0x45, - 0xa8, 0xcb, 0x3f, 0x13, 0x7c, 0x52, 0x85, 0x2c, 0x41, 0x53, 0x0a, 0xa4, 0xff, 0x2a, 0x59, 0x4e, - 0xb5, 0xeb, 0x66, 0x8d, 0x98, 0x7a, 0xd3, 0x6d, 0x02, 0x4a, 0x54, 0xda, 0x31, 0xeb, 0xe8, 0x33, - 0x75, 0x30, 0x9b, 0x0d, 0xb2, 0x9a, 0xd5, 0x79, 0x9a, 0x4d, 0x34, 0x4f, 0x1d, 0xb0, 0xe6, 0x02, - 0x2e, 0x51, 0x21, 0x12, 0x73, 0x11, 0xd7, 0x93, 0x78, 0xb9, 0xa6, 0x49, 0xd6, 0xf3, 0x9a, 0x3c, - 0x73, 0x69, 0x8b, 0x45, 0x05, 0x88, 0x58, 0x11, 0x07, 0xc6, 0xed, 0x3e, 0xf7, 0x30, 0x12, 0xe6, - 0x1c, 0xae, 0x48, 0x11, 0xcb, 0xc8, 0x9a, 0x86, 0x62, 0xfe, 0x86, 0x07, 0xbf, 0x3b, 0xe9, 0xf7, - 0xcd, 0x82, 0x22, 0x8e, 0xd7, 0x6b, 0x16, 0x9f, 0x75, 0xbe, 0xff, 0xf7, 0x86, 0xf1, 0xdd, 0xfb, - 0x0d, 0xe3, 0xfb, 0xf7, 0x1b, 0xc6, 0xbf, 0xde, 0x6f, 0xcc, 0xfd, 0xe5, 0x3f, 0x1b, 0xc6, 0xef, - 0xd4, 0xff, 0x5b, 0x17, 0x4e, 0x18, 0xb8, 0xd7, 0x3e, 0x2f, 0x20, 0xa3, 0x81, 0xc7, 0xb6, 0x47, - 0xe7, 0xa7, 0xdb, 0xa3, 0x93, 0x6d, 0x5c, 0xf0, 0x49, 0x99, 0xff, 0xd5, 0x7a, 0xf4, 0xbf, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x25, 0xdb, 0xc2, 0x32, 0x29, 0x1b, 0x00, 0x00, + 0x7b, 0x2a, 0x71, 0xde, 0x20, 0x95, 0x07, 0x48, 0xf5, 0xcc, 0x80, 0x98, 0xc1, 0x8f, 0xb8, 0xce, + 0x0d, 0xd3, 0xdd, 0xf3, 0xf5, 0x4c, 0xa3, 0xf1, 0x4d, 0xf7, 0x00, 0x60, 0xe8, 0xf7, 0xcf, 0x1f, + 0x8c, 0x02, 0x3f, 0xf4, 0x49, 0x09, 0x9f, 0xd7, 0x3f, 0x3b, 0x75, 0xc3, 0xb3, 0xc9, 0xc9, 0x83, + 0xbe, 0x7f, 0xb1, 0x7d, 0xea, 0x9f, 0xfa, 0xdb, 0x5c, 0x79, 0x32, 0x79, 0xc7, 0x47, 0x7c, 0xc0, + 0x9f, 0xc4, 0xa4, 0xf5, 0xc5, 0xd0, 0xbd, 0x60, 0xe3, 0xd0, 0xb9, 0x18, 0x09, 0x81, 0xfd, 0xdf, + 0x02, 0xd4, 0x5f, 0xf9, 0xfd, 0xf3, 0xe3, 0x51, 0xe8, 0xfa, 0xde, 0x98, 0x3c, 0x82, 0xfa, 0x41, + 0xe0, 0x78, 0x93, 0xa1, 0x13, 0xb8, 0xe1, 0x8d, 0x65, 0xb4, 0x8c, 0xf6, 0xc2, 0xce, 0xd2, 0x03, + 0xee, 0x57, 0x51, 0x50, 0xd5, 0x8a, 0xd8, 0x50, 0x3a, 0xf2, 0x07, 0xcc, 0x2a, 0x70, 0xeb, 0x05, + 0x61, 0x8d, 0xa8, 0x28, 0xa5, 0x5c, 0x47, 0xda, 0x50, 0xfe, 0xc6, 0x1f, 0xba, 0xfd, 0x1b, 0xab, + 0xc8, 0xad, 0x4c, 0x61, 0xf5, 0x5b, 0xc7, 0x0d, 0x85, 0x9c, 0x4a, 0x3d, 0xf9, 0x08, 0x6a, 0xfb, + 0x7e, 0x70, 0xe5, 0x04, 0x83, 0x9e, 0x6f, 0x95, 0x5a, 0x46, 0xbb, 0x46, 0x63, 0x01, 0x69, 0xc3, + 0x62, 0xcf, 0x39, 0x19, 0xb2, 0x3d, 0xf6, 0xae, 0x73, 0xe6, 0x78, 0xa7, 0x6c, 0x60, 0xcd, 0xb7, + 0x8c, 0x76, 0x95, 0x26, 0xc5, 0x88, 0x43, 0x59, 0x18, 0xdc, 0xa0, 0x0b, 0xab, 0xdc, 0x32, 0xda, + 0x45, 0x1a, 0x0b, 0xc8, 0x0a, 0xcc, 0x1f, 0x04, 0xfe, 0x64, 0x64, 0x55, 0x5a, 0x46, 0xbb, 0x49, + 0xc5, 0x80, 0x6c, 0x41, 0xb5, 0x7b, 0xe6, 0x04, 0x03, 0xd7, 0x3b, 0xb5, 0xaa, 0xea, 0x6e, 0x22, + 0x29, 0x9d, 0xea, 0xc9, 0x13, 0x80, 0xae, 0xe7, 0x8c, 0xba, 0x67, 0x7e, 0xd8, 0x1b, 0x5b, 0xb5, + 0x96, 0xd1, 0xae, 0xef, 0xac, 0x3c, 0x88, 0x03, 0xdc, 0x8b, 0x9e, 0x9e, 0x95, 0xbe, 0xfb, 0xc7, + 0xbd, 0x39, 0xaa, 0x58, 0xdb, 0x7f, 0x37, 0xa0, 0x86, 0x01, 0xe2, 0x6b, 0xc6, 0xb5, 0xf0, 0x07, + 0x1e, 0xee, 0x12, 0x15, 0x03, 0x5c, 0x7f, 0x97, 0x05, 0x97, 0x6e, 0x9f, 0x1d, 0xee, 0xf1, 0xd0, + 0xd6, 0x68, 0x2c, 0x20, 0x16, 0x54, 0xde, 0xb2, 0x60, 0xec, 0xfa, 0x1e, 0x0f, 0x68, 0x89, 0x46, + 0x43, 0x44, 0x7b, 0xeb, 0x0c, 0xdd, 0x01, 0x8f, 0x5d, 0x95, 0x8a, 0x41, 0xbc, 0xdf, 0xf9, 0xbc, + 0xfd, 0x96, 0x67, 0xec, 0xb7, 0x05, 0xf5, 0xe3, 0xc0, 0x3d, 0x75, 0x3d, 0xb1, 0xd6, 0x0a, 0xf7, + 0xaa, 0x8a, 0xec, 0x3f, 0x01, 0x54, 0x28, 0xfb, 0xfd, 0x84, 0x8d, 0x43, 0x11, 0x7d, 0xfe, 0x78, + 0xb8, 0x27, 0xf7, 0x15, 0x0b, 0xc8, 0x23, 0x65, 0xfb, 0x7c, 0x6f, 0xf5, 0x9d, 0xc5, 0x38, 0x6d, + 0xb8, 0x58, 0x46, 0x4d, 0x09, 0xd3, 0x26, 0x94, 0x8f, 0x58, 0x78, 0xe6, 0x0f, 0x64, 0x0a, 0x35, + 0xc4, 0x0c, 0x21, 0xa3, 0x52, 0x47, 0xee, 0x43, 0x09, 0xa7, 0xf0, 0xdd, 0xd7, 0xa3, 0xd4, 0x45, + 0x89, 0xf4, 0x2e, 0x71, 0xb9, 0x11, 0x79, 0x08, 0xe5, 0x37, 0x1e, 0x5a, 0xf0, 0xb0, 0xd4, 0x77, + 0x96, 0x85, 0xb9, 0x90, 0xe9, 0x13, 0xa4, 0x21, 0xf9, 0x15, 0xc0, 0x01, 0x0b, 0x7b, 0xd7, 0x1e, + 0xf7, 0x52, 0xe6, 0xd3, 0xee, 0xca, 0x0f, 0x64, 0x2a, 0xd7, 0xa7, 0x2a, 0x13, 0xc8, 0x21, 0x2c, + 0x1c, 0xb0, 0x10, 0x53, 0xd0, 0xf5, 0x4e, 0x5f, 0xb9, 0xe3, 0x90, 0x07, 0xb2, 0xbe, 0xf3, 0xa3, + 0x29, 0x84, 0xa2, 0xd3, 0x61, 0x12, 0x13, 0xc9, 0xcf, 0xa1, 0x72, 0xc0, 0xc2, 0x67, 0xae, 0x37, + 0xe0, 0xb9, 0x8a, 0xd9, 0x17, 0x61, 0xa0, 0x50, 0x9f, 0x1c, 0x99, 0x12, 0x0a, 0x4b, 0x2f, 0x19, + 0x1b, 0xc5, 0x71, 0xc6, 0xf9, 0x22, 0x7b, 0x37, 0xc4, 0xfc, 0x94, 0x5a, 0x47, 0x4a, 0x4f, 0xc7, + 0x4d, 0xa1, 0x90, 0xb2, 0x0b, 0x3f, 0x64, 0x3c, 0x2e, 0xa0, 0x6e, 0x4a, 0xd7, 0x25, 0x36, 0xa5, + 0x2b, 0xc9, 0x2b, 0x58, 0xe4, 0x09, 0xeb, 0x84, 0x4c, 0x26, 0xbb, 0x55, 0xe7, 0x58, 0x1f, 0x09, + 0xac, 0x84, 0x52, 0x07, 0x4b, 0x4e, 0x25, 0x1d, 0x68, 0x74, 0x1c, 0xcf, 0xf3, 0xc3, 0x8e, 0x7f, + 0x71, 0xe1, 0x86, 0x56, 0x83, 0x43, 0xad, 0x09, 0x28, 0x55, 0xa3, 0xe3, 0x68, 0x93, 0x10, 0xe4, + 0x80, 0x85, 0xbb, 0xfd, 0xd0, 0xbd, 0x64, 0xbd, 0x6b, 0xcf, 0x6a, 0xaa, 0x20, 0xaa, 0x26, 0x01, + 0xa2, 0xaa, 0x30, 0xec, 0x5d, 0x16, 0x52, 0x64, 0x84, 0x20, 0x8c, 0x76, 0xb6, 0xa0, 0x86, 0x3d, + 0xa5, 0x4e, 0x84, 0x3d, 0xa5, 0x47, 0xcc, 0x8e, 0xe3, 0x25, 0x30, 0x17, 0x55, 0xcc, 0x94, 0x3a, + 0x81, 0x99, 0xd2, 0x93, 0x37, 0x40, 0x28, 0xbb, 0x70, 0x5c, 0xaf, 0x77, 0xed, 0x1d, 0x7a, 0x11, + 0xa8, 0xc9, 0x41, 0xef, 0x09, 0xd0, 0xb4, 0x5e, 0x47, 0xcd, 0x00, 0x20, 0xbf, 0x86, 0x7a, 0xe7, + 0x8c, 0xf5, 0xcf, 0x8f, 0x83, 0xd1, 0x99, 0xe3, 0x59, 0x4b, 0x1c, 0xcf, 0x92, 0x8b, 0x8c, 0x15, + 0x3a, 0x90, 0x3a, 0x05, 0x13, 0x83, 0xb2, 0xf1, 0xe4, 0x82, 0x1d, 0x7a, 0x97, 0xf8, 0x96, 0x3b, + 0xaf, 0x2d, 0xa2, 0x26, 0x46, 0x42, 0x99, 0x48, 0x8c, 0x84, 0x96, 0x38, 0xb0, 0xba, 0x7b, 0xe2, + 0x07, 0xa1, 0xc8, 0xbc, 0x3d, 0xe6, 0x0c, 0x10, 0x04, 0xdf, 0xee, 0x0a, 0x07, 0xfd, 0x89, 0x00, + 0xcd, 0xb6, 0xd1, 0xb1, 0x73, 0x80, 0xec, 0x6f, 0x01, 0xaa, 0x94, 0x8d, 0x47, 0xbe, 0x37, 0x66, + 0x33, 0xe8, 0x30, 0x66, 0xb6, 0xc2, 0x2d, 0xcc, 0xb6, 0x02, 0xf3, 0xcf, 0x83, 0xc0, 0x0f, 0x38, + 0xfd, 0x35, 0xa8, 0x18, 0x90, 0x4f, 0xa1, 0xf2, 0x9a, 0x5d, 0xf1, 0xaf, 0xb8, 0x94, 0x49, 0xa4, + 0x34, 0xd2, 0x93, 0x9f, 0x4a, 0x6a, 0x14, 0x5c, 0x47, 0x54, 0x6a, 0x14, 0xcb, 0xd4, 0xb8, 0x71, + 0x67, 0xca, 0x8d, 0x65, 0x95, 0x5d, 0x22, 0x6e, 0xd4, 0x66, 0x44, 0xe4, 0xf8, 0x54, 0x23, 0xc7, + 0x8a, 0xfa, 0x96, 0x55, 0x72, 0xd4, 0xe6, 0xaa, 0xec, 0xf8, 0x75, 0x8a, 0x1d, 0xab, 0xea, 0x3b, + 0x4e, 0xb2, 0xa3, 0x86, 0x93, 0xa4, 0xc7, 0xc7, 0x31, 0x3d, 0x0a, 0x7a, 0xbb, 0x93, 0xa0, 0x47, + 0x6d, 0xf6, 0x94, 0x1f, 0xbb, 0x59, 0xfc, 0x08, 0x6a, 0xfe, 0x67, 0xf0, 0xa3, 0x06, 0x95, 0x41, + 0x90, 0x5f, 0xa7, 0x08, 0x52, 0x23, 0xb5, 0x24, 0x41, 0xea, 0xfb, 0x4a, 0x30, 0xe4, 0x51, 0x9a, + 0x21, 0x05, 0xad, 0x7d, 0x9c, 0xc3, 0x90, 0x1a, 0x5a, 0x8a, 0x22, 0xf7, 0x12, 0x14, 0x29, 0xd8, + 0x6d, 0x3d, 0x8b, 0x22, 0x35, 0x20, 0x9d, 0x23, 0xf7, 0x12, 0x1c, 0xb9, 0xa0, 0xa2, 0xe8, 0x1c, + 0xa9, 0xa3, 0x68, 0x24, 0xd9, 0xcd, 0x22, 0xc9, 0x45, 0x35, 0xf6, 0x19, 0x24, 0xa9, 0xc7, 0x3e, + 0xcd, 0x92, 0xdd, 0x2c, 0x96, 0xd4, 0x08, 0x2d, 0x83, 0x25, 0x75, 0xd0, 0x34, 0x4d, 0xbe, 0xcd, + 0xa4, 0x49, 0x41, 0x6b, 0xad, 0x7c, 0x9a, 0xd4, 0x60, 0xb3, 0x78, 0x72, 0x57, 0xe7, 0x49, 0xa2, + 0x9d, 0x57, 0x2a, 0x4f, 0x6a, 0x48, 0x1a, 0x51, 0x1e, 0xa5, 0x89, 0x72, 0x59, 0xcd, 0x8f, 0x14, + 0x51, 0xea, 0xf9, 0x91, 0x64, 0xca, 0x93, 0x19, 0x4c, 0xb9, 0x79, 0x3b, 0x53, 0x6a, 0xe0, 0x79, + 0x54, 0xf9, 0x47, 0x43, 0x74, 0x21, 0x51, 0xf1, 0x88, 0x05, 0xf1, 0xb5, 0x27, 0x99, 0xb2, 0x41, + 0xc5, 0x60, 0x46, 0x41, 0x4c, 0xa0, 0x44, 0xfd, 0xab, 0xb1, 0x55, 0x6c, 0x15, 0xdb, 0x0d, 0xca, + 0x9f, 0xc9, 0x43, 0xa8, 0xc8, 0xc6, 0x26, 0x5d, 0x0e, 0x4a, 0x45, 0xf4, 0xf9, 0xcb, 0xa1, 0xfd, + 0x04, 0x1a, 0xea, 0x37, 0x48, 0xb6, 0xa0, 0x8c, 0x11, 0x19, 0x86, 0x7c, 0x2d, 0xf5, 0x88, 0x9a, + 0x85, 0x2c, 0x62, 0x3f, 0x31, 0xb2, 0xbf, 0x82, 0xa5, 0x54, 0x09, 0x98, 0xb3, 0x17, 0x13, 0x8a, + 0xd4, 0xbf, 0xe2, 0xbb, 0x68, 0x50, 0x7c, 0xb4, 0xff, 0x6a, 0x00, 0x49, 0x73, 0xa4, 0xac, 0xe6, + 0x27, 0xa2, 0x37, 0x98, 0xa7, 0x62, 0x40, 0x1e, 0x43, 0x5d, 0x25, 0xc9, 0x42, 0xab, 0xd8, 0xae, + 0xef, 0x34, 0xe3, 0x96, 0xaa, 0x77, 0xed, 0x45, 0xa9, 0xa1, 0x52, 0xe2, 0x7d, 0x28, 0xbf, 0xf0, + 0x87, 0x03, 0x26, 0x8e, 0x90, 0x9c, 0x19, 0xd2, 0x04, 0x3d, 0xef, 0xfb, 0x13, 0x6f, 0xda, 0x47, + 0xf0, 0x81, 0xfd, 0x14, 0xee, 0x64, 0xd6, 0xa8, 0xe4, 0x13, 0x28, 0x62, 0x52, 0x18, 0xf9, 0xc0, + 0xa8, 0xb7, 0x8f, 0x61, 0x35, 0x9b, 0xc5, 0x93, 0x7b, 0x32, 0x7e, 0xd8, 0x9e, 0xec, 0x3e, 0x54, + 0xa4, 0x36, 0x3f, 0x6d, 0x3a, 0x01, 0x73, 0x42, 0x36, 0x38, 0xf6, 0xa2, 0xb4, 0x99, 0x0a, 0xc8, + 0x26, 0x34, 0x71, 0x3a, 0x0b, 0x76, 0x07, 0x83, 0x80, 0x8d, 0xc7, 0x3c, 0x32, 0x35, 0xaa, 0x0b, + 0xed, 0x3f, 0x1b, 0xd0, 0xd4, 0x9a, 0x82, 0x1c, 0x5f, 0x9f, 0x43, 0x55, 0x10, 0x62, 0xaf, 0x2b, + 0xdb, 0x9a, 0xdb, 0x3a, 0xc2, 0xa9, 0x2d, 0xf9, 0x02, 0x6a, 0x47, 0x93, 0xd0, 0x11, 0xa9, 0x5a, + 0xe4, 0x3b, 0x97, 0xad, 0xc8, 0xf3, 0xeb, 0x30, 0x70, 0x22, 0x5d, 0xd4, 0x13, 0x4d, 0x6d, 0x6d, + 0x13, 0x16, 0xf4, 0x03, 0xd9, 0xfe, 0xd6, 0xe0, 0x67, 0xa8, 0x52, 0xb7, 0xeb, 0x1f, 0x8e, 0x91, + 0xfc, 0x70, 0xa6, 0xdd, 0x67, 0x41, 0xed, 0x3e, 0xa7, 0xfd, 0x62, 0x31, 0xaf, 0x5f, 0x2c, 0x7d, + 0x58, 0xbf, 0x38, 0x9f, 0xee, 0x17, 0xf7, 0x61, 0x31, 0x71, 0x18, 0xff, 0x5f, 0x8d, 0xa1, 0xfd, + 0x37, 0x03, 0xac, 0xbc, 0xa6, 0x65, 0xc6, 0xe6, 0x37, 0xa1, 0xdc, 0x0d, 0x9d, 0x70, 0x32, 0xd6, + 0x2b, 0x2f, 0x21, 0xa3, 0x52, 0x47, 0x56, 0xa1, 0xcc, 0xdf, 0x6f, 0xc4, 0x2e, 0x72, 0x44, 0x1e, + 0x03, 0x4c, 0x7d, 0x22, 0xc5, 0x14, 0xf3, 0x97, 0xab, 0x18, 0xda, 0xbf, 0x81, 0xb5, 0xdc, 0x1a, + 0x82, 0x2c, 0x40, 0xe1, 0xf8, 0x25, 0x5f, 0x68, 0x95, 0x16, 0x8e, 0x5f, 0xfe, 0xb0, 0x15, 0xda, + 0x5f, 0x82, 0x95, 0xd7, 0x3f, 0xdc, 0x1e, 0x01, 0xfb, 0x3e, 0xac, 0xe5, 0x1e, 0xaa, 0xc9, 0xc5, + 0xa0, 0x9b, 0xbc, 0x96, 0x62, 0xb6, 0x9b, 0xdc, 0x63, 0x36, 0xe5, 0xe6, 0x17, 0xb0, 0x96, 0xdb, + 0x64, 0xcc, 0xf0, 0xf3, 0x04, 0xd6, 0xf3, 0x0f, 0x5e, 0x51, 0x86, 0x4b, 0xad, 0x64, 0xd4, 0x58, + 0x60, 0x3f, 0x86, 0x3b, 0x99, 0xad, 0xea, 0x0c, 0x97, 0x6d, 0x58, 0xcd, 0x2e, 0xe0, 0x52, 0xfb, + 0xfa, 0x1c, 0x56, 0xb3, 0xfb, 0xd7, 0x19, 0x1e, 0x3e, 0x85, 0xbb, 0x39, 0x55, 0x5d, 0xca, 0xc5, + 0x3e, 0x7c, 0x7c, 0x6b, 0xd3, 0x82, 0x3c, 0x1d, 0xce, 0xe0, 0xe9, 0xf0, 0xda, 0xb3, 0x7f, 0x06, + 0x1b, 0xb7, 0x1f, 0xe9, 0x29, 0xcf, 0x14, 0x96, 0x33, 0x3a, 0x6a, 0xf2, 0x15, 0x34, 0x45, 0x61, + 0x82, 0x27, 0x5b, 0x4c, 0xec, 0xf2, 0x33, 0x99, 0xaa, 0xa4, 0x6f, 0xdd, 0xd6, 0xfe, 0x25, 0xac, + 0x64, 0x95, 0xa0, 0xc8, 0xda, 0x42, 0x82, 0xc7, 0x80, 0x78, 0x97, 0xf8, 0x5d, 0xea, 0x42, 0xfb, + 0x11, 0x2c, 0x67, 0xb4, 0xe7, 0x33, 0x62, 0xfd, 0x14, 0x56, 0xb2, 0xea, 0xd5, 0xf8, 0x5a, 0xcd, + 0x50, 0xaf, 0xd5, 0x4c, 0x71, 0xea, 0x15, 0xb8, 0x7b, 0x7e, 0xc0, 0xed, 0x01, 0x49, 0x37, 0xb4, + 0x33, 0x58, 0x68, 0x8a, 0x62, 0x44, 0x28, 0x9f, 0xc1, 0x72, 0x46, 0xb9, 0x87, 0x44, 0x24, 0x2b, + 0x43, 0xb1, 0x0a, 0x39, 0xb2, 0xbf, 0x80, 0xda, 0x34, 0x70, 0xc4, 0x82, 0x4a, 0x54, 0x90, 0x0a, + 0x4f, 0xd1, 0x30, 0x63, 0xb5, 0x7f, 0x28, 0x46, 0xf5, 0x0d, 0x79, 0x08, 0x55, 0x4c, 0x5e, 0x7e, + 0x4c, 0x1a, 0xb7, 0x31, 0xef, 0xd4, 0x0c, 0x29, 0xfe, 0x85, 0x33, 0xee, 0xf8, 0xde, 0xbb, 0xa1, + 0xdb, 0x0f, 0xf9, 0xfa, 0xab, 0x54, 0x15, 0xe1, 0x8b, 0x7a, 0xe1, 0x8c, 0xbf, 0x09, 0xd8, 0xa5, + 0x6c, 0x2f, 0x8a, 0xdc, 0x46, 0x17, 0x92, 0x2f, 0xa1, 0x36, 0x3d, 0x1b, 0x65, 0xa5, 0x76, 0xdb, + 0xb9, 0x19, 0x1b, 0x7f, 0xc0, 0x75, 0x70, 0x0b, 0xea, 0xd1, 0xaa, 0x5e, 0xb2, 0x1b, 0xde, 0xd3, + 0x36, 0xa8, 0x2a, 0x52, 0x2d, 0x30, 0x4a, 0x15, 0xdd, 0x02, 0x23, 0xbb, 0x01, 0x80, 0xab, 0x16, + 0xb5, 0x01, 0x6f, 0x4d, 0x1b, 0x54, 0x91, 0x60, 0xe4, 0xc5, 0x93, 0xb8, 0x0f, 0x6e, 0xd2, 0x68, + 0x88, 0x33, 0x5f, 0xb3, 0x2b, 0x0c, 0xdc, 0xee, 0x40, 0xb4, 0x93, 0x55, 0xaa, 0x48, 0xec, 0x2e, + 0x34, 0xb5, 0x93, 0x1e, 0x5f, 0xd5, 0x39, 0xbb, 0x91, 0xd5, 0x05, 0x3e, 0x62, 0x81, 0x3b, 0x3e, + 0x77, 0x47, 0x32, 0xca, 0xfc, 0x19, 0xd3, 0x2a, 0x60, 0xa3, 0xa1, 0xd3, 0x67, 0x3d, 0x5f, 0x5e, + 0x0b, 0xc4, 0x02, 0xa4, 0x9b, 0xec, 0x5b, 0x91, 0x19, 0x9f, 0xc0, 0x1a, 0xdc, 0xcd, 0x69, 0x12, + 0xb6, 0x7e, 0xac, 0xfd, 0x1f, 0x20, 0x15, 0x5e, 0xc6, 0x9a, 0x73, 0xa4, 0x06, 0xf3, 0x14, 0xe3, + 0x6c, 0x1a, 0x5b, 0x9f, 0x88, 0x3c, 0xe2, 0xb7, 0xfe, 0x4d, 0xa8, 0x3d, 0xbf, 0xee, 0x0f, 0x27, + 0x63, 0xf7, 0x92, 0x99, 0x73, 0x04, 0xa0, 0x8c, 0xe5, 0x01, 0x1b, 0x98, 0xc6, 0xd6, 0x26, 0x40, + 0x7c, 0xf9, 0x4f, 0xaa, 0x50, 0xc2, 0x91, 0x39, 0x47, 0x1a, 0x50, 0xdd, 0x77, 0xc6, 0xe1, 0xbe, + 0xe3, 0x0e, 0x4d, 0x63, 0xeb, 0x5e, 0x5c, 0x70, 0xa0, 0xcd, 0x6b, 0xdf, 0x63, 0xc2, 0xdb, 0xb3, + 0x1b, 0x74, 0x6c, 0x6c, 0xfd, 0xa7, 0x10, 0xdd, 0x9d, 0xa0, 0x1e, 0x1d, 0x0b, 0x3f, 0xa2, 0x2a, + 0x32, 0x0d, 0xb2, 0xa0, 0x5e, 0x49, 0x98, 0x05, 0x42, 0x92, 0x57, 0x0c, 0x66, 0x11, 0x65, 0x3a, + 0x83, 0x9b, 0x25, 0x52, 0x9f, 0x5e, 0x1f, 0x98, 0xf3, 0xe4, 0x4e, 0xc6, 0xa5, 0x80, 0x59, 0x26, + 0x8b, 0x50, 0x97, 0x7f, 0x26, 0xf8, 0xa4, 0x0a, 0x59, 0x82, 0xa6, 0x14, 0x48, 0xff, 0x55, 0xb2, + 0x9c, 0x6a, 0xd7, 0xcd, 0x1a, 0x31, 0xf5, 0xa6, 0xdb, 0x04, 0x94, 0xa8, 0xb4, 0x63, 0xd6, 0xd1, + 0x67, 0xea, 0x60, 0x36, 0x1b, 0x64, 0x35, 0xab, 0xf3, 0x34, 0x9b, 0x68, 0x9e, 0x3a, 0x60, 0xcd, + 0x05, 0x5c, 0xa2, 0x42, 0x24, 0xe6, 0x22, 0xae, 0x27, 0xf1, 0x72, 0x4d, 0x93, 0xac, 0xe7, 0x35, + 0x79, 0xe6, 0x12, 0xee, 0xe9, 0x80, 0x85, 0xb8, 0x41, 0xd1, 0x18, 0x98, 0x64, 0x8b, 0x45, 0x35, + 0x89, 0x58, 0x24, 0xf7, 0x85, 0x06, 0xcf, 0x3d, 0x0c, 0x8e, 0x39, 0x87, 0x8b, 0x54, 0xc4, 0x32, + 0xd8, 0xa6, 0xa1, 0x98, 0xbf, 0xe1, 0xef, 0xa3, 0x3b, 0xe9, 0xf7, 0xcd, 0x82, 0x22, 0x8e, 0xb7, + 0x60, 0x16, 0x9f, 0x75, 0xbe, 0xff, 0xd7, 0x86, 0xf1, 0xdd, 0xfb, 0x0d, 0xe3, 0xfb, 0xf7, 0x1b, + 0xc6, 0x3f, 0xdf, 0x6f, 0xcc, 0xfd, 0xe5, 0xdf, 0x1b, 0xc6, 0xef, 0xd4, 0x5f, 0x5e, 0x17, 0x4e, + 0x18, 0xb8, 0xd7, 0x3e, 0xaf, 0x29, 0xa3, 0x81, 0xc7, 0xb6, 0x47, 0xe7, 0xa7, 0xdb, 0xa3, 0x93, + 0x6d, 0xdc, 0xc3, 0x49, 0x99, 0xff, 0xe8, 0x7a, 0xf4, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x17, + 0xa4, 0x0b, 0x37, 0x3c, 0x1b, 0x00, 0x00, } func (m *LockOptions) Marshal() (dAtA []byte, err error) { diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 0134532877f26..99d1bc01cb0e6 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -7022,6 +7022,9 @@ func normalizeUserLevelLockName(name string) (string, error) { if len(name) == 0 { return "", moerr.NewInternalErrorNoCtx("user-level lock name must not be empty") } + if strings.IndexByte(name, 0) >= 0 { + return "", moerr.NewInternalErrorNoCtx("user-level lock name must not contain NUL bytes") + } normalized := strings.ToLower(name) if utf8.RuneCountInString(normalized) > maxUserLevelLockNameLength { return "", moerr.NewInternalErrorNoCtxf( @@ -7032,6 +7035,10 @@ func normalizeUserLevelLockName(name string) (string, error) { return normalized, nil } +func userLevelLockProbeOwner(owner, probeType string) string { + return "probe:" + probeType + ":" + owner +} + func userLevelLockTxnID(owner string, connID uint64, name string) []byte { return []byte(fmt.Sprintf("mo-user-level-lock\x00%s\x00%s\x00%d", owner, name, connID)) } @@ -7212,7 +7219,7 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro if count == 0 { // Probe the lockservice to distinguish "lock does not exist" (NULL) // from "lock exists but held by another session" (0). - probeOwner := owner + "\x00release_probe\x00" + name + probeOwner := userLevelLockProbeOwner(owner, "release") _, probeErr := ls.Lock( proc.Ctx, userLevelLockTableID, @@ -7255,7 +7262,7 @@ func isUserLevelLockFree(name string, proc *process.Process) (int64, error) { } owner := userLevelLockOwner(proc) connID := userLevelLockConnectionID(proc) - probeOwner := owner + "\x00probe\x00" + name + probeOwner := userLevelLockProbeOwner(owner, "is_free") _, err = ls.Lock( proc.Ctx, userLevelLockTableID, @@ -7290,6 +7297,9 @@ func isUserLevelLockUsed(name string, proc *process.Process) (uint64, bool, erro userLevelLockRow(proc, name), userLevelLockOptions(lockpb.WaitPolicy_FastFail)) if err != nil { + if moerr.IsMoErrCode(err, moerr.ErrNotSupported) { + return 0, true, nil + } return 0, false, err } if !ok { diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index 8dec53be4dbfd..41a7e1f7e2011 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7179,6 +7179,14 @@ type userLevelLockTestService struct { state *userLevelLockTestState } +type userLevelLockNotSupportedService struct { + lockservice.LockService +} + +func (s *userLevelLockNotSupportedService) GetLockHolder(context.Context, uint64, []byte, lockpb.LockOptions) (lockpb.WaitTxn, bool, error) { + return lockpb.WaitTxn{}, false, moerr.NewNotSupportedNoCtx("GetLockHolder") +} + func (s *userLevelLockTestService) GetServiceID() string { return s.id } @@ -7558,6 +7566,17 @@ func TestIsUsedLockReturnsNullForLegacyHolderTxnID(t *testing.T) { }) } +func TestIsUsedLockReturnsNullWhenHolderLookupNotSupported(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc := newUserLevelLockTestProcess(t, &userLevelLockNotSupportedService{LockService: services[0]}, "acc") + + holder, isNull, err := isUserLevelLockUsed("holder_lookup_not_supported", proc) + require.NoError(t, err) + require.True(t, isNull) + require.Equal(t, uint64(0), holder) + }) +} + func TestIsUsedLockReturnsNullForMalformedHolderTxnID(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7707,6 +7726,25 @@ func TestUserLevelLockEmptyName(t *testing.T) { }) } +func TestUserLevelLockNameContainsNUL(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc1 := newUserLevelLockTestProcess(t, services[0], "acc") + name := "bad\x00lock" + + _, err := getUserLevelLock(name, 0, proc1) + require.Error(t, err) + + _, _, err = releaseUserLevelLock(name, proc1) + require.Error(t, err) + + _, err = isUserLevelLockFree(name, proc1) + require.Error(t, err) + + _, _, err = isUserLevelLockUsed(name, proc1) + require.Error(t, err) + }) +} + func TestUserLevelLockCaseInsensitive(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") diff --git a/proto/lock.proto b/proto/lock.proto index 53f9c887d7b39..7852e068e23d7 100644 --- a/proto/lock.proto +++ b/proto/lock.proto @@ -117,6 +117,8 @@ enum Method { ResumeInvalidCN = 16; // AbortRemoteDeadlockTxn abort remote txn for deadlock AbortRemoteDeadlockTxn = 17; + // GetLockHolder get current holder on a special lock + GetLockHolder = 18; } enum Status { From 0e1d4cd1517456b1587c6bc168206d319d2453ac Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 14:44:00 +0800 Subject: [PATCH 09/17] update --- pkg/sql/plan/function/func_unary.go | 22 ++++++------- pkg/sql/plan/function/func_unary_test.go | 41 ++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 99d1bc01cb0e6..25be67df76ab1 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -7035,14 +7035,14 @@ func normalizeUserLevelLockName(name string) (string, error) { return normalized, nil } -func userLevelLockProbeOwner(owner, probeType string) string { - return "probe:" + probeType + ":" + owner -} - func userLevelLockTxnID(owner string, connID uint64, name string) []byte { return []byte(fmt.Sprintf("mo-user-level-lock\x00%s\x00%s\x00%d", owner, name, connID)) } +func userLevelLockProbeTxnID(owner string, connID uint64, name, probeType string) []byte { + return []byte(fmt.Sprintf("mo-user-level-lock-probe\x00%s\x00%s\x00%s\x00%d", probeType, owner, name, connID)) +} + func userLevelLockConnectionIDFromTxnID(txnID []byte) (uint64, bool) { parts := strings.Split(string(txnID), "\x00") if len(parts) < 3 || len(parts) > 4 || parts[0] != "mo-user-level-lock" { @@ -7219,12 +7219,11 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro if count == 0 { // Probe the lockservice to distinguish "lock does not exist" (NULL) // from "lock exists but held by another session" (0). - probeOwner := userLevelLockProbeOwner(owner, "release") _, probeErr := ls.Lock( proc.Ctx, userLevelLockTableID, [][]byte{userLevelLockRow(proc, name)}, - userLevelLockTxnID(probeOwner, connID, name), + userLevelLockProbeTxnID(owner, connID, name, "release"), userLevelLockOptions(lockpb.WaitPolicy_FastFail)) if probeErr != nil { if userLevelLockConflictOrTimeout(probeErr) { @@ -7235,7 +7234,7 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro } // Lock did not exist — we acquired it via the probe. Release it and // return NULL to signal the lock was already free. - if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(probeOwner, connID, name), timestamp.Timestamp{}); err != nil { + if err := ls.Unlock(proc.Ctx, userLevelLockProbeTxnID(owner, connID, name, "release"), timestamp.Timestamp{}); err != nil { return 0, false, err } return 0, true, nil @@ -7262,12 +7261,11 @@ func isUserLevelLockFree(name string, proc *process.Process) (int64, error) { } owner := userLevelLockOwner(proc) connID := userLevelLockConnectionID(proc) - probeOwner := userLevelLockProbeOwner(owner, "is_free") _, err = ls.Lock( proc.Ctx, userLevelLockTableID, [][]byte{userLevelLockRow(proc, name)}, - userLevelLockTxnID(probeOwner, connID, name), + userLevelLockProbeTxnID(owner, connID, name, "is_free"), userLevelLockOptions(lockpb.WaitPolicy_FastFail)) if err != nil { if userLevelLockConflictOrTimeout(err) { @@ -7275,7 +7273,7 @@ func isUserLevelLockFree(name string, proc *process.Process) (int64, error) { } return 0, err } - if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(probeOwner, connID, name), timestamp.Timestamp{}); err != nil { + if err := ls.Unlock(proc.Ctx, userLevelLockProbeTxnID(owner, connID, name, "is_free"), timestamp.Timestamp{}); err != nil { return 0, err } return 1, nil @@ -7327,7 +7325,9 @@ func releaseAllUserLevelLocks(proc *process.Process) int64 { break } if count == 0 { - _ = proc.GetLockService().Unlock(context.Background(), userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}) + if err := proc.GetLockService().Unlock(context.Background(), userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}); err != nil { + logutil.Warn(fmt.Sprintf("releaseAllUserLevelLocks unlock failed: owner=%s lock=%s err=%v", owner, name, err)) + } break } } diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index 41a7e1f7e2011..36c9f57dca43d 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7175,8 +7175,9 @@ type userLevelLockTestState struct { } type userLevelLockTestService struct { - id string - state *userLevelLockTestState + id string + state *userLevelLockTestState + unlockErr error } type userLevelLockNotSupportedService struct { @@ -7223,6 +7224,9 @@ func (s *userLevelLockTestService) Lock(ctx context.Context, tableID uint64, row } func (s *userLevelLockTestService) Unlock(ctx context.Context, txnID []byte, commitTS timestamp.Timestamp, mutations ...lockpb.ExtraMutation) error { + if s.unlockErr != nil { + return s.unlockErr + } owner := string(txnID) s.state.Lock() defer s.state.Unlock() @@ -7285,6 +7289,13 @@ func userLevelLockTxnIDOld(owner, name string) []byte { return []byte("mo-user-level-lock\x00" + owner + "\x00" + name) } +func TestUserLevelLockConnectionIDFromProbeTxnID(t *testing.T) { + txnID := userLevelLockProbeTxnID("owner-1", 1001, "probe_lock", "is_free") + connID, ok := userLevelLockConnectionIDFromTxnID(txnID) + require.False(t, ok) + require.Equal(t, uint64(0), connID) +} + func TestUserLevelLockFunctions(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7630,6 +7641,32 @@ func TestReleaseAllUserLevelLocksReturnsReleasedCount(t *testing.T) { }) } +func TestReleaseAllUserLevelLocksReturnsCountWhenUnlockFails(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc1 := newUserLevelLockTestProcess(t, services[0], "acc") + proc2 := newUserLevelLockTestProcess(t, services[1], "acc") + services[0].(*userLevelLockTestService).unlockErr = moerr.NewInternalErrorNoCtx("unlock failed") + + v, err := getUserLevelLock("release_all_fail_a", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + v, err = getUserLevelLock("release_all_fail_a", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + v, err = getUserLevelLock("release_all_fail_b", 0, proc1) + require.NoError(t, err) + require.Equal(t, int64(1), v) + + released := releaseAllUserLevelLocks(proc1) + require.Equal(t, int64(2), released) + require.Equal(t, int64(0), releaseAllUserLevelLocks(proc1)) + + v, err = getUserLevelLock("release_all_fail_a", 0, proc2) + require.NoError(t, err) + require.Equal(t, int64(0), v) + }) +} + func TestReleaseLockNeverCreatedReturnsNull(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") From 19c23733664fc700738928ed185d6c0859275557 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 16:22:55 +0800 Subject: [PATCH 10/17] update --- pkg/sql/plan/function/func_unary.go | 18 ++- pkg/sql/plan/function/func_unary_test.go | 172 ++++++++++++++++++++++- 2 files changed, 182 insertions(+), 8 deletions(-) diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 25be67df76ab1..787af35eac4c7 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -7039,6 +7039,10 @@ func userLevelLockTxnID(owner string, connID uint64, name string) []byte { return []byte(fmt.Sprintf("mo-user-level-lock\x00%s\x00%s\x00%d", owner, name, connID)) } +func userLevelLockTxnIDOld(owner, name string) []byte { + return []byte("mo-user-level-lock\x00" + owner + "\x00" + name) +} + func userLevelLockProbeTxnID(owner string, connID uint64, name, probeType string) []byte { return []byte(fmt.Sprintf("mo-user-level-lock-probe\x00%s\x00%s\x00%s\x00%d", probeType, owner, name, connID)) } @@ -7073,6 +7077,13 @@ func userLevelLockService(proc *process.Process) (lockservice.LockService, error return proc.GetLockService(), nil } +func unlockUserLevelLockTxnIDs(ctx context.Context, ls lockservice.LockService, owner string, connID uint64, name string) error { + if err := ls.Unlock(ctx, userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}); err != nil { + return err + } + return ls.Unlock(ctx, userLevelLockTxnIDOld(owner, name), timestamp.Timestamp{}) +} + func userLevelLockOptions(policy lockpb.WaitPolicy) lockpb.LockOptions { return lockpb.LockOptions{ Granularity: lockpb.Granularity_Row, @@ -7243,7 +7254,7 @@ func releaseUserLevelLock(name string, proc *process.Process) (int64, bool, erro untrackUserLevelLock(owner, name) return 1, false, nil } - if err := ls.Unlock(proc.Ctx, userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}); err != nil { + if err := unlockUserLevelLockTxnIDs(proc.Ctx, ls, owner, connID, name); err != nil { return 0, false, err } untrackUserLevelLock(owner, name) @@ -7318,15 +7329,16 @@ func releaseAllUserLevelLocks(proc *process.Process) int64 { connID := userLevelLockConnectionID(proc) var released int64 for _, name := range userLevelLocksForOwner(owner) { - released++ for { count, held := untrackUserLevelLock(owner, name) if !held { break } if count == 0 { - if err := proc.GetLockService().Unlock(context.Background(), userLevelLockTxnID(owner, connID, name), timestamp.Timestamp{}); err != nil { + if err := unlockUserLevelLockTxnIDs(context.Background(), proc.GetLockService(), owner, connID, name); err != nil { logutil.Warn(fmt.Sprintf("releaseAllUserLevelLocks unlock failed: owner=%s lock=%s err=%v", owner, name, err)) + } else { + released++ } break } diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index 36c9f57dca43d..1c726834afc6a 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7285,10 +7285,6 @@ func runUserLevelLockTest(t *testing.T, fn func([]lockservice.LockService)) { resetUserLevelLocksForTest(t) } -func userLevelLockTxnIDOld(owner, name string) []byte { - return []byte("mo-user-level-lock\x00" + owner + "\x00" + name) -} - func TestUserLevelLockConnectionIDFromProbeTxnID(t *testing.T) { txnID := userLevelLockProbeTxnID("owner-1", 1001, "probe_lock", "is_free") connID, ok := userLevelLockConnectionIDFromTxnID(txnID) @@ -7539,6 +7535,105 @@ func TestReleaseUserLevelLocksCleanup(t *testing.T) { }) } +func TestUserLevelLockConcurrentSessionOperations(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + const ( + workers = 8 + iterations = 40 + ) + + lockName := "concurrent_lock" + procs := make([]*process.Process, 0, workers) + for i := 0; i < workers; i++ { + procs = append(procs, newUserLevelLockTestProcess(t, services[i%len(services)], "acc")) + } + + start := make(chan struct{}) + errCh := make(chan error, workers) + var wg sync.WaitGroup + + for idx, proc := range procs { + wg.Add(1) + go func(worker int, proc *process.Process) { + defer wg.Done() + <-start + + for iter := 0; iter < iterations; iter++ { + value, err := getUserLevelLock(lockName, 0, proc) + if err != nil { + errCh <- fmt.Errorf("worker %d iter %d get lock: %w", worker, iter, err) + return + } + if value == 1 { + if iter%3 == 0 { + reentrant, err := getUserLevelLock(lockName, 0, proc) + if err != nil { + errCh <- fmt.Errorf("worker %d iter %d reentrant get: %w", worker, iter, err) + return + } + if reentrant != 1 { + errCh <- fmt.Errorf("worker %d iter %d expected reentrant get to succeed, got %d", worker, iter, reentrant) + return + } + } + + if iter%2 == 0 { + released, isNull, err := releaseUserLevelLock(lockName, proc) + if err != nil { + errCh <- fmt.Errorf("worker %d iter %d release lock: %w", worker, iter, err) + return + } + if isNull || released != 1 { + errCh <- fmt.Errorf("worker %d iter %d unexpected release result: released=%d isNull=%v", worker, iter, released, isNull) + return + } + } else { + released := releaseAllUserLevelLocks(proc) + if released < 1 { + errCh <- fmt.Errorf("worker %d iter %d expected release_all to release at least one lock, got %d", worker, iter, released) + return + } + } + } else { + _, _, err := isUserLevelLockUsed(lockName, proc) + if err != nil { + errCh <- fmt.Errorf("worker %d iter %d is_used_lock: %w", worker, iter, err) + return + } + if iter%5 == 0 { + released := releaseAllUserLevelLocks(proc) + if released != 0 { + errCh <- fmt.Errorf("worker %d iter %d expected release_all to release 0 locks, got %d", worker, iter, released) + return + } + } + } + } + }(idx, proc) + } + + close(start) + wg.Wait() + close(errCh) + for err := range errCh { + require.NoError(t, err) + } + + for _, proc := range procs { + require.Equal(t, int64(0), releaseAllUserLevelLocks(proc)) + } + + finalProc := newUserLevelLockTestProcess(t, services[0], "acc") + value, err := getUserLevelLock(lockName, 0, finalProc) + require.NoError(t, err) + require.Equal(t, int64(1), value) + released, isNull, err := releaseUserLevelLock(lockName, finalProc) + require.NoError(t, err) + require.False(t, isNull) + require.Equal(t, int64(1), released) + }) +} + func TestIsUsedLockReturnsHolderConnectionID(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7588,6 +7683,21 @@ func TestIsUsedLockReturnsNullWhenHolderLookupNotSupported(t *testing.T) { }) } +func TestIsUsedLockReturnsZeroConnectionID(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc := newUserLevelLockTestProcess(t, services[0], "acc") + state := services[0].(*userLevelLockTestService).state + state.Lock() + state.locks[string(userLevelLockRow(proc, "zero_conn_holder"))] = string(userLevelLockTxnID(userLevelLockOwner(proc), 0, "zero_conn_holder")) + state.Unlock() + + holder, isNull, err := isUserLevelLockUsed("zero_conn_holder", proc) + require.NoError(t, err) + require.False(t, isNull) + require.Equal(t, uint64(0), holder) + }) +} + func TestIsUsedLockReturnsNullForMalformedHolderTxnID(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7658,7 +7768,7 @@ func TestReleaseAllUserLevelLocksReturnsCountWhenUnlockFails(t *testing.T) { require.Equal(t, int64(1), v) released := releaseAllUserLevelLocks(proc1) - require.Equal(t, int64(2), released) + require.Equal(t, int64(0), released) require.Equal(t, int64(0), releaseAllUserLevelLocks(proc1)) v, err = getUserLevelLock("release_all_fail_a", 0, proc2) @@ -7667,6 +7777,58 @@ func TestReleaseAllUserLevelLocksReturnsCountWhenUnlockFails(t *testing.T) { }) } +func TestReleaseLockLegacyTxnIDCompatible(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc1 := newUserLevelLockTestProcess(t, services[0], "acc") + proc2 := newUserLevelLockTestProcess(t, services[1], "acc") + owner := userLevelLockOwner(proc1) + state := services[0].(*userLevelLockTestService).state + name := "legacy_release" + + state.Lock() + state.locks[string(userLevelLockRow(proc1, name))] = string(userLevelLockTxnIDOld(owner, name)) + state.Unlock() + trackUserLevelLock(owner, name) + + v, isNull, err := releaseUserLevelLock(name, proc1) + require.NoError(t, err) + require.False(t, isNull) + require.Equal(t, int64(1), v) + + v, err = getUserLevelLock(name, 0, proc2) + require.NoError(t, err) + require.Equal(t, int64(1), v) + }) +} + +func TestReleaseAllUserLevelLocksLegacyTxnIDCompatible(t *testing.T) { + runUserLevelLockTest(t, func(services []lockservice.LockService) { + proc1 := newUserLevelLockTestProcess(t, services[0], "acc") + proc2 := newUserLevelLockTestProcess(t, services[1], "acc") + owner := userLevelLockOwner(proc1) + state := services[0].(*userLevelLockTestService).state + + state.Lock() + state.locks[string(userLevelLockRow(proc1, "legacy_all_a"))] = string(userLevelLockTxnIDOld(owner, "legacy_all_a")) + state.locks[string(userLevelLockRow(proc1, "legacy_all_b"))] = string(userLevelLockTxnIDOld(owner, "legacy_all_b")) + state.Unlock() + trackUserLevelLock(owner, "legacy_all_a") + trackUserLevelLock(owner, "legacy_all_a") + trackUserLevelLock(owner, "legacy_all_b") + + released := releaseAllUserLevelLocks(proc1) + require.Equal(t, int64(2), released) + + v, err := getUserLevelLock("legacy_all_a", 0, proc2) + require.NoError(t, err) + require.Equal(t, int64(1), v) + + v, err = getUserLevelLock("legacy_all_b", 0, proc2) + require.NoError(t, err) + require.Equal(t, int64(1), v) + }) +} + func TestReleaseLockNeverCreatedReturnsNull(t *testing.T) { runUserLevelLockTest(t, func(services []lockservice.LockService) { proc1 := newUserLevelLockTestProcess(t, services[0], "acc") From 2168c20a87db08a91e871d442bfe43529a40e768 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 17:15:20 +0800 Subject: [PATCH 11/17] update --- pkg/sql/plan/function/func_unary.go | 27 ++++++++++++++----- pkg/sql/plan/function/func_unary_test.go | 33 ++++++++++++++++++------ 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index 787af35eac4c7..fe1d7aac2fde5 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -7321,13 +7321,14 @@ func isUserLevelLockUsed(name string, proc *process.Process) (uint64, bool, erro return holderConnID, false, nil } -func releaseAllUserLevelLocks(proc *process.Process) int64 { +func releaseAllUserLevelLocks(proc *process.Process) (int64, error) { if proc == nil || proc.GetLockService() == nil { - return 0 + return 0, nil } owner := userLevelLockOwner(proc) connID := userLevelLockConnectionID(proc) var released int64 + var firstErr error for _, name := range userLevelLocksForOwner(owner) { for { count, held := untrackUserLevelLock(owner, name) @@ -7337,6 +7338,9 @@ func releaseAllUserLevelLocks(proc *process.Process) int64 { if count == 0 { if err := unlockUserLevelLockTxnIDs(context.Background(), proc.GetLockService(), owner, connID, name); err != nil { logutil.Warn(fmt.Sprintf("releaseAllUserLevelLocks unlock failed: owner=%s lock=%s err=%v", owner, name, err)) + if firstErr == nil { + firstErr = err + } } else { released++ } @@ -7344,11 +7348,11 @@ func releaseAllUserLevelLocks(proc *process.Process) int64 { } } } - return released + return released, firstErr } func ReleaseUserLevelLocks(proc *process.Process) { - _ = releaseAllUserLevelLocks(proc) + _, _ = releaseAllUserLevelLocks(proc) } func GetLock(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, selectList *FunctionSelectList) error { @@ -7446,9 +7450,18 @@ func IsUsedLock(ivecs []*vector.Vector, result vector.FunctionResultWrapper, pro } func ReleaseAllLocks(_ []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, selectList *FunctionSelectList) error { - return opNoneParamToFixed[int64](result, proc, length, func() int64 { - return releaseAllUserLevelLocks(proc) - }) + rs := vector.MustFunctionResult[int64](result) + rsVec := rs.GetResultVector() + rss := vector.MustFixedColNoTypeCheck[int64](rsVec) + + for i := 0; i < length; i++ { + released, err := releaseAllUserLevelLocks(proc) + if err != nil { + return err + } + rss[i] = released + } + return nil } func Version( diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index 1c726834afc6a..abdb7e2c12afa 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7588,7 +7588,11 @@ func TestUserLevelLockConcurrentSessionOperations(t *testing.T) { return } } else { - released := releaseAllUserLevelLocks(proc) + released, err := releaseAllUserLevelLocks(proc) + if err != nil { + errCh <- fmt.Errorf("worker %d iter %d release_all: %w", worker, iter, err) + return + } if released < 1 { errCh <- fmt.Errorf("worker %d iter %d expected release_all to release at least one lock, got %d", worker, iter, released) return @@ -7601,7 +7605,11 @@ func TestUserLevelLockConcurrentSessionOperations(t *testing.T) { return } if iter%5 == 0 { - released := releaseAllUserLevelLocks(proc) + released, err := releaseAllUserLevelLocks(proc) + if err != nil { + errCh <- fmt.Errorf("worker %d iter %d release_all: %w", worker, iter, err) + return + } if released != 0 { errCh <- fmt.Errorf("worker %d iter %d expected release_all to release 0 locks, got %d", worker, iter, released) return @@ -7620,7 +7628,9 @@ func TestUserLevelLockConcurrentSessionOperations(t *testing.T) { } for _, proc := range procs { - require.Equal(t, int64(0), releaseAllUserLevelLocks(proc)) + released, err := releaseAllUserLevelLocks(proc) + require.NoError(t, err) + require.Equal(t, int64(0), released) } finalProc := newUserLevelLockTestProcess(t, services[0], "acc") @@ -7728,9 +7738,12 @@ func TestReleaseAllUserLevelLocksReturnsReleasedCount(t *testing.T) { require.NoError(t, err) require.Equal(t, int64(1), v) - released := releaseAllUserLevelLocks(proc1) + released, err := releaseAllUserLevelLocks(proc1) + require.NoError(t, err) require.Equal(t, int64(2), released) - require.Equal(t, int64(0), releaseAllUserLevelLocks(proc1)) + released, err = releaseAllUserLevelLocks(proc1) + require.NoError(t, err) + require.Equal(t, int64(0), released) v, err = getUserLevelLock("release_all_a", 0, proc2) require.NoError(t, err) @@ -7767,9 +7780,12 @@ func TestReleaseAllUserLevelLocksReturnsCountWhenUnlockFails(t *testing.T) { require.NoError(t, err) require.Equal(t, int64(1), v) - released := releaseAllUserLevelLocks(proc1) + released, err := releaseAllUserLevelLocks(proc1) + require.Error(t, err) + require.Equal(t, int64(0), released) + released, err = releaseAllUserLevelLocks(proc1) + require.NoError(t, err) require.Equal(t, int64(0), released) - require.Equal(t, int64(0), releaseAllUserLevelLocks(proc1)) v, err = getUserLevelLock("release_all_fail_a", 0, proc2) require.NoError(t, err) @@ -7816,7 +7832,8 @@ func TestReleaseAllUserLevelLocksLegacyTxnIDCompatible(t *testing.T) { trackUserLevelLock(owner, "legacy_all_a") trackUserLevelLock(owner, "legacy_all_b") - released := releaseAllUserLevelLocks(proc1) + released, err := releaseAllUserLevelLocks(proc1) + require.NoError(t, err) require.Equal(t, int64(2), released) v, err := getUserLevelLock("legacy_all_a", 0, proc2) From d10a2d1eb6154b776e82179b7b4b1504ff9bd3b8 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 17:33:20 +0800 Subject: [PATCH 12/17] update bvt --- .../cases/function/user_lock.result | 33 +++++++++++++++++++ test/distributed/cases/function/user_lock.sql | 13 ++++++++ 2 files changed, 46 insertions(+) diff --git a/test/distributed/cases/function/user_lock.result b/test/distributed/cases/function/user_lock.result index d640b2b43bedd..dc5edfc8f99c9 100644 --- a/test/distributed/cases/function/user_lock.result +++ b/test/distributed/cases/function/user_lock.result @@ -66,5 +66,38 @@ select release_all_locks(); select release_all_locks(); ➤ release_all_locks()[-5,64,0] 𝄀 0 +select get_lock('user_lock_bvt_multi_a', 0); +➤ get_lock(user_lock_bvt_multi_a, 0)[-5,64,0] 𝄀 +1 +select get_lock('user_lock_bvt_multi_a', 0); +➤ get_lock(user_lock_bvt_multi_a, 0)[-5,64,0] 𝄀 +1 +select get_lock('user_lock_bvt_multi_a', 0); +➤ get_lock(user_lock_bvt_multi_a, 0)[-5,64,0] 𝄀 +1 +select get_lock('user_lock_bvt_multi_b', 0); +➤ get_lock(user_lock_bvt_multi_b, 0)[-5,64,0] 𝄀 +1 +select release_all_locks(); +➤ release_all_locks()[-5,64,0] 𝄀 +2 +select is_free_lock('user_lock_bvt_multi_a'); +➤ is_free_lock(user_lock_bvt_multi_a)[-5,64,0] 𝄀 +1 +select is_free_lock('user_lock_bvt_multi_b'); +➤ is_free_lock(user_lock_bvt_multi_b)[-5,64,0] 𝄀 +1 +select get_lock('User_Lock_Bvt_Case', 0); +➤ get_lock(User_Lock_Bvt_Case, 0)[-5,64,0] 𝄀 +1 +select is_free_lock('user_lock_bvt_case'); +➤ is_free_lock(user_lock_bvt_case)[-5,64,0] 𝄀 +0 +select release_lock('USER_LOCK_BVT_CASE'); +➤ release_lock(USER_LOCK_BVT_CASE)[-5,64,0] 𝄀 +1 +select is_free_lock('user_lock_bvt_case'); +➤ is_free_lock(user_lock_bvt_case)[-5,64,0] 𝄀 +1 drop table user_lock_bvt_holder; drop database user_lock_bvt_db; diff --git a/test/distributed/cases/function/user_lock.sql b/test/distributed/cases/function/user_lock.sql index 8f6bee0efe43e..74aa7805cbd6b 100644 --- a/test/distributed/cases/function/user_lock.sql +++ b/test/distributed/cases/function/user_lock.sql @@ -45,5 +45,18 @@ select get_lock('user_lock_bvt_lock', 0); select release_all_locks(); select release_all_locks(); +select get_lock('user_lock_bvt_multi_a', 0); +select get_lock('user_lock_bvt_multi_a', 0); +select get_lock('user_lock_bvt_multi_a', 0); +select get_lock('user_lock_bvt_multi_b', 0); +select release_all_locks(); +select is_free_lock('user_lock_bvt_multi_a'); +select is_free_lock('user_lock_bvt_multi_b'); + +select get_lock('User_Lock_Bvt_Case', 0); +select is_free_lock('user_lock_bvt_case'); +select release_lock('USER_LOCK_BVT_CASE'); +select is_free_lock('user_lock_bvt_case'); + drop table user_lock_bvt_holder; drop database user_lock_bvt_db; From 2c21bd8273c7c69f02832ddd11ff60db995c9318 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 17:59:26 +0800 Subject: [PATCH 13/17] update --- pkg/lockservice/lock_table_remote.go | 6 +- pkg/lockservice/lock_table_remote_test.go | 2 - pkg/lockservice/service_remote.go | 10 +- pkg/pb/lock/lock.pb.go | 810 ++++++++++++++++------ proto/lock.proto | 14 +- 5 files changed, 615 insertions(+), 227 deletions(-) diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index b991b4d351c9c..6d926ed057abf 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -344,7 +344,7 @@ func (l *remoteLockTable) doGetLockHolder(key []byte) (pb.WaitTxn, bool, error) req.Method = pb.Method_GetLockHolder req.LockTable = l.bind - req.GetTxnLock.Row = key + req.GetLockHolder.Row = key resp, err := l.client.Send(ctx, req) if err == nil { @@ -352,10 +352,10 @@ func (l *remoteLockTable) doGetLockHolder(key []byte) (pb.WaitTxn, bool, error) if err := l.maybeHandleBindChanged(resp); err != nil { return pb.WaitTxn{}, false, err } - if !resp.GetTxnLock.Found { + if len(resp.GetLockHolder.Holder.TxnID) == 0 { return pb.WaitTxn{}, false, nil } - return resp.GetTxnLock.Holder, true, nil + return resp.GetLockHolder.Holder, true, nil } return pb.WaitTxn{}, false, moerr.AttachCause(ctx, err) } diff --git a/pkg/lockservice/lock_table_remote_test.go b/pkg/lockservice/lock_table_remote_test.go index ee277a24a5752..85b7f03cd3631 100644 --- a/pkg/lockservice/lock_table_remote_test.go +++ b/pkg/lockservice/lock_table_remote_test.go @@ -352,9 +352,7 @@ func TestGetLockRemoteWithRetry(t *testing.T) { writeResponse(getLogger(""), cancel, resp, moerr.NewRPCTimeout(ctx), cs) return } - resp.GetTxnLock.Found = true resp.GetTxnLock.Value = int32(pb.Granularity_Row) - resp.GetTxnLock.Holder = pb.WaitTxn{TxnID: []byte("txn1")} writeResponse(getLogger(""), cancel, resp, nil, cs) }, ) diff --git a/pkg/lockservice/service_remote.go b/pkg/lockservice/service_remote.go index c249f3bafd1af..739c9ae5daf7d 100644 --- a/pkg/lockservice/service_remote.go +++ b/pkg/lockservice/service_remote.go @@ -419,12 +419,7 @@ func (s *service) handleRemoteGetLock( req.GetTxnLock.Row, pb.WaitTxn{TxnID: req.GetTxnLock.TxnID}, func(lock Lock) { - resp.GetTxnLock.Found = true resp.GetTxnLock.Value = int32(lock.value) - lock.IterHolders(func(holder pb.WaitTxn) bool { - resp.GetTxnLock.Holder = holder - return false - }) values := make([]pb.WaitTxn, 0) lock.waiters.iter(func(w *waiter) bool { values = append(values, w.txn) @@ -447,10 +442,9 @@ func (s *service) handleRemoteGetLockHolder( return } - holder, found, err := l.getLockHolder(req.GetTxnLock.Row) + holder, found, err := l.getLockHolder(req.GetLockHolder.Row) if err == nil && found { - resp.GetTxnLock.Holder = holder - resp.GetTxnLock.Found = true + resp.GetLockHolder.Holder = holder } writeResponse(s.logger, cancel, resp, err, cs) } diff --git a/pkg/pb/lock/lock.pb.go b/pkg/pb/lock/lock.pb.go index ac426dad71d3c..26b3cb9eb217e 100644 --- a/pkg/pb/lock/lock.pb.go +++ b/pkg/pb/lock/lock.pb.go @@ -492,6 +492,7 @@ type Request struct { RemainTxnInService RemainTxnInServiceRequest `protobuf:"bytes,16,opt,name=RemainTxnInService,proto3" json:"RemainTxnInService"` CheckOrphan CheckOrphanRequest `protobuf:"bytes,17,opt,name=CheckOrphan,proto3" json:"CheckOrphan"` ResumeInvalidCN ResumeInvalidCNRequest `protobuf:"bytes,18,opt,name=ResumeInvalidCN,proto3" json:"ResumeInvalidCN"` + GetLockHolder GetLockHolderRequest `protobuf:"bytes,19,opt,name=GetLockHolder,proto3" json:"GetLockHolder"` AbortRemoteDeadlockTxn AbortRemoteDeadlockTxnRequest `protobuf:"bytes,20,opt,name=AbortRemoteDeadlockTxn,proto3" json:"AbortRemoteDeadlockTxn"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -657,6 +658,13 @@ func (m *Request) GetResumeInvalidCN() ResumeInvalidCNRequest { return ResumeInvalidCNRequest{} } +func (m *Request) GetGetLockHolder() GetLockHolderRequest { + if m != nil { + return m.GetLockHolder + } + return GetLockHolderRequest{} +} + func (m *Request) GetAbortRemoteDeadlockTxn() AbortRemoteDeadlockTxnRequest { if m != nil { return m.AbortRemoteDeadlockTxn @@ -689,6 +697,7 @@ type Response struct { CheckOrphan CheckOrphanResponse `protobuf:"bytes,18,opt,name=CheckOrphan,proto3" json:"CheckOrphan"` ResumeInvalidCN ResumeInvalidCNResponse `protobuf:"bytes,19,opt,name=ResumeInvalidCN,proto3" json:"ResumeInvalidCN"` AbortRemoteDeadlockTxn AbortRemoteDeadlockTxnResponse `protobuf:"bytes,20,opt,name=AbortRemoteDeadlockTxn,proto3" json:"AbortRemoteDeadlockTxn"` + GetLockHolder GetLockHolderResponse `protobuf:"bytes,21,opt,name=GetLockHolder,proto3" json:"GetLockHolder"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -867,6 +876,13 @@ func (m *Response) GetAbortRemoteDeadlockTxn() AbortRemoteDeadlockTxnResponse { return AbortRemoteDeadlockTxnResponse{} } +func (m *Response) GetGetLockHolder() GetLockHolderResponse { + if m != nil { + return m.GetLockHolder + } + return GetLockHolderResponse{} +} + // LockRequest lock request type LockRequest struct { TxnID []byte `protobuf:"bytes,1,opt,name=TxnID,proto3" json:"TxnID,omitempty"` @@ -1049,8 +1065,6 @@ func (m *GetTxnLockRequest) GetRow() []byte { type GetTxnLockResponse struct { Value int32 `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"` WaitingList []WaitTxn `protobuf:"bytes,2,rep,name=WaitingList,proto3" json:"WaitingList"` - Holder WaitTxn `protobuf:"bytes,3,opt,name=Holder,proto3" json:"Holder"` - Found bool `protobuf:"varint,4,opt,name=Found,proto3" json:"Found,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1103,18 +1117,100 @@ func (m *GetTxnLockResponse) GetWaitingList() []WaitTxn { return nil } -func (m *GetTxnLockResponse) GetHolder() WaitTxn { +// GetLockHolderRequest gets the current holder on a special row lock. +type GetLockHolderRequest struct { + Row []byte `protobuf:"bytes,1,opt,name=Row,proto3" json:"Row,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetLockHolderRequest) Reset() { *m = GetLockHolderRequest{} } +func (m *GetLockHolderRequest) String() string { return proto.CompactTextString(m) } +func (*GetLockHolderRequest) ProtoMessage() {} +func (*GetLockHolderRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_164ad2988c7acaf1, []int{8} +} +func (m *GetLockHolderRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetLockHolderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetLockHolderRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetLockHolderRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetLockHolderRequest.Merge(m, src) +} +func (m *GetLockHolderRequest) XXX_Size() int { + return m.ProtoSize() +} +func (m *GetLockHolderRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetLockHolderRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetLockHolderRequest proto.InternalMessageInfo + +func (m *GetLockHolderRequest) GetRow() []byte { if m != nil { - return m.Holder + return m.Row } - return WaitTxn{} + return nil } -func (m *GetTxnLockResponse) GetFound() bool { +// GetLockHolderResponse gets the current holder on a special row lock. +type GetLockHolderResponse struct { + Holder WaitTxn `protobuf:"bytes,1,opt,name=Holder,proto3" json:"Holder"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetLockHolderResponse) Reset() { *m = GetLockHolderResponse{} } +func (m *GetLockHolderResponse) String() string { return proto.CompactTextString(m) } +func (*GetLockHolderResponse) ProtoMessage() {} +func (*GetLockHolderResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_164ad2988c7acaf1, []int{9} +} +func (m *GetLockHolderResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetLockHolderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetLockHolderResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetLockHolderResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetLockHolderResponse.Merge(m, src) +} +func (m *GetLockHolderResponse) XXX_Size() int { + return m.ProtoSize() +} +func (m *GetLockHolderResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetLockHolderResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetLockHolderResponse proto.InternalMessageInfo + +func (m *GetLockHolderResponse) GetHolder() WaitTxn { if m != nil { - return m.Found + return m.Holder } - return false + return WaitTxn{} } // GetWaitingListRequest get a waiting txn list on a specical txn request. CN -> CN @@ -1129,7 +1225,7 @@ func (m *GetWaitingListRequest) Reset() { *m = GetWaitingListRequest{} } func (m *GetWaitingListRequest) String() string { return proto.CompactTextString(m) } func (*GetWaitingListRequest) ProtoMessage() {} func (*GetWaitingListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{8} + return fileDescriptor_164ad2988c7acaf1, []int{10} } func (m *GetWaitingListRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1177,7 +1273,7 @@ func (m *GetWaitingListResponse) Reset() { *m = GetWaitingListResponse{} func (m *GetWaitingListResponse) String() string { return proto.CompactTextString(m) } func (*GetWaitingListResponse) ProtoMessage() {} func (*GetWaitingListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{9} + return fileDescriptor_164ad2988c7acaf1, []int{11} } func (m *GetWaitingListResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1227,7 +1323,7 @@ func (m *WaitTxn) Reset() { *m = WaitTxn{} } func (m *WaitTxn) String() string { return proto.CompactTextString(m) } func (*WaitTxn) ProtoMessage() {} func (*WaitTxn) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{10} + return fileDescriptor_164ad2988c7acaf1, []int{12} } func (m *WaitTxn) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1293,7 +1389,7 @@ func (m *UnlockRequest) Reset() { *m = UnlockRequest{} } func (m *UnlockRequest) String() string { return proto.CompactTextString(m) } func (*UnlockRequest) ProtoMessage() {} func (*UnlockRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{11} + return fileDescriptor_164ad2988c7acaf1, []int{13} } func (m *UnlockRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1354,7 +1450,7 @@ func (m *UnlockResponse) Reset() { *m = UnlockResponse{} } func (m *UnlockResponse) String() string { return proto.CompactTextString(m) } func (*UnlockResponse) ProtoMessage() {} func (*UnlockResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{12} + return fileDescriptor_164ad2988c7acaf1, []int{14} } func (m *UnlockResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1399,7 +1495,7 @@ func (m *GetBindRequest) Reset() { *m = GetBindRequest{} } func (m *GetBindRequest) String() string { return proto.CompactTextString(m) } func (*GetBindRequest) ProtoMessage() {} func (*GetBindRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{13} + return fileDescriptor_164ad2988c7acaf1, []int{15} } func (m *GetBindRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1475,7 +1571,7 @@ func (m *GetBindResponse) Reset() { *m = GetBindResponse{} } func (m *GetBindResponse) String() string { return proto.CompactTextString(m) } func (*GetBindResponse) ProtoMessage() {} func (*GetBindResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{14} + return fileDescriptor_164ad2988c7acaf1, []int{16} } func (m *GetBindResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1526,7 +1622,7 @@ func (m *KeepLockTableBindRequest) Reset() { *m = KeepLockTableBindReque func (m *KeepLockTableBindRequest) String() string { return proto.CompactTextString(m) } func (*KeepLockTableBindRequest) ProtoMessage() {} func (*KeepLockTableBindRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{15} + return fileDescriptor_164ad2988c7acaf1, []int{17} } func (m *KeepLockTableBindRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1596,7 +1692,7 @@ func (m *KeepLockTableBindResponse) Reset() { *m = KeepLockTableBindResp func (m *KeepLockTableBindResponse) String() string { return proto.CompactTextString(m) } func (*KeepLockTableBindResponse) ProtoMessage() {} func (*KeepLockTableBindResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{16} + return fileDescriptor_164ad2988c7acaf1, []int{18} } func (m *KeepLockTableBindResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1651,7 +1747,7 @@ func (m *SetRestartServiceRequest) Reset() { *m = SetRestartServiceReque func (m *SetRestartServiceRequest) String() string { return proto.CompactTextString(m) } func (*SetRestartServiceRequest) ProtoMessage() {} func (*SetRestartServiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{17} + return fileDescriptor_164ad2988c7acaf1, []int{19} } func (m *SetRestartServiceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1699,7 +1795,7 @@ func (m *SetRestartServiceResponse) Reset() { *m = SetRestartServiceResp func (m *SetRestartServiceResponse) String() string { return proto.CompactTextString(m) } func (*SetRestartServiceResponse) ProtoMessage() {} func (*SetRestartServiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{18} + return fileDescriptor_164ad2988c7acaf1, []int{20} } func (m *SetRestartServiceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1747,7 +1843,7 @@ func (m *CanRestartServiceRequest) Reset() { *m = CanRestartServiceReque func (m *CanRestartServiceRequest) String() string { return proto.CompactTextString(m) } func (*CanRestartServiceRequest) ProtoMessage() {} func (*CanRestartServiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{19} + return fileDescriptor_164ad2988c7acaf1, []int{21} } func (m *CanRestartServiceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1795,7 +1891,7 @@ func (m *CanRestartServiceResponse) Reset() { *m = CanRestartServiceResp func (m *CanRestartServiceResponse) String() string { return proto.CompactTextString(m) } func (*CanRestartServiceResponse) ProtoMessage() {} func (*CanRestartServiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{20} + return fileDescriptor_164ad2988c7acaf1, []int{22} } func (m *CanRestartServiceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1843,7 +1939,7 @@ func (m *RemainTxnInServiceRequest) Reset() { *m = RemainTxnInServiceReq func (m *RemainTxnInServiceRequest) String() string { return proto.CompactTextString(m) } func (*RemainTxnInServiceRequest) ProtoMessage() {} func (*RemainTxnInServiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{21} + return fileDescriptor_164ad2988c7acaf1, []int{23} } func (m *RemainTxnInServiceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1891,7 +1987,7 @@ func (m *RemainTxnInServiceResponse) Reset() { *m = RemainTxnInServiceRe func (m *RemainTxnInServiceResponse) String() string { return proto.CompactTextString(m) } func (*RemainTxnInServiceResponse) ProtoMessage() {} func (*RemainTxnInServiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{22} + return fileDescriptor_164ad2988c7acaf1, []int{24} } func (m *RemainTxnInServiceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1939,7 +2035,7 @@ func (m *KeepRemoteLockRequest) Reset() { *m = KeepRemoteLockRequest{} } func (m *KeepRemoteLockRequest) String() string { return proto.CompactTextString(m) } func (*KeepRemoteLockRequest) ProtoMessage() {} func (*KeepRemoteLockRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{23} + return fileDescriptor_164ad2988c7acaf1, []int{25} } func (m *KeepRemoteLockRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1987,7 +2083,7 @@ func (m *KeepRemoteLockResponse) Reset() { *m = KeepRemoteLockResponse{} func (m *KeepRemoteLockResponse) String() string { return proto.CompactTextString(m) } func (*KeepRemoteLockResponse) ProtoMessage() {} func (*KeepRemoteLockResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{24} + return fileDescriptor_164ad2988c7acaf1, []int{26} } func (m *KeepRemoteLockResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2035,7 +2131,7 @@ func (m *ValidateServiceRequest) Reset() { *m = ValidateServiceRequest{} func (m *ValidateServiceRequest) String() string { return proto.CompactTextString(m) } func (*ValidateServiceRequest) ProtoMessage() {} func (*ValidateServiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{25} + return fileDescriptor_164ad2988c7acaf1, []int{27} } func (m *ValidateServiceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2083,7 +2179,7 @@ func (m *ValidateServiceResponse) Reset() { *m = ValidateServiceResponse func (m *ValidateServiceResponse) String() string { return proto.CompactTextString(m) } func (*ValidateServiceResponse) ProtoMessage() {} func (*ValidateServiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{26} + return fileDescriptor_164ad2988c7acaf1, []int{28} } func (m *ValidateServiceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2131,7 +2227,7 @@ func (m *AbortRemoteDeadlockTxnRequest) Reset() { *m = AbortRemoteDeadlo func (m *AbortRemoteDeadlockTxnRequest) String() string { return proto.CompactTextString(m) } func (*AbortRemoteDeadlockTxnRequest) ProtoMessage() {} func (*AbortRemoteDeadlockTxnRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{27} + return fileDescriptor_164ad2988c7acaf1, []int{29} } func (m *AbortRemoteDeadlockTxnRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2179,7 +2275,7 @@ func (m *AbortRemoteDeadlockTxnResponse) Reset() { *m = AbortRemoteDeadl func (m *AbortRemoteDeadlockTxnResponse) String() string { return proto.CompactTextString(m) } func (*AbortRemoteDeadlockTxnResponse) ProtoMessage() {} func (*AbortRemoteDeadlockTxnResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{28} + return fileDescriptor_164ad2988c7acaf1, []int{30} } func (m *AbortRemoteDeadlockTxnResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2227,7 +2323,7 @@ func (m *CannotCommitRequest) Reset() { *m = CannotCommitRequest{} } func (m *CannotCommitRequest) String() string { return proto.CompactTextString(m) } func (*CannotCommitRequest) ProtoMessage() {} func (*CannotCommitRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{29} + return fileDescriptor_164ad2988c7acaf1, []int{31} } func (m *CannotCommitRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2275,7 +2371,7 @@ func (m *CannotCommitResponse) Reset() { *m = CannotCommitResponse{} } func (m *CannotCommitResponse) String() string { return proto.CompactTextString(m) } func (*CannotCommitResponse) ProtoMessage() {} func (*CannotCommitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{30} + return fileDescriptor_164ad2988c7acaf1, []int{32} } func (m *CannotCommitResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2322,7 +2418,7 @@ func (m *GetActiveTxnRequest) Reset() { *m = GetActiveTxnRequest{} } func (m *GetActiveTxnRequest) String() string { return proto.CompactTextString(m) } func (*GetActiveTxnRequest) ProtoMessage() {} func (*GetActiveTxnRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{31} + return fileDescriptor_164ad2988c7acaf1, []int{33} } func (m *GetActiveTxnRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2370,7 +2466,7 @@ func (m *GetActiveTxnResponse) Reset() { *m = GetActiveTxnResponse{} } func (m *GetActiveTxnResponse) String() string { return proto.CompactTextString(m) } func (*GetActiveTxnResponse) ProtoMessage() {} func (*GetActiveTxnResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{32} + return fileDescriptor_164ad2988c7acaf1, []int{34} } func (m *GetActiveTxnResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2425,7 +2521,7 @@ func (m *CheckOrphanRequest) Reset() { *m = CheckOrphanRequest{} } func (m *CheckOrphanRequest) String() string { return proto.CompactTextString(m) } func (*CheckOrphanRequest) ProtoMessage() {} func (*CheckOrphanRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{33} + return fileDescriptor_164ad2988c7acaf1, []int{35} } func (m *CheckOrphanRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2479,7 +2575,7 @@ func (m *CheckOrphanResponse) Reset() { *m = CheckOrphanResponse{} } func (m *CheckOrphanResponse) String() string { return proto.CompactTextString(m) } func (*CheckOrphanResponse) ProtoMessage() {} func (*CheckOrphanResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{34} + return fileDescriptor_164ad2988c7acaf1, []int{36} } func (m *CheckOrphanResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2527,7 +2623,7 @@ func (m *OrphanTxn) Reset() { *m = OrphanTxn{} } func (m *OrphanTxn) String() string { return proto.CompactTextString(m) } func (*OrphanTxn) ProtoMessage() {} func (*OrphanTxn) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{35} + return fileDescriptor_164ad2988c7acaf1, []int{37} } func (m *OrphanTxn) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2601,7 +2697,7 @@ func (m *Result) Reset() { *m = Result{} } func (m *Result) String() string { return proto.CompactTextString(m) } func (*Result) ProtoMessage() {} func (*Result) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{36} + return fileDescriptor_164ad2988c7acaf1, []int{38} } func (m *Result) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2713,7 +2809,7 @@ func (m *ExtraMutation) Reset() { *m = ExtraMutation{} } func (m *ExtraMutation) String() string { return proto.CompactTextString(m) } func (*ExtraMutation) ProtoMessage() {} func (*ExtraMutation) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{37} + return fileDescriptor_164ad2988c7acaf1, []int{39} } func (m *ExtraMutation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2774,7 +2870,7 @@ func (m *ResumeInvalidCNRequest) Reset() { *m = ResumeInvalidCNRequest{} func (m *ResumeInvalidCNRequest) String() string { return proto.CompactTextString(m) } func (*ResumeInvalidCNRequest) ProtoMessage() {} func (*ResumeInvalidCNRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{38} + return fileDescriptor_164ad2988c7acaf1, []int{40} } func (m *ResumeInvalidCNRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2820,7 +2916,7 @@ func (m *ResumeInvalidCNResponse) Reset() { *m = ResumeInvalidCNResponse func (m *ResumeInvalidCNResponse) String() string { return proto.CompactTextString(m) } func (*ResumeInvalidCNResponse) ProtoMessage() {} func (*ResumeInvalidCNResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_164ad2988c7acaf1, []int{39} + return fileDescriptor_164ad2988c7acaf1, []int{41} } func (m *ResumeInvalidCNResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2864,6 +2960,8 @@ func init() { proto.RegisterType((*LockResponse)(nil), "lock.LockResponse") proto.RegisterType((*GetTxnLockRequest)(nil), "lock.GetTxnLockRequest") proto.RegisterType((*GetTxnLockResponse)(nil), "lock.GetTxnLockResponse") + proto.RegisterType((*GetLockHolderRequest)(nil), "lock.GetLockHolderRequest") + proto.RegisterType((*GetLockHolderResponse)(nil), "lock.GetLockHolderResponse") proto.RegisterType((*GetWaitingListRequest)(nil), "lock.GetWaitingListRequest") proto.RegisterType((*GetWaitingListResponse)(nil), "lock.GetWaitingListResponse") proto.RegisterType((*WaitTxn)(nil), "lock.WaitTxn") @@ -2901,141 +2999,143 @@ func init() { func init() { proto.RegisterFile("lock.proto", fileDescriptor_164ad2988c7acaf1) } var fileDescriptor_164ad2988c7acaf1 = []byte{ - // 2135 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0xcd, 0x72, 0xdb, 0xc8, - 0x11, 0x16, 0x48, 0x8a, 0x3f, 0x4d, 0x52, 0x82, 0x46, 0xb2, 0x0c, 0x29, 0xbb, 0x32, 0x83, 0x68, - 0xab, 0xb8, 0x72, 0xd6, 0x8a, 0xe5, 0x78, 0x77, 0xe3, 0x4d, 0x5c, 0x91, 0x29, 0x4b, 0xd6, 0xda, - 0xb2, 0x36, 0x43, 0xda, 0xa9, 0xca, 0x0d, 0x22, 0xc7, 0x12, 0x4a, 0x14, 0xc0, 0x80, 0xa0, 0x7e, - 0x1e, 0x20, 0x55, 0xa9, 0xca, 0x3d, 0xe7, 0x1c, 0x72, 0xd8, 0x4b, 0xde, 0x63, 0x8f, 0x5b, 0x95, - 0x7b, 0x2a, 0x71, 0xde, 0x20, 0x95, 0x07, 0x48, 0xf5, 0xcc, 0x80, 0x98, 0xc1, 0x8f, 0xb8, 0xce, - 0x0d, 0xd3, 0xdd, 0xf3, 0xf5, 0x4c, 0xa3, 0xf1, 0x4d, 0xf7, 0x00, 0x60, 0xe8, 0xf7, 0xcf, 0x1f, - 0x8c, 0x02, 0x3f, 0xf4, 0x49, 0x09, 0x9f, 0xd7, 0x3f, 0x3b, 0x75, 0xc3, 0xb3, 0xc9, 0xc9, 0x83, - 0xbe, 0x7f, 0xb1, 0x7d, 0xea, 0x9f, 0xfa, 0xdb, 0x5c, 0x79, 0x32, 0x79, 0xc7, 0x47, 0x7c, 0xc0, - 0x9f, 0xc4, 0xa4, 0xf5, 0xc5, 0xd0, 0xbd, 0x60, 0xe3, 0xd0, 0xb9, 0x18, 0x09, 0x81, 0xfd, 0xdf, - 0x02, 0xd4, 0x5f, 0xf9, 0xfd, 0xf3, 0xe3, 0x51, 0xe8, 0xfa, 0xde, 0x98, 0x3c, 0x82, 0xfa, 0x41, - 0xe0, 0x78, 0x93, 0xa1, 0x13, 0xb8, 0xe1, 0x8d, 0x65, 0xb4, 0x8c, 0xf6, 0xc2, 0xce, 0xd2, 0x03, - 0xee, 0x57, 0x51, 0x50, 0xd5, 0x8a, 0xd8, 0x50, 0x3a, 0xf2, 0x07, 0xcc, 0x2a, 0x70, 0xeb, 0x05, - 0x61, 0x8d, 0xa8, 0x28, 0xa5, 0x5c, 0x47, 0xda, 0x50, 0xfe, 0xc6, 0x1f, 0xba, 0xfd, 0x1b, 0xab, - 0xc8, 0xad, 0x4c, 0x61, 0xf5, 0x5b, 0xc7, 0x0d, 0x85, 0x9c, 0x4a, 0x3d, 0xf9, 0x08, 0x6a, 0xfb, - 0x7e, 0x70, 0xe5, 0x04, 0x83, 0x9e, 0x6f, 0x95, 0x5a, 0x46, 0xbb, 0x46, 0x63, 0x01, 0x69, 0xc3, - 0x62, 0xcf, 0x39, 0x19, 0xb2, 0x3d, 0xf6, 0xae, 0x73, 0xe6, 0x78, 0xa7, 0x6c, 0x60, 0xcd, 0xb7, - 0x8c, 0x76, 0x95, 0x26, 0xc5, 0x88, 0x43, 0x59, 0x18, 0xdc, 0xa0, 0x0b, 0xab, 0xdc, 0x32, 0xda, - 0x45, 0x1a, 0x0b, 0xc8, 0x0a, 0xcc, 0x1f, 0x04, 0xfe, 0x64, 0x64, 0x55, 0x5a, 0x46, 0xbb, 0x49, - 0xc5, 0x80, 0x6c, 0x41, 0xb5, 0x7b, 0xe6, 0x04, 0x03, 0xd7, 0x3b, 0xb5, 0xaa, 0xea, 0x6e, 0x22, - 0x29, 0x9d, 0xea, 0xc9, 0x13, 0x80, 0xae, 0xe7, 0x8c, 0xba, 0x67, 0x7e, 0xd8, 0x1b, 0x5b, 0xb5, - 0x96, 0xd1, 0xae, 0xef, 0xac, 0x3c, 0x88, 0x03, 0xdc, 0x8b, 0x9e, 0x9e, 0x95, 0xbe, 0xfb, 0xc7, - 0xbd, 0x39, 0xaa, 0x58, 0xdb, 0x7f, 0x37, 0xa0, 0x86, 0x01, 0xe2, 0x6b, 0xc6, 0xb5, 0xf0, 0x07, - 0x1e, 0xee, 0x12, 0x15, 0x03, 0x5c, 0x7f, 0x97, 0x05, 0x97, 0x6e, 0x9f, 0x1d, 0xee, 0xf1, 0xd0, - 0xd6, 0x68, 0x2c, 0x20, 0x16, 0x54, 0xde, 0xb2, 0x60, 0xec, 0xfa, 0x1e, 0x0f, 0x68, 0x89, 0x46, - 0x43, 0x44, 0x7b, 0xeb, 0x0c, 0xdd, 0x01, 0x8f, 0x5d, 0x95, 0x8a, 0x41, 0xbc, 0xdf, 0xf9, 0xbc, - 0xfd, 0x96, 0x67, 0xec, 0xb7, 0x05, 0xf5, 0xe3, 0xc0, 0x3d, 0x75, 0x3d, 0xb1, 0xd6, 0x0a, 0xf7, - 0xaa, 0x8a, 0xec, 0x3f, 0x01, 0x54, 0x28, 0xfb, 0xfd, 0x84, 0x8d, 0x43, 0x11, 0x7d, 0xfe, 0x78, - 0xb8, 0x27, 0xf7, 0x15, 0x0b, 0xc8, 0x23, 0x65, 0xfb, 0x7c, 0x6f, 0xf5, 0x9d, 0xc5, 0x38, 0x6d, - 0xb8, 0x58, 0x46, 0x4d, 0x09, 0xd3, 0x26, 0x94, 0x8f, 0x58, 0x78, 0xe6, 0x0f, 0x64, 0x0a, 0x35, - 0xc4, 0x0c, 0x21, 0xa3, 0x52, 0x47, 0xee, 0x43, 0x09, 0xa7, 0xf0, 0xdd, 0xd7, 0xa3, 0xd4, 0x45, - 0x89, 0xf4, 0x2e, 0x71, 0xb9, 0x11, 0x79, 0x08, 0xe5, 0x37, 0x1e, 0x5a, 0xf0, 0xb0, 0xd4, 0x77, - 0x96, 0x85, 0xb9, 0x90, 0xe9, 0x13, 0xa4, 0x21, 0xf9, 0x15, 0xc0, 0x01, 0x0b, 0x7b, 0xd7, 0x1e, - 0xf7, 0x52, 0xe6, 0xd3, 0xee, 0xca, 0x0f, 0x64, 0x2a, 0xd7, 0xa7, 0x2a, 0x13, 0xc8, 0x21, 0x2c, - 0x1c, 0xb0, 0x10, 0x53, 0xd0, 0xf5, 0x4e, 0x5f, 0xb9, 0xe3, 0x90, 0x07, 0xb2, 0xbe, 0xf3, 0xa3, - 0x29, 0x84, 0xa2, 0xd3, 0x61, 0x12, 0x13, 0xc9, 0xcf, 0xa1, 0x72, 0xc0, 0xc2, 0x67, 0xae, 0x37, - 0xe0, 0xb9, 0x8a, 0xd9, 0x17, 0x61, 0xa0, 0x50, 0x9f, 0x1c, 0x99, 0x12, 0x0a, 0x4b, 0x2f, 0x19, - 0x1b, 0xc5, 0x71, 0xc6, 0xf9, 0x22, 0x7b, 0x37, 0xc4, 0xfc, 0x94, 0x5a, 0x47, 0x4a, 0x4f, 0xc7, - 0x4d, 0xa1, 0x90, 0xb2, 0x0b, 0x3f, 0x64, 0x3c, 0x2e, 0xa0, 0x6e, 0x4a, 0xd7, 0x25, 0x36, 0xa5, - 0x2b, 0xc9, 0x2b, 0x58, 0xe4, 0x09, 0xeb, 0x84, 0x4c, 0x26, 0xbb, 0x55, 0xe7, 0x58, 0x1f, 0x09, - 0xac, 0x84, 0x52, 0x07, 0x4b, 0x4e, 0x25, 0x1d, 0x68, 0x74, 0x1c, 0xcf, 0xf3, 0xc3, 0x8e, 0x7f, - 0x71, 0xe1, 0x86, 0x56, 0x83, 0x43, 0xad, 0x09, 0x28, 0x55, 0xa3, 0xe3, 0x68, 0x93, 0x10, 0xe4, - 0x80, 0x85, 0xbb, 0xfd, 0xd0, 0xbd, 0x64, 0xbd, 0x6b, 0xcf, 0x6a, 0xaa, 0x20, 0xaa, 0x26, 0x01, - 0xa2, 0xaa, 0x30, 0xec, 0x5d, 0x16, 0x52, 0x64, 0x84, 0x20, 0x8c, 0x76, 0xb6, 0xa0, 0x86, 0x3d, - 0xa5, 0x4e, 0x84, 0x3d, 0xa5, 0x47, 0xcc, 0x8e, 0xe3, 0x25, 0x30, 0x17, 0x55, 0xcc, 0x94, 0x3a, - 0x81, 0x99, 0xd2, 0x93, 0x37, 0x40, 0x28, 0xbb, 0x70, 0x5c, 0xaf, 0x77, 0xed, 0x1d, 0x7a, 0x11, - 0xa8, 0xc9, 0x41, 0xef, 0x09, 0xd0, 0xb4, 0x5e, 0x47, 0xcd, 0x00, 0x20, 0xbf, 0x86, 0x7a, 0xe7, - 0x8c, 0xf5, 0xcf, 0x8f, 0x83, 0xd1, 0x99, 0xe3, 0x59, 0x4b, 0x1c, 0xcf, 0x92, 0x8b, 0x8c, 0x15, - 0x3a, 0x90, 0x3a, 0x05, 0x13, 0x83, 0xb2, 0xf1, 0xe4, 0x82, 0x1d, 0x7a, 0x97, 0xf8, 0x96, 0x3b, - 0xaf, 0x2d, 0xa2, 0x26, 0x46, 0x42, 0x99, 0x48, 0x8c, 0x84, 0x96, 0x38, 0xb0, 0xba, 0x7b, 0xe2, - 0x07, 0xa1, 0xc8, 0xbc, 0x3d, 0xe6, 0x0c, 0x10, 0x04, 0xdf, 0xee, 0x0a, 0x07, 0xfd, 0x89, 0x00, - 0xcd, 0xb6, 0xd1, 0xb1, 0x73, 0x80, 0xec, 0x6f, 0x01, 0xaa, 0x94, 0x8d, 0x47, 0xbe, 0x37, 0x66, - 0x33, 0xe8, 0x30, 0x66, 0xb6, 0xc2, 0x2d, 0xcc, 0xb6, 0x02, 0xf3, 0xcf, 0x83, 0xc0, 0x0f, 0x38, - 0xfd, 0x35, 0xa8, 0x18, 0x90, 0x4f, 0xa1, 0xf2, 0x9a, 0x5d, 0xf1, 0xaf, 0xb8, 0x94, 0x49, 0xa4, - 0x34, 0xd2, 0x93, 0x9f, 0x4a, 0x6a, 0x14, 0x5c, 0x47, 0x54, 0x6a, 0x14, 0xcb, 0xd4, 0xb8, 0x71, - 0x67, 0xca, 0x8d, 0x65, 0x95, 0x5d, 0x22, 0x6e, 0xd4, 0x66, 0x44, 0xe4, 0xf8, 0x54, 0x23, 0xc7, - 0x8a, 0xfa, 0x96, 0x55, 0x72, 0xd4, 0xe6, 0xaa, 0xec, 0xf8, 0x75, 0x8a, 0x1d, 0xab, 0xea, 0x3b, - 0x4e, 0xb2, 0xa3, 0x86, 0x93, 0xa4, 0xc7, 0xc7, 0x31, 0x3d, 0x0a, 0x7a, 0xbb, 0x93, 0xa0, 0x47, - 0x6d, 0xf6, 0x94, 0x1f, 0xbb, 0x59, 0xfc, 0x08, 0x6a, 0xfe, 0x67, 0xf0, 0xa3, 0x06, 0x95, 0x41, - 0x90, 0x5f, 0xa7, 0x08, 0x52, 0x23, 0xb5, 0x24, 0x41, 0xea, 0xfb, 0x4a, 0x30, 0xe4, 0x51, 0x9a, - 0x21, 0x05, 0xad, 0x7d, 0x9c, 0xc3, 0x90, 0x1a, 0x5a, 0x8a, 0x22, 0xf7, 0x12, 0x14, 0x29, 0xd8, - 0x6d, 0x3d, 0x8b, 0x22, 0x35, 0x20, 0x9d, 0x23, 0xf7, 0x12, 0x1c, 0xb9, 0xa0, 0xa2, 0xe8, 0x1c, - 0xa9, 0xa3, 0x68, 0x24, 0xd9, 0xcd, 0x22, 0xc9, 0x45, 0x35, 0xf6, 0x19, 0x24, 0xa9, 0xc7, 0x3e, - 0xcd, 0x92, 0xdd, 0x2c, 0x96, 0xd4, 0x08, 0x2d, 0x83, 0x25, 0x75, 0xd0, 0x34, 0x4d, 0xbe, 0xcd, - 0xa4, 0x49, 0x41, 0x6b, 0xad, 0x7c, 0x9a, 0xd4, 0x60, 0xb3, 0x78, 0x72, 0x57, 0xe7, 0x49, 0xa2, - 0x9d, 0x57, 0x2a, 0x4f, 0x6a, 0x48, 0x1a, 0x51, 0x1e, 0xa5, 0x89, 0x72, 0x59, 0xcd, 0x8f, 0x14, - 0x51, 0xea, 0xf9, 0x91, 0x64, 0xca, 0x93, 0x19, 0x4c, 0xb9, 0x79, 0x3b, 0x53, 0x6a, 0xe0, 0x79, - 0x54, 0xf9, 0x47, 0x43, 0x74, 0x21, 0x51, 0xf1, 0x88, 0x05, 0xf1, 0xb5, 0x27, 0x99, 0xb2, 0x41, - 0xc5, 0x60, 0x46, 0x41, 0x4c, 0xa0, 0x44, 0xfd, 0xab, 0xb1, 0x55, 0x6c, 0x15, 0xdb, 0x0d, 0xca, - 0x9f, 0xc9, 0x43, 0xa8, 0xc8, 0xc6, 0x26, 0x5d, 0x0e, 0x4a, 0x45, 0xf4, 0xf9, 0xcb, 0xa1, 0xfd, - 0x04, 0x1a, 0xea, 0x37, 0x48, 0xb6, 0xa0, 0x8c, 0x11, 0x19, 0x86, 0x7c, 0x2d, 0xf5, 0x88, 0x9a, - 0x85, 0x2c, 0x62, 0x3f, 0x31, 0xb2, 0xbf, 0x82, 0xa5, 0x54, 0x09, 0x98, 0xb3, 0x17, 0x13, 0x8a, - 0xd4, 0xbf, 0xe2, 0xbb, 0x68, 0x50, 0x7c, 0xb4, 0xff, 0x6a, 0x00, 0x49, 0x73, 0xa4, 0xac, 0xe6, - 0x27, 0xa2, 0x37, 0x98, 0xa7, 0x62, 0x40, 0x1e, 0x43, 0x5d, 0x25, 0xc9, 0x42, 0xab, 0xd8, 0xae, - 0xef, 0x34, 0xe3, 0x96, 0xaa, 0x77, 0xed, 0x45, 0xa9, 0xa1, 0x52, 0xe2, 0x7d, 0x28, 0xbf, 0xf0, - 0x87, 0x03, 0x26, 0x8e, 0x90, 0x9c, 0x19, 0xd2, 0x04, 0x3d, 0xef, 0xfb, 0x13, 0x6f, 0xda, 0x47, - 0xf0, 0x81, 0xfd, 0x14, 0xee, 0x64, 0xd6, 0xa8, 0xe4, 0x13, 0x28, 0x62, 0x52, 0x18, 0xf9, 0xc0, - 0xa8, 0xb7, 0x8f, 0x61, 0x35, 0x9b, 0xc5, 0x93, 0x7b, 0x32, 0x7e, 0xd8, 0x9e, 0xec, 0x3e, 0x54, - 0xa4, 0x36, 0x3f, 0x6d, 0x3a, 0x01, 0x73, 0x42, 0x36, 0x38, 0xf6, 0xa2, 0xb4, 0x99, 0x0a, 0xc8, - 0x26, 0x34, 0x71, 0x3a, 0x0b, 0x76, 0x07, 0x83, 0x80, 0x8d, 0xc7, 0x3c, 0x32, 0x35, 0xaa, 0x0b, - 0xed, 0x3f, 0x1b, 0xd0, 0xd4, 0x9a, 0x82, 0x1c, 0x5f, 0x9f, 0x43, 0x55, 0x10, 0x62, 0xaf, 0x2b, - 0xdb, 0x9a, 0xdb, 0x3a, 0xc2, 0xa9, 0x2d, 0xf9, 0x02, 0x6a, 0x47, 0x93, 0xd0, 0x11, 0xa9, 0x5a, - 0xe4, 0x3b, 0x97, 0xad, 0xc8, 0xf3, 0xeb, 0x30, 0x70, 0x22, 0x5d, 0xd4, 0x13, 0x4d, 0x6d, 0x6d, - 0x13, 0x16, 0xf4, 0x03, 0xd9, 0xfe, 0xd6, 0xe0, 0x67, 0xa8, 0x52, 0xb7, 0xeb, 0x1f, 0x8e, 0x91, - 0xfc, 0x70, 0xa6, 0xdd, 0x67, 0x41, 0xed, 0x3e, 0xa7, 0xfd, 0x62, 0x31, 0xaf, 0x5f, 0x2c, 0x7d, - 0x58, 0xbf, 0x38, 0x9f, 0xee, 0x17, 0xf7, 0x61, 0x31, 0x71, 0x18, 0xff, 0x5f, 0x8d, 0xa1, 0xfd, - 0x37, 0x03, 0xac, 0xbc, 0xa6, 0x65, 0xc6, 0xe6, 0x37, 0xa1, 0xdc, 0x0d, 0x9d, 0x70, 0x32, 0xd6, - 0x2b, 0x2f, 0x21, 0xa3, 0x52, 0x47, 0x56, 0xa1, 0xcc, 0xdf, 0x6f, 0xc4, 0x2e, 0x72, 0x44, 0x1e, - 0x03, 0x4c, 0x7d, 0x22, 0xc5, 0x14, 0xf3, 0x97, 0xab, 0x18, 0xda, 0xbf, 0x81, 0xb5, 0xdc, 0x1a, - 0x82, 0x2c, 0x40, 0xe1, 0xf8, 0x25, 0x5f, 0x68, 0x95, 0x16, 0x8e, 0x5f, 0xfe, 0xb0, 0x15, 0xda, - 0x5f, 0x82, 0x95, 0xd7, 0x3f, 0xdc, 0x1e, 0x01, 0xfb, 0x3e, 0xac, 0xe5, 0x1e, 0xaa, 0xc9, 0xc5, - 0xa0, 0x9b, 0xbc, 0x96, 0x62, 0xb6, 0x9b, 0xdc, 0x63, 0x36, 0xe5, 0xe6, 0x17, 0xb0, 0x96, 0xdb, - 0x64, 0xcc, 0xf0, 0xf3, 0x04, 0xd6, 0xf3, 0x0f, 0x5e, 0x51, 0x86, 0x4b, 0xad, 0x64, 0xd4, 0x58, - 0x60, 0x3f, 0x86, 0x3b, 0x99, 0xad, 0xea, 0x0c, 0x97, 0x6d, 0x58, 0xcd, 0x2e, 0xe0, 0x52, 0xfb, - 0xfa, 0x1c, 0x56, 0xb3, 0xfb, 0xd7, 0x19, 0x1e, 0x3e, 0x85, 0xbb, 0x39, 0x55, 0x5d, 0xca, 0xc5, - 0x3e, 0x7c, 0x7c, 0x6b, 0xd3, 0x82, 0x3c, 0x1d, 0xce, 0xe0, 0xe9, 0xf0, 0xda, 0xb3, 0x7f, 0x06, - 0x1b, 0xb7, 0x1f, 0xe9, 0x29, 0xcf, 0x14, 0x96, 0x33, 0x3a, 0x6a, 0xf2, 0x15, 0x34, 0x45, 0x61, - 0x82, 0x27, 0x5b, 0x4c, 0xec, 0xf2, 0x33, 0x99, 0xaa, 0xa4, 0x6f, 0xdd, 0xd6, 0xfe, 0x25, 0xac, - 0x64, 0x95, 0xa0, 0xc8, 0xda, 0x42, 0x82, 0xc7, 0x80, 0x78, 0x97, 0xf8, 0x5d, 0xea, 0x42, 0xfb, - 0x11, 0x2c, 0x67, 0xb4, 0xe7, 0x33, 0x62, 0xfd, 0x14, 0x56, 0xb2, 0xea, 0xd5, 0xf8, 0x5a, 0xcd, - 0x50, 0xaf, 0xd5, 0x4c, 0x71, 0xea, 0x15, 0xb8, 0x7b, 0x7e, 0xc0, 0xed, 0x01, 0x49, 0x37, 0xb4, - 0x33, 0x58, 0x68, 0x8a, 0x62, 0x44, 0x28, 0x9f, 0xc1, 0x72, 0x46, 0xb9, 0x87, 0x44, 0x24, 0x2b, - 0x43, 0xb1, 0x0a, 0x39, 0xb2, 0xbf, 0x80, 0xda, 0x34, 0x70, 0xc4, 0x82, 0x4a, 0x54, 0x90, 0x0a, - 0x4f, 0xd1, 0x30, 0x63, 0xb5, 0x7f, 0x28, 0x46, 0xf5, 0x0d, 0x79, 0x08, 0x55, 0x4c, 0x5e, 0x7e, - 0x4c, 0x1a, 0xb7, 0x31, 0xef, 0xd4, 0x0c, 0x29, 0xfe, 0x85, 0x33, 0xee, 0xf8, 0xde, 0xbb, 0xa1, - 0xdb, 0x0f, 0xf9, 0xfa, 0xab, 0x54, 0x15, 0xe1, 0x8b, 0x7a, 0xe1, 0x8c, 0xbf, 0x09, 0xd8, 0xa5, - 0x6c, 0x2f, 0x8a, 0xdc, 0x46, 0x17, 0x92, 0x2f, 0xa1, 0x36, 0x3d, 0x1b, 0x65, 0xa5, 0x76, 0xdb, - 0xb9, 0x19, 0x1b, 0x7f, 0xc0, 0x75, 0x70, 0x0b, 0xea, 0xd1, 0xaa, 0x5e, 0xb2, 0x1b, 0xde, 0xd3, - 0x36, 0xa8, 0x2a, 0x52, 0x2d, 0x30, 0x4a, 0x15, 0xdd, 0x02, 0x23, 0xbb, 0x01, 0x80, 0xab, 0x16, - 0xb5, 0x01, 0x6f, 0x4d, 0x1b, 0x54, 0x91, 0x60, 0xe4, 0xc5, 0x93, 0xb8, 0x0f, 0x6e, 0xd2, 0x68, - 0x88, 0x33, 0x5f, 0xb3, 0x2b, 0x0c, 0xdc, 0xee, 0x40, 0xb4, 0x93, 0x55, 0xaa, 0x48, 0xec, 0x2e, - 0x34, 0xb5, 0x93, 0x1e, 0x5f, 0xd5, 0x39, 0xbb, 0x91, 0xd5, 0x05, 0x3e, 0x62, 0x81, 0x3b, 0x3e, - 0x77, 0x47, 0x32, 0xca, 0xfc, 0x19, 0xd3, 0x2a, 0x60, 0xa3, 0xa1, 0xd3, 0x67, 0x3d, 0x5f, 0x5e, - 0x0b, 0xc4, 0x02, 0xa4, 0x9b, 0xec, 0x5b, 0x91, 0x19, 0x9f, 0xc0, 0x1a, 0xdc, 0xcd, 0x69, 0x12, - 0xb6, 0x7e, 0xac, 0xfd, 0x1f, 0x20, 0x15, 0x5e, 0xc6, 0x9a, 0x73, 0xa4, 0x06, 0xf3, 0x14, 0xe3, - 0x6c, 0x1a, 0x5b, 0x9f, 0x88, 0x3c, 0xe2, 0xb7, 0xfe, 0x4d, 0xa8, 0x3d, 0xbf, 0xee, 0x0f, 0x27, - 0x63, 0xf7, 0x92, 0x99, 0x73, 0x04, 0xa0, 0x8c, 0xe5, 0x01, 0x1b, 0x98, 0xc6, 0xd6, 0x26, 0x40, - 0x7c, 0xf9, 0x4f, 0xaa, 0x50, 0xc2, 0x91, 0x39, 0x47, 0x1a, 0x50, 0xdd, 0x77, 0xc6, 0xe1, 0xbe, - 0xe3, 0x0e, 0x4d, 0x63, 0xeb, 0x5e, 0x5c, 0x70, 0xa0, 0xcd, 0x6b, 0xdf, 0x63, 0xc2, 0xdb, 0xb3, - 0x1b, 0x74, 0x6c, 0x6c, 0xfd, 0xa7, 0x10, 0xdd, 0x9d, 0xa0, 0x1e, 0x1d, 0x0b, 0x3f, 0xa2, 0x2a, - 0x32, 0x0d, 0xb2, 0xa0, 0x5e, 0x49, 0x98, 0x05, 0x42, 0x92, 0x57, 0x0c, 0x66, 0x11, 0x65, 0x3a, - 0x83, 0x9b, 0x25, 0x52, 0x9f, 0x5e, 0x1f, 0x98, 0xf3, 0xe4, 0x4e, 0xc6, 0xa5, 0x80, 0x59, 0x26, - 0x8b, 0x50, 0x97, 0x7f, 0x26, 0xf8, 0xa4, 0x0a, 0x59, 0x82, 0xa6, 0x14, 0x48, 0xff, 0x55, 0xb2, - 0x9c, 0x6a, 0xd7, 0xcd, 0x1a, 0x31, 0xf5, 0xa6, 0xdb, 0x04, 0x94, 0xa8, 0xb4, 0x63, 0xd6, 0xd1, - 0x67, 0xea, 0x60, 0x36, 0x1b, 0x64, 0x35, 0xab, 0xf3, 0x34, 0x9b, 0x68, 0x9e, 0x3a, 0x60, 0xcd, - 0x05, 0x5c, 0xa2, 0x42, 0x24, 0xe6, 0x22, 0xae, 0x27, 0xf1, 0x72, 0x4d, 0x93, 0xac, 0xe7, 0x35, - 0x79, 0xe6, 0x12, 0xee, 0xe9, 0x80, 0x85, 0xb8, 0x41, 0xd1, 0x18, 0x98, 0x64, 0x8b, 0x45, 0x35, - 0x89, 0x58, 0x24, 0xf7, 0x85, 0x06, 0xcf, 0x3d, 0x0c, 0x8e, 0x39, 0x87, 0x8b, 0x54, 0xc4, 0x32, - 0xd8, 0xa6, 0xa1, 0x98, 0xbf, 0xe1, 0xef, 0xa3, 0x3b, 0xe9, 0xf7, 0xcd, 0x82, 0x22, 0x8e, 0xb7, - 0x60, 0x16, 0x9f, 0x75, 0xbe, 0xff, 0xd7, 0x86, 0xf1, 0xdd, 0xfb, 0x0d, 0xe3, 0xfb, 0xf7, 0x1b, - 0xc6, 0x3f, 0xdf, 0x6f, 0xcc, 0xfd, 0xe5, 0xdf, 0x1b, 0xc6, 0xef, 0xd4, 0x5f, 0x5e, 0x17, 0x4e, - 0x18, 0xb8, 0xd7, 0x3e, 0xaf, 0x29, 0xa3, 0x81, 0xc7, 0xb6, 0x47, 0xe7, 0xa7, 0xdb, 0xa3, 0x93, - 0x6d, 0xdc, 0xc3, 0x49, 0x99, 0xff, 0xe8, 0x7a, 0xf4, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x17, - 0xa4, 0x0b, 0x37, 0x3c, 0x1b, 0x00, 0x00, + // 2175 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0xdb, 0x72, 0xdb, 0xc8, + 0xd1, 0x16, 0x48, 0x8a, 0x87, 0x26, 0x29, 0x41, 0xa3, 0x83, 0x21, 0xfd, 0xbb, 0x32, 0x7f, 0x44, + 0x5b, 0xc5, 0x95, 0xb3, 0x56, 0x2c, 0xc7, 0xbb, 0x1b, 0x6f, 0xe2, 0x8a, 0x4c, 0x59, 0xb2, 0xd6, + 0x96, 0xb5, 0x19, 0xd2, 0x4e, 0x55, 0xee, 0x20, 0x72, 0x2c, 0xa1, 0x44, 0x01, 0x0c, 0x08, 0xea, + 0xf0, 0x00, 0xa9, 0xca, 0x13, 0xe4, 0x3a, 0x97, 0xb9, 0xc9, 0x7b, 0xec, 0xe5, 0x56, 0xed, 0x7d, + 0x2a, 0x71, 0x9e, 0x20, 0xa9, 0x3c, 0x40, 0xaa, 0x67, 0x06, 0xc4, 0x0c, 0x0e, 0xe2, 0x6e, 0xee, + 0x30, 0xdd, 0x3d, 0x5f, 0xcf, 0x34, 0x1a, 0xdf, 0x74, 0x0f, 0x00, 0x86, 0x7e, 0xff, 0xe2, 0xe1, + 0x28, 0xf0, 0x43, 0x9f, 0x94, 0xf0, 0x79, 0xe3, 0xb3, 0x33, 0x37, 0x3c, 0x9f, 0x9c, 0x3e, 0xec, + 0xfb, 0x97, 0x3b, 0x67, 0xfe, 0x99, 0xbf, 0xc3, 0x95, 0xa7, 0x93, 0xf7, 0x7c, 0xc4, 0x07, 0xfc, + 0x49, 0x4c, 0xda, 0x58, 0x0c, 0xdd, 0x4b, 0x36, 0x0e, 0x9d, 0xcb, 0x91, 0x10, 0xd8, 0xff, 0x29, + 0x40, 0xfd, 0xb5, 0xdf, 0xbf, 0x38, 0x19, 0x85, 0xae, 0xef, 0x8d, 0xc9, 0x63, 0xa8, 0x1f, 0x06, + 0x8e, 0x37, 0x19, 0x3a, 0x81, 0x1b, 0xde, 0x5a, 0x46, 0xcb, 0x68, 0x2f, 0xec, 0x2e, 0x3d, 0xe4, + 0x7e, 0x15, 0x05, 0x55, 0xad, 0x88, 0x0d, 0xa5, 0x63, 0x7f, 0xc0, 0xac, 0x02, 0xb7, 0x5e, 0x10, + 0xd6, 0x88, 0x8a, 0x52, 0xca, 0x75, 0xa4, 0x0d, 0xe5, 0x6f, 0xfc, 0xa1, 0xdb, 0xbf, 0xb5, 0x8a, + 0xdc, 0xca, 0x14, 0x56, 0xbf, 0x75, 0xdc, 0x50, 0xc8, 0xa9, 0xd4, 0x93, 0x8f, 0xa0, 0x76, 0xe0, + 0x07, 0xd7, 0x4e, 0x30, 0xe8, 0xf9, 0x56, 0xa9, 0x65, 0xb4, 0x6b, 0x34, 0x16, 0x90, 0x36, 0x2c, + 0xf6, 0x9c, 0xd3, 0x21, 0xdb, 0x67, 0xef, 0x3b, 0xe7, 0x8e, 0x77, 0xc6, 0x06, 0xd6, 0x7c, 0xcb, + 0x68, 0x57, 0x69, 0x52, 0x8c, 0x38, 0x94, 0x85, 0xc1, 0x2d, 0xba, 0xb0, 0xca, 0x2d, 0xa3, 0x5d, + 0xa4, 0xb1, 0x80, 0xac, 0xc0, 0xfc, 0x61, 0xe0, 0x4f, 0x46, 0x56, 0xa5, 0x65, 0xb4, 0x9b, 0x54, + 0x0c, 0xc8, 0x36, 0x54, 0xbb, 0xe7, 0x4e, 0x30, 0x70, 0xbd, 0x33, 0xab, 0xaa, 0xee, 0x26, 0x92, + 0xd2, 0xa9, 0x9e, 0x3c, 0x05, 0xe8, 0x7a, 0xce, 0xa8, 0x7b, 0xee, 0x87, 0xbd, 0xb1, 0x55, 0x6b, + 0x19, 0xed, 0xfa, 0xee, 0xca, 0xc3, 0x38, 0xc0, 0xbd, 0xe8, 0xe9, 0x79, 0xe9, 0xdb, 0xbf, 0xdd, + 0x9f, 0xa3, 0x8a, 0xb5, 0xfd, 0xbd, 0x01, 0x35, 0x0c, 0x10, 0x5f, 0x33, 0xae, 0x85, 0x3f, 0xf0, + 0x70, 0x97, 0xa8, 0x18, 0xe0, 0xfa, 0xbb, 0x2c, 0xb8, 0x72, 0xfb, 0xec, 0x68, 0x9f, 0x87, 0xb6, + 0x46, 0x63, 0x01, 0xb1, 0xa0, 0xf2, 0x8e, 0x05, 0x63, 0xd7, 0xf7, 0x78, 0x40, 0x4b, 0x34, 0x1a, + 0x22, 0xda, 0x3b, 0x67, 0xe8, 0x0e, 0x78, 0xec, 0xaa, 0x54, 0x0c, 0xe2, 0xfd, 0xce, 0xe7, 0xed, + 0xb7, 0x3c, 0x63, 0xbf, 0x2d, 0xa8, 0x9f, 0x04, 0xee, 0x99, 0xeb, 0x89, 0xb5, 0x56, 0xb8, 0x57, + 0x55, 0x64, 0x7f, 0x0f, 0x50, 0xa1, 0xec, 0xf7, 0x13, 0x36, 0x0e, 0x45, 0xf4, 0xf9, 0xe3, 0xd1, + 0xbe, 0xdc, 0x57, 0x2c, 0x20, 0x8f, 0x95, 0xed, 0xf3, 0xbd, 0xd5, 0x77, 0x17, 0xe3, 0xb4, 0xe1, + 0x62, 0x19, 0x35, 0x25, 0x4c, 0x5b, 0x50, 0x3e, 0x66, 0xe1, 0xb9, 0x3f, 0x90, 0x29, 0xd4, 0x10, + 0x33, 0x84, 0x8c, 0x4a, 0x1d, 0x79, 0x00, 0x25, 0x9c, 0xc2, 0x77, 0x5f, 0x8f, 0x52, 0x17, 0x25, + 0xd2, 0xbb, 0xc4, 0xe5, 0x46, 0xe4, 0x11, 0x94, 0xdf, 0x7a, 0x68, 0xc1, 0xc3, 0x52, 0xdf, 0x5d, + 0x16, 0xe6, 0x42, 0xa6, 0x4f, 0x90, 0x86, 0xe4, 0x57, 0x00, 0x87, 0x2c, 0xec, 0xdd, 0x78, 0xdc, + 0x4b, 0x99, 0x4f, 0xbb, 0x27, 0x3f, 0x90, 0xa9, 0x5c, 0x9f, 0xaa, 0x4c, 0x20, 0x47, 0xb0, 0x70, + 0xc8, 0x42, 0x4c, 0x41, 0xd7, 0x3b, 0x7b, 0xed, 0x8e, 0x43, 0x1e, 0xc8, 0xfa, 0xee, 0xff, 0x4d, + 0x21, 0x14, 0x9d, 0x0e, 0x93, 0x98, 0x48, 0x7e, 0x0e, 0x95, 0x43, 0x16, 0x3e, 0x77, 0xbd, 0x01, + 0xcf, 0x55, 0xcc, 0xbe, 0x08, 0x03, 0x85, 0xfa, 0xe4, 0xc8, 0x94, 0x50, 0x58, 0x7a, 0xc5, 0xd8, + 0x28, 0x8e, 0x33, 0xce, 0x17, 0xd9, 0xbb, 0x29, 0xe6, 0xa7, 0xd4, 0x3a, 0x52, 0x7a, 0x3a, 0x6e, + 0x0a, 0x85, 0x94, 0x5d, 0xfa, 0x21, 0xe3, 0x71, 0x01, 0x75, 0x53, 0xba, 0x2e, 0xb1, 0x29, 0x5d, + 0x49, 0x5e, 0xc3, 0x22, 0x4f, 0x58, 0x27, 0x64, 0x32, 0xd9, 0xad, 0x3a, 0xc7, 0xfa, 0x48, 0x60, + 0x25, 0x94, 0x3a, 0x58, 0x72, 0x2a, 0xe9, 0x40, 0xa3, 0xe3, 0x78, 0x9e, 0x1f, 0x76, 0xfc, 0xcb, + 0x4b, 0x37, 0xb4, 0x1a, 0x1c, 0x6a, 0x5d, 0x40, 0xa9, 0x1a, 0x1d, 0x47, 0x9b, 0x84, 0x20, 0x87, + 0x2c, 0xdc, 0xeb, 0x87, 0xee, 0x15, 0xeb, 0xdd, 0x78, 0x56, 0x53, 0x05, 0x51, 0x35, 0x09, 0x10, + 0x55, 0x85, 0x61, 0xef, 0xb2, 0x90, 0x22, 0x23, 0x04, 0x61, 0xb4, 0xb3, 0x05, 0x35, 0xec, 0x29, + 0x75, 0x22, 0xec, 0x29, 0x3d, 0x62, 0x76, 0x1c, 0x2f, 0x81, 0xb9, 0xa8, 0x62, 0xa6, 0xd4, 0x09, + 0xcc, 0x94, 0x9e, 0xbc, 0x05, 0x42, 0xd9, 0xa5, 0xe3, 0x7a, 0xbd, 0x1b, 0xef, 0xc8, 0x8b, 0x40, + 0x4d, 0x0e, 0x7a, 0x5f, 0x80, 0xa6, 0xf5, 0x3a, 0x6a, 0x06, 0x00, 0xf9, 0x35, 0xd4, 0x3b, 0xe7, + 0xac, 0x7f, 0x71, 0x12, 0x8c, 0xce, 0x1d, 0xcf, 0x5a, 0xe2, 0x78, 0x96, 0x5c, 0x64, 0xac, 0xd0, + 0x81, 0xd4, 0x29, 0x98, 0x18, 0x94, 0x8d, 0x27, 0x97, 0xec, 0xc8, 0xbb, 0xc2, 0xb7, 0xdc, 0x79, + 0x63, 0x11, 0x35, 0x31, 0x12, 0xca, 0x44, 0x62, 0x24, 0xb4, 0xe4, 0x00, 0x9a, 0x87, 0x2c, 0xc4, + 0x8c, 0x7b, 0xe9, 0x0f, 0x07, 0x2c, 0xb0, 0x96, 0x39, 0xd6, 0xc6, 0xf4, 0xa5, 0xc6, 0x2a, 0x1d, + 0x49, 0x9f, 0x46, 0x1c, 0x58, 0xdb, 0x3b, 0xf5, 0x83, 0x50, 0x64, 0xf0, 0x3e, 0x73, 0x06, 0x08, + 0x80, 0x59, 0xb2, 0xc2, 0x01, 0x7f, 0x22, 0x00, 0xb3, 0x6d, 0x74, 0xe4, 0x1c, 0x20, 0xfb, 0x5f, + 0x00, 0x55, 0xca, 0xc6, 0x23, 0xdf, 0x1b, 0xb3, 0x19, 0xb4, 0x1a, 0x33, 0x64, 0xe1, 0x0e, 0x86, + 0x5c, 0x81, 0xf9, 0x17, 0x41, 0xe0, 0x07, 0x9c, 0x46, 0x1b, 0x54, 0x0c, 0xc8, 0xa7, 0x50, 0x79, + 0xc3, 0xae, 0x39, 0x1b, 0x94, 0x32, 0x09, 0x99, 0x46, 0x7a, 0xf2, 0x53, 0x49, 0xb1, 0x82, 0x33, + 0x89, 0x4a, 0xb1, 0x62, 0x99, 0x1a, 0xc7, 0xee, 0x4e, 0x39, 0xb6, 0xac, 0xb2, 0x54, 0xc4, 0xb1, + 0xda, 0x8c, 0x88, 0x64, 0x9f, 0x69, 0x24, 0x5b, 0x51, 0xb3, 0x45, 0x25, 0x59, 0x6d, 0xae, 0xca, + 0xb2, 0x5f, 0xa7, 0x58, 0xb6, 0xaa, 0xe6, 0x4a, 0x92, 0x65, 0x35, 0x9c, 0x24, 0xcd, 0x3e, 0x89, + 0x69, 0x56, 0xd0, 0xe4, 0x6a, 0x82, 0x66, 0xb5, 0xd9, 0x53, 0x9e, 0xed, 0x66, 0xf1, 0x2c, 0xa8, + 0xdf, 0x51, 0x06, 0xcf, 0x6a, 0x50, 0x19, 0x44, 0xfb, 0x75, 0x8a, 0x68, 0x35, 0x72, 0x4c, 0x12, + 0xad, 0xbe, 0xaf, 0x04, 0xd3, 0x1e, 0xa7, 0x99, 0x56, 0xd0, 0xe3, 0xc7, 0x39, 0x4c, 0xab, 0xa1, + 0xa5, 0xa8, 0x76, 0x3f, 0x41, 0xb5, 0x4d, 0xf5, 0x83, 0xd2, 0xa9, 0x56, 0x03, 0xd2, 0xb9, 0x76, + 0x3f, 0xc1, 0xb5, 0x0b, 0x89, 0xcf, 0x52, 0xe1, 0x5a, 0x1d, 0x45, 0x23, 0xdb, 0x6e, 0x16, 0xd9, + 0x2e, 0xaa, 0xb1, 0xcf, 0x20, 0x5b, 0x3d, 0xf6, 0x69, 0xb6, 0xed, 0x66, 0xb1, 0xad, 0x46, 0x8c, + 0x19, 0x6c, 0xab, 0x83, 0xa6, 0xe9, 0xf6, 0x5d, 0x26, 0xdd, 0x0a, 0x7a, 0x6c, 0xe5, 0xd3, 0xad, + 0x06, 0x9b, 0xc5, 0xb7, 0x7b, 0x3a, 0xdf, 0x12, 0xed, 0xdc, 0x53, 0xf9, 0x56, 0x43, 0xd2, 0x08, + 0xf7, 0x38, 0x4d, 0xb8, 0xcb, 0x6a, 0x7e, 0xa4, 0x08, 0x57, 0xcf, 0x8f, 0x24, 0xe3, 0x9e, 0xce, + 0x60, 0xca, 0xad, 0xbb, 0x99, 0x52, 0x03, 0xcf, 0x41, 0x22, 0x87, 0x49, 0x56, 0x5f, 0x4d, 0xd4, + 0x56, 0x2a, 0xab, 0x6b, 0x88, 0xfa, 0x3c, 0xfb, 0x8f, 0x86, 0x68, 0x8b, 0xa2, 0x6a, 0x16, 0x2b, + 0xf4, 0x1b, 0x4f, 0x52, 0x6e, 0x83, 0x8a, 0xc1, 0x8c, 0x0a, 0x9d, 0x40, 0x89, 0xfa, 0xd7, 0x63, + 0xab, 0xd8, 0x2a, 0xb6, 0x1b, 0x94, 0x3f, 0x93, 0x47, 0x50, 0x91, 0x9d, 0x56, 0xba, 0x3e, 0x95, + 0x8a, 0x88, 0x47, 0xe4, 0xd0, 0x7e, 0x0a, 0x0d, 0xf5, 0x63, 0x26, 0xdb, 0x50, 0xc6, 0xd0, 0x0e, + 0x43, 0xbe, 0x96, 0x7a, 0xc4, 0xf1, 0x42, 0x16, 0xd1, 0xa8, 0x18, 0xd9, 0x5f, 0xc1, 0x52, 0xaa, + 0x26, 0xcd, 0xd9, 0x8b, 0x09, 0x45, 0xea, 0x5f, 0xf3, 0x5d, 0x34, 0x28, 0x3e, 0xda, 0x0e, 0x90, + 0x34, 0xd7, 0xca, 0xee, 0x62, 0x22, 0x7a, 0x95, 0x79, 0x2a, 0x06, 0xe4, 0x09, 0xd4, 0x55, 0xb2, + 0x2d, 0xb4, 0x8a, 0xed, 0xfa, 0x6e, 0x33, 0x6e, 0xf1, 0x7a, 0x37, 0x5e, 0x94, 0x62, 0x8a, 0x9d, + 0xdd, 0x86, 0x95, 0xac, 0xa3, 0x36, 0x5a, 0x8c, 0x11, 0x2f, 0x66, 0x1f, 0x56, 0x33, 0x5f, 0x1f, + 0x79, 0x00, 0x65, 0xf9, 0xae, 0x45, 0x38, 0x32, 0x9d, 0x4a, 0x13, 0xfb, 0x19, 0x47, 0x49, 0x17, + 0xd8, 0xe4, 0x13, 0x28, 0x62, 0x26, 0xde, 0x01, 0x81, 0x7a, 0xfb, 0x04, 0xd6, 0xb2, 0x8f, 0x8e, + 0x64, 0x00, 0x8c, 0x1f, 0x18, 0x80, 0x3e, 0x54, 0xa4, 0x36, 0x3f, 0xc5, 0x3a, 0x01, 0x73, 0x42, + 0x36, 0x38, 0xf1, 0xa2, 0x14, 0x9b, 0x0a, 0xc8, 0x16, 0x34, 0x71, 0x3a, 0x0b, 0xf6, 0x06, 0x83, + 0x80, 0x8d, 0xc7, 0xfc, 0x44, 0xaf, 0x51, 0x5d, 0x68, 0xff, 0xc9, 0x80, 0xa6, 0xd6, 0xd1, 0xe4, + 0xf8, 0xfa, 0x1c, 0xaa, 0x82, 0x85, 0x7b, 0x5d, 0xd9, 0x93, 0xdd, 0xd5, 0xce, 0x4e, 0x6d, 0xc9, + 0x17, 0x50, 0x3b, 0x9e, 0x84, 0x8e, 0x48, 0xeb, 0x22, 0xdf, 0xb9, 0xec, 0xa3, 0x5e, 0xdc, 0x84, + 0x81, 0x13, 0xe9, 0xa2, 0x86, 0x6e, 0x6a, 0x6b, 0x9b, 0xb0, 0xa0, 0x57, 0x01, 0xf6, 0x5f, 0x0c, + 0x7e, 0x70, 0x2b, 0x4d, 0x87, 0xfe, 0x91, 0x19, 0xc9, 0x8f, 0x6c, 0xda, 0x3a, 0x17, 0xd4, 0xd6, + 0x79, 0xda, 0xec, 0x16, 0xf3, 0x9a, 0xdd, 0xd2, 0x8f, 0x6b, 0x76, 0xe7, 0xd3, 0xcd, 0xee, 0x01, + 0x2c, 0x26, 0x2a, 0x80, 0xff, 0xa9, 0xab, 0xb5, 0xff, 0x6a, 0x80, 0x95, 0xd7, 0x71, 0xcd, 0xd8, + 0xfc, 0x16, 0x94, 0xbb, 0xa1, 0x13, 0x4e, 0xc6, 0x7a, 0xb9, 0x27, 0x64, 0x54, 0xea, 0xc8, 0x1a, + 0x94, 0xf9, 0xfb, 0x8d, 0x98, 0x48, 0x8e, 0xc8, 0x13, 0x80, 0xa9, 0x4f, 0xa4, 0xa3, 0x62, 0xfe, + 0x72, 0x15, 0x43, 0xfb, 0x37, 0xb0, 0x9e, 0x5b, 0xb8, 0x90, 0x05, 0x28, 0x9c, 0xbc, 0xe2, 0x0b, + 0xad, 0xd2, 0xc2, 0xc9, 0xab, 0x1f, 0xb6, 0x42, 0xfb, 0x4b, 0xb0, 0xf2, 0x9a, 0x9f, 0xbb, 0x23, + 0x60, 0x3f, 0x80, 0xf5, 0xdc, 0x93, 0x3c, 0xb9, 0x18, 0x74, 0x93, 0xd7, 0x0f, 0xcd, 0x76, 0x93, + 0x7b, 0xb6, 0xa7, 0xdc, 0xfc, 0x02, 0xd6, 0x73, 0x3b, 0xa4, 0x19, 0x7e, 0x9e, 0xc2, 0x46, 0xfe, + 0x69, 0x2f, 0x6a, 0x7f, 0xa9, 0x95, 0xf4, 0x1b, 0x0b, 0xec, 0x27, 0xb0, 0x9a, 0xd9, 0x67, 0xcf, + 0x70, 0xd9, 0x86, 0xb5, 0xec, 0xaa, 0x31, 0xb5, 0xaf, 0xcf, 0x61, 0x2d, 0xbb, 0xf9, 0x9e, 0xe1, + 0xe1, 0x53, 0xb8, 0x97, 0x53, 0x4a, 0xa6, 0x5c, 0x1c, 0xc0, 0xc7, 0x77, 0x76, 0x4a, 0xc8, 0xd3, + 0xe1, 0x0c, 0x9e, 0x0e, 0x6f, 0x3c, 0xfb, 0x67, 0xb0, 0x79, 0x77, 0x1d, 0x91, 0xf2, 0x4c, 0x61, + 0x39, 0xe3, 0x3a, 0x80, 0x7c, 0x05, 0x4d, 0x51, 0x0d, 0xe1, 0x31, 0x18, 0x13, 0xbb, 0xfc, 0x4c, + 0xa6, 0xaa, 0xa8, 0x88, 0xd0, 0x6c, 0xed, 0x5f, 0xc2, 0x4a, 0x56, 0xdd, 0x8b, 0xac, 0x2d, 0x24, + 0x78, 0x0c, 0x88, 0x77, 0x89, 0xdf, 0xa5, 0x2e, 0xb4, 0x1f, 0xc3, 0x72, 0xc6, 0xdd, 0xc2, 0x8c, + 0x58, 0x3f, 0xe3, 0x07, 0x6a, 0xaa, 0x48, 0x8e, 0xef, 0x04, 0x0d, 0xf5, 0x4e, 0xd0, 0x14, 0xa7, + 0x5e, 0x81, 0xbb, 0xe7, 0x07, 0xdc, 0x3e, 0x90, 0x74, 0x37, 0x3e, 0x83, 0x85, 0xa6, 0x28, 0x46, + 0x84, 0xf2, 0x19, 0x2c, 0x67, 0xd4, 0x98, 0x48, 0x44, 0xb2, 0x1c, 0x15, 0xab, 0x90, 0x23, 0xfb, + 0x0b, 0xa8, 0x4d, 0x03, 0x47, 0x2c, 0xa8, 0x44, 0x55, 0xb0, 0xf0, 0x14, 0x0d, 0x33, 0x56, 0xfb, + 0x87, 0x62, 0x54, 0x0b, 0x91, 0x47, 0x50, 0xc5, 0xe4, 0xe5, 0xc7, 0xa4, 0x71, 0x17, 0xf3, 0x4e, + 0xcd, 0x90, 0xe2, 0x5f, 0x3a, 0xe3, 0x8e, 0xef, 0xbd, 0x1f, 0xba, 0xfd, 0x90, 0xaf, 0xbf, 0x4a, + 0x55, 0x11, 0xbe, 0xa8, 0x97, 0xce, 0xf8, 0x9b, 0x80, 0x5d, 0xc9, 0x9e, 0xa6, 0xc8, 0x6d, 0x74, + 0x21, 0xf9, 0x12, 0x6a, 0xd3, 0xb3, 0x51, 0x56, 0x75, 0x77, 0x9d, 0x9b, 0xb1, 0xf1, 0x8f, 0xb8, + 0xcb, 0x6e, 0x41, 0x3d, 0x5a, 0xd5, 0x2b, 0x76, 0xcb, 0x1b, 0xe9, 0x06, 0x55, 0x45, 0xaa, 0x05, + 0x46, 0xa9, 0xa2, 0x5b, 0x60, 0x64, 0x37, 0x01, 0x70, 0xd5, 0xa2, 0x36, 0xe0, 0xfd, 0x70, 0x83, + 0x2a, 0x12, 0x8c, 0xbc, 0x78, 0x12, 0x97, 0xd9, 0x4d, 0x1a, 0x0d, 0x71, 0xe6, 0x1b, 0x76, 0x8d, + 0x81, 0xdb, 0x1b, 0x88, 0x1e, 0xb6, 0x4a, 0x15, 0x89, 0xdd, 0x85, 0xa6, 0x76, 0xd2, 0xe3, 0xab, + 0xba, 0x60, 0xb7, 0x51, 0xfd, 0x76, 0xc1, 0x6e, 0xb1, 0x18, 0x1e, 0x5f, 0xb8, 0x23, 0x19, 0x65, + 0xfe, 0x8c, 0x69, 0x15, 0xb0, 0xd1, 0xd0, 0xe9, 0xb3, 0x9e, 0x2f, 0xef, 0x22, 0x62, 0x01, 0xd2, + 0x4d, 0xf6, 0x95, 0xce, 0x8c, 0x4f, 0x60, 0x1d, 0xee, 0xe5, 0x74, 0x26, 0xdb, 0xff, 0xaf, 0xfd, + 0xdc, 0x20, 0x15, 0x5e, 0x65, 0x9a, 0x73, 0xa4, 0x06, 0xf3, 0x14, 0xe3, 0x6c, 0x1a, 0xdb, 0x9f, + 0x88, 0x3c, 0xe2, 0xbf, 0x2c, 0x9a, 0x50, 0x7b, 0x71, 0xd3, 0x1f, 0x4e, 0xc6, 0xee, 0x15, 0x33, + 0xe7, 0x08, 0x40, 0x19, 0xcb, 0x03, 0x36, 0x30, 0x8d, 0xed, 0x2d, 0x80, 0xf8, 0xcf, 0x05, 0xa9, + 0x42, 0x09, 0x47, 0xe6, 0x1c, 0x69, 0x40, 0xf5, 0xc0, 0x19, 0x87, 0x07, 0x8e, 0x3b, 0x34, 0x8d, + 0xed, 0xfb, 0x71, 0xc1, 0x81, 0x36, 0x6f, 0x7c, 0x8f, 0x09, 0x6f, 0xcf, 0x6f, 0xd1, 0xb1, 0xb1, + 0xfd, 0xef, 0x42, 0x74, 0x61, 0x83, 0x7a, 0x74, 0x2c, 0xfc, 0x88, 0xaa, 0xc8, 0x34, 0xc8, 0x82, + 0x7a, 0x0f, 0x62, 0x16, 0x08, 0x49, 0xde, 0x6b, 0x98, 0x45, 0x94, 0xe9, 0x0c, 0x6e, 0x96, 0x48, + 0x7d, 0x7a, 0x67, 0x61, 0xce, 0x93, 0xd5, 0x8c, 0x9b, 0x08, 0xb3, 0x4c, 0x16, 0xa1, 0x2e, 0x7f, + 0xab, 0xf0, 0x49, 0x15, 0xb2, 0x04, 0x4d, 0x29, 0x90, 0xfe, 0xab, 0x64, 0x39, 0x75, 0x47, 0x60, + 0xd6, 0x88, 0xa9, 0x77, 0xfa, 0x26, 0xa0, 0x44, 0xa5, 0x1d, 0xb3, 0x8e, 0x3e, 0x53, 0x07, 0xb3, + 0xd9, 0x20, 0x6b, 0x59, 0xed, 0xae, 0xd9, 0x44, 0xf3, 0xd4, 0x01, 0x6b, 0x2e, 0xe0, 0x12, 0x15, + 0x22, 0x31, 0x17, 0x71, 0x3d, 0x89, 0x97, 0x6b, 0x9a, 0x64, 0x23, 0xaf, 0xb3, 0x34, 0x97, 0x70, + 0x4f, 0x5a, 0xdf, 0x60, 0x92, 0x6d, 0x16, 0xd5, 0x24, 0x62, 0x91, 0xdc, 0x17, 0x1a, 0xbc, 0xf0, + 0x30, 0x38, 0xe6, 0x1c, 0x2e, 0x52, 0x11, 0xcb, 0x60, 0x9b, 0x86, 0x62, 0xfe, 0x96, 0xbf, 0x8f, + 0xee, 0xa4, 0xdf, 0x37, 0x0b, 0x8a, 0x38, 0xde, 0x82, 0x59, 0x7c, 0xde, 0xf9, 0xee, 0x1f, 0x9b, + 0xc6, 0xb7, 0x1f, 0x36, 0x8d, 0xef, 0x3e, 0x6c, 0x1a, 0x7f, 0xff, 0xb0, 0x39, 0xf7, 0xe7, 0x7f, + 0x6e, 0x1a, 0xbf, 0x53, 0xff, 0xd7, 0x5d, 0x3a, 0x61, 0xe0, 0xde, 0xf8, 0xbc, 0xa6, 0x8c, 0x06, + 0x1e, 0xdb, 0x19, 0x5d, 0x9c, 0xed, 0x8c, 0x4e, 0x77, 0x70, 0x0f, 0xa7, 0x65, 0xfe, 0x97, 0xee, + 0xf1, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x32, 0x0c, 0xed, 0xff, 0xf9, 0x1b, 0x00, 0x00, } func (m *LockOptions) Marshal() (dAtA []byte, err error) { @@ -3227,6 +3327,18 @@ func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x1 i-- dAtA[i] = 0xa2 + { + size, err := m.GetLockHolder.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x9a { size, err := m.ResumeInvalidCN.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -3430,6 +3542,18 @@ func (m *Response) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + { + size, err := m.GetLockHolder.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xaa { size, err := m.AbortRemoteDeadlockTxn.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -3794,26 +3918,6 @@ func (m *GetTxnLockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - if m.Found { - i-- - if m.Found { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x20 - } - { - size, err := m.Holder.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintLock(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a if len(m.WaitingList) > 0 { for iNdEx := len(m.WaitingList) - 1; iNdEx >= 0; iNdEx-- { { @@ -3836,6 +3940,77 @@ func (m *GetTxnLockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GetLockHolderRequest) Marshal() (dAtA []byte, err error) { + size := m.ProtoSize() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetLockHolderRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetLockHolderRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Row) > 0 { + i -= len(m.Row) + copy(dAtA[i:], m.Row) + i = encodeVarintLock(dAtA, i, uint64(len(m.Row))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetLockHolderResponse) Marshal() (dAtA []byte, err error) { + size := m.ProtoSize() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetLockHolderResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetLockHolderResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + { + size, err := m.Holder.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *GetWaitingListRequest) Marshal() (dAtA []byte, err error) { size := m.ProtoSize() dAtA = make([]byte, size) @@ -5297,6 +5472,8 @@ func (m *Request) ProtoSize() (n int) { n += 2 + l + sovLock(uint64(l)) l = m.ResumeInvalidCN.ProtoSize() n += 2 + l + sovLock(uint64(l)) + l = m.GetLockHolder.ProtoSize() + n += 2 + l + sovLock(uint64(l)) l = m.AbortRemoteDeadlockTxn.ProtoSize() n += 2 + l + sovLock(uint64(l)) if m.XXX_unrecognized != nil { @@ -5357,6 +5534,8 @@ func (m *Response) ProtoSize() (n int) { n += 2 + l + sovLock(uint64(l)) l = m.AbortRemoteDeadlockTxn.ProtoSize() n += 2 + l + sovLock(uint64(l)) + l = m.GetLockHolder.ProtoSize() + n += 2 + l + sovLock(uint64(l)) if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -5440,11 +5619,36 @@ func (m *GetTxnLockResponse) ProtoSize() (n int) { n += 1 + l + sovLock(uint64(l)) } } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *GetLockHolderRequest) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Row) + if l > 0 { + n += 1 + l + sovLock(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *GetLockHolderResponse) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l l = m.Holder.ProtoSize() n += 1 + l + sovLock(uint64(l)) - if m.Found { - n += 2 - } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -7091,6 +7295,39 @@ func (m *Request) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GetLockHolder", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GetLockHolder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 20: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field AbortRemoteDeadlockTxn", wireType) @@ -7811,6 +8048,39 @@ func (m *Response) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 21: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GetLockHolder", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GetLockHolder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipLock(dAtA[iNdEx:]) @@ -8300,11 +8570,62 @@ func (m *GetTxnLockResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: + default: + iNdEx = preIndex + skippy, err := skipLock(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthLock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetLockHolderRequest) 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 ErrIntOverflowLock + } + 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: GetLockHolderRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetLockHolderRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Holder", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Row", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowLock @@ -8314,30 +8635,82 @@ func (m *GetTxnLockResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthLock } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthLock } if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Holder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.Row = append(m.Row[:0], dAtA[iNdEx:postIndex]...) + if m.Row == nil { + m.Row = []byte{} } iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Found", wireType) + default: + iNdEx = preIndex + skippy, err := skipLock(dAtA[iNdEx:]) + if err != nil { + return err } - var v int + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthLock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetLockHolderResponse) 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 ErrIntOverflowLock + } + 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: GetLockHolderResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetLockHolderResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Holder", wireType) + } + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowLock @@ -8347,12 +8720,25 @@ func (m *GetTxnLockResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - m.Found = bool(v != 0) + if msglen < 0 { + return ErrInvalidLengthLock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Holder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipLock(dAtA[iNdEx:]) diff --git a/proto/lock.proto b/proto/lock.proto index 7852e068e23d7..936601fb4df3e 100644 --- a/proto/lock.proto +++ b/proto/lock.proto @@ -151,6 +151,7 @@ message Request { RemainTxnInServiceRequest RemainTxnInService = 16 [(gogoproto.nullable) = false]; CheckOrphanRequest CheckOrphan = 17 [(gogoproto.nullable) = false]; ResumeInvalidCNRequest ResumeInvalidCN = 18 [(gogoproto.nullable) = false]; + GetLockHolderRequest GetLockHolder = 19 [(gogoproto.nullable) = false]; AbortRemoteDeadlockTxnRequest AbortRemoteDeadlockTxn = 20 [(gogoproto.nullable) = false]; } @@ -181,6 +182,7 @@ message Response { CheckOrphanResponse CheckOrphan = 18 [(gogoproto.nullable) = false]; ResumeInvalidCNResponse ResumeInvalidCN = 19 [(gogoproto.nullable) = false]; AbortRemoteDeadlockTxnResponse AbortRemoteDeadlockTxn = 20 [(gogoproto.nullable) = false]; + GetLockHolderResponse GetLockHolder = 21 [(gogoproto.nullable) = false]; } // LockRequest lock request @@ -208,8 +210,16 @@ message GetTxnLockRequest { message GetTxnLockResponse { int32 Value = 1; repeated WaitTxn WaitingList = 2 [(gogoproto.nullable) = false]; - WaitTxn Holder = 3 [(gogoproto.nullable) = false]; - bool Found = 4; +} + +// GetLockHolderRequest gets the current holder on a special row lock. +message GetLockHolderRequest { + bytes Row = 1; +} + +// GetLockHolderResponse gets the current holder on a special row lock. +message GetLockHolderResponse { + WaitTxn Holder = 1 [(gogoproto.nullable) = false]; } // GetWaitingListRequest get a waiting txn list on a specical txn request. CN -> CN From 657aa1b49ee96c5ee716c91a28105135f22f6aad Mon Sep 17 00:00:00 2001 From: daviszhen Date: Thu, 18 Jun 2026 22:40:09 +0800 Subject: [PATCH 14/17] update --- pkg/lockservice/lock_table_remote.go | 3 +- pkg/lockservice/lock_table_remote_test.go | 58 +++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index 6d926ed057abf..2de625a909206 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -250,7 +250,8 @@ func (l *remoteLockTable) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { return holder, ok, nil } if err = l.handleError(err, false); err == nil { - return pb.WaitTxn{}, false, nil + // Bind was refreshed successfully; retry with the new bind instead of surfacing a false "not found". + continue } waitRemoteRetryBackoff(backoff) backoff = nextRemoteRetryBackoff(backoff) diff --git a/pkg/lockservice/lock_table_remote_test.go b/pkg/lockservice/lock_table_remote_test.go index 85b7f03cd3631..42b0fb2b3722b 100644 --- a/pkg/lockservice/lock_table_remote_test.go +++ b/pkg/lockservice/lock_table_remote_test.go @@ -384,6 +384,64 @@ func TestGetLockRemoteWithRetry(t *testing.T) { ) } +func TestGetLockHolderRemoteRetriesAfterBindRefresh(t *testing.T) { + oldInitial := remoteRetryInitialBackoff + oldMaxBackoff := remoteRetryMaxBackoff + remoteRetryInitialBackoff = time.Millisecond + remoteRetryMaxBackoff = time.Millisecond + defer func() { + remoteRetryInitialBackoff = oldInitial + remoteRetryMaxBackoff = oldMaxBackoff + }() + + n := 0 + holder := pb.WaitTxn{TxnID: []byte("txn-holder")} + refreshedBind := pb.LockTable{ServiceID: "s1", Table: 1, Version: 2} + runRemoteLockTableTests( + t, + pb.LockTable{ServiceID: "s1", Table: 1, Version: 1}, + func(s Server) { + s.RegisterMethodHandler( + pb.Method_GetLockHolder, + func( + ctx context.Context, + cancel context.CancelFunc, + req *pb.Request, + resp *pb.Response, + cs morpc.ClientSession) { + n++ + if n == 1 { + writeResponse(getLogger(""), cancel, resp, moerr.NewRPCTimeout(ctx), cs) + return + } + resp.GetLockHolder.Holder = holder + writeResponse(getLogger(""), cancel, resp, nil, cs) + }, + ) + s.RegisterMethodHandler( + pb.Method_GetBind, + func( + ctx context.Context, + cancel context.CancelFunc, + req *pb.Request, + resp *pb.Response, + cs morpc.ClientSession) { + resp.GetBind.LockTable = refreshedBind + writeResponse(getLogger(""), cancel, resp, nil, cs) + }, + ) + }, + func(l *remoteLockTable, s Server) { + got, ok, err := l.getLockHolder([]byte("row1")) + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, holder, got) + require.Equal(t, 2, n) + }, + func(lt pb.LockTable) {}, + ) +} + func TestRemoteWithBindChanged(t *testing.T) { newBind := pb.LockTable{ ServiceID: "s2", From 48cd4d2815e5c48ec3cbf7fab3452c488ca38e43 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Mon, 22 Jun 2026 11:44:37 +0800 Subject: [PATCH 15/17] update --- pkg/lockservice/lock_table_remote.go | 6 +- pkg/lockservice/lock_table_remote_test.go | 19 +-- pkg/lockservice/service_observability.go | 17 ++- pkg/lockservice/service_observability_test.go | 142 ++++++++++++++++++ pkg/sql/plan/function/func_unary.go | 45 ++++-- pkg/sql/plan/function/func_unary_test.go | 10 +- 6 files changed, 203 insertions(+), 36 deletions(-) diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index 2de625a909206..203883cba476c 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -250,8 +250,10 @@ func (l *remoteLockTable) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { return holder, ok, nil } if err = l.handleError(err, false); err == nil { - // Bind was refreshed successfully; retry with the new bind instead of surfacing a false "not found". - continue + // The bind-change handler replaces the lock-table object in service.tableGroups. + // This in-flight remote table still carries the stale bind, so let the service + // reacquire the current table before retrying the holder lookup. + return pb.WaitTxn{}, false, ErrLockTableBindChanged } waitRemoteRetryBackoff(backoff) backoff = nextRemoteRetryBackoff(backoff) diff --git a/pkg/lockservice/lock_table_remote_test.go b/pkg/lockservice/lock_table_remote_test.go index 42b0fb2b3722b..10b40cf4888f1 100644 --- a/pkg/lockservice/lock_table_remote_test.go +++ b/pkg/lockservice/lock_table_remote_test.go @@ -384,7 +384,7 @@ func TestGetLockRemoteWithRetry(t *testing.T) { ) } -func TestGetLockHolderRemoteRetriesAfterBindRefresh(t *testing.T) { +func TestGetLockHolderRemoteReturnsBindChangedAfterBindRefresh(t *testing.T) { oldInitial := remoteRetryInitialBackoff oldMaxBackoff := remoteRetryMaxBackoff remoteRetryInitialBackoff = time.Millisecond @@ -395,7 +395,6 @@ func TestGetLockHolderRemoteRetriesAfterBindRefresh(t *testing.T) { }() n := 0 - holder := pb.WaitTxn{TxnID: []byte("txn-holder")} refreshedBind := pb.LockTable{ServiceID: "s1", Table: 1, Version: 2} runRemoteLockTableTests( t, @@ -410,12 +409,7 @@ func TestGetLockHolderRemoteRetriesAfterBindRefresh(t *testing.T) { resp *pb.Response, cs morpc.ClientSession) { n++ - if n == 1 { - writeResponse(getLogger(""), cancel, resp, moerr.NewRPCTimeout(ctx), cs) - return - } - resp.GetLockHolder.Holder = holder - writeResponse(getLogger(""), cancel, resp, nil, cs) + writeResponse(getLogger(""), cancel, resp, moerr.NewRPCTimeout(ctx), cs) }, ) s.RegisterMethodHandler( @@ -432,11 +426,10 @@ func TestGetLockHolderRemoteRetriesAfterBindRefresh(t *testing.T) { ) }, func(l *remoteLockTable, s Server) { - got, ok, err := l.getLockHolder([]byte("row1")) - require.NoError(t, err) - require.True(t, ok) - require.Equal(t, holder, got) - require.Equal(t, 2, n) + _, ok, err := l.getLockHolder([]byte("row1")) + require.True(t, moerr.IsMoErrCode(err, moerr.ErrLockTableBindChanged)) + require.False(t, ok) + require.Equal(t, 1, n) }, func(lt pb.LockTable) {}, ) diff --git a/pkg/lockservice/service_observability.go b/pkg/lockservice/service_observability.go index b02b03343e66f..d00945fca1b27 100644 --- a/pkg/lockservice/service_observability.go +++ b/pkg/lockservice/service_observability.go @@ -17,6 +17,7 @@ package lockservice import ( "context" + "github.com/matrixorigin/matrixone/pkg/common/moerr" pb "github.com/matrixorigin/matrixone/pkg/pb/lock" ) @@ -55,11 +56,19 @@ func (s *service) GetLockHolder( row []byte, options pb.LockOptions) (pb.WaitTxn, bool, error) { s.wait() - l, err := s.getLockTableWithCreate(options.Group, tableID, [][]byte{row}, options.Sharding) - if err != nil { - return pb.WaitTxn{}, false, err + for { + if err := ctx.Err(); err != nil { + return pb.WaitTxn{}, false, err + } + l, err := s.getLockTableWithCreate(options.Group, tableID, [][]byte{row}, options.Sharding) + if err != nil { + return pb.WaitTxn{}, false, err + } + holder, ok, err := l.getLockHolder(row) + if !moerr.IsMoErrCode(err, moerr.ErrLockTableBindChanged) { + return holder, ok, err + } } - return l.getLockHolder(row) } func (s *service) ForceRefreshLockTableBinds( diff --git a/pkg/lockservice/service_observability_test.go b/pkg/lockservice/service_observability_test.go index c6ce6fff7d6db..d198a41f0b846 100644 --- a/pkg/lockservice/service_observability_test.go +++ b/pkg/lockservice/service_observability_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "github.com/matrixorigin/matrixone/pkg/common/morpc" pb "github.com/matrixorigin/matrixone/pkg/pb/lock" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" "github.com/stretchr/testify/assert" @@ -137,6 +138,147 @@ func TestGetLockHolder(t *testing.T) { ) } +func TestGetLockHolderReacquiresLockTableAfterBindChanged(t *testing.T) { + runLockServiceTests( + t, + []string{"s1", "s2"}, + func(alloc *lockTableAllocator, s []*service) { + l2 := s[1] + + ctx, cancel := context.WithTimeout( + context.Background(), + time.Second*10) + defer cancel() + + table := uint64(11) + row := []byte{1} + holder := pb.WaitTxn{TxnID: []byte("txn-new-holder")} + oldBind := pb.LockTable{ + Group: 0, + Table: table, + OriginTable: table, + ServiceID: "stale-service", + Version: 1, + Valid: true, + } + newBind := pb.LockTable{ + Group: 0, + Table: table, + OriginTable: table, + ServiceID: l2.serviceID, + Version: 2, + Valid: true, + } + + newTable := &getLockHolderTestTable{ + bind: newBind, + holder: holder, + found: true, + } + client := &getLockHolderBindChangedClient{ + t: t, + wantBind: oldBind, + newBind: newBind, + } + staleRemote := newRemoteLockTable( + l2.serviceID, + time.Second, + oldBind, + client, + func(bind pb.LockTable) { + require.Equal(t, newBind, bind) + l2.tableGroups.set(bind.Group, bind.Table, newTable) + }, + l2.logger, + ) + l2.tableGroups.set(oldBind.Group, oldBind.Table, staleRemote) + + got, ok, err := l2.GetLockHolder(ctx, table, row, pb.LockOptions{ + Granularity: pb.Granularity_Row, + Mode: pb.LockMode_Exclusive, + Policy: pb.WaitPolicy_Wait, + }) + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, holder, got) + require.Equal(t, 1, client.calls) + require.Equal(t, 1, newTable.calls) + require.Same(t, newTable, l2.tableGroups.get(newBind.Group, newBind.Table)) + }, + ) +} + +type getLockHolderBindChangedClient struct { + t *testing.T + wantBind pb.LockTable + newBind pb.LockTable + calls int +} + +func (c *getLockHolderBindChangedClient) Send( + ctx context.Context, + req *pb.Request) (*pb.Response, error) { + c.calls++ + require.Equal(c.t, pb.Method_GetLockHolder, req.Method) + require.Equal(c.t, c.wantBind, req.LockTable) + resp := acquireResponse() + resp.NewBind = &c.newBind + return resp, nil +} + +func (c *getLockHolderBindChangedClient) AsyncSend( + ctx context.Context, + req *pb.Request) (*morpc.Future, error) { + panic("unexpected async send") +} + +func (c *getLockHolderBindChangedClient) Close() error { + return nil +} + +type getLockHolderTestTable struct { + bind pb.LockTable + holder pb.WaitTxn + found bool + calls int +} + +func (l *getLockHolderTestTable) lock( + ctx context.Context, + txn *activeTxn, + rows [][]byte, + options LockOptions, + cb func(pb.Result, error)) { + panic("unexpected lock") +} + +func (l *getLockHolderTestTable) unlock( + txn *activeTxn, + ls *cowSlice, + commitTS timestamp.Timestamp, + mutations ...pb.ExtraMutation) { + panic("unexpected unlock") +} + +func (l *getLockHolderTestTable) getLock( + key []byte, + txn pb.WaitTxn, + fn func(Lock)) { + panic("unexpected getLock") +} + +func (l *getLockHolderTestTable) getLockHolder( + key []byte) (pb.WaitTxn, bool, error) { + l.calls++ + return l.holder, l.found, nil +} + +func (l *getLockHolderTestTable) getBind() pb.LockTable { + return l.bind +} + +func (l *getLockHolderTestTable) close(reason closeReason) {} + func TestForceRefreshLockTableBinds(t *testing.T) { runBindChangedTests( t, diff --git a/pkg/sql/plan/function/func_unary.go b/pkg/sql/plan/function/func_unary.go index fe1d7aac2fde5..fcc88c845fddb 100644 --- a/pkg/sql/plan/function/func_unary.go +++ b/pkg/sql/plan/function/func_unary.go @@ -7154,6 +7154,25 @@ func untrackUserLevelLock(owner, name string) (uint64, bool) { return 0, true } +func untrackAllUserLevelLock(owner, name string) (uint64, bool) { + key := userLevelLockKey{owner: owner, name: name} + userLevelLocks.Lock() + defer userLevelLocks.Unlock() + + count := userLevelLocks.counts[key] + if count == 0 { + return 0, false + } + delete(userLevelLocks.counts, key) + if names := userLevelLocks.byOwner[owner]; names != nil { + delete(names, name) + if len(names) == 0 { + delete(userLevelLocks.byOwner, owner) + } + } + return count, true +} + func userLevelLocksForOwner(owner string) []string { userLevelLocks.Lock() defer userLevelLocks.Unlock() @@ -7330,22 +7349,18 @@ func releaseAllUserLevelLocks(proc *process.Process) (int64, error) { var released int64 var firstErr error for _, name := range userLevelLocksForOwner(owner) { - for { - count, held := untrackUserLevelLock(owner, name) - if !held { - break - } - if count == 0 { - if err := unlockUserLevelLockTxnIDs(context.Background(), proc.GetLockService(), owner, connID, name); err != nil { - logutil.Warn(fmt.Sprintf("releaseAllUserLevelLocks unlock failed: owner=%s lock=%s err=%v", owner, name, err)) - if firstErr == nil { - firstErr = err - } - } else { - released++ - } - break + if userLevelLockRefCount(owner, name) == 0 { + continue + } + if err := unlockUserLevelLockTxnIDs(context.Background(), proc.GetLockService(), owner, connID, name); err != nil { + logutil.Warn(fmt.Sprintf("releaseAllUserLevelLocks unlock failed: owner=%s lock=%s err=%v", owner, name, err)) + if firstErr == nil { + firstErr = err } + continue + } + if _, held := untrackAllUserLevelLock(owner, name); held { + released++ } } return released, firstErr diff --git a/pkg/sql/plan/function/func_unary_test.go b/pkg/sql/plan/function/func_unary_test.go index abdb7e2c12afa..7cc1ac7b1741f 100644 --- a/pkg/sql/plan/function/func_unary_test.go +++ b/pkg/sql/plan/function/func_unary_test.go @@ -7783,13 +7783,19 @@ func TestReleaseAllUserLevelLocksReturnsCountWhenUnlockFails(t *testing.T) { released, err := releaseAllUserLevelLocks(proc1) require.Error(t, err) require.Equal(t, int64(0), released) + released, err = releaseAllUserLevelLocks(proc1) - require.NoError(t, err) + require.Error(t, err) require.Equal(t, int64(0), released) + services[0].(*userLevelLockTestService).unlockErr = nil + released, err = releaseAllUserLevelLocks(proc1) + require.NoError(t, err) + require.Equal(t, int64(2), released) + v, err = getUserLevelLock("release_all_fail_a", 0, proc2) require.NoError(t, err) - require.Equal(t, int64(0), v) + require.Equal(t, int64(1), v) }) } From 89bbc8d2a09b5841bf2de69ca2caf93e2bfe5d88 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Mon, 22 Jun 2026 19:01:57 +0800 Subject: [PATCH 16/17] fix blocking --- pkg/lockservice/lock_table_local.go | 2 +- pkg/lockservice/lock_table_proxy.go | 4 +- pkg/lockservice/lock_table_remote.go | 33 +- pkg/lockservice/lock_table_remote_test.go | 78 ++++- pkg/lockservice/service_observability.go | 2 +- pkg/lockservice/service_observability_test.go | 1 + pkg/lockservice/service_remote.go | 18 +- pkg/lockservice/service_remote_test.go | 26 ++ pkg/lockservice/types.go | 2 +- pkg/pb/lock/lock.pb.go | 304 ++++++++++-------- proto/lock.proto | 3 +- 11 files changed, 324 insertions(+), 149 deletions(-) diff --git a/pkg/lockservice/lock_table_local.go b/pkg/lockservice/lock_table_local.go index 20d3cffd790d9..f51cf3a4befff 100644 --- a/pkg/lockservice/lock_table_local.go +++ b/pkg/lockservice/lock_table_local.go @@ -354,7 +354,7 @@ func (l *localLockTable) getLock( } } -func (l *localLockTable) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { +func (l *localLockTable) getLockHolder(ctx context.Context, key []byte) (pb.WaitTxn, bool, error) { l.mu.RLock() defer l.mu.RUnlock() if l.mu.closed { diff --git a/pkg/lockservice/lock_table_proxy.go b/pkg/lockservice/lock_table_proxy.go index e7b13aa2e8361..360a708c0c164 100644 --- a/pkg/lockservice/lock_table_proxy.go +++ b/pkg/lockservice/lock_table_proxy.go @@ -202,8 +202,8 @@ func (lp *localLockTableProxy) getLock( lp.remote.getLock(key, txn, fn) } -func (lp *localLockTableProxy) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { - return lp.remote.getLockHolder(key) +func (lp *localLockTableProxy) getLockHolder(ctx context.Context, key []byte) (pb.WaitTxn, bool, error) { + return lp.remote.getLockHolder(ctx, key) } func (lp *localLockTableProxy) getBind() pb.LockTable { diff --git a/pkg/lockservice/lock_table_remote.go b/pkg/lockservice/lock_table_remote.go index 203883cba476c..7a4d657474dec 100644 --- a/pkg/lockservice/lock_table_remote.go +++ b/pkg/lockservice/lock_table_remote.go @@ -242,20 +242,28 @@ func (l *remoteLockTable) getLock( } } -func (l *remoteLockTable) getLockHolder(key []byte) (pb.WaitTxn, bool, error) { +func (l *remoteLockTable) getLockHolder(ctx context.Context, key []byte) (pb.WaitTxn, bool, error) { backoff := remoteRetryInitialBackoff for { - holder, ok, err := l.doGetLockHolder(key) + if err := ctx.Err(); err != nil { + return pb.WaitTxn{}, false, err + } + holder, ok, err := l.doGetLockHolder(ctx, key) if err == nil { return holder, ok, nil } + if err := ctx.Err(); err != nil { + return pb.WaitTxn{}, false, err + } if err = l.handleError(err, false); err == nil { // The bind-change handler replaces the lock-table object in service.tableGroups. // This in-flight remote table still carries the stale bind, so let the service // reacquire the current table before retrying the holder lookup. return pb.WaitTxn{}, false, ErrLockTableBindChanged } - waitRemoteRetryBackoff(backoff) + if err := waitRemoteRetryBackoffWithContext(ctx, backoff); err != nil { + return pb.WaitTxn{}, false, err + } backoff = nextRemoteRetryBackoff(backoff) } } @@ -266,6 +274,20 @@ func waitRemoteRetryBackoff(backoff time.Duration) { } } +func waitRemoteRetryBackoffWithContext(ctx context.Context, backoff time.Duration) error { + if backoff <= 0 { + return ctx.Err() + } + timer := time.NewTimer(backoff) + defer timer.Stop() + select { + case <-ctx.Done(): + return ctx.Err() + case <-timer.C: + return nil + } +} + func nextRemoteRetryBackoff(backoff time.Duration) time.Duration { if backoff <= 0 { return remoteRetryInitialBackoff @@ -338,8 +360,8 @@ func (l *remoteLockTable) doGetLock(key []byte, txn pb.WaitTxn) (Lock, bool, err return Lock{}, false, moerr.AttachCause(ctx, err) } -func (l *remoteLockTable) doGetLockHolder(key []byte) (pb.WaitTxn, bool, error) { - ctx, cancel := context.WithTimeoutCause(context.Background(), defaultRPCTimeout, moerr.CauseDoGetLock) +func (l *remoteLockTable) doGetLockHolder(ctx context.Context, key []byte) (pb.WaitTxn, bool, error) { + ctx, cancel := context.WithTimeoutCause(ctx, defaultRPCTimeout, moerr.CauseDoGetLock) defer cancel() req := acquireRequest() @@ -348,6 +370,7 @@ func (l *remoteLockTable) doGetLockHolder(key []byte) (pb.WaitTxn, bool, error) req.Method = pb.Method_GetLockHolder req.LockTable = l.bind req.GetLockHolder.Row = key + req.GetLockHolder.Sharding = l.bind.Sharding resp, err := l.client.Send(ctx, req) if err == nil { diff --git a/pkg/lockservice/lock_table_remote_test.go b/pkg/lockservice/lock_table_remote_test.go index 10b40cf4888f1..3312e1f249887 100644 --- a/pkg/lockservice/lock_table_remote_test.go +++ b/pkg/lockservice/lock_table_remote_test.go @@ -426,7 +426,7 @@ func TestGetLockHolderRemoteReturnsBindChangedAfterBindRefresh(t *testing.T) { ) }, func(l *remoteLockTable, s Server) { - _, ok, err := l.getLockHolder([]byte("row1")) + _, ok, err := l.getLockHolder(context.Background(), []byte("row1")) require.True(t, moerr.IsMoErrCode(err, moerr.ErrLockTableBindChanged)) require.False(t, ok) require.Equal(t, 1, n) @@ -435,6 +435,82 @@ func TestGetLockHolderRemoteReturnsBindChangedAfterBindRefresh(t *testing.T) { ) } +func TestGetLockHolderRemoteCarriesSharding(t *testing.T) { + runRemoteLockTableTests( + t, + pb.LockTable{ServiceID: "s1", Table: 1, Sharding: pb.Sharding_ByRow}, + func(s Server) { + s.RegisterMethodHandler( + pb.Method_GetLockHolder, + func( + ctx context.Context, + cancel context.CancelFunc, + req *pb.Request, + resp *pb.Response, + cs morpc.ClientSession) { + require.Equal(t, pb.Sharding_ByRow, req.GetLockHolder.Sharding) + writeResponse(getLogger(""), cancel, resp, nil, cs) + }, + ) + }, + func(l *remoteLockTable, s Server) { + _, ok, err := l.getLockHolder(context.Background(), []byte("row1")) + require.NoError(t, err) + require.False(t, ok) + }, + func(lt pb.LockTable) {}, + ) +} + +func TestGetLockHolderRemoteStopsRetryWhenContextCanceled(t *testing.T) { + oldInitial := remoteRetryInitialBackoff + oldMaxBackoff := remoteRetryMaxBackoff + remoteRetryInitialBackoff = time.Millisecond + remoteRetryMaxBackoff = time.Millisecond + defer func() { + remoteRetryInitialBackoff = oldInitial + remoteRetryMaxBackoff = oldMaxBackoff + }() + + runRemoteLockTableTests( + t, + pb.LockTable{ServiceID: "s1", Table: 1, Version: 1}, + func(s Server) { + s.RegisterMethodHandler( + pb.Method_GetLockHolder, + func( + ctx context.Context, + cancel context.CancelFunc, + req *pb.Request, + resp *pb.Response, + cs morpc.ClientSession) { + writeResponse(getLogger(""), cancel, resp, moerr.NewRPCTimeout(ctx), cs) + }, + ) + s.RegisterMethodHandler( + pb.Method_GetBind, + func( + ctx context.Context, + cancel context.CancelFunc, + req *pb.Request, + resp *pb.Response, + cs morpc.ClientSession) { + resp.GetBind.LockTable = req.LockTable + writeResponse(getLogger(""), cancel, resp, nil, cs) + }, + ) + }, + func(l *remoteLockTable, s Server) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, ok, err := l.getLockHolder(ctx, []byte("row1")) + require.ErrorIs(t, err, context.Canceled) + require.False(t, ok) + }, + func(lt pb.LockTable) {}, + ) +} + func TestRemoteWithBindChanged(t *testing.T) { newBind := pb.LockTable{ ServiceID: "s2", diff --git a/pkg/lockservice/service_observability.go b/pkg/lockservice/service_observability.go index d00945fca1b27..ed8672a7e1b25 100644 --- a/pkg/lockservice/service_observability.go +++ b/pkg/lockservice/service_observability.go @@ -64,7 +64,7 @@ func (s *service) GetLockHolder( if err != nil { return pb.WaitTxn{}, false, err } - holder, ok, err := l.getLockHolder(row) + holder, ok, err := l.getLockHolder(ctx, row) if !moerr.IsMoErrCode(err, moerr.ErrLockTableBindChanged) { return holder, ok, err } diff --git a/pkg/lockservice/service_observability_test.go b/pkg/lockservice/service_observability_test.go index d198a41f0b846..405cf490e52d7 100644 --- a/pkg/lockservice/service_observability_test.go +++ b/pkg/lockservice/service_observability_test.go @@ -268,6 +268,7 @@ func (l *getLockHolderTestTable) getLock( } func (l *getLockHolderTestTable) getLockHolder( + ctx context.Context, key []byte) (pb.WaitTxn, bool, error) { l.calls++ return l.holder, l.found, nil diff --git a/pkg/lockservice/service_remote.go b/pkg/lockservice/service_remote.go index 739c9ae5daf7d..193f9ff07241b 100644 --- a/pkg/lockservice/service_remote.go +++ b/pkg/lockservice/service_remote.go @@ -442,7 +442,7 @@ func (s *service) handleRemoteGetLockHolder( return } - holder, found, err := l.getLockHolder(req.GetLockHolder.Row) + holder, found, err := l.getLockHolder(ctx, req.GetLockHolder.Row) if err == nil && found { resp.GetLockHolder.Holder = holder } @@ -502,11 +502,12 @@ func (s *service) getLocalLockTable( return nil, err } if l == nil { + rows, sharding := lockTableLookupInputsFromRequest(req) l, err = s.getLockTableWithCreate( req.LockTable.Group, req.LockTable.Table, - req.Lock.Rows, - req.Lock.Options.Sharding) + rows, + sharding) if err != nil || l.getBind().Changed(req.LockTable) { return nil, ErrLockTableNotFound } @@ -551,6 +552,17 @@ func (s *service) getLocalLockTable( return l, nil } +func lockTableLookupInputsFromRequest(req *pb.Request) ([][]byte, pb.Sharding) { + switch req.Method { + case pb.Method_GetLockHolder: + return [][]byte{req.GetLockHolder.Row}, req.GetLockHolder.Sharding + case pb.Method_GetTxnLock: + return [][]byte{req.GetTxnLock.Row}, req.LockTable.Sharding + default: + return req.Lock.Rows, req.Lock.Options.Sharding + } +} + func (s *service) getTxnWaitingListOnRemote( txnID []byte, createdOn string) ([]pb.WaitTxn, error) { diff --git a/pkg/lockservice/service_remote_test.go b/pkg/lockservice/service_remote_test.go index b74bca603a14f..70f26fc3b9fa1 100644 --- a/pkg/lockservice/service_remote_test.go +++ b/pkg/lockservice/service_remote_test.go @@ -61,6 +61,32 @@ func TestLockBlockedOnRemote(t *testing.T) { ) } +func TestGetLocalLockTableUsesGetLockHolderLookupInputs(t *testing.T) { + runLockServiceTests( + t, + []string{"s1"}, + func(alloc *lockTableAllocator, s []*service) { + l := s[0] + originTableID := uint64(10) + row := []byte("row1") + tableID := ShardingByRow(row) + bind := alloc.Get(l.serviceID, 0, tableID, originTableID, pb.Sharding_ByRow) + req := &pb.Request{ + Method: pb.Method_GetLockHolder, + LockTable: bind, + } + req.GetLockHolder.Row = row + req.GetLockHolder.Sharding = pb.Sharding_ByRow + resp := &pb.Response{} + + lt, err := l.getLocalLockTable(req, resp) + require.NoError(t, err) + require.NotNil(t, lt) + require.Equal(t, bind, lt.getBind()) + }, + ) +} + func TestRemoteLockResponseLogFieldsDoNotRetainRequest(t *testing.T) { req := &pb.Request{ LockTable: pb.LockTable{ diff --git a/pkg/lockservice/types.go b/pkg/lockservice/types.go index 8b2de393d8b29..b34226d6586f1 100644 --- a/pkg/lockservice/types.go +++ b/pkg/lockservice/types.go @@ -159,7 +159,7 @@ type lockTable interface { // getLock get a lock getLock(key []byte, txn pb.WaitTxn, fn func(Lock)) // getLockHolder returns the current holder if the lock is actively held. - getLockHolder(key []byte) (pb.WaitTxn, bool, error) + getLockHolder(ctx context.Context, key []byte) (pb.WaitTxn, bool, error) // getBind returns lock table binding getBind() pb.LockTable // close close the locktable diff --git a/pkg/pb/lock/lock.pb.go b/pkg/pb/lock/lock.pb.go index 26b3cb9eb217e..f28dbf10d3cec 100644 --- a/pkg/pb/lock/lock.pb.go +++ b/pkg/pb/lock/lock.pb.go @@ -1120,6 +1120,7 @@ func (m *GetTxnLockResponse) GetWaitingList() []WaitTxn { // GetLockHolderRequest gets the current holder on a special row lock. type GetLockHolderRequest struct { Row []byte `protobuf:"bytes,1,opt,name=Row,proto3" json:"Row,omitempty"` + Sharding Sharding `protobuf:"varint,2,opt,name=Sharding,proto3,enum=lock.Sharding" json:"Sharding,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1165,6 +1166,13 @@ func (m *GetLockHolderRequest) GetRow() []byte { return nil } +func (m *GetLockHolderRequest) GetSharding() Sharding { + if m != nil { + return m.Sharding + } + return Sharding_None +} + // GetLockHolderResponse gets the current holder on a special row lock. type GetLockHolderResponse struct { Holder WaitTxn `protobuf:"bytes,1,opt,name=Holder,proto3" json:"Holder"` @@ -2999,143 +3007,144 @@ func init() { func init() { proto.RegisterFile("lock.proto", fileDescriptor_164ad2988c7acaf1) } var fileDescriptor_164ad2988c7acaf1 = []byte{ - // 2175 bytes of a gzipped FileDescriptorProto + // 2182 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0xdb, 0x72, 0xdb, 0xc8, 0xd1, 0x16, 0x48, 0x8a, 0x87, 0x26, 0x29, 0x41, 0xa3, 0x83, 0x21, 0xfd, 0xbb, 0x32, 0x7f, 0x44, 0x5b, 0xc5, 0x95, 0xb3, 0x56, 0x2c, 0xc7, 0xbb, 0x1b, 0x6f, 0xe2, 0x8a, 0x4c, 0x59, 0xb2, 0xd6, - 0x96, 0xb5, 0x19, 0xd2, 0x4e, 0x55, 0xee, 0x20, 0x72, 0x2c, 0xa1, 0x44, 0x01, 0x0c, 0x08, 0xea, - 0xf0, 0x00, 0xa9, 0xca, 0x13, 0xe4, 0x3a, 0x97, 0xb9, 0xc9, 0x7b, 0xec, 0xe5, 0x56, 0xed, 0x7d, - 0x2a, 0x71, 0x9e, 0x20, 0xa9, 0x3c, 0x40, 0xaa, 0x67, 0x06, 0xc4, 0x0c, 0x0e, 0xe2, 0x6e, 0xee, - 0x30, 0xdd, 0x3d, 0x5f, 0xcf, 0x34, 0x1a, 0xdf, 0x74, 0x0f, 0x00, 0x86, 0x7e, 0xff, 0xe2, 0xe1, - 0x28, 0xf0, 0x43, 0x9f, 0x94, 0xf0, 0x79, 0xe3, 0xb3, 0x33, 0x37, 0x3c, 0x9f, 0x9c, 0x3e, 0xec, - 0xfb, 0x97, 0x3b, 0x67, 0xfe, 0x99, 0xbf, 0xc3, 0x95, 0xa7, 0x93, 0xf7, 0x7c, 0xc4, 0x07, 0xfc, - 0x49, 0x4c, 0xda, 0x58, 0x0c, 0xdd, 0x4b, 0x36, 0x0e, 0x9d, 0xcb, 0x91, 0x10, 0xd8, 0xff, 0x29, - 0x40, 0xfd, 0xb5, 0xdf, 0xbf, 0x38, 0x19, 0x85, 0xae, 0xef, 0x8d, 0xc9, 0x63, 0xa8, 0x1f, 0x06, - 0x8e, 0x37, 0x19, 0x3a, 0x81, 0x1b, 0xde, 0x5a, 0x46, 0xcb, 0x68, 0x2f, 0xec, 0x2e, 0x3d, 0xe4, - 0x7e, 0x15, 0x05, 0x55, 0xad, 0x88, 0x0d, 0xa5, 0x63, 0x7f, 0xc0, 0xac, 0x02, 0xb7, 0x5e, 0x10, - 0xd6, 0x88, 0x8a, 0x52, 0xca, 0x75, 0xa4, 0x0d, 0xe5, 0x6f, 0xfc, 0xa1, 0xdb, 0xbf, 0xb5, 0x8a, - 0xdc, 0xca, 0x14, 0x56, 0xbf, 0x75, 0xdc, 0x50, 0xc8, 0xa9, 0xd4, 0x93, 0x8f, 0xa0, 0x76, 0xe0, - 0x07, 0xd7, 0x4e, 0x30, 0xe8, 0xf9, 0x56, 0xa9, 0x65, 0xb4, 0x6b, 0x34, 0x16, 0x90, 0x36, 0x2c, - 0xf6, 0x9c, 0xd3, 0x21, 0xdb, 0x67, 0xef, 0x3b, 0xe7, 0x8e, 0x77, 0xc6, 0x06, 0xd6, 0x7c, 0xcb, - 0x68, 0x57, 0x69, 0x52, 0x8c, 0x38, 0x94, 0x85, 0xc1, 0x2d, 0xba, 0xb0, 0xca, 0x2d, 0xa3, 0x5d, - 0xa4, 0xb1, 0x80, 0xac, 0xc0, 0xfc, 0x61, 0xe0, 0x4f, 0x46, 0x56, 0xa5, 0x65, 0xb4, 0x9b, 0x54, - 0x0c, 0xc8, 0x36, 0x54, 0xbb, 0xe7, 0x4e, 0x30, 0x70, 0xbd, 0x33, 0xab, 0xaa, 0xee, 0x26, 0x92, - 0xd2, 0xa9, 0x9e, 0x3c, 0x05, 0xe8, 0x7a, 0xce, 0xa8, 0x7b, 0xee, 0x87, 0xbd, 0xb1, 0x55, 0x6b, - 0x19, 0xed, 0xfa, 0xee, 0xca, 0xc3, 0x38, 0xc0, 0xbd, 0xe8, 0xe9, 0x79, 0xe9, 0xdb, 0xbf, 0xdd, - 0x9f, 0xa3, 0x8a, 0xb5, 0xfd, 0xbd, 0x01, 0x35, 0x0c, 0x10, 0x5f, 0x33, 0xae, 0x85, 0x3f, 0xf0, - 0x70, 0x97, 0xa8, 0x18, 0xe0, 0xfa, 0xbb, 0x2c, 0xb8, 0x72, 0xfb, 0xec, 0x68, 0x9f, 0x87, 0xb6, - 0x46, 0x63, 0x01, 0xb1, 0xa0, 0xf2, 0x8e, 0x05, 0x63, 0xd7, 0xf7, 0x78, 0x40, 0x4b, 0x34, 0x1a, - 0x22, 0xda, 0x3b, 0x67, 0xe8, 0x0e, 0x78, 0xec, 0xaa, 0x54, 0x0c, 0xe2, 0xfd, 0xce, 0xe7, 0xed, - 0xb7, 0x3c, 0x63, 0xbf, 0x2d, 0xa8, 0x9f, 0x04, 0xee, 0x99, 0xeb, 0x89, 0xb5, 0x56, 0xb8, 0x57, - 0x55, 0x64, 0x7f, 0x0f, 0x50, 0xa1, 0xec, 0xf7, 0x13, 0x36, 0x0e, 0x45, 0xf4, 0xf9, 0xe3, 0xd1, - 0xbe, 0xdc, 0x57, 0x2c, 0x20, 0x8f, 0x95, 0xed, 0xf3, 0xbd, 0xd5, 0x77, 0x17, 0xe3, 0xb4, 0xe1, - 0x62, 0x19, 0x35, 0x25, 0x4c, 0x5b, 0x50, 0x3e, 0x66, 0xe1, 0xb9, 0x3f, 0x90, 0x29, 0xd4, 0x10, - 0x33, 0x84, 0x8c, 0x4a, 0x1d, 0x79, 0x00, 0x25, 0x9c, 0xc2, 0x77, 0x5f, 0x8f, 0x52, 0x17, 0x25, - 0xd2, 0xbb, 0xc4, 0xe5, 0x46, 0xe4, 0x11, 0x94, 0xdf, 0x7a, 0x68, 0xc1, 0xc3, 0x52, 0xdf, 0x5d, - 0x16, 0xe6, 0x42, 0xa6, 0x4f, 0x90, 0x86, 0xe4, 0x57, 0x00, 0x87, 0x2c, 0xec, 0xdd, 0x78, 0xdc, - 0x4b, 0x99, 0x4f, 0xbb, 0x27, 0x3f, 0x90, 0xa9, 0x5c, 0x9f, 0xaa, 0x4c, 0x20, 0x47, 0xb0, 0x70, - 0xc8, 0x42, 0x4c, 0x41, 0xd7, 0x3b, 0x7b, 0xed, 0x8e, 0x43, 0x1e, 0xc8, 0xfa, 0xee, 0xff, 0x4d, - 0x21, 0x14, 0x9d, 0x0e, 0x93, 0x98, 0x48, 0x7e, 0x0e, 0x95, 0x43, 0x16, 0x3e, 0x77, 0xbd, 0x01, - 0xcf, 0x55, 0xcc, 0xbe, 0x08, 0x03, 0x85, 0xfa, 0xe4, 0xc8, 0x94, 0x50, 0x58, 0x7a, 0xc5, 0xd8, - 0x28, 0x8e, 0x33, 0xce, 0x17, 0xd9, 0xbb, 0x29, 0xe6, 0xa7, 0xd4, 0x3a, 0x52, 0x7a, 0x3a, 0x6e, - 0x0a, 0x85, 0x94, 0x5d, 0xfa, 0x21, 0xe3, 0x71, 0x01, 0x75, 0x53, 0xba, 0x2e, 0xb1, 0x29, 0x5d, - 0x49, 0x5e, 0xc3, 0x22, 0x4f, 0x58, 0x27, 0x64, 0x32, 0xd9, 0xad, 0x3a, 0xc7, 0xfa, 0x48, 0x60, - 0x25, 0x94, 0x3a, 0x58, 0x72, 0x2a, 0xe9, 0x40, 0xa3, 0xe3, 0x78, 0x9e, 0x1f, 0x76, 0xfc, 0xcb, - 0x4b, 0x37, 0xb4, 0x1a, 0x1c, 0x6a, 0x5d, 0x40, 0xa9, 0x1a, 0x1d, 0x47, 0x9b, 0x84, 0x20, 0x87, - 0x2c, 0xdc, 0xeb, 0x87, 0xee, 0x15, 0xeb, 0xdd, 0x78, 0x56, 0x53, 0x05, 0x51, 0x35, 0x09, 0x10, - 0x55, 0x85, 0x61, 0xef, 0xb2, 0x90, 0x22, 0x23, 0x04, 0x61, 0xb4, 0xb3, 0x05, 0x35, 0xec, 0x29, - 0x75, 0x22, 0xec, 0x29, 0x3d, 0x62, 0x76, 0x1c, 0x2f, 0x81, 0xb9, 0xa8, 0x62, 0xa6, 0xd4, 0x09, - 0xcc, 0x94, 0x9e, 0xbc, 0x05, 0x42, 0xd9, 0xa5, 0xe3, 0x7a, 0xbd, 0x1b, 0xef, 0xc8, 0x8b, 0x40, - 0x4d, 0x0e, 0x7a, 0x5f, 0x80, 0xa6, 0xf5, 0x3a, 0x6a, 0x06, 0x00, 0xf9, 0x35, 0xd4, 0x3b, 0xe7, - 0xac, 0x7f, 0x71, 0x12, 0x8c, 0xce, 0x1d, 0xcf, 0x5a, 0xe2, 0x78, 0x96, 0x5c, 0x64, 0xac, 0xd0, - 0x81, 0xd4, 0x29, 0x98, 0x18, 0x94, 0x8d, 0x27, 0x97, 0xec, 0xc8, 0xbb, 0xc2, 0xb7, 0xdc, 0x79, - 0x63, 0x11, 0x35, 0x31, 0x12, 0xca, 0x44, 0x62, 0x24, 0xb4, 0xe4, 0x00, 0x9a, 0x87, 0x2c, 0xc4, - 0x8c, 0x7b, 0xe9, 0x0f, 0x07, 0x2c, 0xb0, 0x96, 0x39, 0xd6, 0xc6, 0xf4, 0xa5, 0xc6, 0x2a, 0x1d, - 0x49, 0x9f, 0x46, 0x1c, 0x58, 0xdb, 0x3b, 0xf5, 0x83, 0x50, 0x64, 0xf0, 0x3e, 0x73, 0x06, 0x08, - 0x80, 0x59, 0xb2, 0xc2, 0x01, 0x7f, 0x22, 0x00, 0xb3, 0x6d, 0x74, 0xe4, 0x1c, 0x20, 0xfb, 0x5f, - 0x00, 0x55, 0xca, 0xc6, 0x23, 0xdf, 0x1b, 0xb3, 0x19, 0xb4, 0x1a, 0x33, 0x64, 0xe1, 0x0e, 0x86, - 0x5c, 0x81, 0xf9, 0x17, 0x41, 0xe0, 0x07, 0x9c, 0x46, 0x1b, 0x54, 0x0c, 0xc8, 0xa7, 0x50, 0x79, - 0xc3, 0xae, 0x39, 0x1b, 0x94, 0x32, 0x09, 0x99, 0x46, 0x7a, 0xf2, 0x53, 0x49, 0xb1, 0x82, 0x33, - 0x89, 0x4a, 0xb1, 0x62, 0x99, 0x1a, 0xc7, 0xee, 0x4e, 0x39, 0xb6, 0xac, 0xb2, 0x54, 0xc4, 0xb1, - 0xda, 0x8c, 0x88, 0x64, 0x9f, 0x69, 0x24, 0x5b, 0x51, 0xb3, 0x45, 0x25, 0x59, 0x6d, 0xae, 0xca, - 0xb2, 0x5f, 0xa7, 0x58, 0xb6, 0xaa, 0xe6, 0x4a, 0x92, 0x65, 0x35, 0x9c, 0x24, 0xcd, 0x3e, 0x89, - 0x69, 0x56, 0xd0, 0xe4, 0x6a, 0x82, 0x66, 0xb5, 0xd9, 0x53, 0x9e, 0xed, 0x66, 0xf1, 0x2c, 0xa8, - 0xdf, 0x51, 0x06, 0xcf, 0x6a, 0x50, 0x19, 0x44, 0xfb, 0x75, 0x8a, 0x68, 0x35, 0x72, 0x4c, 0x12, - 0xad, 0xbe, 0xaf, 0x04, 0xd3, 0x1e, 0xa7, 0x99, 0x56, 0xd0, 0xe3, 0xc7, 0x39, 0x4c, 0xab, 0xa1, - 0xa5, 0xa8, 0x76, 0x3f, 0x41, 0xb5, 0x4d, 0xf5, 0x83, 0xd2, 0xa9, 0x56, 0x03, 0xd2, 0xb9, 0x76, - 0x3f, 0xc1, 0xb5, 0x0b, 0x89, 0xcf, 0x52, 0xe1, 0x5a, 0x1d, 0x45, 0x23, 0xdb, 0x6e, 0x16, 0xd9, - 0x2e, 0xaa, 0xb1, 0xcf, 0x20, 0x5b, 0x3d, 0xf6, 0x69, 0xb6, 0xed, 0x66, 0xb1, 0xad, 0x46, 0x8c, - 0x19, 0x6c, 0xab, 0x83, 0xa6, 0xe9, 0xf6, 0x5d, 0x26, 0xdd, 0x0a, 0x7a, 0x6c, 0xe5, 0xd3, 0xad, - 0x06, 0x9b, 0xc5, 0xb7, 0x7b, 0x3a, 0xdf, 0x12, 0xed, 0xdc, 0x53, 0xf9, 0x56, 0x43, 0xd2, 0x08, - 0xf7, 0x38, 0x4d, 0xb8, 0xcb, 0x6a, 0x7e, 0xa4, 0x08, 0x57, 0xcf, 0x8f, 0x24, 0xe3, 0x9e, 0xce, - 0x60, 0xca, 0xad, 0xbb, 0x99, 0x52, 0x03, 0xcf, 0x41, 0x22, 0x87, 0x49, 0x56, 0x5f, 0x4d, 0xd4, - 0x56, 0x2a, 0xab, 0x6b, 0x88, 0xfa, 0x3c, 0xfb, 0x8f, 0x86, 0x68, 0x8b, 0xa2, 0x6a, 0x16, 0x2b, - 0xf4, 0x1b, 0x4f, 0x52, 0x6e, 0x83, 0x8a, 0xc1, 0x8c, 0x0a, 0x9d, 0x40, 0x89, 0xfa, 0xd7, 0x63, - 0xab, 0xd8, 0x2a, 0xb6, 0x1b, 0x94, 0x3f, 0x93, 0x47, 0x50, 0x91, 0x9d, 0x56, 0xba, 0x3e, 0x95, - 0x8a, 0x88, 0x47, 0xe4, 0xd0, 0x7e, 0x0a, 0x0d, 0xf5, 0x63, 0x26, 0xdb, 0x50, 0xc6, 0xd0, 0x0e, - 0x43, 0xbe, 0x96, 0x7a, 0xc4, 0xf1, 0x42, 0x16, 0xd1, 0xa8, 0x18, 0xd9, 0x5f, 0xc1, 0x52, 0xaa, - 0x26, 0xcd, 0xd9, 0x8b, 0x09, 0x45, 0xea, 0x5f, 0xf3, 0x5d, 0x34, 0x28, 0x3e, 0xda, 0x0e, 0x90, - 0x34, 0xd7, 0xca, 0xee, 0x62, 0x22, 0x7a, 0x95, 0x79, 0x2a, 0x06, 0xe4, 0x09, 0xd4, 0x55, 0xb2, - 0x2d, 0xb4, 0x8a, 0xed, 0xfa, 0x6e, 0x33, 0x6e, 0xf1, 0x7a, 0x37, 0x5e, 0x94, 0x62, 0x8a, 0x9d, - 0xdd, 0x86, 0x95, 0xac, 0xa3, 0x36, 0x5a, 0x8c, 0x11, 0x2f, 0x66, 0x1f, 0x56, 0x33, 0x5f, 0x1f, - 0x79, 0x00, 0x65, 0xf9, 0xae, 0x45, 0x38, 0x32, 0x9d, 0x4a, 0x13, 0xfb, 0x19, 0x47, 0x49, 0x17, - 0xd8, 0xe4, 0x13, 0x28, 0x62, 0x26, 0xde, 0x01, 0x81, 0x7a, 0xfb, 0x04, 0xd6, 0xb2, 0x8f, 0x8e, - 0x64, 0x00, 0x8c, 0x1f, 0x18, 0x80, 0x3e, 0x54, 0xa4, 0x36, 0x3f, 0xc5, 0x3a, 0x01, 0x73, 0x42, - 0x36, 0x38, 0xf1, 0xa2, 0x14, 0x9b, 0x0a, 0xc8, 0x16, 0x34, 0x71, 0x3a, 0x0b, 0xf6, 0x06, 0x83, - 0x80, 0x8d, 0xc7, 0xfc, 0x44, 0xaf, 0x51, 0x5d, 0x68, 0xff, 0xc9, 0x80, 0xa6, 0xd6, 0xd1, 0xe4, - 0xf8, 0xfa, 0x1c, 0xaa, 0x82, 0x85, 0x7b, 0x5d, 0xd9, 0x93, 0xdd, 0xd5, 0xce, 0x4e, 0x6d, 0xc9, - 0x17, 0x50, 0x3b, 0x9e, 0x84, 0x8e, 0x48, 0xeb, 0x22, 0xdf, 0xb9, 0xec, 0xa3, 0x5e, 0xdc, 0x84, - 0x81, 0x13, 0xe9, 0xa2, 0x86, 0x6e, 0x6a, 0x6b, 0x9b, 0xb0, 0xa0, 0x57, 0x01, 0xf6, 0x5f, 0x0c, - 0x7e, 0x70, 0x2b, 0x4d, 0x87, 0xfe, 0x91, 0x19, 0xc9, 0x8f, 0x6c, 0xda, 0x3a, 0x17, 0xd4, 0xd6, - 0x79, 0xda, 0xec, 0x16, 0xf3, 0x9a, 0xdd, 0xd2, 0x8f, 0x6b, 0x76, 0xe7, 0xd3, 0xcd, 0xee, 0x01, - 0x2c, 0x26, 0x2a, 0x80, 0xff, 0xa9, 0xab, 0xb5, 0xff, 0x6a, 0x80, 0x95, 0xd7, 0x71, 0xcd, 0xd8, - 0xfc, 0x16, 0x94, 0xbb, 0xa1, 0x13, 0x4e, 0xc6, 0x7a, 0xb9, 0x27, 0x64, 0x54, 0xea, 0xc8, 0x1a, - 0x94, 0xf9, 0xfb, 0x8d, 0x98, 0x48, 0x8e, 0xc8, 0x13, 0x80, 0xa9, 0x4f, 0xa4, 0xa3, 0x62, 0xfe, - 0x72, 0x15, 0x43, 0xfb, 0x37, 0xb0, 0x9e, 0x5b, 0xb8, 0x90, 0x05, 0x28, 0x9c, 0xbc, 0xe2, 0x0b, - 0xad, 0xd2, 0xc2, 0xc9, 0xab, 0x1f, 0xb6, 0x42, 0xfb, 0x4b, 0xb0, 0xf2, 0x9a, 0x9f, 0xbb, 0x23, - 0x60, 0x3f, 0x80, 0xf5, 0xdc, 0x93, 0x3c, 0xb9, 0x18, 0x74, 0x93, 0xd7, 0x0f, 0xcd, 0x76, 0x93, - 0x7b, 0xb6, 0xa7, 0xdc, 0xfc, 0x02, 0xd6, 0x73, 0x3b, 0xa4, 0x19, 0x7e, 0x9e, 0xc2, 0x46, 0xfe, - 0x69, 0x2f, 0x6a, 0x7f, 0xa9, 0x95, 0xf4, 0x1b, 0x0b, 0xec, 0x27, 0xb0, 0x9a, 0xd9, 0x67, 0xcf, - 0x70, 0xd9, 0x86, 0xb5, 0xec, 0xaa, 0x31, 0xb5, 0xaf, 0xcf, 0x61, 0x2d, 0xbb, 0xf9, 0x9e, 0xe1, - 0xe1, 0x53, 0xb8, 0x97, 0x53, 0x4a, 0xa6, 0x5c, 0x1c, 0xc0, 0xc7, 0x77, 0x76, 0x4a, 0xc8, 0xd3, - 0xe1, 0x0c, 0x9e, 0x0e, 0x6f, 0x3c, 0xfb, 0x67, 0xb0, 0x79, 0x77, 0x1d, 0x91, 0xf2, 0x4c, 0x61, - 0x39, 0xe3, 0x3a, 0x80, 0x7c, 0x05, 0x4d, 0x51, 0x0d, 0xe1, 0x31, 0x18, 0x13, 0xbb, 0xfc, 0x4c, - 0xa6, 0xaa, 0xa8, 0x88, 0xd0, 0x6c, 0xed, 0x5f, 0xc2, 0x4a, 0x56, 0xdd, 0x8b, 0xac, 0x2d, 0x24, - 0x78, 0x0c, 0x88, 0x77, 0x89, 0xdf, 0xa5, 0x2e, 0xb4, 0x1f, 0xc3, 0x72, 0xc6, 0xdd, 0xc2, 0x8c, - 0x58, 0x3f, 0xe3, 0x07, 0x6a, 0xaa, 0x48, 0x8e, 0xef, 0x04, 0x0d, 0xf5, 0x4e, 0xd0, 0x14, 0xa7, - 0x5e, 0x81, 0xbb, 0xe7, 0x07, 0xdc, 0x3e, 0x90, 0x74, 0x37, 0x3e, 0x83, 0x85, 0xa6, 0x28, 0x46, - 0x84, 0xf2, 0x19, 0x2c, 0x67, 0xd4, 0x98, 0x48, 0x44, 0xb2, 0x1c, 0x15, 0xab, 0x90, 0x23, 0xfb, - 0x0b, 0xa8, 0x4d, 0x03, 0x47, 0x2c, 0xa8, 0x44, 0x55, 0xb0, 0xf0, 0x14, 0x0d, 0x33, 0x56, 0xfb, - 0x87, 0x62, 0x54, 0x0b, 0x91, 0x47, 0x50, 0xc5, 0xe4, 0xe5, 0xc7, 0xa4, 0x71, 0x17, 0xf3, 0x4e, - 0xcd, 0x90, 0xe2, 0x5f, 0x3a, 0xe3, 0x8e, 0xef, 0xbd, 0x1f, 0xba, 0xfd, 0x90, 0xaf, 0xbf, 0x4a, - 0x55, 0x11, 0xbe, 0xa8, 0x97, 0xce, 0xf8, 0x9b, 0x80, 0x5d, 0xc9, 0x9e, 0xa6, 0xc8, 0x6d, 0x74, - 0x21, 0xf9, 0x12, 0x6a, 0xd3, 0xb3, 0x51, 0x56, 0x75, 0x77, 0x9d, 0x9b, 0xb1, 0xf1, 0x8f, 0xb8, - 0xcb, 0x6e, 0x41, 0x3d, 0x5a, 0xd5, 0x2b, 0x76, 0xcb, 0x1b, 0xe9, 0x06, 0x55, 0x45, 0xaa, 0x05, - 0x46, 0xa9, 0xa2, 0x5b, 0x60, 0x64, 0x37, 0x01, 0x70, 0xd5, 0xa2, 0x36, 0xe0, 0xfd, 0x70, 0x83, - 0x2a, 0x12, 0x8c, 0xbc, 0x78, 0x12, 0x97, 0xd9, 0x4d, 0x1a, 0x0d, 0x71, 0xe6, 0x1b, 0x76, 0x8d, - 0x81, 0xdb, 0x1b, 0x88, 0x1e, 0xb6, 0x4a, 0x15, 0x89, 0xdd, 0x85, 0xa6, 0x76, 0xd2, 0xe3, 0xab, - 0xba, 0x60, 0xb7, 0x51, 0xfd, 0x76, 0xc1, 0x6e, 0xb1, 0x18, 0x1e, 0x5f, 0xb8, 0x23, 0x19, 0x65, - 0xfe, 0x8c, 0x69, 0x15, 0xb0, 0xd1, 0xd0, 0xe9, 0xb3, 0x9e, 0x2f, 0xef, 0x22, 0x62, 0x01, 0xd2, - 0x4d, 0xf6, 0x95, 0xce, 0x8c, 0x4f, 0x60, 0x1d, 0xee, 0xe5, 0x74, 0x26, 0xdb, 0xff, 0xaf, 0xfd, - 0xdc, 0x20, 0x15, 0x5e, 0x65, 0x9a, 0x73, 0xa4, 0x06, 0xf3, 0x14, 0xe3, 0x6c, 0x1a, 0xdb, 0x9f, - 0x88, 0x3c, 0xe2, 0xbf, 0x2c, 0x9a, 0x50, 0x7b, 0x71, 0xd3, 0x1f, 0x4e, 0xc6, 0xee, 0x15, 0x33, - 0xe7, 0x08, 0x40, 0x19, 0xcb, 0x03, 0x36, 0x30, 0x8d, 0xed, 0x2d, 0x80, 0xf8, 0xcf, 0x05, 0xa9, - 0x42, 0x09, 0x47, 0xe6, 0x1c, 0x69, 0x40, 0xf5, 0xc0, 0x19, 0x87, 0x07, 0x8e, 0x3b, 0x34, 0x8d, - 0xed, 0xfb, 0x71, 0xc1, 0x81, 0x36, 0x6f, 0x7c, 0x8f, 0x09, 0x6f, 0xcf, 0x6f, 0xd1, 0xb1, 0xb1, - 0xfd, 0xef, 0x42, 0x74, 0x61, 0x83, 0x7a, 0x74, 0x2c, 0xfc, 0x88, 0xaa, 0xc8, 0x34, 0xc8, 0x82, - 0x7a, 0x0f, 0x62, 0x16, 0x08, 0x49, 0xde, 0x6b, 0x98, 0x45, 0x94, 0xe9, 0x0c, 0x6e, 0x96, 0x48, - 0x7d, 0x7a, 0x67, 0x61, 0xce, 0x93, 0xd5, 0x8c, 0x9b, 0x08, 0xb3, 0x4c, 0x16, 0xa1, 0x2e, 0x7f, - 0xab, 0xf0, 0x49, 0x15, 0xb2, 0x04, 0x4d, 0x29, 0x90, 0xfe, 0xab, 0x64, 0x39, 0x75, 0x47, 0x60, - 0xd6, 0x88, 0xa9, 0x77, 0xfa, 0x26, 0xa0, 0x44, 0xa5, 0x1d, 0xb3, 0x8e, 0x3e, 0x53, 0x07, 0xb3, - 0xd9, 0x20, 0x6b, 0x59, 0xed, 0xae, 0xd9, 0x44, 0xf3, 0xd4, 0x01, 0x6b, 0x2e, 0xe0, 0x12, 0x15, - 0x22, 0x31, 0x17, 0x71, 0x3d, 0x89, 0x97, 0x6b, 0x9a, 0x64, 0x23, 0xaf, 0xb3, 0x34, 0x97, 0x70, - 0x4f, 0x5a, 0xdf, 0x60, 0x92, 0x6d, 0x16, 0xd5, 0x24, 0x62, 0x91, 0xdc, 0x17, 0x1a, 0xbc, 0xf0, - 0x30, 0x38, 0xe6, 0x1c, 0x2e, 0x52, 0x11, 0xcb, 0x60, 0x9b, 0x86, 0x62, 0xfe, 0x96, 0xbf, 0x8f, - 0xee, 0xa4, 0xdf, 0x37, 0x0b, 0x8a, 0x38, 0xde, 0x82, 0x59, 0x7c, 0xde, 0xf9, 0xee, 0x1f, 0x9b, - 0xc6, 0xb7, 0x1f, 0x36, 0x8d, 0xef, 0x3e, 0x6c, 0x1a, 0x7f, 0xff, 0xb0, 0x39, 0xf7, 0xe7, 0x7f, - 0x6e, 0x1a, 0xbf, 0x53, 0xff, 0xd7, 0x5d, 0x3a, 0x61, 0xe0, 0xde, 0xf8, 0xbc, 0xa6, 0x8c, 0x06, - 0x1e, 0xdb, 0x19, 0x5d, 0x9c, 0xed, 0x8c, 0x4e, 0x77, 0x70, 0x0f, 0xa7, 0x65, 0xfe, 0x97, 0xee, - 0xf1, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x32, 0x0c, 0xed, 0xff, 0xf9, 0x1b, 0x00, 0x00, + 0x96, 0xb5, 0x19, 0xd2, 0x4e, 0x55, 0xee, 0x20, 0x72, 0x2c, 0xa1, 0x44, 0x01, 0x0c, 0x38, 0x94, + 0xa8, 0x07, 0x48, 0x55, 0x9e, 0x20, 0xd7, 0xb9, 0xcc, 0x4d, 0xde, 0x63, 0x2f, 0xb7, 0x6a, 0xef, + 0x53, 0x89, 0xf3, 0x04, 0x49, 0xe5, 0x01, 0x52, 0x73, 0x00, 0x30, 0x83, 0x03, 0xb9, 0x9b, 0x3b, + 0x4c, 0x77, 0xcf, 0xd7, 0x33, 0x8d, 0xc6, 0x37, 0xdd, 0x03, 0x80, 0xa1, 0xdf, 0xbf, 0x7a, 0x38, + 0x0a, 0x7c, 0xea, 0xa3, 0x12, 0x7b, 0xde, 0xfa, 0xec, 0xc2, 0xa5, 0x97, 0x93, 0xf3, 0x87, 0x7d, + 0xff, 0x7a, 0xef, 0xc2, 0xbf, 0xf0, 0xf7, 0xb8, 0xf2, 0x7c, 0xf2, 0x9e, 0x8f, 0xf8, 0x80, 0x3f, + 0x89, 0x49, 0x5b, 0xcb, 0xd4, 0xbd, 0x26, 0x63, 0xea, 0x5c, 0x8f, 0x84, 0xc0, 0xfe, 0x4f, 0x01, + 0xea, 0xaf, 0xfd, 0xfe, 0xd5, 0xd9, 0x88, 0xba, 0xbe, 0x37, 0x46, 0x8f, 0xa1, 0x7e, 0x1c, 0x38, + 0xde, 0x64, 0xe8, 0x04, 0x2e, 0xbd, 0xb3, 0x8c, 0x96, 0xd1, 0x5e, 0xda, 0x5f, 0x79, 0xc8, 0xfd, + 0x2a, 0x0a, 0xac, 0x5a, 0x21, 0x1b, 0x4a, 0xa7, 0xfe, 0x80, 0x58, 0x05, 0x6e, 0xbd, 0x24, 0xac, + 0x19, 0x2a, 0x93, 0x62, 0xae, 0x43, 0x6d, 0x28, 0x7f, 0xe3, 0x0f, 0xdd, 0xfe, 0x9d, 0x55, 0xe4, + 0x56, 0xa6, 0xb0, 0xfa, 0xad, 0xe3, 0x52, 0x21, 0xc7, 0x52, 0x8f, 0x3e, 0x82, 0xda, 0x91, 0x1f, + 0xdc, 0x3a, 0xc1, 0xa0, 0xe7, 0x5b, 0xa5, 0x96, 0xd1, 0xae, 0xe1, 0x58, 0x80, 0xda, 0xb0, 0xdc, + 0x73, 0xce, 0x87, 0xe4, 0x90, 0xbc, 0xef, 0x5c, 0x3a, 0xde, 0x05, 0x19, 0x58, 0x8b, 0x2d, 0xa3, + 0x5d, 0xc5, 0x49, 0x31, 0xc3, 0xc1, 0x84, 0x06, 0x77, 0xcc, 0x85, 0x55, 0x6e, 0x19, 0xed, 0x22, + 0x8e, 0x05, 0x68, 0x0d, 0x16, 0x8f, 0x03, 0x7f, 0x32, 0xb2, 0x2a, 0x2d, 0xa3, 0xdd, 0xc4, 0x62, + 0x80, 0x76, 0xa1, 0xda, 0xbd, 0x74, 0x82, 0x81, 0xeb, 0x5d, 0x58, 0x55, 0x75, 0x37, 0xa1, 0x14, + 0x47, 0x7a, 0xf4, 0x14, 0xa0, 0xeb, 0x39, 0xa3, 0xee, 0xa5, 0x4f, 0x7b, 0x63, 0xab, 0xd6, 0x32, + 0xda, 0xf5, 0xfd, 0xb5, 0x87, 0x71, 0x80, 0x7b, 0xe1, 0xd3, 0xf3, 0xd2, 0xb7, 0x7f, 0xbb, 0xbf, + 0x80, 0x15, 0x6b, 0xfb, 0x7b, 0x03, 0x6a, 0x2c, 0x40, 0x7c, 0xcd, 0x6c, 0x2d, 0xfc, 0x81, 0x87, + 0xbb, 0x84, 0xc5, 0x80, 0xad, 0xbf, 0x4b, 0x82, 0x1b, 0xb7, 0x4f, 0x4e, 0x0e, 0x79, 0x68, 0x6b, + 0x38, 0x16, 0x20, 0x0b, 0x2a, 0xef, 0x48, 0x30, 0x76, 0x7d, 0x8f, 0x07, 0xb4, 0x84, 0xc3, 0x21, + 0x43, 0x7b, 0xe7, 0x0c, 0xdd, 0x01, 0x8f, 0x5d, 0x15, 0x8b, 0x41, 0xbc, 0xdf, 0xc5, 0xbc, 0xfd, + 0x96, 0xe7, 0xec, 0xb7, 0x05, 0xf5, 0xb3, 0xc0, 0xbd, 0x70, 0x3d, 0xb1, 0xd6, 0x0a, 0xf7, 0xaa, + 0x8a, 0xec, 0xef, 0x01, 0x2a, 0x98, 0xfc, 0x7e, 0x42, 0xc6, 0x54, 0x44, 0x9f, 0x3f, 0x9e, 0x1c, + 0xca, 0x7d, 0xc5, 0x02, 0xf4, 0x58, 0xd9, 0x3e, 0xdf, 0x5b, 0x7d, 0x7f, 0x39, 0x4e, 0x1b, 0x2e, + 0x96, 0x51, 0x53, 0xc2, 0xb4, 0x03, 0xe5, 0x53, 0x42, 0x2f, 0xfd, 0x81, 0x4c, 0xa1, 0x86, 0x98, + 0x21, 0x64, 0x58, 0xea, 0xd0, 0x03, 0x28, 0xb1, 0x29, 0x7c, 0xf7, 0xf5, 0x30, 0x75, 0x99, 0x44, + 0x7a, 0x97, 0xb8, 0xdc, 0x08, 0x3d, 0x82, 0xf2, 0x5b, 0x8f, 0x59, 0xf0, 0xb0, 0xd4, 0xf7, 0x57, + 0x85, 0xb9, 0x90, 0xe9, 0x13, 0xa4, 0x21, 0xfa, 0x15, 0xc0, 0x31, 0xa1, 0xbd, 0xa9, 0xc7, 0xbd, + 0x94, 0xf9, 0xb4, 0x7b, 0xf2, 0x03, 0x89, 0xe4, 0xfa, 0x54, 0x65, 0x02, 0x3a, 0x81, 0xa5, 0x63, + 0x42, 0x59, 0x0a, 0xba, 0xde, 0xc5, 0x6b, 0x77, 0x4c, 0x79, 0x20, 0xeb, 0xfb, 0xff, 0x17, 0x41, + 0x28, 0x3a, 0x1d, 0x26, 0x31, 0x11, 0xfd, 0x1c, 0x2a, 0xc7, 0x84, 0x3e, 0x77, 0xbd, 0x01, 0xcf, + 0x55, 0x96, 0x7d, 0x21, 0x06, 0x13, 0xea, 0x93, 0x43, 0x53, 0x84, 0x61, 0xe5, 0x15, 0x21, 0xa3, + 0x38, 0xce, 0x6c, 0xbe, 0xc8, 0xde, 0x6d, 0x31, 0x3f, 0xa5, 0xd6, 0x91, 0xd2, 0xd3, 0xd9, 0xa6, + 0x98, 0x10, 0x93, 0x6b, 0x9f, 0x12, 0x1e, 0x17, 0x50, 0x37, 0xa5, 0xeb, 0x12, 0x9b, 0xd2, 0x95, + 0xe8, 0x35, 0x2c, 0xf3, 0x84, 0x75, 0x28, 0x91, 0xc9, 0x6e, 0xd5, 0x39, 0xd6, 0x47, 0x02, 0x2b, + 0xa1, 0xd4, 0xc1, 0x92, 0x53, 0x51, 0x07, 0x1a, 0x1d, 0xc7, 0xf3, 0x7c, 0xda, 0xf1, 0xaf, 0xaf, + 0x5d, 0x6a, 0x35, 0x38, 0xd4, 0xa6, 0x80, 0x52, 0x35, 0x3a, 0x8e, 0x36, 0x89, 0x81, 0x1c, 0x13, + 0x7a, 0xd0, 0xa7, 0xee, 0x0d, 0xe9, 0x4d, 0x3d, 0xab, 0xa9, 0x82, 0xa8, 0x9a, 0x04, 0x88, 0xaa, + 0x62, 0x61, 0xef, 0x12, 0x8a, 0x19, 0x23, 0x04, 0x34, 0xdc, 0xd9, 0x92, 0x1a, 0xf6, 0x94, 0x3a, + 0x11, 0xf6, 0x94, 0x9e, 0x61, 0x76, 0x1c, 0x2f, 0x81, 0xb9, 0xac, 0x62, 0xa6, 0xd4, 0x09, 0xcc, + 0x94, 0x1e, 0xbd, 0x05, 0x84, 0xc9, 0xb5, 0xe3, 0x7a, 0xbd, 0xa9, 0x77, 0xe2, 0x85, 0xa0, 0x26, + 0x07, 0xbd, 0x2f, 0x40, 0xd3, 0x7a, 0x1d, 0x35, 0x03, 0x00, 0xfd, 0x1a, 0xea, 0x9d, 0x4b, 0xd2, + 0xbf, 0x3a, 0x0b, 0x46, 0x97, 0x8e, 0x67, 0xad, 0x70, 0x3c, 0x4b, 0x2e, 0x32, 0x56, 0xe8, 0x40, + 0xea, 0x14, 0x96, 0x18, 0x98, 0x8c, 0x27, 0xd7, 0xe4, 0xc4, 0xbb, 0x61, 0x6f, 0xb9, 0xf3, 0xc6, + 0x42, 0x6a, 0x62, 0x24, 0x94, 0x89, 0xc4, 0x48, 0x68, 0xd1, 0x11, 0x34, 0x8f, 0x09, 0x65, 0x19, + 0xf7, 0xd2, 0x1f, 0x0e, 0x48, 0x60, 0xad, 0x72, 0xac, 0xad, 0xe8, 0xa5, 0xc6, 0x2a, 0x1d, 0x49, + 0x9f, 0x86, 0x1c, 0xd8, 0x38, 0x38, 0xf7, 0x03, 0x2a, 0x32, 0xf8, 0x90, 0x38, 0x03, 0x06, 0xc0, + 0xb2, 0x64, 0x8d, 0x03, 0xfe, 0x44, 0x00, 0x66, 0xdb, 0xe8, 0xc8, 0x39, 0x40, 0xf6, 0xbf, 0x00, + 0xaa, 0x98, 0x8c, 0x47, 0xbe, 0x37, 0x26, 0x73, 0x68, 0x35, 0x66, 0xc8, 0xc2, 0x0c, 0x86, 0x5c, + 0x83, 0xc5, 0x17, 0x41, 0xe0, 0x07, 0x9c, 0x46, 0x1b, 0x58, 0x0c, 0xd0, 0xa7, 0x50, 0x79, 0x43, + 0x6e, 0x39, 0x1b, 0x94, 0x32, 0x09, 0x19, 0x87, 0x7a, 0xf4, 0x53, 0x49, 0xb1, 0x82, 0x33, 0x91, + 0x4a, 0xb1, 0x62, 0x99, 0x1a, 0xc7, 0xee, 0x47, 0x1c, 0x5b, 0x56, 0x59, 0x2a, 0xe4, 0x58, 0x6d, + 0x46, 0x48, 0xb2, 0xcf, 0x34, 0x92, 0xad, 0xa8, 0xd9, 0xa2, 0x92, 0xac, 0x36, 0x57, 0x65, 0xd9, + 0xaf, 0x53, 0x2c, 0x5b, 0x55, 0x73, 0x25, 0xc9, 0xb2, 0x1a, 0x4e, 0x92, 0x66, 0x9f, 0xc4, 0x34, + 0x2b, 0x68, 0x72, 0x3d, 0x41, 0xb3, 0xda, 0xec, 0x88, 0x67, 0xbb, 0x59, 0x3c, 0x0b, 0xea, 0x77, + 0x94, 0xc1, 0xb3, 0x1a, 0x54, 0x06, 0xd1, 0x7e, 0x9d, 0x22, 0x5a, 0x8d, 0x1c, 0x93, 0x44, 0xab, + 0xef, 0x2b, 0xc1, 0xb4, 0xa7, 0x69, 0xa6, 0x15, 0xf4, 0xf8, 0x71, 0x0e, 0xd3, 0x6a, 0x68, 0x29, + 0xaa, 0x3d, 0x4c, 0x50, 0x6d, 0x53, 0xfd, 0xa0, 0x74, 0xaa, 0xd5, 0x80, 0x74, 0xae, 0x3d, 0x4c, + 0x70, 0xed, 0x52, 0xe2, 0xb3, 0x54, 0xb8, 0x56, 0x47, 0xd1, 0xc8, 0xb6, 0x9b, 0x45, 0xb6, 0xcb, + 0x6a, 0xec, 0x33, 0xc8, 0x56, 0x8f, 0x7d, 0x9a, 0x6d, 0xbb, 0x59, 0x6c, 0xab, 0x11, 0x63, 0x06, + 0xdb, 0xea, 0xa0, 0x69, 0xba, 0x7d, 0x97, 0x49, 0xb7, 0x82, 0x1e, 0x5b, 0xf9, 0x74, 0xab, 0xc1, + 0x66, 0xf1, 0xed, 0x81, 0xce, 0xb7, 0x48, 0x3b, 0xf7, 0x54, 0xbe, 0xd5, 0x90, 0x34, 0xc2, 0x3d, + 0x4d, 0x13, 0xee, 0xaa, 0x9a, 0x1f, 0x29, 0xc2, 0xd5, 0xf3, 0x23, 0xc9, 0xb8, 0xe7, 0x73, 0x98, + 0x72, 0x67, 0x36, 0x53, 0x6a, 0xe0, 0x39, 0x48, 0xe8, 0x38, 0xc9, 0xea, 0xeb, 0x89, 0xda, 0x4a, + 0x65, 0x75, 0x0d, 0x51, 0x9f, 0x67, 0xff, 0xd1, 0x10, 0x6d, 0x51, 0x58, 0xcd, 0xb2, 0x0a, 0x7d, + 0xea, 0x49, 0xca, 0x6d, 0x60, 0x31, 0x98, 0x53, 0xa1, 0x23, 0x28, 0x61, 0xff, 0x76, 0x6c, 0x15, + 0x5b, 0xc5, 0x76, 0x03, 0xf3, 0x67, 0xf4, 0x08, 0x2a, 0xb2, 0xd3, 0x4a, 0xd7, 0xa7, 0x52, 0x11, + 0xf2, 0x88, 0x1c, 0xda, 0x4f, 0xa1, 0xa1, 0x7e, 0xcc, 0x68, 0x17, 0xca, 0x2c, 0xb4, 0x43, 0xca, + 0xd7, 0x52, 0x0f, 0x39, 0x5e, 0xc8, 0x42, 0x1a, 0x15, 0x23, 0xfb, 0x2b, 0x58, 0x49, 0xd5, 0xa4, + 0x39, 0x7b, 0x31, 0xa1, 0x88, 0xfd, 0x5b, 0xbe, 0x8b, 0x06, 0x66, 0x8f, 0xb6, 0x03, 0x28, 0xcd, + 0xb5, 0xb2, 0xbb, 0x98, 0x88, 0x5e, 0x65, 0x11, 0x8b, 0x01, 0x7a, 0x02, 0x75, 0x95, 0x6c, 0x0b, + 0xad, 0x62, 0xbb, 0xbe, 0xdf, 0x8c, 0x5b, 0xbc, 0xde, 0xd4, 0x0b, 0x53, 0x4c, 0xb1, 0xb3, 0x7b, + 0xb0, 0x96, 0x75, 0xd4, 0x86, 0x8b, 0x31, 0xa2, 0xc5, 0x68, 0x8d, 0x4a, 0x61, 0x76, 0xa3, 0x62, + 0x1f, 0xc2, 0x7a, 0xe6, 0xab, 0x46, 0x0f, 0xa0, 0x2c, 0xf3, 0x42, 0x84, 0x2e, 0x73, 0x81, 0xd2, + 0xc4, 0x7e, 0xc6, 0x51, 0xd2, 0xc5, 0x38, 0xfa, 0x04, 0x8a, 0x2c, 0x6b, 0x67, 0x40, 0x30, 0xbd, + 0x7d, 0x06, 0x1b, 0xd9, 0xc7, 0x4c, 0x32, 0x58, 0xc6, 0x0f, 0x0c, 0x56, 0x1f, 0x2a, 0x52, 0x9b, + 0x9f, 0x8e, 0x9d, 0x80, 0x38, 0x94, 0x0c, 0xce, 0xbc, 0x30, 0x1d, 0x23, 0x01, 0xda, 0x81, 0x26, + 0x9b, 0x4e, 0x82, 0x83, 0xc1, 0x20, 0x20, 0xe3, 0x31, 0x3f, 0xfd, 0x6b, 0x58, 0x17, 0xda, 0x7f, + 0x32, 0xa0, 0xa9, 0x75, 0x3f, 0x39, 0xbe, 0x3e, 0x87, 0xaa, 0x60, 0xec, 0x5e, 0x57, 0xf6, 0x6f, + 0xb3, 0x5a, 0xdf, 0xc8, 0x16, 0x7d, 0x01, 0xb5, 0xd3, 0x09, 0x75, 0xc4, 0x27, 0x50, 0xe4, 0x3b, + 0x97, 0x3d, 0xd7, 0x8b, 0x29, 0x0d, 0x9c, 0x50, 0x17, 0x36, 0x7f, 0x91, 0xad, 0x6d, 0xc2, 0x92, + 0x5e, 0x31, 0xd8, 0x7f, 0x31, 0xf8, 0x21, 0xaf, 0x34, 0x28, 0xfa, 0x07, 0x69, 0x24, 0x3f, 0xc8, + 0xa8, 0xcd, 0x2e, 0xa8, 0x6d, 0x76, 0xd4, 0x18, 0x17, 0xf3, 0x1a, 0xe3, 0xd2, 0x8f, 0x6b, 0x8c, + 0x17, 0xd3, 0x8d, 0xf1, 0x11, 0x2c, 0x27, 0xaa, 0x85, 0xff, 0xa9, 0x03, 0xb6, 0xff, 0x6a, 0x80, + 0x95, 0xd7, 0x9d, 0xcd, 0xd9, 0xfc, 0x0e, 0x94, 0xbb, 0xd4, 0xa1, 0x93, 0xb1, 0x5e, 0x1a, 0x0a, + 0x19, 0x96, 0x3a, 0xb4, 0x01, 0x65, 0xfe, 0x7e, 0x43, 0xd6, 0x92, 0x23, 0xf4, 0x04, 0x20, 0xf2, + 0xc9, 0xa8, 0xab, 0x98, 0xbf, 0x5c, 0xc5, 0xd0, 0xfe, 0x0d, 0x6c, 0xe6, 0x16, 0x39, 0x68, 0x09, + 0x0a, 0x67, 0xaf, 0xf8, 0x42, 0xab, 0xb8, 0x70, 0xf6, 0xea, 0x87, 0xad, 0xd0, 0xfe, 0x12, 0xac, + 0xbc, 0x46, 0x69, 0x76, 0x04, 0xec, 0x07, 0xb0, 0x99, 0x7b, 0xea, 0x27, 0x17, 0xc3, 0xdc, 0xe4, + 0xf5, 0x4e, 0xf3, 0xdd, 0xe4, 0xd6, 0x01, 0x29, 0x37, 0xbf, 0x80, 0xcd, 0xdc, 0x6e, 0x6a, 0x8e, + 0x9f, 0xa7, 0xb0, 0x95, 0x5f, 0x19, 0x88, 0x3e, 0x41, 0x6a, 0x25, 0x55, 0xc7, 0x02, 0xfb, 0x09, + 0xac, 0x67, 0xf6, 0xe4, 0x73, 0x5c, 0xb6, 0x61, 0x23, 0xbb, 0xc2, 0x4c, 0xed, 0xeb, 0x73, 0xd8, + 0xc8, 0x6e, 0xd4, 0xe7, 0x78, 0xf8, 0x14, 0xee, 0xe5, 0x94, 0x9d, 0x29, 0x17, 0x47, 0xf0, 0xf1, + 0xcc, 0xae, 0x8a, 0xf1, 0x34, 0x9d, 0xc3, 0xd3, 0x74, 0xea, 0xd9, 0x3f, 0x83, 0xed, 0xd9, 0x35, + 0x47, 0xca, 0x33, 0x86, 0xd5, 0x8c, 0xab, 0x03, 0xf4, 0x15, 0x34, 0x45, 0xe5, 0xc4, 0x8e, 0xcc, + 0x98, 0xd8, 0xe5, 0x67, 0x12, 0xa9, 0xc2, 0x82, 0x43, 0xb3, 0xb5, 0x7f, 0x09, 0x6b, 0x59, 0x35, + 0x32, 0x63, 0x6d, 0x21, 0x61, 0xc7, 0x80, 0x78, 0x97, 0xec, 0xbb, 0xd4, 0x85, 0xf6, 0x63, 0x58, + 0xcd, 0xb8, 0x87, 0x98, 0x13, 0xeb, 0x67, 0xfc, 0xf0, 0x4d, 0x15, 0xd4, 0xf1, 0xfd, 0xa1, 0xa1, + 0xde, 0x1f, 0x9a, 0xe2, 0xd4, 0x2b, 0x70, 0xf7, 0xfc, 0x80, 0x3b, 0x04, 0x94, 0xee, 0xdc, 0xe7, + 0xb0, 0x50, 0x84, 0x62, 0x84, 0x28, 0x9f, 0xc1, 0x6a, 0x46, 0x3d, 0xca, 0x88, 0x48, 0x96, 0xae, + 0x62, 0x15, 0x72, 0x64, 0x7f, 0x01, 0xb5, 0x28, 0x70, 0xc8, 0x82, 0x4a, 0x58, 0x31, 0x0b, 0x4f, + 0xe1, 0x30, 0x63, 0xb5, 0x7f, 0x28, 0x86, 0x75, 0x13, 0x7a, 0x04, 0x55, 0x96, 0xbc, 0xfc, 0x98, + 0x34, 0x66, 0x31, 0x6f, 0x64, 0xc6, 0x28, 0xfe, 0xa5, 0x33, 0xee, 0xf8, 0xde, 0xfb, 0xa1, 0xdb, + 0xa7, 0x7c, 0xfd, 0x55, 0xac, 0x8a, 0xd8, 0x8b, 0x7a, 0xe9, 0x8c, 0xbf, 0x09, 0xc8, 0x8d, 0xec, + 0x7f, 0x8a, 0xdc, 0x46, 0x17, 0xa2, 0x2f, 0xa1, 0x16, 0x9d, 0x8d, 0xb2, 0x02, 0x9c, 0x75, 0x6e, + 0xc6, 0xc6, 0x3f, 0xe2, 0xde, 0xbb, 0x05, 0xf5, 0x70, 0x55, 0xaf, 0xc8, 0x1d, 0x6f, 0xba, 0x1b, + 0x58, 0x15, 0xa9, 0x16, 0x2c, 0x4a, 0x15, 0xdd, 0x82, 0x45, 0x76, 0x1b, 0x80, 0xad, 0x5a, 0xd4, + 0x06, 0xbc, 0x77, 0x6e, 0x60, 0x45, 0xc2, 0x22, 0x2f, 0x9e, 0xc4, 0xc5, 0x77, 0x13, 0x87, 0x43, + 0x36, 0xf3, 0x0d, 0xb9, 0x65, 0x81, 0x3b, 0x18, 0x88, 0x7e, 0xb7, 0x8a, 0x15, 0x89, 0xdd, 0x85, + 0xa6, 0x76, 0xd2, 0xb3, 0x57, 0x75, 0x45, 0xee, 0xc2, 0x5a, 0xef, 0x8a, 0xdc, 0xb1, 0xc2, 0x79, + 0x7c, 0xe5, 0x8e, 0x64, 0x94, 0xf9, 0x33, 0x4b, 0xab, 0x80, 0x8c, 0x86, 0x4e, 0x9f, 0xf4, 0x7c, + 0x79, 0x6f, 0x11, 0x0b, 0x18, 0xdd, 0x64, 0x5f, 0xff, 0xcc, 0xf9, 0x04, 0x36, 0xe1, 0x5e, 0x4e, + 0x17, 0xb3, 0xfb, 0xff, 0xda, 0x8f, 0x10, 0x54, 0xe1, 0x15, 0xa9, 0xb9, 0x80, 0x6a, 0xb0, 0x88, + 0x59, 0x9c, 0x4d, 0x63, 0xf7, 0x13, 0x91, 0x47, 0xfc, 0xf7, 0x46, 0x13, 0x6a, 0x2f, 0xa6, 0xfd, + 0xe1, 0x64, 0xec, 0xde, 0x10, 0x73, 0x01, 0x01, 0x94, 0x59, 0x79, 0x40, 0x06, 0xa6, 0xb1, 0xbb, + 0x03, 0x10, 0xff, 0xe5, 0x40, 0x55, 0x28, 0xb1, 0x91, 0xb9, 0x80, 0x1a, 0x50, 0x3d, 0x72, 0xc6, + 0xf4, 0xc8, 0x71, 0x87, 0xa6, 0xb1, 0x7b, 0x3f, 0x2e, 0x38, 0x98, 0xcd, 0x1b, 0xdf, 0x23, 0xc2, + 0xdb, 0xf3, 0x3b, 0xe6, 0xd8, 0xd8, 0xfd, 0x77, 0x21, 0xbc, 0xdc, 0x61, 0x7a, 0xe6, 0x58, 0xf8, + 0x11, 0x55, 0x91, 0x69, 0xa0, 0x25, 0xf5, 0xce, 0xc4, 0x2c, 0x20, 0x94, 0xbc, 0x03, 0x31, 0x8b, + 0x4c, 0xa6, 0x33, 0xb8, 0x59, 0x42, 0xf5, 0xe8, 0x7e, 0xc3, 0x5c, 0x44, 0xeb, 0x19, 0xb7, 0x16, + 0x66, 0x19, 0x2d, 0x43, 0x5d, 0xfe, 0x82, 0xe1, 0x93, 0x2a, 0x68, 0x05, 0x9a, 0x52, 0x20, 0xfd, + 0x57, 0xd1, 0x6a, 0xea, 0x3e, 0xc1, 0xac, 0x21, 0x53, 0xbf, 0x15, 0x30, 0x81, 0x49, 0x54, 0xda, + 0x31, 0xeb, 0xcc, 0x67, 0xea, 0x60, 0x36, 0x1b, 0x68, 0x23, 0xab, 0x35, 0x36, 0x9b, 0xcc, 0x3c, + 0x75, 0xc0, 0x9a, 0x4b, 0x6c, 0x89, 0x0a, 0x91, 0x98, 0xcb, 0x6c, 0x3d, 0x89, 0x97, 0x6b, 0x9a, + 0x68, 0x2b, 0xaf, 0x0b, 0x35, 0x57, 0xd8, 0x9e, 0xb4, 0xbe, 0xc1, 0x44, 0xbb, 0x24, 0xac, 0x49, + 0xc4, 0x22, 0xb9, 0x2f, 0x66, 0xf0, 0xc2, 0x63, 0xc1, 0x31, 0x17, 0xd8, 0x22, 0x15, 0xb1, 0x0c, + 0xb6, 0x69, 0x28, 0xe6, 0x6f, 0xf9, 0xfb, 0xe8, 0x4e, 0xfa, 0x7d, 0xb3, 0xa0, 0x88, 0xe3, 0x2d, + 0x98, 0xc5, 0xe7, 0x9d, 0xef, 0xfe, 0xb1, 0x6d, 0x7c, 0xfb, 0x61, 0xdb, 0xf8, 0xee, 0xc3, 0xb6, + 0xf1, 0xf7, 0x0f, 0xdb, 0x0b, 0x7f, 0xfe, 0xe7, 0xb6, 0xf1, 0x3b, 0xf5, 0xdf, 0xde, 0xb5, 0x43, + 0x03, 0x77, 0xea, 0xf3, 0x9a, 0x32, 0x1c, 0x78, 0x64, 0x6f, 0x74, 0x75, 0xb1, 0x37, 0x3a, 0xdf, + 0x63, 0x7b, 0x38, 0x2f, 0xf3, 0x3f, 0x7a, 0x8f, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x91, 0xd7, + 0xe0, 0x62, 0x25, 0x1c, 0x00, 0x00, } func (m *LockOptions) Marshal() (dAtA []byte, err error) { @@ -3964,6 +3973,11 @@ func (m *GetLockHolderRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.Sharding != 0 { + i = encodeVarintLock(dAtA, i, uint64(m.Sharding)) + i-- + dAtA[i] = 0x10 + } if len(m.Row) > 0 { i -= len(m.Row) copy(dAtA[i:], m.Row) @@ -5635,6 +5649,9 @@ func (m *GetLockHolderRequest) ProtoSize() (n int) { if l > 0 { n += 1 + l + sovLock(uint64(l)) } + if m.Sharding != 0 { + n += 1 + sovLock(uint64(m.Sharding)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -8655,6 +8672,25 @@ func (m *GetLockHolderRequest) Unmarshal(dAtA []byte) error { m.Row = []byte{} } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sharding", wireType) + } + m.Sharding = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sharding |= Sharding(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipLock(dAtA[iNdEx:]) diff --git a/proto/lock.proto b/proto/lock.proto index 936601fb4df3e..956bd914fc6c9 100644 --- a/proto/lock.proto +++ b/proto/lock.proto @@ -214,7 +214,8 @@ message GetTxnLockResponse { // GetLockHolderRequest gets the current holder on a special row lock. message GetLockHolderRequest { - bytes Row = 1; + bytes Row = 1; + Sharding Sharding = 2; } // GetLockHolderResponse gets the current holder on a special row lock. From fa233eae4dafefe45fcd8dbd0796e1af70151873 Mon Sep 17 00:00:00 2001 From: daviszhen Date: Tue, 23 Jun 2026 12:27:27 +0800 Subject: [PATCH 17/17] update --- pkg/lockservice/service_observability.go | 3 + pkg/lockservice/service_observability_test.go | 61 +++++++++++++++++-- pkg/lockservice/service_remote.go | 3 + 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/pkg/lockservice/service_observability.go b/pkg/lockservice/service_observability.go index ed8672a7e1b25..9997846bf46fc 100644 --- a/pkg/lockservice/service_observability.go +++ b/pkg/lockservice/service_observability.go @@ -60,11 +60,14 @@ func (s *service) GetLockHolder( if err := ctx.Err(); err != nil { return pb.WaitTxn{}, false, err } + s.bindChangeMu.RLock() l, err := s.getLockTableWithCreate(options.Group, tableID, [][]byte{row}, options.Sharding) if err != nil { + s.bindChangeMu.RUnlock() return pb.WaitTxn{}, false, err } holder, ok, err := l.getLockHolder(ctx, row) + s.bindChangeMu.RUnlock() if !moerr.IsMoErrCode(err, moerr.ErrLockTableBindChanged) { return holder, ok, err } diff --git a/pkg/lockservice/service_observability_test.go b/pkg/lockservice/service_observability_test.go index 405cf490e52d7..e4b2f343e8393 100644 --- a/pkg/lockservice/service_observability_test.go +++ b/pkg/lockservice/service_observability_test.go @@ -208,6 +208,55 @@ func TestGetLockHolderReacquiresLockTableAfterBindChanged(t *testing.T) { ) } +func TestGetLockHolderHoldsBindChangeLockAcrossLocalLookup(t *testing.T) { + runLockServiceTests( + t, + []string{"s1"}, + func(alloc *lockTableAllocator, s []*service) { + l := s[0] + + ctx, cancel := context.WithTimeout( + context.Background(), + time.Second*10) + defer cancel() + + table := uint64(12) + row := []byte{1} + holder := pb.WaitTxn{TxnID: []byte("txn-holder")} + bind := pb.LockTable{ + Group: 0, + Table: table, + OriginTable: table, + ServiceID: l.serviceID, + Version: 1, + Valid: true, + } + lockTable := &getLockHolderTestTable{ + bind: bind, + holder: holder, + found: true, + onGetLockHolder: func() { + if l.bindChangeMu.TryLock() { + l.bindChangeMu.Unlock() + require.Fail(t, "GetLockHolder must hold bindChangeMu while reading a local lock table") + } + }, + } + l.tableGroups.set(bind.Group, bind.Table, lockTable) + + got, ok, err := l.GetLockHolder(ctx, table, row, pb.LockOptions{ + Granularity: pb.Granularity_Row, + Mode: pb.LockMode_Exclusive, + Policy: pb.WaitPolicy_Wait, + }) + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, holder, got) + require.Equal(t, 1, lockTable.calls) + }, + ) +} + type getLockHolderBindChangedClient struct { t *testing.T wantBind pb.LockTable @@ -237,10 +286,11 @@ func (c *getLockHolderBindChangedClient) Close() error { } type getLockHolderTestTable struct { - bind pb.LockTable - holder pb.WaitTxn - found bool - calls int + bind pb.LockTable + holder pb.WaitTxn + found bool + calls int + onGetLockHolder func() } func (l *getLockHolderTestTable) lock( @@ -271,6 +321,9 @@ func (l *getLockHolderTestTable) getLockHolder( ctx context.Context, key []byte) (pb.WaitTxn, bool, error) { l.calls++ + if l.onGetLockHolder != nil { + l.onGetLockHolder() + } return l.holder, l.found, nil } diff --git a/pkg/lockservice/service_remote.go b/pkg/lockservice/service_remote.go index 193f9ff07241b..83f0f91ff1dca 100644 --- a/pkg/lockservice/service_remote.go +++ b/pkg/lockservice/service_remote.go @@ -436,13 +436,16 @@ func (s *service) handleRemoteGetLockHolder( req *pb.Request, resp *pb.Response, cs morpc.ClientSession) { + s.bindChangeMu.RLock() l, err := s.getLocalLockTable(req, resp) if err != nil || l == nil { + s.bindChangeMu.RUnlock() writeResponse(s.logger, cancel, resp, err, cs) return } holder, found, err := l.getLockHolder(ctx, req.GetLockHolder.Row) + s.bindChangeMu.RUnlock() if err == nil && found { resp.GetLockHolder.Holder = holder }