<commit_before>// +build linux

package notify

import (
	"errors"
	"fmt"
	"os"
	//"path/filepath"
	"runtime"
	"sync"
	"syscall"
)

// TODO(ppknap) : doc.
const maxEventSize = syscall.SizeofInotifyEvent + syscall.PathMax + 1

// TODO(ppknap) : This type should be dropped. It is useless since
// we use it only here. Use:
//  var handlers struct {
//  	...
//  }
type handlersType struct {
	sync.RWMutex
	m      map[int]*watched
	fd     *int
	buffer [64 * maxEventSize]byte
	// TODO(ppknap) : I don't like this:<.
	c chan EventInfo
}

// TODO(ppknap) : doc.
var handlers handlersType

// TODO(ppknap) : doc.
type watched struct {
	sync.Mutex
	path string
	mask uint32
}

// TODO(ppknap) : doc.
func init() {
	fd, err := syscall.InotifyInit()
	if err != nil {
		panic(os.NewSyscallError("InotifyInit", err))
	}

	handlers.fd, handlers.m = &fd, make(map[int]*watched)
	runtime.SetFinalizer(handlers.fd, func(fd *int) {
		syscall.Close(*fd)
	})
	// TODO(ppknap) : this should be removed:<.
	handlers.c = make(chan EventInfo) // TODO(pknap) : rm me
	global.Watcher = &handlers
	go loop()
}

// TODO(ppknap) : doc.
func loop() {
	for {
		process()
	}
}

// TODO(ppknap) : doc.
func process() {
	var n int
	var err error

	n, err = syscall.Read(*handlers.fd, handlers.buffer[:])

	fmt.Println("\n====================\n")
	fmt.Println("NumberOfBytes:", n)
	fmt.Println("Error:", err)
	fmt.Println("\n====================\n")

	if n != 0 {
	} else {
		fmt.Println("no data received")
	}
}

// TODO(ppknap) : doc.
func watch(path string, event Event) error {
	wd, err := syscall.InotifyAddWatch(*handlers.fd, path, uint32(event))
	if err != nil {
		return os.NewSyscallError("InotifyAddWatch", err)
	}

	handlers.RLock()
	w := handlers.m[wd]
	handlers.RUnlock()

	if w == nil {
		w = &watched{path: path, mask: uint32(event)}
		handlers.Lock()
		handlers.m[wd] = w
		handlers.Unlock()
	} else {
		w.Lock()
		w.mask = uint32(event)
		w.Unlock()
	}
	return nil
}

// TODO(ppknap) : doc.
func unwatch(path string) error {
	wd := -1
	handlers.RLock()
	for wdkey, w := range handlers.m {
		if w.path == path {
			wd = wdkey
			break
		}
	}<commit_msg>Use atomic store instead of raw mutex per watched type<commit_after>// +build linux

package notify

import (
	"errors"
	"fmt"
	"os"
	//"path/filepath"
	"runtime"
	"sync"
	"sync/atomic"
	"syscall"
)

// TODO(ppknap) : doc.
const maxEventSize = syscall.SizeofInotifyEvent + syscall.PathMax + 1

// TODO(ppknap) : This type should be dropped. It is useless since
// we use it only here. Use:
//  var handlers struct {
//  	...
//  }
type handlersType struct {
	sync.RWMutex
	m      map[int]*watched
	fd     *int
	buffer [64 * maxEventSize]byte
	// TODO(ppknap) : I don't like this:<.
	c chan EventInfo
}

// TODO(ppknap) : doc.
var handlers handlersType

// TODO(ppknap) : doc.
type watched struct {
	path string
	mask uint32
}

// TODO(ppknap) : doc.
func init() {
	fd, err := syscall.InotifyInit()
	if err != nil {
		panic(os.NewSyscallError("InotifyInit", err))
	}

	handlers.fd, handlers.m = &fd, make(map[int]*watched)
	runtime.SetFinalizer(handlers.fd, func(fd *int) {
		syscall.Close(*fd)
	})
	// TODO(ppknap) : this should be removed:<.
	handlers.c = make(chan EventInfo) // TODO(pknap) : rm me
	global.Watcher = &handlers
	go loop()
}

// TODO(ppknap) : doc.
func loop() {
	for {
		process()
	}
}

// TODO(ppknap) : impl/doc.
func process() {
	var n int
	var err error

	n, err = syscall.Read(*handlers.fd, handlers.buffer[:])

	fmt.Println("\n====================\n")
	fmt.Println("NumberOfBytes:", n)
	fmt.Println("Error:", err)
	fmt.Println("\n====================\n")

	if n != 0 {
	} else {
		fmt.Println("no data received")
	}
}

// TODO(ppknap) : doc.
func watch(path string, event Event) error {
	wd, err := syscall.InotifyAddWatch(*handlers.fd, path, uint32(event))
	if err != nil {
		return os.NewSyscallError("InotifyAddWatch", err)
	}

	handlers.RLock()
	w := handlers.m[wd]
	handlers.RUnlock()

	if w == nil {
		w = &watched{path: path, mask: uint32(event)}
		handlers.Lock()
		handlers.m[wd] = w
		handlers.Unlock()
	} else {
		atomic.StoreUint32(&w.mask, uint32(event))
	}
	return nil
}

// TODO(ppknap) : doc.
func unwatch(path string) error {
	wd := -1
	handlers.RLock()
	for wdkey, w := range handlers.m {
		if w.path == path {
			wd = wdkey
			break
		}
	}
{'fraction_non_alphanumeric': 0.17943968511229452, 'fraction_numerical': 0.006482982171799027, 'mean_word_length': 3.3156843156843157, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2180619', 'n_tokens_mistral': 1816, 'n_tokens_neox': 1696, 'n_words': 413}