Created
June 1, 2018 11:50
-
-
Save mchampaneri/8490194be0293a61371fc7ed5a1e4834 to your computer and use it in GitHub Desktop.
Multie Threaded In Mechine Copier Program in Golang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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