* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			234 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package themis
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"sort"
 | 
						|
 | 
						|
	"github.com/juju/errors"
 | 
						|
	"github.com/ngaut/log"
 | 
						|
	"github.com/pingcap/go-hbase"
 | 
						|
	"github.com/pingcap/go-hbase/proto"
 | 
						|
)
 | 
						|
 | 
						|
type mutationValuePair struct {
 | 
						|
	typ   hbase.Type
 | 
						|
	value []byte
 | 
						|
}
 | 
						|
 | 
						|
func (mp *mutationValuePair) String() string {
 | 
						|
	return fmt.Sprintf("type: %d value: %s", mp.typ, mp.value)
 | 
						|
}
 | 
						|
 | 
						|
type columnMutation struct {
 | 
						|
	*hbase.Column
 | 
						|
	*mutationValuePair
 | 
						|
}
 | 
						|
 | 
						|
func getEntriesFromDel(p *hbase.Delete) ([]*columnMutation, error) {
 | 
						|
	errMsg := "must set at least one column for themis delete"
 | 
						|
	if len(p.FamilyQuals) == 0 {
 | 
						|
		return nil, errors.New(errMsg)
 | 
						|
	}
 | 
						|
 | 
						|
	var ret []*columnMutation
 | 
						|
	for f, _ := range p.Families {
 | 
						|
		quilifiers := p.FamilyQuals[f]
 | 
						|
		if len(quilifiers) == 0 {
 | 
						|
			return nil, errors.New(errMsg)
 | 
						|
		}
 | 
						|
		for q, _ := range quilifiers {
 | 
						|
			mutation := &columnMutation{
 | 
						|
				Column: &hbase.Column{
 | 
						|
					Family: []byte(f),
 | 
						|
					Qual:   []byte(q),
 | 
						|
				},
 | 
						|
				mutationValuePair: &mutationValuePair{
 | 
						|
					typ: hbase.TypeDeleteColumn,
 | 
						|
				},
 | 
						|
			}
 | 
						|
			ret = append(ret, mutation)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ret, nil
 | 
						|
}
 | 
						|
 | 
						|
func getEntriesFromPut(p *hbase.Put) []*columnMutation {
 | 
						|
	var ret []*columnMutation
 | 
						|
	for i, f := range p.Families {
 | 
						|
		qualifiers := p.Qualifiers[i]
 | 
						|
		for j, q := range qualifiers {
 | 
						|
			mutation := &columnMutation{
 | 
						|
				Column: &hbase.Column{
 | 
						|
					Family: f,
 | 
						|
					Qual:   q,
 | 
						|
				},
 | 
						|
				mutationValuePair: &mutationValuePair{
 | 
						|
					typ:   hbase.TypePut,
 | 
						|
					value: p.Values[i][j],
 | 
						|
				},
 | 
						|
			}
 | 
						|
			ret = append(ret, mutation)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func (cm *columnMutation) toCell() *proto.Cell {
 | 
						|
	ret := &proto.Cell{
 | 
						|
		Family:    cm.Family,
 | 
						|
		Qualifier: cm.Qual,
 | 
						|
		Value:     cm.value,
 | 
						|
	}
 | 
						|
	if cm.typ == hbase.TypePut { // put
 | 
						|
		ret.CellType = proto.CellType_PUT.Enum()
 | 
						|
	} else if cm.typ == hbase.TypeMinimum { // onlyLock
 | 
						|
		ret.CellType = proto.CellType_MINIMUM.Enum()
 | 
						|
	} else { // delete, themis delete API only support delete column
 | 
						|
		ret.CellType = proto.CellType_DELETE_COLUMN.Enum()
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
type rowMutation struct {
 | 
						|
	tbl []byte
 | 
						|
	row []byte
 | 
						|
	// mutations := { 'cf:col' => mutationValuePair }
 | 
						|
	mutations map[string]*mutationValuePair
 | 
						|
}
 | 
						|
 | 
						|
func (r *rowMutation) getColumns() []hbase.Column {
 | 
						|
	var ret []hbase.Column
 | 
						|
	for k, _ := range r.mutations {
 | 
						|
		c := &hbase.Column{}
 | 
						|
		// TODO: handle error, now just ignore
 | 
						|
		if err := c.ParseFromString(k); err != nil {
 | 
						|
			log.Warnf("parse from string error, column: %s, mutation: %s, error: %v", c, k, err)
 | 
						|
		}
 | 
						|
		ret = append(ret, *c)
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func (r *rowMutation) getSize() int {
 | 
						|
	return len(r.mutations)
 | 
						|
}
 | 
						|
 | 
						|
func (r *rowMutation) getType(c hbase.Column) hbase.Type {
 | 
						|
	p, ok := r.mutations[c.String()]
 | 
						|
	if !ok {
 | 
						|
		return hbase.TypeMinimum
 | 
						|
	}
 | 
						|
	return p.typ
 | 
						|
}
 | 
						|
 | 
						|
func newRowMutation(tbl, row []byte) *rowMutation {
 | 
						|
	return &rowMutation{
 | 
						|
		tbl:       tbl,
 | 
						|
		row:       row,
 | 
						|
		mutations: map[string]*mutationValuePair{},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (r *rowMutation) addMutation(c *hbase.Column, typ hbase.Type, val []byte, onlyLock bool) {
 | 
						|
	// 3 scene: put, delete, onlyLock
 | 
						|
	// if it is onlyLock scene, then has not data modify, when has contained the qualifier, can't replace exist value,
 | 
						|
	// becuase put or delete operation has add mutation
 | 
						|
	if onlyLock && r.mutations[c.String()] != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	r.mutations[c.String()] = &mutationValuePair{
 | 
						|
		typ:   typ,
 | 
						|
		value: val,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (r *rowMutation) mutationList(withValue bool) []*columnMutation {
 | 
						|
	var ret []*columnMutation
 | 
						|
	var keys []string
 | 
						|
	for k, _ := range r.mutations {
 | 
						|
		keys = append(keys, k)
 | 
						|
	}
 | 
						|
	sort.Strings(keys)
 | 
						|
	for _, k := range keys {
 | 
						|
		v := &mutationValuePair{
 | 
						|
			typ: r.mutations[k].typ,
 | 
						|
		}
 | 
						|
		if withValue {
 | 
						|
			v.value = r.mutations[k].value
 | 
						|
		}
 | 
						|
		c := &hbase.Column{}
 | 
						|
		// TODO: handle error, now just ignore
 | 
						|
		if err := c.ParseFromString(k); err != nil {
 | 
						|
			log.Warnf("parse from string error, column: %s, mutation: %s, error: %v", c, k, err)
 | 
						|
		}
 | 
						|
		ret = append(ret, &columnMutation{
 | 
						|
			Column:            c,
 | 
						|
			mutationValuePair: v,
 | 
						|
		})
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
type columnMutationCache struct {
 | 
						|
	// mutations => {table => { rowKey => row mutations } }
 | 
						|
	mutations map[string]map[string]*rowMutation
 | 
						|
}
 | 
						|
 | 
						|
func newColumnMutationCache() *columnMutationCache {
 | 
						|
	return &columnMutationCache{
 | 
						|
		mutations: map[string]map[string]*rowMutation{},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c *columnMutationCache) addMutation(tbl []byte, row []byte, col *hbase.Column, t hbase.Type, v []byte, onlyLock bool) {
 | 
						|
	tblRowMutations, ok := c.mutations[string(tbl)]
 | 
						|
	if !ok {
 | 
						|
		// create table mutation map
 | 
						|
		tblRowMutations = map[string]*rowMutation{}
 | 
						|
		c.mutations[string(tbl)] = tblRowMutations
 | 
						|
	}
 | 
						|
 | 
						|
	rowMutations, ok := tblRowMutations[string(row)]
 | 
						|
	if !ok {
 | 
						|
		// create row mutation map
 | 
						|
		rowMutations = newRowMutation(tbl, row)
 | 
						|
		tblRowMutations[string(row)] = rowMutations
 | 
						|
	}
 | 
						|
	rowMutations.addMutation(col, t, v, onlyLock)
 | 
						|
}
 | 
						|
 | 
						|
func (c *columnMutationCache) getMutation(cc *hbase.ColumnCoordinate) *mutationValuePair {
 | 
						|
	t, ok := c.mutations[string(cc.Table)]
 | 
						|
	if !ok {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	rowMutation, ok := t[string(cc.Row)]
 | 
						|
	if !ok {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	p, ok := rowMutation.mutations[cc.GetColumn().String()]
 | 
						|
	if !ok {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	return p
 | 
						|
}
 | 
						|
 | 
						|
func (c *columnMutationCache) getRowCount() int {
 | 
						|
	ret := 0
 | 
						|
	for _, v := range c.mutations {
 | 
						|
		ret += len(v)
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func (c *columnMutationCache) getMutationCount() int {
 | 
						|
	ret := 0
 | 
						|
	for _, v := range c.mutations {
 | 
						|
		for _, vv := range v {
 | 
						|
			ret += len(vv.mutationList(false))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ret
 | 
						|
}
 |