func NewVar(uuid *common.VarUUId, exe *dispatcher.Executor, db *db.Databases, vm *VarManager) *Var { v := newVar(uuid, exe, db, vm) clock := NewVectorClock().Bump(*v.UUId, 0) written := NewVectorClock().Bump(*v.UUId, 0) v.curFrame = NewFrame(nil, v, nil, nil, clock, written) seg := capn.NewBuffer(nil) varCap := msgs.NewRootVar(seg) varCap.SetId(v.UUId[:]) v.varCap = &varCap return v }
func (v *Var) maybeWriteFrame(f *frame, action *localAction, positions *common.Positions) { if v.writeInProgress != nil { v.writeInProgress = func() { v.writeInProgress = nil v.maybeWriteFrame(f, action, positions) } return } v.writeInProgress = func() { v.writeInProgress = nil v.maybeMakeInactive() } oldVarCap := *v.varCap varSeg := capn.NewBuffer(nil) varCap := msgs.NewRootVar(varSeg) v.varCap = &varCap varCap.SetId(oldVarCap.Id()) if positions != nil { varCap.SetPositions(capn.UInt8List(*positions)) } else { varCap.SetPositions(oldVarCap.Positions()) } varCap.SetWriteTxnId(f.frameTxnId[:]) varCap.SetWriteTxnClock(f.frameTxnClock.AddToSeg(varSeg)) varCap.SetWritesClock(f.frameWritesClock.AddToSeg(varSeg)) varData := server.SegToBytes(varSeg) txnBytes := action.TxnRootBytes() // to ensure correct order of writes, schedule the write from // the current go-routine... future := v.db.ReadWriteTransaction(false, func(rwtxn *mdbs.RWTxn) interface{} { if err := v.db.WriteTxnToDisk(rwtxn, f.frameTxnId, txnBytes); err == nil { if err = rwtxn.Put(v.db.Vars, v.UUId[:], varData, 0); err == nil { if v.curFrameOnDisk != nil { v.db.DeleteTxnFromDisk(rwtxn, v.curFrameOnDisk.frameTxnId) } } } return true }) go func() { // ... but process the result in a new go-routine to avoid blocking the executor. if ran, err := future.ResultError(); err != nil { panic(fmt.Sprintf("Var error when writing to disk: %v\n", err)) } else if ran != nil { // Switch back to the right go-routine v.applyToVar(func() { server.Log(v.UUId, "Wrote", f.frameTxnId) v.curFrameOnDisk = f for ancestor := f.parent; ancestor != nil && ancestor.DescendentOnDisk(); ancestor = ancestor.parent { } v.writeInProgress() }) } }() }