Esempio n. 1
0
// scan scans the directory tree for files.
func (cache *Cache) scan() {
	cache.cachedFiles = cmap.New()
	cache.totalSize = 0

	if !core.PathExists(cache.rootPath) {
		if err := os.MkdirAll(cache.rootPath, core.DirPermissions); err != nil {
			log.Fatalf("Failed to create cache directory %s: %s", cache.rootPath, err)
		}
		return
	}

	log.Info("Scanning cache directory %s...", cache.rootPath)
	filepath.Walk(cache.rootPath, func(name string, info os.FileInfo, err error) error {
		if err != nil {
			log.Fatalf("%s", err)
		} else if !info.IsDir() { // We don't have directory entries.
			name = name[len(cache.rootPath)+1:]
			log.Debug("Found file %s", name)
			size := info.Size()
			cache.cachedFiles.Set(name, &cachedFile{
				lastReadTime: time.Unix(tools.AccessTime(info), 0),
				readCount:    0,
				size:         size,
			})
			cache.totalSize += size
		}
		return nil
	})
	log.Info("Scan complete, found %d entries", cache.cachedFiles.Count())
}
Esempio n. 2
0
func start(directory string, highWaterMark, lowWaterMark int64) {
	entries := CacheEntries{}
	var totalSize int64 = 0
	if err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		} else if (len(info.Name()) == 28 || len(info.Name()) == 29) && info.Name()[27] == '=' {
			// Directory has the right length. We do this in an attempt to clean only entire
			// entries in the cache, not just individual files from them.
			// 28 == length of 20-byte sha1 hash, encoded to base64, which always gets a trailing =
			// as padding so we can check that to be "sure".
			// Also 29 in case we appended an extra = (see below)
			if size, err := findSize(path); err != nil {
				return err
			} else {
				entries = append(entries, CacheEntry{path, size, tools.AccessTime(info)})
				totalSize += size
				return filepath.SkipDir
			}
		} else {
			return nil // nothing particularly to do for other entries
		}
	}); err != nil {
		log.Fatalf("error walking cache directory: %s\n", err)
	}
	log.Notice("Total cache size: %s", humanize.Bytes(uint64(totalSize)))
	if totalSize < highWaterMark {
		return // Nothing to do, cache is small enough.
	}
	// OK, we need to slim it down a bit. We implement a simple LRU algorithm.
	sort.Sort(entries)
	for _, entry := range entries {
		log.Notice("Cleaning %s, accessed %s, saves %s", entry.Path, humanize.Time(time.Unix(entry.Atime, 0)), humanize.Bytes(uint64(entry.Size)))
		// Try to rename the directory first so we don't delete bits while someone might access them.
		newPath := entry.Path + "="
		if err := os.Rename(entry.Path, newPath); err != nil {
			log.Errorf("Couldn't rename %s: %s", entry.Path, err)
			continue
		}
		if err := os.RemoveAll(newPath); err != nil {
			log.Errorf("Couldn't remove %s: %s", newPath, err)
			continue
		}
		totalSize -= entry.Size
		if totalSize < lowWaterMark {
			break
		}
	}
}