github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgCache/FileChangeCache.go (about) 1 package kmgCache 2 3 import ( 4 "os" 5 "path/filepath" 6 7 "github.com/bronze1man/kmg/encoding/kmgGob" 8 "github.com/bronze1man/kmg/kmgConfig" 9 "github.com/bronze1man/kmg/kmgCrypto" 10 "github.com/bronze1man/kmg/kmgFile" 11 ) 12 13 //这个测试要用到. 14 func getFileChangeCachePath(key string) string { 15 // 此处key长度不可控,所以用md5. 16 return filepath.Join(kmgConfig.DefaultEnv().TmpPath, "FileChangeCache", kmgCrypto.Md5HexFromString(key)) 17 } 18 19 // key 表示一组缓存,pathList 即这组缓存相关的文件 20 // 比较容易用错的情况: 21 // key := 1 22 // pathList := []string{"/a.txt","/b.txt"} 23 // a.txt 或者 b.txt 中任意有文件发生变化,这个 key 对应的缓存都会被更新 24 // 如果要对单个文件进行缓存控制,那么应该一个文件一个 key 25 func MustMd5FileChangeCache(key string, pathList []string, f func()) { 26 // 此处需要考虑, 27 // 用户新添加了一个文件 28 // 用户删除了一个文件 29 // 用户编辑了一个文件 30 // 用户在目录里面添加了一个文件 31 // 用在在目录里面删除了一个文件 32 //读取文件修改时间缓存信息 33 toChange := false 34 cacheInfo := map[string]string{} 35 cacheFilePath := getFileChangeCachePath(key) 36 err := kmgGob.ReadFile(cacheFilePath, &cacheInfo) 37 if err != nil { 38 //忽略缓存读取的任何错误 39 cacheInfo = map[string]string{} 40 } 41 hasReadFileMap := map[string]bool{} 42 for _, path := range pathList { 43 statList, err := kmgFile.GetAllFileAndDirectoryStat(path) 44 if err != nil { 45 if os.IsNotExist(err) { 46 toChange = true 47 //fmt.Printf("[MustFileChangeCache] path:[%s] not exist\n", path) 48 break 49 } 50 panic(err) 51 } 52 53 for _, stat := range statList { 54 if stat.Fi.IsDir() { 55 continue 56 } 57 hasReadFileMap[stat.FullPath] = true 58 if stat.Fi.Mode()&os.ModeSymlink == os.ModeSymlink { 59 if "symlink_"+kmgFile.MustReadSymbolLink(stat.FullPath)!=cacheInfo[stat.FullPath]{ 60 toChange = true 61 break 62 } 63 continue 64 } 65 if kmgCrypto.MustMd5File(stat.FullPath) != cacheInfo[stat.FullPath] { 66 toChange = true 67 //fmt.Printf("[MustMd5FileChangeCache] path:[%s] mod md5 not match save[%s] file[%s]\n", stat.FullPath, 68 // cacheMd5, kmgCrypto.MustMd5File(stat.FullPath)) 69 break 70 } 71 } 72 if toChange { 73 break 74 } 75 } 76 //删除一个已经存储在缓存列表里面的文件,是一个修改. 77 for fullPath := range cacheInfo { 78 if !hasReadFileMap[fullPath] { 79 toChange = true 80 break 81 } 82 } 83 if !toChange { 84 return 85 } 86 f() 87 cacheInfo = map[string]string{} 88 for _, path := range pathList { 89 statList, err := kmgFile.GetAllFileAndDirectoryStat(path) 90 if err != nil { 91 panic(err) 92 } 93 for _, stat := range statList { 94 if stat.Fi.IsDir() { 95 continue 96 } 97 if stat.Fi.Mode()&os.ModeSymlink == os.ModeSymlink { 98 linkToPath:=kmgFile.MustReadSymbolLink(stat.FullPath) 99 cacheInfo[stat.FullPath] = "symlink_"+linkToPath 100 continue 101 } 102 cacheInfo[stat.FullPath] = kmgCrypto.MustMd5File(stat.FullPath) 103 } 104 } 105 kmgFile.MustMkdirForFile(cacheFilePath) 106 kmgGob.MustWriteFile(cacheFilePath, cacheInfo) 107 //保存文件缓存信息 108 return 109 }