func VarFromData(data []byte, exe *dispatcher.Executor, disk *mdbs.MDBServer, vm *VarManager) (*Var, error) { seg, _, err := capn.ReadFromMemoryZeroCopy(data) if err != nil { return nil, err } varCap := msgs.ReadRootVar(seg) v := newVar(common.MakeVarUUId(varCap.Id()), exe, disk, vm) positions := varCap.Positions() if positions.Len() != 0 { v.positions = (*common.Positions)(&positions) } writeTxnId := common.MakeTxnId(varCap.WriteTxnId()) writeTxnClock := VectorClockFromCap(varCap.WriteTxnClock()) writesClock := VectorClockFromCap(varCap.WritesClock()) server.Log(v.UUId, "Restored", writeTxnId) if result, err := disk.ReadonlyTransaction(func(rtxn *mdbs.RTxn) (interface{}, error) { return db.ReadTxnFromDisk(rtxn, writeTxnId) }).ResultError(); err == nil { if result == nil || result.(*msgs.Txn) == nil { panic(fmt.Sprintf("%v Unable to find txn %v on disk (%v)", v.UUId, writeTxnId, result)) } actions := result.(*msgs.Txn).Actions() v.curFrame = NewFrame(nil, v, writeTxnId, &actions, writeTxnClock, writesClock) v.curFrameOnDisk = v.curFrame } else { return nil, err } v.varCap = &varCap return v, nil }
func populate(records int, server *mdbs.MDBServer, dbs *DBs) error { key := make([]byte, keySize) val := make([]byte, valSize) _, err := server.ReadWriteTransaction(false, func(txn *mdbs.RWTxn) (interface{}, error) { for idx := 0; idx < records; idx++ { int64ToBytes(int64(idx), key) int64ToBytes(int64(idx), val) if err := txn.Put(dbs.Test, key, val, 0); err != nil { return nil, err } } return nil, nil }).ResultError() return err }
func (ad *AcceptorDispatcher) loadFromDisk(server *mdbs.MDBServer) { res, err := server.ReadonlyTransaction(func(rtxn *mdbs.RTxn) (interface{}, error) { return rtxn.WithCursor(db.DB.BallotOutcomes, func(cursor *mdb.Cursor) (interface{}, error) { // cursor.Get returns a copy of the data. So it's fine for us // to store and process this later - it's not about to be // overwritten on disk. count := 0 txnIdData, acceptorState, err := cursor.Get(nil, nil, mdb.FIRST) for ; err == nil; txnIdData, acceptorState, err = cursor.Get(nil, nil, mdb.NEXT) { count++ txnId := common.MakeTxnId(txnIdData) acceptorStateCopy := acceptorState ad.withAcceptorManager(txnId, func(am *AcceptorManager) { am.loadFromData(txnId, acceptorStateCopy) }) } if err == mdb.NotFound { // fine, we just fell off the end as expected. return count, nil } else { return count, err } }) }).ResultError() if err == nil { log.Printf("Loaded %v acceptors from disk\n", res.(int)) } else { log.Println("AcceptorDispatcher error loading from disk:", err) } }
func loadVars(disk *mdbs.MDBServer, vars map[common.VarUUId]*varstate) { _, err := disk.ReadonlyTransaction(func(rtxn *mdbs.RTxn) (interface{}, error) { return rtxn.WithCursor(db.DB.Vars, func(cursor *mdb.Cursor) (interface{}, error) { key, data, err := cursor.Get(nil, nil, mdb.FIRST) for ; err == nil; key, data, err = cursor.Get(nil, nil, mdb.NEXT) { vUUId := common.MakeVarUUId(key) seg, _, err := capn.ReadFromMemoryZeroCopy(data) if err != nil { log.Println(err) continue } varCap := msgs.ReadRootVar(seg) pos := varCap.Positions() positions := (*common.Positions)(&pos) writeTxnId := common.MakeTxnId(varCap.WriteTxnId()) writeTxnClock := eng.VectorClockFromCap(varCap.WriteTxnClock()) writesClock := eng.VectorClockFromCap(varCap.WritesClock()) if state, found := vars[*vUUId]; found { if err := state.matches(disk, writeTxnId, writeTxnClock, writesClock, positions); err != nil { log.Println(err) } } else { state = &varstate{ vUUId: vUUId, disks: []*mdbs.MDBServer{disk}, writeTxnId: writeTxnId, writeTxnClock: writeTxnClock, writeWritesClock: writesClock, positions: positions, } vars[*vUUId] = state } } if err == mdb.NotFound { return nil, nil } else { return nil, err } }) }).ResultError() if err != nil { log.Println(err) } }
func worker(records int64, server *mdbs.MDBServer, dbs *DBs, readers, id int, write bool) error { msg := fmt.Sprint(id, ": Read") if write { msg = ": Wrote" } start := time.Now() count := 0 ticker := time.NewTicker(time.Duration(readers) * time.Second) randSource := rand.New(rand.NewSource(time.Now().UnixNano())) var err error for { select { case <-ticker.C: now := time.Now() elapsed := now.Sub(start) rate := float64(int64(count)*time.Second.Nanoseconds()) / float64(elapsed.Nanoseconds()) log.Println(msg, count, "records in", elapsed, "(", rate, "records/sec )") start = now count = 0 default: if write { keyNum := randSource.Int63n(records) key := make([]byte, keySize) int64ToBytes(keyNum, key) forceFlush := keyNum%10 == 0 future := server.ReadWriteTransaction(forceFlush, func(txn *mdbs.RWTxn) (interface{}, error) { val, err1 := txn.Get(dbs.Test, key) if err1 != nil { return nil, err1 } num := bytesToInt64(val) if num < keyNum { return nil, fmt.Errorf("Expected val (%v) >= key (%v)", num, keyNum) } int64ToBytes(num+1, val) return nil, txn.Put(dbs.Test, key, val, 0) }) if forceFlush { _, err = future.ResultError() } } else { keyNum := randSource.Int63n(records) key := make([]byte, keySize) int64ToBytes(keyNum, key) _, err = server.ReadonlyTransaction(func(txn *mdbs.RTxn) (interface{}, error) { val, err1 := txn.GetVal(dbs.Test, key) if err1 != nil { return nil, err1 } num := bytesToInt64(val.BytesNoCopy()) if num < keyNum { return nil, fmt.Errorf("Expected val (%v) >= key (%v)", num, keyNum) } return nil, nil }).ResultError() } if err != nil { log.Fatal(err) } count++ } } }