package themis import ( "bytes" "encoding/binary" "io" "github.com/juju/errors" "github.com/pingcap/go-hbase" "github.com/pingcap/go-hbase/iohelper" ) var ( _ Lock = (*themisPrimaryLock)(nil) _ Lock = (*themisSecondaryLock)(nil) ) type themisLock struct { // lock coordinate, table, row, cf, q coordinate *hbase.ColumnCoordinate // lock type: put/delete/minimal(lock only) typ hbase.Type // prewrite ts ts uint64 // not used, for alignment wallTs uint64 // not used, for alignment clientAddr string expired bool } func (l *themisLock) Timestamp() uint64 { return l.ts } func (l *themisLock) IsExpired() bool { return l.expired } func (l *themisLock) SetExpired(b bool) { l.expired = b } func (l *themisLock) SetCoordinate(c *hbase.ColumnCoordinate) { l.coordinate = c } func (l *themisLock) Coordinate() *hbase.ColumnCoordinate { return l.coordinate } func (l *themisLock) Context() interface{} { return nil } func (l *themisLock) Type() hbase.Type { return l.typ } func (l *themisLock) write(w io.Writer) { binary.Write(w, binary.BigEndian, byte(l.typ)) binary.Write(w, binary.BigEndian, int64(l.ts)) // write client addr iohelper.WriteVarBytes(w, []byte(l.clientAddr)) binary.Write(w, binary.BigEndian, int64(l.wallTs)) } func (l *themisLock) parse(r iohelper.ByteMultiReader) error { // read type var typ uint8 err := binary.Read(r, binary.BigEndian, &typ) if err != nil { return errors.Trace(err) } l.typ = hbase.Type(typ) // read ts var ts int64 err = binary.Read(r, binary.BigEndian, &ts) if err != nil { return errors.Trace(err) } l.ts = uint64(ts) // read client addr sz, err := binary.ReadUvarint(r) if err != nil { return errors.Trace(err) } addr := make([]byte, sz) r.Read(addr) l.clientAddr = string(addr) // read wall time var wallTs int64 err = binary.Read(r, binary.BigEndian, &wallTs) if err != nil { return errors.Trace(err) } l.wallTs = uint64(wallTs) return nil } func parseLockFromBytes(b []byte) (Lock, error) { buf := bytes.NewBuffer(b) var isPrimary uint8 err := binary.Read(buf, binary.BigEndian, &isPrimary) if err != nil { return nil, errors.Trace(err) } var ret Lock if isPrimary == 1 { l := newThemisPrimaryLock() err = l.parse(buf) ret = l } else { l := newThemisSecondaryLock() err = l.parse(buf) ret = l } if err != nil { return nil, errors.Trace(err) } return ret, nil } func isLockResult(r *hbase.ResultRow) bool { return len(r.SortedColumns) > 0 && isLockColumn(r.SortedColumns[0].Column) } func isLockColumn(c hbase.Column) bool { return bytes.Compare(c.Family, LockFamilyName) == 0 }