You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

undo.go 4.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package undo
  18. import (
  19. "context"
  20. "database/sql"
  21. "database/sql/driver"
  22. "fmt"
  23. "sync"
  24. "seata.apache.org/seata-go/pkg/datasource/sql/types"
  25. )
  26. var (
  27. undoLogManagerMap = map[types.DBType]*undoLogMgrHolder{}
  28. builders = map[types.ExecutorType]func() UndoLogBuilder{}
  29. )
  30. type undoLogMgrHolder struct {
  31. once sync.Once
  32. mgr UndoLogManager
  33. }
  34. func RegisterUndoLogManager(m UndoLogManager) error {
  35. if _, exist := undoLogManagerMap[m.DBType()]; exist {
  36. return nil
  37. }
  38. undoLogManagerMap[m.DBType()] = &undoLogMgrHolder{
  39. mgr: m,
  40. once: sync.Once{},
  41. }
  42. return nil
  43. }
  44. func RegisterUndoLogBuilder(executorType types.ExecutorType, fun func() UndoLogBuilder) {
  45. if _, ok := builders[executorType]; !ok {
  46. builders[executorType] = fun
  47. }
  48. }
  49. func GetUndologBuilder(sqlType types.ExecutorType) UndoLogBuilder {
  50. if f, ok := builders[sqlType]; ok {
  51. return f()
  52. }
  53. return nil
  54. }
  55. // UndoLogManager
  56. type UndoLogManager interface {
  57. Init()
  58. // DeleteUndoLog
  59. DeleteUndoLog(ctx context.Context, xid string, branchID int64, conn *sql.Conn) error
  60. // BatchDeleteUndoLog
  61. BatchDeleteUndoLog(xid []string, branchID []int64, conn *sql.Conn) error
  62. //FlushUndoLog
  63. FlushUndoLog(tranCtx *types.TransactionContext, conn driver.Conn) error
  64. // RunUndo
  65. RunUndo(ctx context.Context, xid string, branchID int64, conn *sql.DB, dbName string) error
  66. // DBType
  67. DBType() types.DBType
  68. // HasUndoLogTable
  69. HasUndoLogTable(ctx context.Context, conn *sql.Conn) (bool, error)
  70. }
  71. // GetUndoLogManager
  72. func GetUndoLogManager(d types.DBType) (UndoLogManager, error) {
  73. v, ok := undoLogManagerMap[d]
  74. if !ok {
  75. return nil, fmt.Errorf("not found UndoLogManager")
  76. }
  77. v.once.Do(func() {
  78. v.mgr.Init()
  79. })
  80. return v.mgr, nil
  81. }
  82. type UndoLogStatue int8
  83. const (
  84. UndoLogStatueNormnal UndoLogStatue = 0
  85. UndoLogStatueGlobalFinished UndoLogStatue = 1
  86. )
  87. type UndologRecord struct {
  88. BranchID uint64 `json:"branchId"`
  89. XID string `json:"xid"`
  90. Context []byte `json:"context"`
  91. RollbackInfo []byte `json:"rollbackInfo"`
  92. LogStatus UndoLogStatue `json:"logStatus"`
  93. LogCreated []byte `json:"logCreated"`
  94. LogModified []byte `json:"logModified"`
  95. }
  96. func (u *UndologRecord) CanUndo() bool {
  97. return u.LogStatus == UndoLogStatueNormnal
  98. }
  99. // BranchUndoLog
  100. type BranchUndoLog struct {
  101. // Xid
  102. Xid string `json:"xid"`
  103. // BranchID
  104. BranchID uint64 `json:"branchId"`
  105. // Logs
  106. Logs []SQLUndoLog `json:"sqlUndoLogs"`
  107. }
  108. // Marshal
  109. func (b *BranchUndoLog) Marshal() []byte {
  110. return nil
  111. }
  112. func (b *BranchUndoLog) Reverse() {
  113. if len(b.Logs) == 0 {
  114. return
  115. }
  116. left, right := 0, len(b.Logs)-1
  117. for left < right {
  118. b.Logs[left], b.Logs[right] = b.Logs[right], b.Logs[left]
  119. left++
  120. right--
  121. }
  122. }
  123. // SQLUndoLog
  124. type SQLUndoLog struct {
  125. SQLType types.SQLType `json:"sqlType"`
  126. TableName string `json:"tableName"`
  127. BeforeImage *types.RecordImage `json:"beforeImage"`
  128. AfterImage *types.RecordImage `json:"afterImage"`
  129. }
  130. func (s SQLUndoLog) SetTableMeta(tableMeta *types.TableMeta) {
  131. if s.BeforeImage != nil {
  132. s.BeforeImage.TableMeta = tableMeta
  133. s.BeforeImage.TableName = tableMeta.TableName
  134. }
  135. if s.AfterImage != nil {
  136. s.AfterImage.TableMeta = tableMeta
  137. s.AfterImage.TableName = tableMeta.TableName
  138. }
  139. }
  140. type UndoLogBuilder interface {
  141. BeforeImage(ctx context.Context, execCtx *types.ExecContext) ([]*types.RecordImage, error)
  142. AfterImage(ctx context.Context, execCtx *types.ExecContext, beforImages []*types.RecordImage) ([]*types.RecordImage, error)
  143. GetExecutorType() types.ExecutorType
  144. }