github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/go-themis/mutation_cache.go (about)

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