func (repo *RepositoryConfig) GC() {
	TAG := "RepositoryConfig.Vacuum"
	allImages := make(map[string]bool)
	for _, cam := range System.Cameras() {
		for _, kind := range AllKinds {
			for _, img := range repo.ListKind(cam.ID, kind) {
				allImages[img.Handle] = true
			}
		}
	}

	// loop over all raw disk files
	shaRE := regexp.MustCompile("[a-fA-F0-9]{64}")
	for _, cam := range System.Cameras() {
		baseDir := repo.canonDir(filepath.Join(repo.BaseDirectory, cam.ID, MediaData))
		base, err := os.Open(baseDir)
		if err != nil {
			panic(err)
		}
		defer base.Close()
		entries, err := base.Readdir(0)
		if err != nil {
			panic(err)
		}
		for _, entry := range entries {
			// these are the parent directories for our SHA2-256-hashed image/video files
			if !entry.IsDir() {
				continue
			}
			if len(entry.Name()) != 3 {
				// not one of our 3-character summary dirs
				continue
			}
			subdir := repo.canonDir(filepath.Join(baseDir, entry.Name()))
			sd, err := os.Open(subdir)
			if err != nil {
				panic(err)
			}
			defer sd.Close()
			leaves, err := sd.Readdir(0)
			if err != nil {
				panic(err)
			}
			for _, leaf := range leaves {
				// these should be our actual media files
				if leaf.IsDir() {
					continue
				}
				chunks := strings.Split(leaf.Name(), ".")
				if len(chunks) != 3 {
					// not a file we know how to deal with
					continue
				}
				handle := chunks[0]
				if !shaRE.Match([]byte(handle)) {
					// not one of our sha256 filenames
					log.Debug(TAG, fmt.Sprintf("skipping unrecognized file '%s'", leaf.Name()))
					continue
				}
				if _, ok := allImages[handle]; ok {
					// means it's pinned by one of the other MediaKinds
					log.Debug(TAG, fmt.Sprintf("skipping pinned file '%s'", leaf.Name()))
					continue
				}

				// final sanity check, and then remove it
				fpath := filepath.Join(subdir, leaf.Name())
				canonPath := repo.canonFile(fpath)
				if fpath != canonPath {
					log.Error(TAG, fmt.Sprintf("noncanonical path set '%s'/'%s'", fpath, canonPath))
					continue
				}
				err := os.Remove(canonPath)
				if err != nil {
					panic(err)
				}
				log.Debug(TAG, fmt.Sprintf("removed unpinned file '%s'", canonPath))
			}
		}
	}
}
// GC deletes all leaf image files that are not pinned, i.e. it garbage collects.
GC deletes all leaf image files that are not pinned, i.e. it garbage collects.
// GC deletes all leaf image files that are not pinned i . e . it garbage collects .
func (repo *RepositoryConfig) GC() {
	TAG := "RepositoryConfig.Vacuum"
	allImages := make(map[string]bool)
	for _, cam := range System.Cameras() {
		for _, kind := range AllKinds {
			for _, img := range repo.ListKind(cam.ID, kind) {
				allImages[img.Handle] = true
			}
		}
	}
	shaRE := regexp.MustCompile("[a-fA-F0-9]{64}")
	for _, cam := range System.Cameras() {
		baseDir := repo.canonDir(filepath.Join(repo.BaseDirectory, cam.ID, MediaData))
		base, err := os.Open(baseDir)
		if err != nil {
			panic(err)
		}
		defer base.Close()
		entries, err := base.Readdir(0)
		if err != nil {
			panic(err)
		}
		for _, entry := range entries {
			if !entry.IsDir() {
				continue
			}
			if len(entry.Name()) != 3 {
				continue
			}
			subdir := repo.canonDir(filepath.Join(baseDir, entry.Name()))
			sd, err := os.Open(subdir)
			if err != nil {
				panic(err)
			}
			defer sd.Close()
			leaves, err := sd.Readdir(0)
			if err != nil {
				panic(err)
			}
			for _, leaf := range leaves {
				if leaf.IsDir() {
					continue
				}
				chunks := strings.Split(leaf.Name(), ".")
				if len(chunks) != 3 {
					continue
				}
				handle := chunks[0]
				if !shaRE.Match([]byte(handle)) {
					log.Debug(TAG, fmt.Sprintf("skipping unrecognized file '%s'", leaf.Name()))
					continue
				}
				if _, ok := allImages[handle]; ok {
					log.Debug(TAG, fmt.Sprintf("skipping pinned file '%s'", leaf.Name()))
					continue
				}
				fpath := filepath.Join(subdir, leaf.Name())
				canonPath := repo.canonFile(fpath)
				if fpath != canonPath {
					log.Error(TAG, fmt.Sprintf("noncanonical path set '%s'/'%s'", fpath, canonPath))
					continue
				}
				err := os.Remove(canonPath)
				if err != nil {
					panic(err)
				}
				log.Debug(TAG, fmt.Sprintf("removed unpinned file '%s'", canonPath))
			}
		}
	}
}
func ( repo * RepositoryConfig ) GC ( ) { TAG := " " allImages := make ( map [ string ] bool ) for _ , cam := range System . Cameras ( ) { for _ , kind := range AllKinds { for _ , img := range repo . ListKind ( cam . ID , kind ) { allImages [ img . Handle ] = true } } } shaRE := regexp . MustCompile ( " " ) for _ , cam := range System . Cameras ( ) { baseDir := repo . canonDir ( filepath . Join ( repo . BaseDirectory , cam . ID , MediaData ) ) base , err := os . Open ( baseDir ) if err != nil { panic ( err ) } defer base . Close ( ) entries , err := base . Readdir ( 0 ) if err != nil { panic ( err ) } for _ , entry := range entries { if ! entry . IsDir ( ) { continue } if len ( entry . Name ( ) ) != 3 { continue } subdir := repo . canonDir ( filepath . Join ( baseDir , entry . Name ( ) ) ) sd , err := os . Open ( subdir ) if err != nil { panic ( err ) } defer sd . Close ( ) leaves , err := sd . Readdir ( 0 ) if err != nil { panic ( err ) } for _ , leaf := range leaves { if leaf . IsDir ( ) { continue } chunks := strings . Split ( leaf . Name ( ) , " " ) if len ( chunks ) != 3 { continue } handle := chunks [ 0 ] if ! shaRE . Match ( [ ] byte ( handle ) ) { log . Debug ( TAG , fmt . Sprintf ( " " , leaf . Name ( ) ) ) continue } if _ , ok := allImages [ handle ] ; ok { log . Debug ( TAG , fmt . Sprintf ( " " , leaf . Name ( ) ) ) continue } fpath := filepath . Join ( subdir , leaf . Name ( ) ) canonPath := repo . canonFile ( fpath ) if fpath != canonPath { log . Error ( TAG , fmt . Sprintf ( " " , fpath , canonPath ) ) continue } err := os . Remove ( canonPath ) if err != nil { panic ( err ) } log . Debug ( TAG , fmt . Sprintf ( " " , canonPath ) ) } } } }
GC deletes all leaf image files that are not pinned, i.e.
GC deletes all leaf image files that are not pinned i . e .
// loop over all raw disk files // these are the parent directories for our SHA2-256-hashed image/video files // not one of our 3-character summary dirs // these should be our actual media files // not a file we know how to deal with // not one of our sha256 filenames // means it's pinned by one of the other MediaKinds // final sanity check, and then remove it