예제 #1
0
func (self *clientWithPrefix) ListRemove(kv *trib.KeyValue, n *int) error {
	// escape colon
	binName := colon.Escape(self.bin)
	kv.Key = colon.Escape(kv.Key)
	kv.Key = binName + "::" + kv.Key

	// RPC call
	return self.originalClient.ListRemove(kv, n)
}
예제 #2
0
func (self *clientWithPrefix) ListAppend(kv *trib.KeyValue, succ *bool) error {
	// escape colon
	binName := colon.Escape(self.bin)
	kv.Key = colon.Escape(kv.Key)
	kv.Key = binName + "::" + kv.Key

	// RPC call
	return self.originalClient.ListAppend(kv, succ)
}
예제 #3
0
func (self *clientWithPrefix) ListGet(key string, list *trib.List) error {
	// escape colon
	binName := colon.Escape(self.bin)
	key = colon.Escape(key)
	key = binName + "::" + key

	// RPC call
	return self.originalClient.ListGet(key, list)
}
예제 #4
0
func (self *clientWithPrefix) Get(key string, value *string) error {
	// escape colon
	binName := colon.Escape(self.bin)
	key = colon.Escape(key)
	key = binName + "::" + key

	// RPC call
	return self.originalClient.Get(key, value)
}
예제 #5
0
func (self *ReplicaClient) ListAppend(kv *trib.KeyValue, succ *bool) error {
	var clk uint64
	*succ = true
	err1 := self.Clock(0, &clk)
	if err1 != nil {
		return err1
	}

	var newkv trib.KeyValue
	newkv.Key = colon.Escape(self.name) + "::" + kv.Key + "list"
	log := BinLog{"append", kv.Value, clk}
	newkv.Value = EncodeLog(log)

	success := false
	for _, ad := range self.addr {
		tempclient := &client{ad}
		var b bool
		err2 := tempclient.ListAppend(&newkv, &b)
		if err2 == nil {
			success = true
		}
	}

	if success == true {
		return nil
	} else {
		return fmt.Errorf("ListAppend failure on all servers")
	}

}
예제 #6
0
func (self *clientWithPrefix) ListKeys(p *trib.Pattern, list *trib.List) error {
	// escape colon
	binName := colon.Escape(self.bin)
	p.Prefix = binName + "::" + colon.Escape(p.Prefix)
	p.Suffix = colon.Escape(p.Suffix)

	// RPC call
	err := self.originalClient.ListKeys(p, list)
	if err != nil {
		return err
	}

	// unescape and trim
	for i, str := range list.L {
		str = colon.Unescape(str)
		list.L[i] = strings.TrimPrefix(str, self.bin+"::")
	}
	return nil
}
예제 #7
0
func replicateHelper(srcAddr, dstAddr, binName string) error {
	srcClient := NewClient(srcAddr)
	dstClient := NewClient(dstAddr)
	pt := trib.Pattern{Prefix: colon.Escape(binName) + "::", Suffix: ""}
	keyList := new(trib.List)
	// migrate key-value pairs
	err := srcClient.Keys(&pt, keyList)
	if err != nil {
		return err
	}
	var tmpVal string
	var succ bool
	for _, key := range keyList.L {
		err = srcClient.Get(key, &tmpVal)
		if err != nil {
			return err
		}
		err = dstClient.Set(&trib.KeyValue{Key: key, Value: tmpVal}, &succ)
		if err != nil || !succ {
			return fmt.Errorf("Set() fails when migrating")
		}
	}
	// migrate key-list pairs
	err = srcClient.ListKeys(&pt, keyList)
	if err != nil {
		return err
	}
	var valList trib.List
	for _, key := range keyList.L {
		err = srcClient.ListGet(key, &valList)
		if err != nil {
			return err
		}
		for _, val := range valList.L {
			err = dstClient.ListAppend(&trib.KeyValue{Key: key, Value: val}, &succ)
			if err != nil || !succ {
				return fmt.Errorf("ListAppend() fails when migrating")
			}
		}
	}
	return nil
}
예제 #8
0
func (self *ReplicaClient) Get(key string, value *string) error {
	newkey := colon.Escape(self.name) + "::" + key + "valu" // <- key should escape as well! NVM

	var mylist trib.List
	mylist.L = make([]string, 0)
	// get the list of logs of the key
	for index, ad := range self.addr {
		tempclient := &client{ad}
		err1 := tempclient.ListGet(newkey, &mylist)
		if err1 == nil {
			break
		} else if index < len(self.addr)-1 {
			continue
		} else {
			return err1
		}
	}

	s := ""
	if len(mylist.L) == 0 {
		*value = s
		return nil
	}

	// add dedup
	mylist.L = removeDuplicates(mylist.L)

	loglist := make(LogSlice, len(mylist.L))

	// decode the logs
	for index, l := range mylist.L {
		loglist[index] = DecodeLog(l)
	}

	sort.Sort(loglist)

	index := len(loglist) - 1
	result := loglist[index].Val
	*value = result
	return nil
}
예제 #9
0
func (self *ReplicaClient) ListRemove(kv *trib.KeyValue, n *int) error {
	var clk uint64
	err1 := self.Clock(0, &clk)
	if err1 != nil {
		return err1
	}

	var tempList trib.List
	self.ListGet(kv.Key, &tempList)

	r := 0
	for _, element := range tempList.L {
		if element == kv.Value {
			r++
		}
	}

	*n = r

	var newkv trib.KeyValue
	newkv.Key = colon.Escape(self.name) + "::" + kv.Key + "list"
	log := BinLog{"remove", kv.Value, clk}
	newkv.Value = EncodeLog(log)

	success := false
	for _, ad := range self.addr {
		tempclient := &client{ad}
		var b bool
		err2 := tempclient.ListAppend(&newkv, &b)
		if err2 == nil {
			success = true
		}
	}

	if success == true {
		return nil
	} else {
		return fmt.Errorf("ListRemove failure on all servers")
	}
}
예제 #10
0
func (self *ReplicaClient) ListKeys(p *trib.Pattern, list *trib.List) error {
	// escape colon
	binName := colon.Escape(self.name)
	p.Prefix = binName + "::" + p.Prefix
	p.Suffix = p.Suffix + "list"

	// RPC call
	// get the list of logs of the key

	// a list used as temp storage
	tmpList := trib.List{make([]string, 0)}
	for index, ad := range self.addr {
		tempclient := &client{ad}
		err1 := tempclient.ListKeys(p, &tmpList)
		if err1 == nil {
			break
		} else if index < len(self.addr)-1 {
			continue
		} else {
			return err1
		}
	}

	blockCh := make(chan string, len(tmpList.L))
	for _, str := range tmpList.L {
		go func(str string) {
			tmpList2 := trib.List{make([]string, 0)}
			s1 := colon.Escape(self.name) + "::"
			s2 := "list"
			str = strings.TrimPrefix(str, s1)
			str = strings.TrimSuffix(str, s2)
			_ = self.ListGet(str, &tmpList2) // ignore this err?
			if len(tmpList2.L) != 0 {
				blockCh <- str
			} else {
				blockCh <- ""
			}
		}(str)
	}

	list.L = make([]string, 0, len(tmpList.L))
	for _ = range tmpList.L {
		result := <-blockCh
		if result != "" {
			list.L = append(list.L, result)
		}
	}

	// unescape and trim
	if len(list.L) > 0 {
		for i, str := range list.L {
			//str = colon.Unescape(str)
			s1 := colon.Escape(self.name) + "::"
			s2 := "valu"
			str = strings.TrimPrefix(str, s1)
			str = strings.TrimSuffix(str, s2)
			list.L[i] = str
		}
	}
	return nil
}
예제 #11
0
func (self *ReplicaClient) ListGet(key string, list *trib.List) error {

	newkey := colon.Escape(self.name) + "::" + key + "list"

	var mylist trib.List
	mylist.L = make([]string, 0)

	// get the list of logs of the key
	for index, ad := range self.addr {
		tempclient := &client{ad}
		err1 := tempclient.ListGet(newkey, &mylist)
		if err1 == nil {
			break
		} else if index < len(self.addr)-1 {
			continue
		} else {
			return err1
		}
	}

	if len(mylist.L) == 0 {
		list.L = make([]string, 0)
		return nil
	}

	// add dedup
	mylist.L = removeDuplicates(mylist.L)

	loglist := make(LogSlice, len(mylist.L))

	// decode the logs
	for index, l := range mylist.L {
		loglist[index] = DecodeLog(l)
	}

	sort.Sort(loglist)

	var templist trib.List
	//get the real list
	for _, log := range loglist {
		if log.Op == "append" {
			templist.L = append(templist.L, log.Val)
		} else { // remove?
			newList := trib.List{[]string{}}
			for _, entry := range templist.L {
				if log.Val != entry {
					newList.L = append(newList.L, entry)
				}
			}
			templist.L = newList.L
			/*i := 0
			for _, l := range templist.L{
				if l == log.Val {
					if i < len(templist.L) {
						templist.L = append(templist.L[:i], templist.L[i+1:]...)
					} else {
						templist.L = templist.L[:i]
					}
				} else {
					i++
				}
			}*/
		}
	}
	*list = templist
	return nil
}