|  | @@ -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])
 | 
	
		
			
				|  |  | +}
 |