Example #1
0
func main() {
	flag.Parse()
	args = flag.Args()

	if len(args) <= 0 {
		fmt.Fprintf(os.Stderr, "Must specify at least one argument to run:\n")
		fmt.Fprintf(os.Stderr, "\t%s <options> <command> <arguments>...\n", os.Args[0])
		flag.PrintDefaults()
		return
	}

	startCommand(false)

	usr1c := make(chan os.Signal)
	signal.Notify(usr1c, syscall.SIGUSR1)

	go func() {
		for {
			<-usr1c
			if canExecute() {
				startCommand(true)
			}
		}
	}()

	for {
		inotifyFd, err := syscall.InotifyInit()
		if err != nil {
			log.Fatalf("Inotify init failed: %v", err)
		}

		recdepth := 0
		if *recurse {
			recdepth = *depth
		}

		registerDirectory(inotifyFd, ".", recdepth)

		inotifyBuf := make([]byte, 1024*syscall.SizeofInotifyEvent+16)

		for {
			n, err := syscall.Read(inotifyFd, inotifyBuf[0:])
			if err == io.EOF {
				break
			}
			if err != nil {
				log.Printf("Can not read inotify: %v", err)
				break
			}

			if n > syscall.SizeofInotifyEvent {
				if canExecute() {
					startCommand(true)
				}
			}
		}

		syscall.Close(inotifyFd)
	}
}
Example #2
0
func monitor(root string, action chan uint32) {
	fd, err := syscall.InotifyInit()
	if fd == -1 || err != nil {
		end <- true
		return
	}

	flags := syscall.IN_MODIFY | syscall.IN_CREATE | syscall.IN_DELETE // 2/128/512
	wd, _ := syscall.InotifyAddWatch(fd, root, uint32(flags))
	if wd == -1 {
		end <- true
		return
	}
	var (
		buf [syscall.SizeofInotifyEvent * 10]byte
		n   int
	)

	for {
		n, _ = syscall.Read(fd, buf[0:])
		if n > syscall.SizeofInotifyEvent {
			var offset = 0
			for offset < n {
				raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
				mask := uint32(raw.Mask)
				offset = offset + int(raw.Len) + syscall.SizeofInotifyEvent
				action <- mask

				log.Println("action:", mask)
			}
		}
	}
}
Example #3
0
// lazyinit sets up all required file descriptors and starts 1+consumersCount
// goroutines. The producer goroutine blocks until file-system notifications
// occur. Then, all events are read from system buffer and sent to consumer
// goroutines which construct valid notify events. This method uses
// Double-Checked Locking optimization.
func (i *inotify) lazyinit() error {
	if atomic.LoadInt32(&i.fd) == invalidDescriptor {
		i.Lock()
		defer i.Unlock()
		if atomic.LoadInt32(&i.fd) == invalidDescriptor {
			fd, err := syscall.InotifyInit()
			if err != nil {
				return err
			}
			i.fd = int32(fd)
			if err = i.epollinit(); err != nil {
				_, _ = i.epollclose(), syscall.Close(int(fd)) // Ignore errors.
				i.fd = invalidDescriptor
				return err
			}
			esch := make(chan []*event)
			go i.loop(esch)
			i.wg.Add(consumersCount)
			for n := 0; n < consumersCount; n++ {
				go i.send(esch)
			}
		}
	}
	return nil
}
Example #4
0
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
func NewWatcher() (*Watcher, error) {
	// Create inotify fd
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, errno
	}
	// Create epoll
	poller, err := newFdPoller(fd)
	if err != nil {
		syscall.Close(fd)
		return nil, err
	}
	w := &Watcher{
		fd:       fd,
		poller:   poller,
		watches:  make(map[string]*watch),
		paths:    make(map[int]string),
		Events:   make(chan Event),
		Errors:   make(chan error),
		done:     make(chan struct{}),
		doneResp: make(chan struct{}),
	}

	go w.readEvents()
	return w, nil
}
Example #5
0
func main() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	inotify_fd, err := syscall.InotifyInit()
	if err != nil {
		log.Fatal(err)
	}
	paths := make(map[int]string)
	add_watch_r(inotify_fd, "/home/feng/workspace/rssminer", paths)
	log.Print("watcher added")

	for {
		var (
			buf [syscall.SizeofInotifyEvent * 4096]byte
		)

		n, _ := syscall.Read(inotify_fd, buf[0:])

		offset := 0
		for offset <= n-syscall.SizeofInotifyEvent {
			raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
			wd := int(raw.Wd)
			file := paths[wd]
			mask := raw.Mask
			printEvent(file, mask)
			offset += syscall.SizeofInotifyEvent + int(raw.Len)
		}
	}
}
Example #6
0
func newinotify() (*inotify, error) {
	fd, err := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", err)
	}
	return &inotify{
		fd: fd,
	}, nil
}
Example #7
0
func NewWatcher() (IFSEventsWatcher, error) {
	if fd, errno := syscall.InotifyInit(); errno != nil {
		return nil, os.NewSyscallError("inotify_init", errno)
	} else {
		w := &watcher{
			fd: fd,
		}

		return w, nil
	}
}
Example #8
0
// eventProcessor processes events from the file system
func (pin *Pin) eventProcessor() error {
	fd, err := syscall.InotifyInit()
	pin.Fd = fd
	if err != nil {
		return err
	}

	_, err = syscall.InotifyAddWatch(fd, pin.ValuePath, syscall.IN_MODIFY)
	if err != nil {
		return err
	}

	go pin.watcher()
	return nil
}
Example #9
0
func NewInotify(ctrler Controller) (Watcher, error) {
	watchfd, errno := syscall.InotifyInit()
	if watchfd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	w := &inotify{
		watchfd: watchfd,
		watches: make(map[Id]int32),
		ids:     make(map[int32]Id),
		done:    make(chan bool, 1),
		ctrler:  ctrler,
	}
	go w.readEvents()
	return w, nil
}
Example #10
0
func main() {
	fd, err := syscall.InotifyInit()
	if err != nil {
		log.Fatal(err)
	}
	defer syscall.Close(fd)

	wd, err := syscall.InotifyAddWatch(fd, "test1.log", syscall.IN_ALL_EVENTS)
	_, err = syscall.InotifyAddWatch(fd, "../test2.log", syscall.IN_ALL_EVENTS)
	//_, err = syscall.InotifyAddWatch(fd, ".", syscall.IN_ALL_EVENTS)
	if err != nil {
		log.Fatal(err)
	}
	defer syscall.InotifyRmWatch(fd, uint32(wd))

	fmt.Printf("WD is %d\n", wd)

	for {
		// Room for at least 128 events
		buffer := make([]byte, syscall.SizeofInotifyEvent*128)
		bytesRead, err := syscall.Read(fd, buffer)
		if err != nil {
			log.Fatal(err)
		}

		if bytesRead < syscall.SizeofInotifyEvent {
			// No point trying if we don't have at least one event
			continue
		}

		fmt.Printf("Size of InotifyEvent is %s\n", syscall.SizeofInotifyEvent)
		fmt.Printf("Bytes read: %d\n", bytesRead)

		offset := 0
		for offset < bytesRead-syscall.SizeofInotifyEvent {
			event := (*syscall.InotifyEvent)(unsafe.Pointer(&buffer[offset]))
			fmt.Printf("%+v\n", event)

			if (event.Mask & syscall.IN_ACCESS) > 0 {
				fmt.Printf("Saw IN_ACCESS for %+v\n", event)
			}

			// We need to account for the length of the name
			offset += syscall.SizeofInotifyEvent + int(event.Len)
		}
	}

}
Example #11
0
// NewWatcher creates and returns a new inotify instance using inotify_init(2)
func NewWatcher() (*Watcher, error) {
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	w := &Watcher{
		fd:      fd,
		watches: make(map[string]*watch),
		paths:   make(map[int]string),
		Event:   make(chan *Event),
		Error:   make(chan error),
		state:   new(int32),
	}

	return w, nil
}
Example #12
0
// NewWatcher creates and returns a new inotify instance using inotify_init(2)
func NewWatcher() (*Watcher, error) {
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	w := &Watcher{
		fd:      fd,
		watches: make(map[string]*watch),
		paths:   make(map[int]string),
		Event:   make(chan *Event),
		Error:   make(chan error),
		done:    make(chan bool, 1),
	}

	go w.readEvents()
	return w, nil
}
Example #13
0
//starts inotify tracking
func runInotify() {
	fd, err := syscall.InotifyInit()
	if err != nil {
		log.Fatal("error initializing Inotify: ", err)
		return
	}
	addFilesToInotify(fd, path)

	var buffer []byte = make([]byte, 1024*EVENT_SIZE)

	for {
		n, err := syscall.Read(fd, buffer)
		if err != nil {
			log.Fatal("Read failed: ", err)
			return
		}
		processBuffer(n, buffer)
	}
}
Example #14
0
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
func NewWatcher() (*Watcher, error) {
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	w := &Watcher{
		fd:      fd,
		watches: make(map[string]*watch),
		paths:   make(map[int]string),
		Events:  make(chan Event),
		Errors:  make(chan error),
		done:    make(chan bool),
		closed:  make(chan bool),
	}
	w.cv = sync.NewCond(&w.mu)

	rp, wp, err := os.Pipe() // for done
	if err != nil {
		return nil, err
	}
	epfd, err := syscall.EpollCreate1(0)
	if err != nil {
		return nil, os.NewSyscallError("epoll_create1", err)
	}
	event := &syscall.EpollEvent{syscall.EPOLLIN, int32(w.fd), 0}
	if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, w.fd, event); err != nil {
		return nil, os.NewSyscallError("epoll_ctl", err)
	}
	event = &syscall.EpollEvent{syscall.EPOLLIN, int32(rp.Fd()), 0}
	if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, int(rp.Fd()), event); err != nil {
		return nil, os.NewSyscallError("epoll_ctl", err)
	}

	go func() {
		<-w.done
		wp.Close() // make rp readable
	}()
	go w.epollEvents(epfd, rp)

	return w, nil
}
Example #15
0
// NewWatcher creates and returns a new inotify instance using inotify_init(2)
func NewWatcher() (*Watcher, error) {
	fd, errno := syscall.InotifyInit()
	if fd == -1 {
		return nil, os.NewSyscallError("inotify_init", errno)
	}
	mf := &filter{
		memo:     make(map[string]time.Time),
		interval: time.Minute,
	}
	w := &Watcher{
		fd:      fd,
		watches: make(map[string]*watch),
		paths:   make(map[int]string),
		Event:   make(chan *Event),
		Error:   make(chan error),
		done:    make(chan bool, 1),
		mfilter: mf,
	}

	go w.readEvents()
	return w, nil
}
Example #16
0
func init_inotify() {
	var err error

	name_by_wd = make(map[int32]string)
	wd_by_name = make(map[string]int32)
	var event syscall.InotifyEvent
	event_size = int(unsafe.Sizeof(event))
	inotify_fd, _ = syscall.InotifyInit()
	if -1 == inotify_fd {
		bump_message("InotifyInit failed, file changes outside of tabby " +
			"will remain unnoticed")
		return
	}
	epoll_fd, err = syscall.EpollCreate(1)
	if -1 == epoll_fd {
		tabby_log("init_inotify: " + err.Error())
	}
	var epoll_event syscall.EpollEvent
	epoll_event.Events = syscall.EPOLLIN
	syscall.EpollCtl(epoll_fd, syscall.EPOLL_CTL_ADD, inotify_fd, &epoll_event)
	go inotify_observe()
}
Example #17
0
func NewWatcher() (w *Watcher, err error) {
	fd, err := syscall.InotifyInit()
	if fd == -1 {
		log.Fatal("Watcher Init Error", err)
	}

	watcher := &Watcher{
		wm:          newWatchMap(),
		fd:          fd,
		acceptEvent: make(chan *FileEvent),
		handleEvent: make(chan *FileEvent),
		Error:       make(chan error),
		done:        make(chan bool),
		skipDir:     make(map[string]int),
		skipExt:     make(map[string]int),
		isClose:     false,
	}

	go watcher.readEvent()   //读取事件,把事件发送到acceptEvent通道中
	go watcher.purgeEvents() //处理时间,把处理的结果发送到handleEvent通道中

	return watcher, nil
}
func TestParseInotifyEvent(t *testing.T) {
	logger = setupStdoutLogger()

	setupDatafile()

	defer cleanDatafile()

	dbfiles := make(map[string]int)
	filecount := iterateDatafile(dbname, dbdir, dbfiles)
	if filecount < 0 {
		t.Error("Failed to parse inotify event.\n")
	}

	fd, err := syscall.InotifyInit()
	if err != nil {
		t.Error("Failed to call InotifyInit: [%s].\n", err)
		return
	}

	wd, err := syscall.InotifyAddWatch(fd, dbdir, syscall.IN_CREATE|syscall.IN_OPEN|
		syscall.IN_MOVED_TO|syscall.IN_DELETE)
	if err != nil {
		t.Error("Failed to call InotifyAddWatch: [%s].\n", err)
		syscall.Close(fd)
		return
	}

	go fileCreator()

	buffer := make([]byte, 256)
	for {
		nread, err := syscall.Read(fd, buffer)
		if nread < 0 {
			t.Error("Failed to read inotify event: [%s].\n", err)
		} else {
			err = parseInotifyEvent(dbname, buffer[0:nread], &filecount, dbfiles)
			if err != nil {
				t.Error("Failed to parse inotify event.\n")
			} else {
				fmt.Printf("Current dbfiles are, %v.\n", dbfiles)
				if _, ok := dbfiles["db.10"]; ok {
					break
				}
			}
		}
	}

	syscall.InotifyRmWatch(fd, uint32(wd))
	syscall.Close(fd)

	if filecount < 3 {
		t.Error("Failed to parse inotify event.\n")
	}
	if _, ok := dbfiles["db.0"]; !ok {
		t.Error("Failed to get db.0 file.\n")
	}
	if _, ok := dbfiles["db.1"]; !ok {
		t.Error("Failed to get db.1 file.\n")
	}
	fmt.Printf("Succeed to parse all inotify events.\n")
}
Example #19
0
// Returns errors (if any) triggered by the inotify subsystem or when reading
// the file. Errors when writing to the writer are ignored.
func streamFile(writer io.Writer, path string, maxIdleTime uint32) error {
	handle, err := os.Open(path)
	if err != nil {
		return err
	}

	_, err = handle.Seek(0, os.SEEK_END)
	if err != nil {
		handle.Close()
		return err
	}

	reader := bufio.NewReader(handle)
	readBuffer := make([]byte, 4096)

	inotifyFd, err := syscall.InotifyInit()
	if err != nil {
		handle.Close()
		return err
	}

	watchDesc, err := syscall.InotifyAddWatch(inotifyFd, path,
		syscall.IN_MODIFY)
	if err != nil {
		syscall.Close(inotifyFd)
		handle.Close()
		return err
	}

	eventsBuffer := make([]byte, syscall.SizeofInotifyEvent*4096)

	selectMaxIdleTime := syscall.Timeval{}
	selectMaxIdleTime.Sec = int64(maxIdleTime)

	inotifyFdSet := syscall.FdSet{}
	lastWriteTime := time.Now()

	canScan := true
	for canScan && !timeout(lastWriteTime, maxIdleTime) {
		clearAll(&inotifyFdSet)
		set(&inotifyFdSet, inotifyFd)
		_, err := syscall.Select(inotifyFd+1, &inotifyFdSet,
			nil, nil, &selectMaxIdleTime)

		if err != nil {
			break
		}

		if !isSet(&inotifyFdSet, inotifyFd) {
			continue
		}

		numEventsBytes, err := syscall.Read(inotifyFd, eventsBuffer[0:])
		if numEventsBytes < syscall.SizeofInotifyEvent {
			if numEventsBytes < 0 {
				err = errors.New("inotify: read failed.")
			} else {
				err = errors.New("inotify: short read.")
			}

			break
		}

		var offset uint32 = 0
		for offset <= uint32(numEventsBytes-syscall.SizeofInotifyEvent) {
			event := (*syscall.InotifyEvent)(unsafe.
				Pointer(&eventsBuffer[offset]))

			n, err := reader.Read(readBuffer)
			if err != nil {
				// Ignore the EOF error and continue polling
				// the file until timeout.
				if err == io.EOF {
					err = nil
				}
				break
			}

			buffer := make([]byte, n)
			for index := 0; index < n; index++ {
				buffer[index] = readBuffer[index]
			}

			_, err = writer.Write(buffer)
			if err != nil {
				// Stop scanning for updates to the file.
				canScan = false
				// Ignore the write error.
				err = nil
				break
			}

			lastWriteTime = time.Now()
			// Move to the next event.
			offset += syscall.SizeofInotifyEvent + event.Len
		}
	}

	// The inotify watch gets automatically removed by the inotify system
	// when the file is removed. If the above loop times out, but the file
	// is removed only just before the if block below is executed, then the
	// removal of the watch below will throw an error as the watch
	// descriptor is obsolete. We ignore this error because it is harmless.
	syscall.InotifyRmWatch(inotifyFd, uint32(watchDesc))

	// Though we return the first error that occured, we still need to
	// attempt to close all the file descriptors.
	inotifyCloseErr := syscall.Close(inotifyFd)
	handleCloseErr := handle.Close()

	if err != nil {
		return err
	} else if inotifyCloseErr != nil {
		return inotifyCloseErr
	}

	return handleCloseErr
}
// Data file number monitor depends on mongodb disk file layout, the layout is
// united in all of current supported versions, 1.8, 2.0 and 2.2.
//
// For example:
//
// Say base dir path is '/tmp/mongodb' and database name is 'db', then the disk
// file layout would be, /tmp/mongodb/db.ns, /tmp/mongodb/db.0, /tmp/mongodb/db.1,
// and /tmp/mongodb/db.2 ...
func (filter *ProxyFilterImpl) MonitorQuotaFiles() {
	var fd, wd, nread int
	var err error
	buffer := make([]byte, 256)
	dbfiles := make(map[string]int)
	asyncops := NewAsyncOps()

	dbname := filter.mongo.DBNAME
	base_dir := filter.config.BASE_DIR
	quota_files := filter.config.QUOTA_FILES

	filter.lock.Lock()
	filter.running++
	filter.lock.Unlock()

	filecount := 0
	filecount = iterateDatafile(dbname, base_dir, dbfiles)
	if filecount < 0 {
		logger.Errorf("Failed to iterate data files under %s.", base_dir)
		goto Error
	}

	logger.Infof("At the begining time we have disk files: [%d].", filecount)
	if filecount > int(quota_files) {
		logger.Error("Disk files exceeds quota.")
		atomic.StoreUint32(&filter.mfblocked, BLOCKED)
	}

	// Golang does not recommend to invoke system call directly, but
	// it does not contain any 'inotify' wrapper function
	fd, err = syscall.InotifyInit()
	if err != nil {
		logger.Errorf("Failed to call InotifyInit: [%s].", err)
		goto Error
	}

	wd, err = syscall.InotifyAddWatch(fd, base_dir, syscall.IN_CREATE|syscall.IN_MOVED_TO|syscall.IN_DELETE)
	if err != nil {
		logger.Errorf("Failed to call InotifyAddWatch: [%s].", err)
		syscall.Close(fd)
		goto Error
	}

	defer func() {
		syscall.InotifyRmWatch(fd, uint32(wd))
		syscall.Close(fd)
	}()

	for {
		select {
		case event := <-filter.file_count_channel:
			if event == STOP_EVENT {
				goto Error
			}
		default:
		}

		nread, err = asyncops.AsyncRead(syscall.Read, fd, buffer, time.Second)
		if err != nil {
			if err == ErrTimeout {
				continue
			}
			logger.Errorf("Failed to read inotify event: [%s].", err)
			break
		} else {
			err = parseInotifyEvent(dbname, buffer[0:nread], &filecount, dbfiles)
			if err != nil {
				logger.Errorf("Failed to parse inotify event.")
				atomic.StoreUint32(&filter.mfblocked, BLOCKED)
			} else {
				logger.Debugf("Current db disk file number: [%d].", filecount)
				if filecount > int(quota_files) {
					logger.Error("Disk files exceeds quota.")
					atomic.StoreUint32(&filter.mfblocked, BLOCKED)
				} else {
					atomic.StoreUint32(&filter.mfblocked, UNBLOCKED)
				}
			}
		}
	}

Error:
	atomic.StoreUint32(&filter.mfblocked, BLOCKED)

	filter.lock.Lock()
	filter.running--
	if filter.running == 0 {
		filter.wait <- STOP_EVENT
	}
	filter.lock.Unlock()
}