func NewVar(uuid *common.VarUUId, exe *dispatcher.Executor, disk *mdbs.MDBServer, vm *VarManager) *Var { v := newVar(uuid, exe, disk, 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.disk.ReadWriteTransaction(false, func(rwtxn *mdbs.RWTxn) (interface{}, error) { if err := db.WriteTxnToDisk(rwtxn, f.frameTxnId, txnBytes); err != nil { return nil, err } if err := rwtxn.Put(db.DB.Vars, v.UUId[:], varData, 0); err != nil { return nil, err } if v.curFrameOnDisk != nil { return nil, db.DeleteTxnFromDisk(rwtxn, v.curFrameOnDisk.frameTxnId) } return nil, nil }) go func() { // ... but process the result in a new go-routine to avoid blocking the executor. if _, err := future.ResultError(); err != nil { log.Println("Var error when writing to disk:", err) return } // 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() }) }() }