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.

233 lines
5.2 KiB

  1. package themis
  2. import (
  3. "fmt"
  4. "sort"
  5. "github.com/juju/errors"
  6. "github.com/ngaut/log"
  7. "github.com/pingcap/go-hbase"
  8. "github.com/pingcap/go-hbase/proto"
  9. )
  10. type mutationValuePair struct {
  11. typ hbase.Type
  12. value []byte
  13. }
  14. func (mp *mutationValuePair) String() string {
  15. return fmt.Sprintf("type: %d value: %s", mp.typ, mp.value)
  16. }
  17. type columnMutation struct {
  18. *hbase.Column
  19. *mutationValuePair
  20. }
  21. func getEntriesFromDel(p *hbase.Delete) ([]*columnMutation, error) {
  22. errMsg := "must set at least one column for themis delete"
  23. if len(p.FamilyQuals) == 0 {
  24. return nil, errors.New(errMsg)
  25. }
  26. var ret []*columnMutation
  27. for f, _ := range p.Families {
  28. quilifiers := p.FamilyQuals[f]
  29. if len(quilifiers) == 0 {
  30. return nil, errors.New(errMsg)
  31. }
  32. for q, _ := range quilifiers {
  33. mutation := &columnMutation{
  34. Column: &hbase.Column{
  35. Family: []byte(f),
  36. Qual: []byte(q),
  37. },
  38. mutationValuePair: &mutationValuePair{
  39. typ: hbase.TypeDeleteColumn,
  40. },
  41. }
  42. ret = append(ret, mutation)
  43. }
  44. }
  45. return ret, nil
  46. }
  47. func getEntriesFromPut(p *hbase.Put) []*columnMutation {
  48. var ret []*columnMutation
  49. for i, f := range p.Families {
  50. qualifiers := p.Qualifiers[i]
  51. for j, q := range qualifiers {
  52. mutation := &columnMutation{
  53. Column: &hbase.Column{
  54. Family: f,
  55. Qual: q,
  56. },
  57. mutationValuePair: &mutationValuePair{
  58. typ: hbase.TypePut,
  59. value: p.Values[i][j],
  60. },
  61. }
  62. ret = append(ret, mutation)
  63. }
  64. }
  65. return ret
  66. }
  67. func (cm *columnMutation) toCell() *proto.Cell {
  68. ret := &proto.Cell{
  69. Family: cm.Family,
  70. Qualifier: cm.Qual,
  71. Value: cm.value,
  72. }
  73. if cm.typ == hbase.TypePut { // put
  74. ret.CellType = proto.CellType_PUT.Enum()
  75. } else if cm.typ == hbase.TypeMinimum { // onlyLock
  76. ret.CellType = proto.CellType_MINIMUM.Enum()
  77. } else { // delete, themis delete API only support delete column
  78. ret.CellType = proto.CellType_DELETE_COLUMN.Enum()
  79. }
  80. return ret
  81. }
  82. type rowMutation struct {
  83. tbl []byte
  84. row []byte
  85. // mutations := { 'cf:col' => mutationValuePair }
  86. mutations map[string]*mutationValuePair
  87. }
  88. func (r *rowMutation) getColumns() []hbase.Column {
  89. var ret []hbase.Column
  90. for k, _ := range r.mutations {
  91. c := &hbase.Column{}
  92. // TODO: handle error, now just ignore
  93. if err := c.ParseFromString(k); err != nil {
  94. log.Warnf("parse from string error, column: %s, mutation: %s, error: %v", c, k, err)
  95. }
  96. ret = append(ret, *c)
  97. }
  98. return ret
  99. }
  100. func (r *rowMutation) getSize() int {
  101. return len(r.mutations)
  102. }
  103. func (r *rowMutation) getType(c hbase.Column) hbase.Type {
  104. p, ok := r.mutations[c.String()]
  105. if !ok {
  106. return hbase.TypeMinimum
  107. }
  108. return p.typ
  109. }
  110. func newRowMutation(tbl, row []byte) *rowMutation {
  111. return &rowMutation{
  112. tbl: tbl,
  113. row: row,
  114. mutations: map[string]*mutationValuePair{},
  115. }
  116. }
  117. func (r *rowMutation) addMutation(c *hbase.Column, typ hbase.Type, val []byte, onlyLock bool) {
  118. // 3 scene: put, delete, onlyLock
  119. // if it is onlyLock scene, then has not data modify, when has contained the qualifier, can't replace exist value,
  120. // becuase put or delete operation has add mutation
  121. if onlyLock && r.mutations[c.String()] != nil {
  122. return
  123. }
  124. r.mutations[c.String()] = &mutationValuePair{
  125. typ: typ,
  126. value: val,
  127. }
  128. }
  129. func (r *rowMutation) mutationList(withValue bool) []*columnMutation {
  130. var ret []*columnMutation
  131. var keys []string
  132. for k, _ := range r.mutations {
  133. keys = append(keys, k)
  134. }
  135. sort.Strings(keys)
  136. for _, k := range keys {
  137. v := &mutationValuePair{
  138. typ: r.mutations[k].typ,
  139. }
  140. if withValue {
  141. v.value = r.mutations[k].value
  142. }
  143. c := &hbase.Column{}
  144. // TODO: handle error, now just ignore
  145. if err := c.ParseFromString(k); err != nil {
  146. log.Warnf("parse from string error, column: %s, mutation: %s, error: %v", c, k, err)
  147. }
  148. ret = append(ret, &columnMutation{
  149. Column: c,
  150. mutationValuePair: v,
  151. })
  152. }
  153. return ret
  154. }
  155. type columnMutationCache struct {
  156. // mutations => {table => { rowKey => row mutations } }
  157. mutations map[string]map[string]*rowMutation
  158. }
  159. func newColumnMutationCache() *columnMutationCache {
  160. return &columnMutationCache{
  161. mutations: map[string]map[string]*rowMutation{},
  162. }
  163. }
  164. func (c *columnMutationCache) addMutation(tbl []byte, row []byte, col *hbase.Column, t hbase.Type, v []byte, onlyLock bool) {
  165. tblRowMutations, ok := c.mutations[string(tbl)]
  166. if !ok {
  167. // create table mutation map
  168. tblRowMutations = map[string]*rowMutation{}
  169. c.mutations[string(tbl)] = tblRowMutations
  170. }
  171. rowMutations, ok := tblRowMutations[string(row)]
  172. if !ok {
  173. // create row mutation map
  174. rowMutations = newRowMutation(tbl, row)
  175. tblRowMutations[string(row)] = rowMutations
  176. }
  177. rowMutations.addMutation(col, t, v, onlyLock)
  178. }
  179. func (c *columnMutationCache) getMutation(cc *hbase.ColumnCoordinate) *mutationValuePair {
  180. t, ok := c.mutations[string(cc.Table)]
  181. if !ok {
  182. return nil
  183. }
  184. rowMutation, ok := t[string(cc.Row)]
  185. if !ok {
  186. return nil
  187. }
  188. p, ok := rowMutation.mutations[cc.GetColumn().String()]
  189. if !ok {
  190. return nil
  191. }
  192. return p
  193. }
  194. func (c *columnMutationCache) getRowCount() int {
  195. ret := 0
  196. for _, v := range c.mutations {
  197. ret += len(v)
  198. }
  199. return ret
  200. }
  201. func (c *columnMutationCache) getMutationCount() int {
  202. ret := 0
  203. for _, v := range c.mutations {
  204. for _, vv := range v {
  205. ret += len(vv.mutationList(false))
  206. }
  207. }
  208. return ret
  209. }