Skip to content

Instantly share code, notes, and snippets.

@mchampaneri
Created June 1, 2018 11:50
Show Gist options
  • Select an option

  • Save mchampaneri/8490194be0293a61371fc7ed5a1e4834 to your computer and use it in GitHub Desktop.

Select an option

Save mchampaneri/8490194be0293a61371fc7ed5a1e4834 to your computer and use it in GitHub Desktop.
Multie Threaded In Mechine Copier Program in Golang
// This program is just of learning purpose
// you might have to do modification in file
// to make it production ready
//
// Make sure you have set size of channel and
// part size appropriatly so you machine do
// not crash due to ram overflow
//
// ...
package main
import (
"bufio"
"fmt"
"os"
"sync"
"time"
)
func main() {
// Start Measureing time //
timeStart := time.Now()
fmt.Println("Process started", timeStart)
var SourceFile string
var DestFile string
var wg sync.WaitGroup
chans := make(chan int, 4) // max 4 gorountines should be working at a time
// Hardcoded Source and Destination Files
// SourceFile = filepath.Join("D:", "sam.zip")
// DestFile = filepath.Join("E:", "copied2.zip")
// Scanning For User Input via Standrad input
fmt.Println("enter detination file")
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
SourceFile = scanner.Text()
}
fmt.Println("enter detination file")
if scanner.Scan() {
DestFile = scanner.Text()
}
// Opening Source and Destination File in Requried mode
// and permissions
soruceFileHandel, _ := os.OpenFile(SourceFile, os.O_RDONLY|os.O_RDWR, os.ModePerm)
destFileHandel, _ := os.OpenFile(DestFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
// Source file statstics
fileStat, _ := soruceFileHandel.Stat()
fmt.Printf("file size is : %d \n", fileStat.Size())
// make read and write chunks and initated write at the time
var offset, partsize int64
offset = 0
partsize = fileStat.Size() / int64(8) // making eight groups of data byte of source file
for i := 1; i < 9; i++ {
wg.Add(1) // increasing wait counter
chans <- 1 // filling channel
go partProcess(i, offset, partsize, soruceFileHandel, destFileHandel, &wg, chans)
offset += partsize + 1 // +1 is essentail [ see output values of offset and till to under stand ]
if i == 8 {
// last part has to cover every thing up to the end
// so it might be more or even less than our partsize we
// used for earlier parts
partsize = fileStat.Size() - offset
}
}
// wait untill process is done
wg.Wait()
// oh!.. Copy is done . Cool !
defer fmt.Printf("end up at \n", time.Since(timeStart))
}
//
func partProcess(id int, offset, size int64, sourcefileHanel, destfileHandel *os.File, wg *sync.WaitGroup, c chan int) {
// Temporary storage where we will read from source file
// and from where we will write to destination file
storage := make([]byte, size)
//read and Write
fmt.Printf("id %d Writing from offset %d till %d \n", id, offset, offset+size)
// Reading source file from offset defined for the part
sourcefileHanel.ReadAt(storage, offset)
// writing destination file from offset defined for the part
destfileHandel.WriteAt(storage, offset)
fmt.Printf("copy done for %d \n", id)
// Decrese wait group and remove one element from channel
defer wg.Done()
<-c
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment