|
@@ -0,0 +1,98 @@
|
|
|
|
+package main
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "fmt"
|
|
|
|
+ "os"
|
|
|
|
+ "path/filepath"
|
|
|
|
+ "sync"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+// go-fakedu - toy approximation of the du (disk usage)
|
|
|
|
+// toy program to learn go concurrency structures
|
|
|
|
+
|
|
|
|
+type FileInfo struct {
|
|
|
|
+ path string
|
|
|
|
+ info os.FileInfo
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type SafeArraySlice struct {
|
|
|
|
+ m sync.Mutex
|
|
|
|
+ data []int64
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func NewSafeIntArraySlice() *SafeArraySlice {
|
|
|
|
+ return &SafeArraySlice{
|
|
|
|
+ m: sync.Mutex{},
|
|
|
|
+ data: make([]int64, 100),
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (a *SafeArraySlice) AppendIntArraySlice(i int64) {
|
|
|
|
+ a.m.Lock()
|
|
|
|
+ defer a.m.Unlock()
|
|
|
|
+ a.data = append(a.data, i)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func enumFiles(dir string) {
|
|
|
|
+ fileCh := make(chan FileInfo)
|
|
|
|
+ errCh := make(chan error, 1) // Buffered channel to prevent blocking
|
|
|
|
+ var wg sync.WaitGroup
|
|
|
|
+
|
|
|
|
+ file_size_storage := NewSafeIntArraySlice()
|
|
|
|
+
|
|
|
|
+ // Start a goroutine for walking the file tree
|
|
|
|
+ go func() {
|
|
|
|
+ // Send any errors to the errCh channel
|
|
|
|
+ errCh <- filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if !info.IsDir() {
|
|
|
|
+ fileCh <- FileInfo{path, info}
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ })
|
|
|
|
+ close(fileCh) // Close the fileCh channel after walking is done
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ // Start a goroutine to process files
|
|
|
|
+ go func() {
|
|
|
|
+ for path := range fileCh {
|
|
|
|
+ wg.Add(1)
|
|
|
|
+ go func(fInfo FileInfo) {
|
|
|
|
+ defer wg.Done()
|
|
|
|
+ // Process file (e.g., read, hash, etc.)
|
|
|
|
+ fmt.Println(fInfo.path, fInfo.info.Size())
|
|
|
|
+ file_size_storage.AppendIntArraySlice(fInfo.info.Size())
|
|
|
|
+
|
|
|
|
+ }(path)
|
|
|
|
+ }
|
|
|
|
+ wg.Wait()
|
|
|
|
+ close(errCh) // Close the errCh channel after all processing is done
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ // Check for errors from filepath.Walk
|
|
|
|
+ if err := <-errCh; err != nil {
|
|
|
|
+ fmt.Println("Error walking the file tree:", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Not getting a lock here as by now we know
|
|
|
|
+ // that nothing is currently accessing this slice
|
|
|
|
+ var size int64 = 0
|
|
|
|
+ for _, value := range file_size_storage.data {
|
|
|
|
+ size = size + value
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fmt.Println("Total size: ", float32(size)/(1<<20), "MBs")
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func main() {
|
|
|
|
+ args := os.Args
|
|
|
|
+ if len(args) < 2 {
|
|
|
|
+ fmt.Println("Must provide path to directory")
|
|
|
|
+ os.Exit(1)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ enumFiles(args[1])
|
|
|
|
+}
|