2018-04-17 18:58:22 +08:00
|
|
|
|
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
|
|
|
|
//
|
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
|
|
|
|
// You can obtain one at https://gitee.com/johng/gf.
|
|
|
|
|
|
|
|
|
|
// 文件监控.
|
2018-10-31 19:00:28 +08:00
|
|
|
|
// 使用时需要注意的是,一旦一个文件被删除,那么对其的监控将会失效;如果删除的是目录,那么该目录及其下的文件都将被递归删除监控。
|
2018-04-17 18:58:22 +08:00
|
|
|
|
package gfsnotify
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"gitee.com/johng/gf/g/container/gmap"
|
2018-04-18 15:17:07 +08:00
|
|
|
|
"gitee.com/johng/gf/g/container/gqueue"
|
2018-11-03 17:50:00 +08:00
|
|
|
|
"gitee.com/johng/gf/g/encoding/ghash"
|
|
|
|
|
"gitee.com/johng/gf/g/os/gcache"
|
|
|
|
|
"gitee.com/johng/gf/third/github.com/fsnotify/fsnotify"
|
2018-04-17 18:58:22 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 监听管理对象
|
|
|
|
|
type Watcher struct {
|
2018-05-17 22:32:50 +08:00
|
|
|
|
watcher *fsnotify.Watcher // 底层fsnotify对象
|
|
|
|
|
events *gqueue.Queue // 过滤后的事件通知,不会出现重复事件
|
|
|
|
|
closeChan chan struct{} // 关闭事件
|
|
|
|
|
callbacks *gmap.StringInterfaceMap // 监听的回调函数
|
2018-11-03 17:50:00 +08:00
|
|
|
|
cache *gcache.Cache // 缓存对象,用于事件重复过滤
|
2018-04-17 18:58:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 监听事件对象
|
|
|
|
|
type Event struct {
|
2018-11-03 17:50:00 +08:00
|
|
|
|
event fsnotify.Event // 底层事件对象
|
|
|
|
|
Path string // 文件绝对路径
|
|
|
|
|
Op Op // 触发监听的文件操作
|
|
|
|
|
Watcher *Watcher // 事件对应的监听对象
|
2018-04-17 18:58:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按位进行识别的操作集合
|
|
|
|
|
type Op uint32
|
|
|
|
|
|
2018-11-03 17:50:00 +08:00
|
|
|
|
// 必须放到一个const分组里面
|
2018-04-17 18:58:22 +08:00
|
|
|
|
const (
|
|
|
|
|
CREATE Op = 1 << iota
|
|
|
|
|
WRITE
|
|
|
|
|
REMOVE
|
|
|
|
|
RENAME
|
|
|
|
|
CHMOD
|
|
|
|
|
)
|
|
|
|
|
|
2018-11-03 17:50:00 +08:00
|
|
|
|
const (
|
|
|
|
|
REPEAT_EVENT_FILTER_INTERVAL = 1 // (毫秒)重复事件过滤间隔
|
2018-11-05 10:34:21 +08:00
|
|
|
|
DEFAULT_WATCHER_COUNT = 8 // 默认创建的监控对象数量(使用哈希取模)
|
2018-11-03 17:50:00 +08:00
|
|
|
|
)
|
|
|
|
|
|
2018-04-17 18:58:22 +08:00
|
|
|
|
// 全局监听对象,方便应用端调用
|
2018-11-03 17:50:00 +08:00
|
|
|
|
var watchers = make([]*Watcher, DEFAULT_WATCHER_COUNT)
|
2018-04-18 15:17:07 +08:00
|
|
|
|
|
2018-11-03 17:50:00 +08:00
|
|
|
|
// 包初始化,创建8个watcher对象,用于包默认管理监听
|
|
|
|
|
func init() {
|
|
|
|
|
for i := 0; i < DEFAULT_WATCHER_COUNT; i++ {
|
|
|
|
|
if w, err := New(); err == nil {
|
|
|
|
|
watchers[i] = w
|
|
|
|
|
} else {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建监听管理对象,主要注意的是创建监听对象会占用系统的inotify句柄数量,受到 fs.inotify.max_user_instances 的限制
|
2018-08-19 11:28:51 +08:00
|
|
|
|
func New() (*Watcher, error) {
|
2018-04-17 18:58:22 +08:00
|
|
|
|
if watch, err := fsnotify.NewWatcher(); err == nil {
|
|
|
|
|
w := &Watcher {
|
2018-11-03 17:50:00 +08:00
|
|
|
|
cache : gcache.New(),
|
2018-05-17 22:32:50 +08:00
|
|
|
|
watcher : watch,
|
|
|
|
|
events : gqueue.New(),
|
2018-09-19 09:47:50 +08:00
|
|
|
|
closeChan : make(chan struct{}),
|
2018-05-17 22:32:50 +08:00
|
|
|
|
callbacks : gmap.NewStringInterfaceMap(),
|
2018-04-17 18:58:22 +08:00
|
|
|
|
}
|
|
|
|
|
w.startWatchLoop()
|
2018-04-18 15:17:07 +08:00
|
|
|
|
w.startEventLoop()
|
2018-04-17 18:58:22 +08:00
|
|
|
|
return w, nil
|
|
|
|
|
} else {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-19 11:25:15 +08:00
|
|
|
|
// 添加对指定文件/目录的监听,并给定回调函数;如果给定的是一个目录,默认递归监控。
|
2018-09-28 22:39:15 +08:00
|
|
|
|
func Add(path string, callback func(event *Event), recursive...bool) error {
|
2018-11-03 17:50:00 +08:00
|
|
|
|
return getWatcherByPath(path).Add(path, callback, recursive...)
|
2018-08-19 11:25:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除监听,默认递归删除。
|
|
|
|
|
func Remove(path string) error {
|
2018-11-03 17:50:00 +08:00
|
|
|
|
return getWatcherByPath(path).Remove(path)
|
2018-08-19 11:25:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-03 17:50:00 +08:00
|
|
|
|
// 根据path计算对应的watcher对象
|
|
|
|
|
func getWatcherByPath(path string) *Watcher {
|
|
|
|
|
return watchers[ghash.BKDRHash([]byte(path)) % DEFAULT_WATCHER_COUNT]
|
2018-04-18 09:16:08 +08:00
|
|
|
|
}
|