blob: 92fceab017f31f743436d24fcb425f1a0cbbedb7 [file] [log] [blame]
khenaidooffe076b2019-01-15 16:08:08 -05001// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package fileutil
16
17import (
18 "os"
19 "path/filepath"
20 "sort"
21 "strings"
22 "time"
23)
24
25func PurgeFile(dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) <-chan error {
26 return purgeFile(dirname, suffix, max, interval, stop, nil)
27}
28
29// purgeFile is the internal implementation for PurgeFile which can post purged files to purgec if non-nil.
30func purgeFile(dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}, purgec chan<- string) <-chan error {
31 errC := make(chan error, 1)
32 go func() {
33 for {
34 fnames, err := ReadDir(dirname)
35 if err != nil {
36 errC <- err
37 return
38 }
39 newfnames := make([]string, 0)
40 for _, fname := range fnames {
41 if strings.HasSuffix(fname, suffix) {
42 newfnames = append(newfnames, fname)
43 }
44 }
45 sort.Strings(newfnames)
46 fnames = newfnames
47 for len(newfnames) > int(max) {
48 f := filepath.Join(dirname, newfnames[0])
49 l, err := TryLockFile(f, os.O_WRONLY, PrivateFileMode)
50 if err != nil {
51 break
52 }
53 if err = os.Remove(f); err != nil {
54 errC <- err
55 return
56 }
57 if err = l.Close(); err != nil {
58 plog.Errorf("error unlocking %s when purging file (%v)", l.Name(), err)
59 errC <- err
60 return
61 }
62 plog.Infof("purged file %s successfully", f)
63 newfnames = newfnames[1:]
64 }
65 if purgec != nil {
66 for i := 0; i < len(fnames)-len(newfnames); i++ {
67 purgec <- fnames[i]
68 }
69 }
70 select {
71 case <-time.After(interval):
72 case <-stop:
73 return
74 }
75 }
76 }()
77 return errC
78}