Example #1
0
// 文件ttl缓存实现,每次都会读取文件,由于没有泛型,此处需要调用者自行解决序列化问题.
// 2.存储在文件里面,以便重启之后可以使用.
// 3.当缓存存在的时候,并且ttl在时间范围内,使用ttl,当缓存不存在的时候,使用回调拉取数据.当缓存过期的时候,使用回调拉取数据.
// 4.每一次使用都会读取文件
// 5.当某一次缓存拉取出现错误的时候,直接返回错误给调用者
func FileTtlCache(key string, f func() (b []byte, ttl time.Duration, err error)) (b []byte, err error) {
	entry := ttlCacheEntryV2{}
	cacheFilePath := getFileTtlCachePath(key)
	now := time.Now()
	err = kmgGob.ReadFile(cacheFilePath, &entry)
	if err == nil && entry.Timeout.After(now) {
		return entry.Value, nil
	}
	b, ttl, err := f()
	if err != nil {
		return nil, err
	}
	entry.Value = b
	entry.Timeout = now.Add(ttl)
	err = kmgFile.MkdirForFile(cacheFilePath)
	if err != nil {
		return nil, err
	}
	err = kmgGob.WriteFile(cacheFilePath, entry)
	if err != nil {
		return nil, err
	}
	return b, nil
}
Example #2
0
func (ctx *goRunInstallContext) goRunInstallIsValidAndInvalidCache(goPath string, pathOrPkg string) bool {
	err := kmgGob.ReadFile(ctx.targetCachePath, &ctx.targetPkgMapCache)
	if err != nil { //此处故意忽略错误 没有缓存文件 TODO 此处需要折腾其他东西吗?
		return false
	}
	err = kmgGob.ReadFile(ctx.pkgCachePath, &ctx.pkgMapCache)
	if err != nil { //此处故意忽略错误 没有缓存文件
		return false
	}
	//kmgDebug.Println(info)
	isValid := true
	task := kmgTask.NewLimitThreadTaskManager(runtime.NumCPU())
	for pkgName := range ctx.targetPkgMapCache {
		pkgName := pkgName
		task.AddFunc(func() {
			pkgInfo, ok := ctx.pkgMapCache[pkgName]
			if !ok {
				// 缓存不一致,删文件?
				pkgPath := filepath.Join("pkg", ctx.platform, pkgName+".a")
				if debug {
					fmt.Println("pkgname not found in pkgMapCache delete ", pkgPath)
				}
				kmgFile.MustDelete(pkgPath)
				isValid = false
				return
			}
			pkgPath := pkgInfo.getPkgBinPath(goPath, ctx.platform)
			if !checkFileWithMd5(pkgPath, pkgInfo.PkgMd5) {
				if debug {
					oldMd5 := uint64(0)
					if kmgFile.MustFileExist(pkgPath) {
						oldMd5 = mustCheckSumFile(pkgPath)
					}
					fmt.Println("pkgBinFile md5 not equal delete ", pkgPath, pkgInfo.PkgMd5, oldMd5)
				}
				kmgFile.MustDelete(pkgPath)
				isValid = false
				return
			}
			srcpkgPath := filepath.Join(goPath, "src", pkgName)
			fileList, err := kmgFile.ReadDirFileOneLevel(srcpkgPath)
			if err != nil {
				if !os.IsNotExist(err) {
					panic(err)
				}
				kmgFile.MustDelete(pkgPath)
				if debug {
					fmt.Println("dir not exist File delete ", pkgPath, srcpkgPath)
				}
				isValid = false
				return
			}
			isThisPkgValid := true
			for _, file := range fileList {
				ext := filepath.Ext(file)
				if ext == ".go" {
					// 多了一个文件
					_, ok := pkgInfo.GoFileMap[file]
					if !ok {
						kmgFile.MustDelete(pkgPath)
						if debug {
							fmt.Println("more file ", file, " delete ", pkgPath)
						}
						isValid = false
						isThisPkgValid = false
						break
					}
				}
			}
			if !isThisPkgValid {
				return
			}
			for name, md5 := range pkgInfo.GoFileMap {
				goFilePath := filepath.Join(srcpkgPath, name)
				if !checkFileWithMd5(goFilePath, md5) {
					kmgFile.MustDelete(pkgPath)
					if debug {
						fmt.Println("gofile not match ", name, " delete ", pkgPath)
					}
					isValid = false
					break
				}
			}
		})
	}
	task.Close()
	return isValid
}
Example #3
0
// key 表示一组缓存,pathList 即这组缓存相关的文件
// 比较容易用错的情况:
// key := 1
// pathList := []string{"/a.txt","/b.txt"}
// a.txt 或者 b.txt 中任意有文件发生变化,这个 key 对应的缓存都会被更新
// 如果要对单个文件进行缓存控制,那么应该一个文件一个 key
func MustMd5FileChangeCache(key string, pathList []string, f func()) {
	// 此处需要考虑,
	//   用户新添加了一个文件
	//   用户删除了一个文件
	//   用户编辑了一个文件
	//   用户在目录里面添加了一个文件
	//   用在在目录里面删除了一个文件
	//读取文件修改时间缓存信息
	toChange := false
	cacheInfo := map[string]string{}
	cacheFilePath := getFileChangeCachePath(key)
	err := kmgGob.ReadFile(cacheFilePath, &cacheInfo)
	if err != nil {
		//忽略缓存读取的任何错误
		cacheInfo = map[string]string{}
	}
	hasReadFileMap := map[string]bool{}
	for _, path := range pathList {
		statList, err := kmgFile.GetAllFileAndDirectoryStat(path)
		if err != nil {
			if os.IsNotExist(err) {
				toChange = true
				//fmt.Printf("[MustFileChangeCache] path:[%s] not exist\n", path)
				break
			}
			panic(err)
		}

		for _, stat := range statList {
			if stat.Fi.IsDir() {
				continue
			}
			hasReadFileMap[stat.FullPath] = true
			if stat.Fi.Mode()&os.ModeSymlink == os.ModeSymlink {
				if "symlink_"+kmgFile.MustReadSymbolLink(stat.FullPath) != cacheInfo[stat.FullPath] {
					toChange = true
					break
				}
				continue
			}
			if kmgCrypto.MustMd5File(stat.FullPath) != cacheInfo[stat.FullPath] {
				toChange = true
				//fmt.Printf("[MustMd5FileChangeCache] path:[%s] mod md5 not match save[%s] file[%s]\n", stat.FullPath,
				//	cacheMd5, kmgCrypto.MustMd5File(stat.FullPath))
				break
			}
		}
		if toChange {
			break
		}
	}
	//删除一个已经存储在缓存列表里面的文件,是一个修改.
	for fullPath := range cacheInfo {
		if !hasReadFileMap[fullPath] {
			toChange = true
			break
		}
	}
	if !toChange {
		return
	}
	f()
	cacheInfo = map[string]string{}
	for _, path := range pathList {
		statList, err := kmgFile.GetAllFileAndDirectoryStat(path)
		if err != nil {
			panic(err)
		}
		for _, stat := range statList {
			if stat.Fi.IsDir() {
				continue
			}
			if stat.Fi.Mode()&os.ModeSymlink == os.ModeSymlink {
				linkToPath := kmgFile.MustReadSymbolLink(stat.FullPath)
				cacheInfo[stat.FullPath] = "symlink_" + linkToPath
				continue
			}
			cacheInfo[stat.FullPath] = kmgCrypto.MustMd5File(stat.FullPath)
		}
	}
	kmgFile.MustMkdirForFile(cacheFilePath)
	kmgGob.MustWriteFile(cacheFilePath, cacheInfo)
	//保存文件缓存信息
	return
}
Example #4
0
// 这个函数bug太多,以废弃,请使用 MustMd5FileChangeCache
// 根据文件变化,对f这个请求进行缓存
// key表示这件事情的缓存key
// pathList表示需要监控的目录
// 文件列表里面如果有文件不存在,会运行代码
// 已知bug,小于1秒的修改不能被检测到.
// @deprecated
func MustFileChangeCache(key string, pathList []string, f func()) {
	//读取文件修改时间缓存信息
	toChange := false
	cacheInfo := map[string]time.Time{}
	cacheFilePath := getFileChangeCachePath(key)
	err := kmgGob.ReadFile(cacheFilePath, &cacheInfo)
	if err != nil {
		cacheInfo = map[string]time.Time{}
	}
	for _, path := range pathList {
		statList, err := kmgFile.GetAllFileAndDirectoryStat(path)
		if err != nil {
			if os.IsNotExist(err) {
				toChange = true
				//fmt.Printf("[MustFileChangeCache] path:[%s] not exist\n", path)
				break
			}
			panic(err)
		}
		for _, stat := range statList {
			if stat.Fi.IsDir() {
				continue
			}
			cacheTime := cacheInfo[stat.FullPath]
			if cacheTime.IsZero() {
				toChange = true
				//fmt.Printf("[MustFileChangeCache] path:[%s] no save mod time\n", stat.FullPath)
				break
			}
			if stat.Fi.ModTime() != cacheTime {
				toChange = true
				//fmt.Printf("[MustFileChangeCache] path:[%s] mod time not match save[%s] file[%s]\n", stat.FullPath,
				//	cacheTime, stat.Fi.ModTime())
				break
			}
		}
		if toChange {
			break
		}
	}
	if !toChange {
		return
	}
	f()
	cacheInfo = map[string]time.Time{}
	for _, path := range pathList {
		statList, err := kmgFile.GetAllFileAndDirectoryStat(path)
		if err != nil {
			panic(err)
		}
		for _, stat := range statList {
			if stat.Fi.IsDir() {
				continue
			}
			cacheInfo[stat.FullPath] = stat.Fi.ModTime()
		}
	}
	kmgFile.MustMkdirForFile(cacheFilePath)
	kmgGob.MustWriteFile(cacheFilePath, cacheInfo)
	//保存文件缓存信息
	return
}