Esempio n. 1
0
File: diff.go Progetto: itchio/wharf
func signFile(sctx *wsync.Context, fileIndex int, reader io.Reader, writeHash wsync.SignatureWriter, errs chan error, done chan bool) {
	err := sctx.CreateSignature(int64(fileIndex), reader, writeHash)
	if err != nil {
		errs <- errors.Wrap(err, 1)
	}

	done <- true
}
Esempio n. 2
0
File: diff.go Progetto: itchio/wharf
func diffFile(sctx *wsync.Context, dctx *DiffContext, blockLibrary *wsync.BlockLibrary, reader io.Reader, opsWriter wsync.OperationWriter, preferredFileIndex int64, errs chan error, done chan bool) {
	err := sctx.ComputeDiff(reader, blockLibrary, opsWriter, preferredFileIndex)
	if err != nil {
		errs <- errors.Wrap(err, 1)
	}

	done <- true
}
Esempio n. 3
0
func (actx *ApplyContext) lazilyPatchFile(sctx *wsync.Context, targetContainer *tlc.Container, targetPool wsync.Pool, outputContainer *tlc.Container, outputPool wsync.WritablePool,
	fileIndex int64, onSourceWrite counter.CountCallback, ops chan wsync.Operation, inplace bool) (written int64, transposition *Transposition, err error) {

	var writer io.WriteCloser

	defer func() {
		if writer != nil {
			cErr := writer.Close()
			if cErr != nil && err == nil {
				err = cErr
			}
		}
	}()

	var realops chan wsync.Operation

	errs := make(chan error, 1)
	first := true

	for op := range ops {
		if first {
			first = false

			// if the first operation is a blockrange that copies an
			// entire file from target into a file from source that has
			// the same name and size, then it's a no-op!
			if inplace && op.Type == wsync.OpBlockRange && op.BlockIndex == 0 {
				outputFile := outputContainer.Files[fileIndex]
				targetFile := targetContainer.Files[op.FileIndex]
				numOutputBlocks := ComputeNumBlocks(outputFile.Size)

				if op.BlockSpan == numOutputBlocks &&
					outputFile.Size == targetFile.Size {
					transposition = &Transposition{
						TargetPath: targetFile.Path,
						OutputPath: outputFile.Path,
					}
				}
			}

			if transposition != nil {
				errs <- nil
			} else {
				realops = make(chan wsync.Operation)

				writer, err = outputPool.GetWriter(fileIndex)
				if err != nil {
					return 0, nil, errors.Wrap(err, 1)
				}
				writeCounter := counter.NewWriterCallback(onSourceWrite, writer)

				go func() {
					failFast := true
					if actx.WoundsConsumer != nil {
						failFast = false
					}

					applyErr := sctx.ApplyPatchFull(writeCounter, targetPool, realops, failFast)
					if applyErr != nil {
						errs <- applyErr
						return
					}

					written = writeCounter.Count()
					errs <- nil
				}()
			}
		}

		// if not a transposition, relay errors
		if transposition == nil {
			select {
			case cErr := <-errs:
				// if we get an error here, ApplyPatch failed so we no longer need to close realops
				if cErr != nil {
					return 0, nil, errors.Wrap(cErr, 1)
				}
			case realops <- op:
				// muffin
			}
		}
	}

	if transposition == nil {
		// realops may be nil if the file was empty (0 ops)
		if realops != nil {
			close(realops)
		} else {
			// if we had 0 ops, signal no errors occured
			errs <- nil
		}
	}

	err = <-errs
	if err != nil {
		return 0, nil, errors.Wrap(err, 1)
	}

	return
}