Example #1
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 #2
0
// watch adds a new watcher to the set of watched objects or modifies the existing
// one. If called for the first time, this function initializes inotify filesystem
// monitor and starts producer-consumers goroutines.
func (i *inotify) watch(path string, e Event) (err error) {
	if e&^(All|Event(syscall.IN_ALL_EVENTS)) != 0 {
		return errors.New("notify: unknown event")
	}
	if err = i.lazyinit(); err != nil {
		return
	}
	iwd, err := syscall.InotifyAddWatch(int(i.fd), path, encode(e))
	if err != nil {
		return
	}
	i.RLock()
	wd := i.m[int32(iwd)]
	i.RUnlock()
	if wd == nil {
		i.Lock()
		if i.m[int32(iwd)] == nil {
			i.m[int32(iwd)] = &watched{path: path, mask: uint32(e)}
		}
		i.Unlock()
	} else {
		i.Lock()
		wd.mask = uint32(e)
		i.Unlock()
	}
	return nil
}
Example #3
0
// Add starts watching the named file or directory (non-recursively).
func (w *Watcher) Add(name string) error {
	name = filepath.Clean(name)
	if w.isClosed() {
		return errors.New("inotify instance already closed")
	}

	const agnosticEvents = syscall.IN_MOVED_TO | syscall.IN_MOVED_FROM |
		syscall.IN_CREATE | syscall.IN_ATTRIB | syscall.IN_MODIFY |
		syscall.IN_MOVE_SELF | syscall.IN_DELETE | syscall.IN_DELETE_SELF

	var flags uint32 = agnosticEvents

	w.mu.Lock()
	watchEntry, found := w.watches[name]
	w.mu.Unlock()
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}
	wd, errno := syscall.InotifyAddWatch(w.fd, name, flags)
	if wd == -1 {
		return errno
	}

	w.mu.Lock()
	w.watches[name] = &watch{wd: uint32(wd), flags: flags}
	w.paths[wd] = name
	w.mu.Unlock()

	return nil
}
Example #4
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 #5
0
func add_watch_r(inotify_fd int, f string, paths map[int]string) {
	fi, err := os.Open(f)
	if err != nil {
		log.Fatal(err)
	}
	defer fi.Close()

	n, err := syscall.InotifyAddWatch(inotify_fd, f, syscall.IN_ALL_EVENTS)
	paths[n] = f
	if err != nil {
		log.Fatal(err)
	}

	s, _ := fi.Stat()
	if s.IsDir() {
		files, _ := ioutil.ReadDir(f)
		for _, file := range files {
			if file.IsDir() {
				f := path.Join(f, file.Name())
				add_watch_r(inotify_fd, f, paths)
				// log.Print(path.Join(f, file.Name()))
			}
		}
	}
}
Example #6
0
// AddWatch adds path to the watched file set.
// The flags are interpreted as described in inotify_add_watch(2).
func (w *Watcher) AddWatch(path string, flags uint32) error {
	if w.isClosed {
		return errors.New("inotify instance already closed")
	}

	watchEntry, found := w.watches[path]
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}

	w.mu.Lock() // synchronize with readEvents goroutine

	wd, err := syscall.InotifyAddWatch(w.fd, path, flags)
	if err != nil {
		w.mu.Unlock()
		return &os.PathError{
			Op:   "inotify_add_watch",
			Path: path,
			Err:  err,
		}
	}

	if !found {
		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
		w.paths[wd] = path
	}
	w.mu.Unlock()
	return nil
}
Example #7
0
//Add directories recursively to the tracking list
func addFilesToInotify(fd int, dirPath string) {
	dir, err := os.Stat(dirPath)
	if err != nil {
		log.Fatal("error getting info on dir: ", err)
		return
	}
	if dir.IsDir() && dir.Name() != ".git" {
		log.Print("adding: ", dirPath)
		_, err = syscall.InotifyAddWatch(fd, dirPath, syscall.IN_CLOSE_WRITE|syscall.IN_DELETE)
		if err != nil {
			log.Fatal("error adding watch: ", err)
			return
		}

		fileList, err := ioutil.ReadDir(dirPath)
		if err != nil {
			log.Fatal("error reading dir: ", err)
			return
		}
		for _, file := range fileList {
			newPath := dirPath + "/" + file.Name()
			if file.IsDir() && file.Name() != ".git" {
				addFilesToInotify(fd, newPath)
			}
		}
	}
}
Example #8
0
func (w *inotify) add(id Id, path string, flags uint32) error {
	wd, err := syscall.InotifyAddWatch(w.watchfd, path, flags)
	if err != nil {
		return err
	}
	watch := int32(wd)
	w.watches[id] = watch
	w.ids[watch] = id
	return nil
}
Example #9
0
func inotify_add_watch(name string) {
	wd, err := syscall.InotifyAddWatch(inotify_fd, name,
		syscall.IN_MODIFY|syscall.IN_DELETE_SELF|syscall.IN_MOVE_SELF)
	if -1 == wd {
		if err == syscall.ENOENT {
			// Dirty hack.
			return
		}
		tabby_log("InotifyAddWatch failed, changes of file " + name +
			" outside of tabby will remain unnoticed, errno = " + err.Error())
		return
	}
	name_by_wd[int32(wd)] = name
	wd_by_name[name] = int32(wd)
}
Example #10
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 #11
0
func (this *watcher) doAdd(path string, flags uint32) error {
	//Check that file exists
	if _, err := os.Lstat(path); err != nil {
		return err
	}

	if wd, errno := syscall.InotifyAddWatch(this.fd, path, flags); wd < 0 {
		return os.NewSyscallError("inotify_add_watch", errno)
	} else {
		this.wd = wd
		this.root = path
	}

	return nil
}
Example #12
0
// AddWatch adds path to the watched file set.
// The flags are interpreted as described in inotify_add_watch(2).
func (w *Watcher) AddWatch(path string, flags uint32) error {
	if w.isClosed {
		return errors.New("inotify instance already closed")
	}

	watchEntry, found := w.watches[path]
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}
	wd, err := syscall.InotifyAddWatch(w.fd, path, flags)
	if err != nil {
		return &os.PathError{"inotify_add_watch", path, err}
	}

	if !found {
		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
		w.paths[wd] = path
	}
	return nil
}
Example #13
0
func (w *Watcher) AddWatch(path string, flags uint32) error {
	if w.isClose {
		log.Fatal("监控已经关闭")
	}

	//判断是否已经监控了
	if found := w.wm.find(path); found != nil {
		f := found.(watch)
		f.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}

	wd, err := syscall.InotifyAddWatch(w.fd, path, flags)
	fmt.Println("开始监控目录:", path, wd)
	if wd == -1 {
		return err
	}
	w.wm.add(path, wd, flags)
	return nil

}
// AddWatch adds path to the watched file set.
// The flags are interpreted as described in inotify_add_watch(2).
func (w *Watcher) AddWatch(path string, flags uint32) os.Error {
	if w.isClosed {
		return os.NewError("inotify instance already closed")
	}

	watchEntry, found := w.watches[path]
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}
	wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
	if wd == -1 {
		return os.NewSyscallError("inotify_add_watch", errno)
	}

	if !found {
		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
		w.paths[wd] = path
	}
	return nil
}
// AddWatch adds path to the watched file set.
// The flags are interpreted as described in inotify_add_watch(2).
func (w *Watcher) addWatch(path string, flags uint32) error {
	if w.isClosed {
		return errors.New("inotify instance already closed")
	}

	watchEntry, found := w.watches[path]
	if found {
		watchEntry.flags |= flags
		flags |= syscall.IN_MASK_ADD
	}
	wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
	if wd == -1 {
		return errno
	}

	w.mu.Lock()
	w.watches[path] = &watch{wd: uint32(wd), flags: flags}
	w.paths[wd] = path
	w.mu.Unlock()

	return nil
}
Example #16
0
func registerDirectory(inotifyFd int, dirname string, recurse int) {
	_, err := syscall.InotifyAddWatch(inotifyFd, dirname, syscall.IN_CREATE|syscall.IN_DELETE|syscall.IN_CLOSE_WRITE)
	if err != nil {
		log.Fatalf("Can not add %s to inotify: %v", dirname, err)
	}

	if recurse <= 0 {
		return
	}

	dir, err := LsDir(dirname)
	if err != nil {
		log.Fatalf("Can not read directory %s: %v", dirname, err)
	}

	for _, cur := range dir {
		if cur.Mode().IsDir() {
			if cur.Name()[0] == '.' {
				continue
			} // skip hidden directories
			registerDirectory(inotifyFd, dirname+"/"+cur.Name(), recurse-1)
		}
	}
}
Example #17
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()
}
Example #19
0
func (i *inotify) add(path string, flags uint32) (int, error) {
	return syscall.InotifyAddWatch(i.fd, path, flags)
}
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")
}