Example #1
0
// Do restore the given file signature from the backup engine to the restore engine
func (r *Restore) Do(fileSig *files.Signature) *spec.JobFile {
	log.Debugf("restoreWorker", "Working on: %v", fileSig.Name)
	jf := &spec.JobFile{}
	jf.Signature = *fileSig

	errc := make(chan error)
	done := make(chan bool)
	defer close(errc)
	defer close(done)

	//get the backup engine's Reader
	reader, err := r.From.Retrieve(*fileSig)
	if err != nil {
		jf.State = spec.Errors
		jf.Message = err.Error()
		return jf
	}

	//setup the restore pipe
	pipeR, pipeW := io.Pipe()

	//configure the restore point
	go r.To.Restore(pipeR, *fileSig, errc)

	//setup the decode pipeline
	pipe := modifications.NewPipeline(reader, errc, false, r.Modifications...)

	//copy the data
	go func() {
		if _, err := io.Copy(pipeW, pipe.Tail); err != nil {
			errc <- err
			return
		}
		done <- true
	}()

	//Wait for an error or jobdone
	select {
	case err := <-errc:
		jf.State = spec.Errors
		jf.Message = err.Error()
	case <-done:
		log.Debugf("restoreWorker", "Restore Done: %v", fileSig.Name)
		jf.State = spec.Complete
	}

	return jf
}
Example #2
0
// Do back up the given File using Modifications to Engines
func (b *Backup) Do(file string) *spec.JobFile {
	jf := &spec.JobFile{}

	//build the signature
	dir, name := filepath.Split(file)

	var ms []string
	for _, mod := range b.Modifications {
		ms = append(ms, mod.Name())
	}

	fileSig := files.Signature{
		Name:          name,
		Path:          dir,
		Modifications: ms}

	imoHash := imohash.NewCustom(24*1024, 3*1024*1024)
	fileHash, err := imoHash.SumFile(file)
	if err != nil {
		//log error
		//fmt.Println(err)
		jf.Message = err.Error()
		jf.State = spec.Errors
		jf.Signature = fileSig

		return jf
	}

	fileSig.Hash = hex.EncodeToString(fileHash[:])

	jf.Signature = fileSig

	var saveEngines []*engines.Backup

	for _, e := range b.Engines {
		store, err := e.ShouldBackup(fileSig)
		if err != nil {
			//Deal with the error!
			//fmt.Println(err)
			jf.Message = err.Error()
			jf.State = spec.Errors
			return jf
		}

		if store {
			saveEngines = append(saveEngines, &e)
		}
	}

	if len(saveEngines) == 0 {
		//Nothing to do!
		//fmt.Println("no save engines, Job Done")
		jf.State = spec.Complete
		jf.Message = "no save engines, Job Done"
		return jf
	}

	fileHandle, err := os.Open(file)
	if err != nil {
		//handle Error
		jf.Message = err.Error()
		jf.State = spec.Errors
		return jf
	}
	defer fileHandle.Close()

	errc := make(chan error)
	done := make(chan bool)

	//configure the Engines
	ew := &engines.Writer{}
	ew.Engines = make([]*io.PipeWriter, len(b.Engines))
	defer ew.Close()

	for i := 0; i < len(b.Engines); i++ {
		r, w := io.Pipe()
		go b.Engines[i].Backup(r, fileSig, errc)
		ew.Engines[i] = w
	}

	//setup the pipeline
	pipe := modifications.NewPipeline(fileHandle, errc, true, b.Modifications...)

	//copy the data
	go func() {
		if _, err := io.Copy(ew, pipe.Tail); err != nil {
			errc <- err
			return
		}
		done <- true
	}()

	//Wait for an error or jobdone
	select {
	case err := <-errc:
		jf.Message = err.Error()
		jf.State = spec.Errors
		return jf
	case <-done:
		jf.State = spec.Complete
		return jf
	}
}