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

133 lines
2.6 KiB

  1. package themis
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "io"
  6. "github.com/juju/errors"
  7. "github.com/pingcap/go-hbase"
  8. "github.com/pingcap/go-hbase/iohelper"
  9. )
  10. var (
  11. _ Lock = (*themisPrimaryLock)(nil)
  12. _ Lock = (*themisSecondaryLock)(nil)
  13. )
  14. type themisLock struct {
  15. // lock coordinate, table, row, cf, q
  16. coordinate *hbase.ColumnCoordinate
  17. // lock type: put/delete/minimal(lock only)
  18. typ hbase.Type
  19. // prewrite ts
  20. ts uint64
  21. // not used, for alignment
  22. wallTs uint64
  23. // not used, for alignment
  24. clientAddr string
  25. expired bool
  26. }
  27. func (l *themisLock) Timestamp() uint64 {
  28. return l.ts
  29. }
  30. func (l *themisLock) IsExpired() bool {
  31. return l.expired
  32. }
  33. func (l *themisLock) SetExpired(b bool) {
  34. l.expired = b
  35. }
  36. func (l *themisLock) SetCoordinate(c *hbase.ColumnCoordinate) {
  37. l.coordinate = c
  38. }
  39. func (l *themisLock) Coordinate() *hbase.ColumnCoordinate {
  40. return l.coordinate
  41. }
  42. func (l *themisLock) Context() interface{} {
  43. return nil
  44. }
  45. func (l *themisLock) Type() hbase.Type {
  46. return l.typ
  47. }
  48. func (l *themisLock) write(w io.Writer) {
  49. binary.Write(w, binary.BigEndian, byte(l.typ))
  50. binary.Write(w, binary.BigEndian, int64(l.ts))
  51. // write client addr
  52. iohelper.WriteVarBytes(w, []byte(l.clientAddr))
  53. binary.Write(w, binary.BigEndian, int64(l.wallTs))
  54. }
  55. func (l *themisLock) parse(r iohelper.ByteMultiReader) error {
  56. // read type
  57. var typ uint8
  58. err := binary.Read(r, binary.BigEndian, &typ)
  59. if err != nil {
  60. return errors.Trace(err)
  61. }
  62. l.typ = hbase.Type(typ)
  63. // read ts
  64. var ts int64
  65. err = binary.Read(r, binary.BigEndian, &ts)
  66. if err != nil {
  67. return errors.Trace(err)
  68. }
  69. l.ts = uint64(ts)
  70. // read client addr
  71. sz, err := binary.ReadUvarint(r)
  72. if err != nil {
  73. return errors.Trace(err)
  74. }
  75. addr := make([]byte, sz)
  76. r.Read(addr)
  77. l.clientAddr = string(addr)
  78. // read wall time
  79. var wallTs int64
  80. err = binary.Read(r, binary.BigEndian, &wallTs)
  81. if err != nil {
  82. return errors.Trace(err)
  83. }
  84. l.wallTs = uint64(wallTs)
  85. return nil
  86. }
  87. func parseLockFromBytes(b []byte) (Lock, error) {
  88. buf := bytes.NewBuffer(b)
  89. var isPrimary uint8
  90. err := binary.Read(buf, binary.BigEndian, &isPrimary)
  91. if err != nil {
  92. return nil, errors.Trace(err)
  93. }
  94. var ret Lock
  95. if isPrimary == 1 {
  96. l := newThemisPrimaryLock()
  97. err = l.parse(buf)
  98. ret = l
  99. } else {
  100. l := newThemisSecondaryLock()
  101. err = l.parse(buf)
  102. ret = l
  103. }
  104. if err != nil {
  105. return nil, errors.Trace(err)
  106. }
  107. return ret, nil
  108. }
  109. func isLockResult(r *hbase.ResultRow) bool {
  110. return len(r.SortedColumns) > 0 && isLockColumn(r.SortedColumns[0].Column)
  111. }
  112. func isLockColumn(c hbase.Column) bool {
  113. return bytes.Compare(c.Family, LockFamilyName) == 0
  114. }