blob: fda96c3711439861bb1f20af92e3a97f38f8a5be [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -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 "go.uber.org/zap"
25)
26
27func PurgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) <-chan error {
28 return purgeFile(lg, dirname, suffix, max, interval, stop, nil)
29}
30
31// purgeFile is the internal implementation for PurgeFile which can post purged files to purgec if non-nil.
32func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}, purgec chan<- string) <-chan error {
33 errC := make(chan error, 1)
34 go func() {
35 for {
36 fnames, err := ReadDir(dirname)
37 if err != nil {
38 errC <- err
39 return
40 }
41 newfnames := make([]string, 0)
42 for _, fname := range fnames {
43 if strings.HasSuffix(fname, suffix) {
44 newfnames = append(newfnames, fname)
45 }
46 }
47 sort.Strings(newfnames)
48 fnames = newfnames
49 for len(newfnames) > int(max) {
50 f := filepath.Join(dirname, newfnames[0])
51 l, err := TryLockFile(f, os.O_WRONLY, PrivateFileMode)
52 if err != nil {
53 break
54 }
55 if err = os.Remove(f); err != nil {
56 errC <- err
57 return
58 }
59 if err = l.Close(); err != nil {
60 if lg != nil {
61 lg.Warn("failed to unlock/close", zap.String("path", l.Name()), zap.Error(err))
62 } else {
63 plog.Errorf("error unlocking %s when purging file (%v)", l.Name(), err)
64 }
65 errC <- err
66 return
67 }
68 if lg != nil {
69 lg.Info("purged", zap.String("path", f))
70 } else {
71 plog.Infof("purged file %s successfully", f)
72 }
73 newfnames = newfnames[1:]
74 }
75 if purgec != nil {
76 for i := 0; i < len(fnames)-len(newfnames); i++ {
77 purgec <- fnames[i]
78 }
79 }
80 select {
81 case <-time.After(interval):
82 case <-stop:
83 return
84 }
85 }
86 }()
87 return errC
88}