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.

mysql_xa_resource.go 4.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 exec
  18. import (
  19. "context"
  20. "database/sql/driver"
  21. "fmt"
  22. "io"
  23. "strings"
  24. "time"
  25. "github.com/pkg/errors"
  26. )
  27. type MysqlXAConn struct {
  28. driver.Conn
  29. }
  30. func (c *MysqlXAConn) Commit(xid string, onePhase bool) error {
  31. var sb strings.Builder
  32. sb.WriteString("XA COMMIT ")
  33. sb.WriteString(xid)
  34. if onePhase {
  35. sb.WriteString(" ONE PHASE")
  36. }
  37. conn, _ := c.Conn.(driver.ExecerContext)
  38. _, err := conn.ExecContext(context.TODO(), sb.String(), nil)
  39. return err
  40. }
  41. func (c *MysqlXAConn) End(xid string, flags int) error {
  42. var sb strings.Builder
  43. sb.WriteString("XA END ")
  44. sb.WriteString(xid)
  45. switch flags {
  46. case TMSUCCESS:
  47. break
  48. case TMSUSPEND:
  49. sb.WriteString(" SUSPEND")
  50. break
  51. case TMFAIL:
  52. break
  53. default:
  54. return errors.New("invalid arguments")
  55. }
  56. conn, _ := c.Conn.(driver.ExecerContext)
  57. _, err := conn.ExecContext(context.TODO(), sb.String(), nil)
  58. return err
  59. }
  60. func (c *MysqlXAConn) Forget(xid string) error {
  61. // mysql doesn't support this
  62. return errors.New("mysql doesn't support this")
  63. }
  64. func (c *MysqlXAConn) GetTransactionTimeout() time.Duration {
  65. return 0
  66. }
  67. // IsSameRM is called to determine if the resource manager instance represented by the target object
  68. // is the same as the resource manager instance represented by the parameter xares.
  69. func (c *MysqlXAConn) IsSameRM(xares XAResource) bool {
  70. // todo: the fn depends on the driver.Conn, but it doesn't support
  71. return false
  72. }
  73. func (c *MysqlXAConn) XAPrepare(xid string) error {
  74. var sb strings.Builder
  75. sb.WriteString("XA PREPARE ")
  76. sb.WriteString(xid)
  77. conn, _ := c.Conn.(driver.ExecerContext)
  78. _, err := conn.ExecContext(context.TODO(), sb.String(), nil)
  79. return err
  80. }
  81. // Recover Obtains a list of prepared transaction branches from a resource manager.
  82. // The transaction manager calls this method during recovery to obtain the list of transaction branches
  83. // that are currently in prepared or heuristically completed states.
  84. func (c *MysqlXAConn) Recover(flag int) (xids []string, err error) {
  85. startRscan := (flag & TMSTARTRSCAN) > 0
  86. endRscan := (flag & TMENDRSCAN) > 0
  87. if !startRscan && !endRscan && flag != TMNOFLAGS {
  88. return nil, errors.New("invalid arguments")
  89. }
  90. if !startRscan {
  91. return nil, nil
  92. }
  93. conn := c.Conn.(driver.QueryerContext)
  94. res, err := conn.QueryContext(context.TODO(), "XA RECOVER", nil)
  95. if err != nil {
  96. return nil, err
  97. }
  98. dest := make([]driver.Value, 4)
  99. for true {
  100. if err = res.Next(dest); err != nil {
  101. if err == io.EOF {
  102. return xids, nil
  103. }
  104. return nil, err
  105. }
  106. gtridAndbqual, ok := dest[3].(string)
  107. if !ok {
  108. return nil, errors.New("the protocol of XA RECOVER statement is error")
  109. }
  110. fmt.Printf("gtr: %v", gtridAndbqual)
  111. xids = append(xids, string(gtridAndbqual))
  112. }
  113. return xids, err
  114. }
  115. func (c *MysqlXAConn) Rollback(xid string) error {
  116. var sb strings.Builder
  117. sb.WriteString("XA ROLLBACK ")
  118. sb.WriteString(xid)
  119. conn, _ := c.Conn.(driver.ExecerContext)
  120. _, err := conn.ExecContext(context.TODO(), sb.String(), nil)
  121. return err
  122. }
  123. func (c *MysqlXAConn) SetTransactionTimeout(duration time.Duration) bool {
  124. return false
  125. }
  126. func (c *MysqlXAConn) Start(xid string, flags int) error {
  127. var sb strings.Builder
  128. sb.WriteString("XA START")
  129. sb.WriteString(xid)
  130. switch flags {
  131. case TMJOIN:
  132. sb.WriteString(" JOIN")
  133. break
  134. case TMRESUME:
  135. sb.WriteString(" RESUME")
  136. break
  137. case TMNOFLAGS:
  138. break
  139. default:
  140. return errors.New("invalid arguments")
  141. }
  142. conn, _ := c.Conn.(driver.ExecerContext)
  143. _, err := conn.ExecContext(context.TODO(), sb.String(), nil)
  144. return err
  145. }