func makeSigWriter(wc *wire.WriteContext) wsync.SignatureWriter { return func(bl wsync.BlockHash) error { return wc.WriteMessage(&BlockHash{ WeakHash: bl.WeakHash, StrongHash: bl.StrongHash, }) } }
func makeOpsWriter(wc *wire.WriteContext, dctx *DiffContext) wsync.OperationWriter { numOps := 0 wop := &SyncOp{} files := dctx.TargetContainer.Files return func(op wsync.Operation) error { numOps++ wop.Reset() switch op.Type { case wsync.OpBlockRange: wop.Type = SyncOp_BLOCK_RANGE wop.FileIndex = op.FileIndex wop.BlockIndex = op.BlockIndex wop.BlockSpan = op.BlockSpan fileSize := files[op.FileIndex].Size lastBlockIndex := op.BlockIndex + op.BlockSpan - 1 tailSize := ComputeBlockSize(fileSize, lastBlockIndex) dctx.ReusedBytes += BlockSize*(op.BlockSpan-1) + tailSize case wsync.OpData: wop.Type = SyncOp_DATA wop.Data = op.Data dctx.FreshBytes += int64(len(op.Data)) default: return errors.Wrap(fmt.Errorf("unknown rsync op type: %d", op.Type), 1) } err := wc.WriteMessage(wop) if err != nil { return errors.Wrap(err, 1) } return nil } }
// Do only create a file at WoundsPath when it receives the first wound. // If no wounds are ever received, Do will effectively be a no-op. func (ww *WoundsWriter) Do(container *tlc.Container, wounds chan *Wound) error { var fw *os.File var wc *wire.WriteContext defer func() { if wc != nil { wc.Close() } if fw != nil { fw.Close() } }() writeWound := func(wound *Wound) error { ww.totalCorrupted += wound.Size() if wc == nil { var err error fw, err = os.Create(ww.WoundsPath) if err != nil { return errors.Wrap(err, 1) } wc = wire.NewWriteContext(fw) if err != nil { return errors.Wrap(err, 1) } err = wc.WriteMagic(WoundsMagic) if err != nil { return errors.Wrap(err, 1) } err = wc.WriteMessage(&WoundsHeader{}) if err != nil { return errors.Wrap(err, 1) } err = wc.WriteMessage(container) if err != nil { return errors.Wrap(err, 1) } } err := wc.WriteMessage(wound) if err != nil { return errors.Wrap(err, 1) } return nil } for wound := range wounds { if wound.Healthy() { continue } ww.hasWounds = true err := writeWound(wound) if err != nil { return err } } return nil }