예제 #1
0
func (w *Worker) doTxn(q *Query) (*Result, error) {
	if q.TXN >= LAST_TXN {
		debug.PrintStack()
		clog.Error("Unknown transaction number %v\n", q.TXN)
	}
	w.NStats[NTXN]++

	if len(q.accessParts) > 1 {
		w.NStats[NCROSSTXN]++
	}

	w.E.Reset(q)

	x, err := w.txns[q.TXN](q, w.E)

	if err == EABORT {
		w.NStats[NABORTS]++
		return nil, err
	} else if err == ENOKEY {
		w.NStats[NENOKEY]++
		return nil, err
	}

	w.NStats[NREADKEYS] += int64(len(q.rKeys))
	w.NStats[NWRITEKEYS] += int64(len(q.wKeys))

	return x, err
	//return nil, nil
}
예제 #2
0
func (w *Worker) ResetTID(bigger TID) {
	big := bigger >> 16
	if big < w.next {
		clog.Error("%v How is supposedly bigger TID %v smaller than %v\n", w.ID, big, w.next)
	}
	w.next = TID(big + 1)
}
예제 #3
0
func PrintStore(s *Store, nKeys int64, p Partitioner) {
	for i := int64(0); i < nKeys; i++ {
		k := Key(i)
		partNum := p.GetPartition(k)
		r := s.GetRecord(k, partNum)
		if r == nil {
			clog.Error("Error No Key")
		}
		clog.Info("Key %v: %v", k, r.Value())
	}
}
예제 #4
0
func getTxn(txntype string) (int, testbed.RecType) {
	if strings.Compare(txntype, "addone") == 0 {
		return testbed.ADD_ONE, testbed.SINGLEINT
	} else if strings.Compare(txntype, "updateint") == 0 {
		return testbed.RANDOM_UPDATE_INT, testbed.SINGLEINT
	} else if strings.Compare(txntype, "updatestring") == 0 {
		return testbed.RANDOM_UPDATE_STRING, testbed.STRINGLIST
	} else {
		clog.Error("Not Supported %s Transaction", txntype)
		return -1, -1
	}
}
예제 #5
0
func (zk *ZipfKey) GetOtherKey(pi int) Key {
	if !zk.isPartition {
		clog.Error("Should not be invoked for non-partition CC")
	}

	if zk.isZipf {
		rank := int64(zk.partZipf[pi].Uint64())
		return zk.hp.GetKey(pi, int64(rank))
	} else {
		return zk.hp.GetKey(pi, zk.partUniform[pi].Int63n(zk.pKeysArray[pi]))
	}
}
예제 #6
0
func PrintPartition(s *Store, nKeys int64, p Partitioner, partNum int) {
	for i := int64(0); i < nKeys; i++ {
		k := Key(i)
		if p.GetPartition(k) != partNum {
			continue
		}
		r := s.GetRecord(k, partNum)
		if r == nil {
			clog.Error("Error No Key")
		}
		clog.Info("Key %v: %v", r.GetKey(), r.Value())
	}
}
예제 #7
0
func MakeRecord(k Key, v Value, rt RecType) Record {
	if *SysType == PARTITION {
		pr := &PRecord{
			key:     k,
			recType: rt,
		}

		// Initiate Value according to different types
		switch rt {
		case SINGLEINT:
			if v != nil {
				pr.intVal = v.(int64)
			}
		case STRINGLIST:
			if v != nil {
				var inputStrList = v.([]string)
				pr.stringVal = make([]string, len(inputStrList))
				for i, _ := range inputStrList {
					pr.stringVal[i] = inputStrList[i]
				}
			}
		}
		return pr
	} else if *SysType == OCC {
		or := &ORecord{
			key:     k,
			recType: rt,
			last:    wfmutex.WFMutex{},
		}
		// Initiate Value according to different types
		switch rt {
		case SINGLEINT:
			if v != nil {
				or.intVal = v.(int64)
			}
		case STRINGLIST:
			if v != nil {
				var inputStrList = v.([]string)
				or.stringVal = make([]string, len(inputStrList))
				for i, _ := range inputStrList {
					or.stringVal[i] = inputStrList[i]
				}
			}
		}
		return or
	} else {
		clog.Error("System Type %v Not Supported Yet", *SysType)
		return nil
	}
}
예제 #8
0
func (or *ORecord) UpdateValue(val Value) bool {
	if val == nil {
		return false
	}
	switch or.recType {
	case SINGLEINT:
		or.intVal = *val.(*int64)
	case STRINGLIST:
		strAttr := val.(*StrAttr)
		if strAttr.index >= len(or.stringVal) {
			clog.Error("Index %v out of range array length %v",
				strAttr.index, len(or.stringVal))
		}
		or.stringVal[strAttr.index] = strAttr.value
	}
	return true
}
예제 #9
0
func NewWorker(id int, s *Store) *Worker {
	w := &Worker{
		ID:     id,
		store:  s,
		txns:   make([]TransactionFunc, LAST_TXN),
		NStats: make([]int64, LAST_STAT),
	}

	if *SysType == PARTITION {
		w.E = StartPTransaction(w)
	} else if *SysType == OCC {
		w.E = StartOTransaction(w)
	} else {
		clog.Error("OCC and 2PL not supported yet")
	}

	w.Register(ADD_ONE, AddOneTXN)
	w.Register(RANDOM_UPDATE_INT, UpdateIntTXN)
	w.Register(RANDOM_UPDATE_STRING, UpdateStringTXN)

	return w
}
예제 #10
0
func (pr *PRecord) SetTID(tid TID) {
	clog.Error("Partition mode does not support SetTID Operation")
}
예제 #11
0
func (dr *DRecord) GetTID() TID {
	clog.Error("Dummy Record does not support GetTID Operation")
	return 0
}
예제 #12
0
func (dr *DRecord) SetTID(tid TID) {
	clog.Error("Dummy Record does not support SetTID Operation")
}
예제 #13
0
func (dr *DRecord) Unlock(tid TID) {
	clog.Error("Dummy Record does not support Unlock Operation")
}
예제 #14
0
func (dr *DRecord) IsUnlocked() (bool, TID) {
	clog.Error("Dummy Record does not support IsUnlocked Operation")
	return false, 0
}
예제 #15
0
func (dr *DRecord) GetKey() Key {
	clog.Error("Dummy Record does not support GetKey Operation")
	return dr.key
}
예제 #16
0
func (dr *DRecord) Lock() (bool, TID) {
	clog.Error("Dummy Record does not support Lock Operation")
	return false, 0
}
예제 #17
0
func (or *ORecord) SetTID(tid TID) {
	clog.Error("OCC mode does not support SetTID Operation")
}
예제 #18
0
func (pr *PRecord) Lock() (bool, TID) {
	clog.Error("Partition mode does not support Lock Operation")
	return false, 0
}
예제 #19
0
func (pr *PRecord) Unlock(tid TID) {
	clog.Error("Partition mode does not support Unlock Operation")
}
예제 #20
0
func (pr *PRecord) GetTID() TID {
	clog.Error("Partition mode does not support GetTID Operation")
	return 0
}
예제 #21
0
func (pr *PRecord) IsUnlocked() (bool, TID) {
	clog.Error("Partition mode does not support IsUnlocked Operation")
	return false, 0
}
예제 #22
0
func main() {
	flag.Parse()

	// set max cores used, number of clients and number of workers
	runtime.GOMAXPROCS(*testbed.NumPart)
	clients := *testbed.NumPart
	nworkers := *testbed.NumPart

	if *contention < 1 {
		clog.Error("Contention factor should be between no less than 1")
	}

	clog.Info("Number of clients %v, Number of workers %v \n", clients, nworkers)
	if *testbed.SysType == testbed.PARTITION {
		clog.Info("Using Partition-based CC\n")
	} else if *testbed.SysType == testbed.OCC {
		if *testbed.PhyPart {
			clog.Info("Using OCC with partition\n")
		} else {
			clog.Info("Using OCC\n")
		}
	} else {
		clog.Error("Not supported type %v CC\n", *testbed.SysType)
	}

	tt, dt := getTxn(*txntype)

	// create store
	s := testbed.NewStore()
	var nParts int
	var hp testbed.Partitioner = nil
	var pKeysArray []int64
	var value interface{}

	if *testbed.SysType == testbed.PARTITION || *testbed.PhyPart {
		nParts = *testbed.NumPart
		pKeysArray = make([]int64, nParts)

		hp = &testbed.HashPartitioner{
			NParts: int64(nParts),
			NKeys:  int64(*nKeys),
		}

		var partNum int
		for i := int64(0); i < *nKeys; i++ {
			k := testbed.Key(i)
			partNum = hp.GetPartition(k)
			pKeysArray[partNum]++
			if dt == testbed.SINGLEINT {
				value = int64(0)
			} else if dt == testbed.STRINGLIST {
				value = testbed.GenStringList()
			}
			s.CreateKV(k, value, dt, partNum)
		}

	} else {
		nParts = 1
		for i := int64(0); i < *nKeys; i++ {
			k := testbed.Key(i)
			if dt == testbed.SINGLEINT {
				value = int64(0)
			} else if dt == testbed.STRINGLIST {
				value = testbed.GenStringList()
			}
			s.CreateKV(k, value, dt, 0)
		}
	}

	generators := make([]*testbed.TxnGen, nworkers)

	for i := 0; i < nworkers; i++ {
		p := &testbed.HashPartitioner{
			NParts: int64(nParts),
			NKeys:  int64(*nKeys),
		}
		zk := testbed.NewZipfKey(i, *nKeys, nParts, pKeysArray, *contention, p)
		generators[i] = testbed.NewTxnGen(i, tt, *rr, *txnlen, *mp, zk)
	}

	coord := testbed.NewCoordinator(nworkers, s)

	clog.Info("Done with Initialization")

	var wg sync.WaitGroup
	for i := 0; i < clients; i++ {
		wg.Add(1)
		go func(n int) {
			//var txn int64
			//var count int
			w := coord.Workers[n]
			end_time := time.Now().Add(time.Duration(*nsec) * time.Second)
			for {
				tm := time.Now()
				if !end_time.After(tm) {
					break
				}

				q := generators[n].GenOneQuery()

				//q.DoNothing()
				w.NGen += time.Since(tm)
				tm = time.Now()
				for j := 0; j < TRIAL; j++ {

					_, err := w.One(q)

					if err == nil {
						break
					} else if err == testbed.ENOKEY {
						clog.Error("No Key Error")
					} else if err != testbed.EABORT {
						clog.Error("Not Support Error Type %v", err)
					}
				}
				//_, err := w.One(q)
				w.NExecute += time.Since(tm)
				/*if err == testbed.ENOKEY {
					clog.Error("No Key Error")
					break
				}*/
				//txn++
			}
			//clog.Info("Worker %d issues %d transactions\n", n, txn)
			wg.Done()
		}(i)
	}
	wg.Wait()

	f, err := os.OpenFile(*out, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
	if err != nil {
		clog.Error("Open File Error %s\n", err.Error())
	}
	defer f.Close()
	coord.PrintStats(f)

	if *benchStat != "" {
		bs, err := os.OpenFile(*benchStat, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
		if err != nil {
			clog.Error("Open File Error %s\n", err.Error())
		}
		defer bs.Close()

		//bs.WriteString(fmt.Sprintf("%v\t%v\n", *testbed.CrossPercent, coord.NStats[testbed.NTXN]-coord.NStats[testbed.NABORTS]))
		bs.WriteString(fmt.Sprintf("%.f\n", float64(coord.NStats[testbed.NTXN]-coord.NStats[testbed.NABORTS])/coord.NExecute.Seconds()))
	}

}
예제 #23
0
func (o *OTransaction) Commit() TID {

	// Phase 1: Lock all write keys
	//for _, wk := range o.wKeys {
	for i := 0; i < len(o.wKeys); i++ {
		wk := &o.wKeys[i]
		var former TID
		var ok bool
		if ok, former = wk.rec.Lock(); !ok {
			o.w.NStats[NLOCKABORTS]++
			return o.Abort()
		}
		wk.locked = true
		if former > o.maxSeen {
			o.maxSeen = former
		}
	}

	tid := o.w.commitTID()
	if tid <= o.maxSeen {
		o.w.ResetTID(o.maxSeen)
		tid = o.w.commitTID()
		if tid < o.maxSeen {
			clog.Error("%v MaxSeen %v, reset TID but %v<%v", o.w.ID, o.maxSeen, tid, o.maxSeen)
		}
	}

	// Phase 2: Check conflicts
	//for k, rk := range o.rKeys {
	for i := 0; i < len(o.rKeys); i++ {
		k := o.rKeys[i].k
		rk := &o.rKeys[i]
		//verify whether TID has changed
		var ok1, ok2 bool
		var tmpTID TID
		ok1, tmpTID = rk.rec.IsUnlocked()
		if tmpTID != rk.last {
			o.w.NStats[NRCHANGEABORTS]++
			return o.Abort()
		}

		// Check whether read key is not in wKeys
		//_, ok2 = o.wKeys[k]
		ok2 = false
		for j := 0; j < len(o.wKeys); j++ {
			wk := &o.wKeys[j]
			if wk.k == k {
				ok2 = true
				break
			}
		}

		if !ok1 && !ok2 {
			o.w.NStats[NRWABORTS]++
			return o.Abort()
		}
	}

	// Phase 3: Apply all writes
	for i, _ := range o.wKeys {
		wk := &o.wKeys[i]
		//wk.rec.UpdateValue(wk.v)
		wk.rec.UpdateValue(&wk.intVal)
		wk.rec.Unlock(tid)
	}

	return tid
}