This repository has been archived on 2019-07-12. You can view files and clone it, but cannot push or open issues or pull requests.
xweb/static.go
商讯在线 7050da6f60 improved
2014-11-23 23:17:43 +08:00

186 lines
3.6 KiB
Go

package xweb
import (
"crypto/md5"
"fmt"
"io"
"os"
"path/filepath"
"sync"
"github.com/howeyc/fsnotify"
)
type StaticVerMgr struct {
Caches map[string]string
mutex *sync.Mutex
Path string
Ignores map[string]bool
app *App
}
func (self *StaticVerMgr) Moniter(staticPath string) error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
done := make(chan bool)
go func() {
for {
select {
case ev := <-watcher.Event:
if ev == nil {
break
}
if _, ok := self.Ignores[filepath.Base(ev.Name)]; ok {
break
}
d, err := os.Stat(ev.Name)
if err != nil {
break
}
if ev.IsCreate() {
if d.IsDir() {
watcher.Watch(ev.Name)
} else {
url := ev.Name[len(self.Path)+1:]
self.CacheItem(url)
}
} else if ev.IsDelete() {
if d.IsDir() {
watcher.RemoveWatch(ev.Name)
} else {
pa := ev.Name[len(self.Path)+1:]
self.CacheDelete(pa)
}
} else if ev.IsModify() {
if d.IsDir() {
} else {
url := ev.Name[len(staticPath)+1:]
self.CacheItem(url)
}
} else if ev.IsRename() {
if d.IsDir() {
watcher.RemoveWatch(ev.Name)
} else {
url := ev.Name[len(staticPath)+1:]
self.CacheDelete(url)
}
}
case err := <-watcher.Error:
self.app.Errorf("error: %v", err)
}
}
}()
err = filepath.Walk(staticPath, func(f string, info os.FileInfo, err error) error {
if info.IsDir() {
return watcher.Watch(f)
}
return nil
})
if err != nil {
fmt.Println(err)
return err
}
<-done
watcher.Close()
return nil
}
func (self *StaticVerMgr) Init(app *App, staticPath string) error {
self.Path = staticPath
self.Caches = make(map[string]string)
self.mutex = &sync.Mutex{}
self.Ignores = map[string]bool{".DS_Store": true}
self.app = app
if dirExists(staticPath) {
self.CacheAll(staticPath)
go self.Moniter(staticPath)
}
return nil
}
func (self *StaticVerMgr) getFileVer(url string) string {
//content, err := ioutil.ReadFile(path.Join(self.Path, url))
fPath := filepath.Join(self.Path, url)
self.app.Debug("loaded static ", fPath)
f, err := os.Open(fPath)
if err != nil {
return ""
}
defer f.Close()
fInfo, err := f.Stat()
if err != nil {
return ""
}
content := make([]byte, int(fInfo.Size()))
_, err = f.Read(content)
if err == nil {
h := md5.New()
io.WriteString(h, string(content))
return fmt.Sprintf("%x", h.Sum(nil))[0:4]
}
return ""
}
func (self *StaticVerMgr) CacheAll(staticPath string) error {
self.mutex.Lock()
defer self.mutex.Unlock()
//fmt.Print("Getting static file version number, please wait... ")
err := filepath.Walk(staticPath, func(f string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
rp := f[len(staticPath)+1:]
if _, ok := self.Ignores[filepath.Base(rp)]; !ok {
self.Caches[rp] = self.getFileVer(rp)
}
return nil
})
//fmt.Println("Complete.")
return err
}
func (self *StaticVerMgr) GetVersion(url string) string {
self.mutex.Lock()
defer self.mutex.Unlock()
if ver, ok := self.Caches[url]; ok {
return ver
}
ver := self.getFileVer(url)
if ver != "" {
self.Caches[url] = ver
}
return ver
}
func (self *StaticVerMgr) CacheDelete(url string) {
self.mutex.Lock()
defer self.mutex.Unlock()
delete(self.Caches, url)
self.app.Infof("static file %s is deleted.\n", url)
}
func (self *StaticVerMgr) CacheItem(url string) {
fmt.Println(url)
ver := self.getFileVer(url)
if ver != "" {
self.mutex.Lock()
defer self.mutex.Unlock()
self.Caches[url] = ver
self.app.Infof("static file %s is created.", url)
}
}