1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.master;
21
22 import java.io.IOException;
23 import java.util.LinkedList;
24 import java.util.List;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FileStatus;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.hbase.Chore;
33 import org.apache.hadoop.hbase.RemoteExceptionHandler;
34 import org.apache.hadoop.hbase.Stoppable;
35 import org.apache.hadoop.hbase.regionserver.wal.HLog;
36 import org.apache.hadoop.hbase.util.FSUtils;
37
38 import static org.apache.hadoop.hbase.HConstants.HBASE_MASTER_LOGCLEANER_PLUGINS;
39
40
41
42
43
44 public class LogCleaner extends Chore {
45 static final Log LOG = LogFactory.getLog(LogCleaner.class.getName());
46
47 private final FileSystem fs;
48 private final Path oldLogDir;
49 private List<LogCleanerDelegate> logCleanersChain;
50 private final Configuration conf;
51
52
53
54
55
56
57
58
59
60 public LogCleaner(final int p, final Stoppable s,
61 Configuration conf, FileSystem fs,
62 Path oldLogDir) {
63 super("LogsCleaner", p, s);
64 this.fs = fs;
65 this.oldLogDir = oldLogDir;
66 this.conf = conf;
67 this.logCleanersChain = new LinkedList<LogCleanerDelegate>();
68
69 initLogCleanersChain();
70 }
71
72
73
74
75
76
77 private void initLogCleanersChain() {
78 String[] logCleaners = conf.getStrings(HBASE_MASTER_LOGCLEANER_PLUGINS);
79 if (logCleaners != null) {
80 for (String className : logCleaners) {
81 LogCleanerDelegate logCleaner = newLogCleaner(className, conf);
82 addLogCleaner(logCleaner);
83 }
84 }
85 }
86
87
88
89
90
91
92
93
94 public static LogCleanerDelegate newLogCleaner(String className, Configuration conf) {
95 try {
96 Class c = Class.forName(className);
97 LogCleanerDelegate cleaner = (LogCleanerDelegate) c.newInstance();
98 cleaner.setConf(conf);
99 return cleaner;
100 } catch(Exception e) {
101 LOG.warn("Can NOT create LogCleanerDelegate: " + className, e);
102
103 return null;
104 }
105 }
106
107
108
109
110
111
112 public void addLogCleaner(LogCleanerDelegate logCleaner) {
113 if (logCleaner != null && !logCleanersChain.contains(logCleaner)) {
114 logCleanersChain.add(logCleaner);
115 LOG.debug("Add log cleaner in chain: " + logCleaner.getClass().getName());
116 }
117 }
118
119 @Override
120 protected void chore() {
121 try {
122 FileStatus [] files = FSUtils.listStatus(this.fs, this.oldLogDir, null);
123 if (files == null) return;
124 FILE: for (FileStatus file : files) {
125 Path filePath = file.getPath();
126 if (HLog.validateHLogFilename(filePath.getName())) {
127 for (LogCleanerDelegate logCleaner : logCleanersChain) {
128 if (logCleaner.isStopped()) {
129 LOG.warn("A log cleaner is stopped, won't delete any log.");
130 return;
131 }
132
133 if (!logCleaner.isLogDeletable(filePath) ) {
134
135 continue FILE;
136 }
137 }
138
139 this.fs.delete(filePath, true);
140 } else {
141 LOG.warn("Found a wrongly formated file: "
142 + file.getPath().getName());
143 this.fs.delete(filePath, true);
144 }
145 }
146 } catch (IOException e) {
147 e = RemoteExceptionHandler.checkIOException(e);
148 LOG.warn("Error while cleaning the logs", e);
149 }
150 }
151
152 @Override
153 public void run() {
154 try {
155 super.run();
156 } finally {
157 for (LogCleanerDelegate lc: this.logCleanersChain) {
158 try {
159 lc.stop("Exiting");
160 } catch (Throwable t) {
161 LOG.warn("Stopping", t);
162 }
163 }
164 }
165 }
166 }