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