1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.snapshot;
20
21 import java.io.Closeable;
22 import java.io.IOException;
23 import java.util.Map;
24 import java.util.TreeMap;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.classification.InterfaceAudience;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.hbase.io.HLogLink;
33 import org.apache.hadoop.hbase.regionserver.HRegion;
34 import org.apache.hadoop.hbase.regionserver.wal.HLog;
35 import org.apache.hadoop.hbase.regionserver.wal.HLogFactory;
36 import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
37 import org.apache.hadoop.hbase.regionserver.wal.HLogUtil;
38 import org.apache.hadoop.hbase.util.Bytes;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @InterfaceAudience.Private
56 class SnapshotLogSplitter implements Closeable {
57 static final Log LOG = LogFactory.getLog(SnapshotLogSplitter.class);
58
59 private final class LogWriter implements Closeable {
60 private HLog.Writer writer;
61 private Path logFile;
62 private long seqId;
63
64 public LogWriter(final Configuration conf, final FileSystem fs,
65 final Path logDir, long seqId) throws IOException {
66 logFile = new Path(logDir, logFileName(seqId, true));
67 this.writer = HLogFactory.createWriter(fs, logFile, conf);
68 this.seqId = seqId;
69 }
70
71 public void close() throws IOException {
72 writer.close();
73
74 Path finalFile = new Path(logFile.getParent(), logFileName(seqId, false));
75 LOG.debug("LogWriter tmpLogFile=" + logFile + " -> logFile=" + finalFile);
76 fs.rename(logFile, finalFile);
77 }
78
79 public void append(final HLog.Entry entry) throws IOException {
80 writer.append(entry);
81 if (seqId < entry.getKey().getLogSeqNum()) {
82 seqId = entry.getKey().getLogSeqNum();
83 }
84 }
85
86 private String logFileName(long seqId, boolean temp) {
87 String fileName = String.format("%019d", seqId);
88 if (temp) fileName += HLog.RECOVERED_LOG_TMPFILE_SUFFIX;
89 return fileName;
90 }
91 }
92
93 private final Map<byte[], LogWriter> regionLogWriters =
94 new TreeMap<byte[], LogWriter>(Bytes.BYTES_COMPARATOR);
95
96 private final Map<byte[], byte[]> regionsMap;
97 private final Configuration conf;
98 private final byte[] snapshotTableName;
99 private final byte[] tableName;
100 private final Path tableDir;
101 private final FileSystem fs;
102
103
104
105
106
107 public SnapshotLogSplitter(final Configuration conf, final FileSystem fs,
108 final Path tableDir, final byte[] snapshotTableName,
109 final Map<byte[], byte[]> regionsMap) {
110 this.regionsMap = regionsMap;
111 this.snapshotTableName = snapshotTableName;
112 this.tableName = Bytes.toBytes(tableDir.getName());
113 this.tableDir = tableDir;
114 this.conf = conf;
115 this.fs = fs;
116 }
117
118 public void close() throws IOException {
119 for (LogWriter writer: regionLogWriters.values()) {
120 writer.close();
121 }
122 }
123
124 public void splitLog(final String serverName, final String logfile) throws IOException {
125 LOG.debug("Restore log=" + logfile + " server=" + serverName +
126 " for snapshotTable=" + Bytes.toString(snapshotTableName) +
127 " to table=" + Bytes.toString(tableName));
128 splitLog(new HLogLink(conf, serverName, logfile).getAvailablePath(fs));
129 }
130
131 public void splitRecoveredEdit(final Path editPath) throws IOException {
132 LOG.debug("Restore recover.edits=" + editPath +
133 " for snapshotTable=" + Bytes.toString(snapshotTableName) +
134 " to table=" + Bytes.toString(tableName));
135 splitLog(editPath);
136 }
137
138
139
140
141
142
143
144
145
146 public void splitLog(final Path logPath) throws IOException {
147 HLog.Reader log = HLogFactory.createReader(fs, logPath, conf);
148 try {
149 HLog.Entry entry;
150 LogWriter writer = null;
151 byte[] regionName = null;
152 byte[] newRegionName = null;
153 while ((entry = log.next()) != null) {
154 HLogKey key = entry.getKey();
155
156
157 if (!Bytes.equals(key.getTablename(), snapshotTableName)) continue;
158
159
160 if (!Bytes.equals(regionName, key.getEncodedRegionName())) {
161 regionName = key.getEncodedRegionName().clone();
162
163
164 newRegionName = regionsMap.get(regionName);
165 if (newRegionName == null) newRegionName = regionName;
166
167 writer = getOrCreateWriter(newRegionName, key.getLogSeqNum());
168 LOG.debug("+ regionName=" + Bytes.toString(regionName));
169 }
170
171
172 key = new HLogKey(newRegionName, tableName,
173 key.getLogSeqNum(), key.getWriteTime(), key.getClusterId());
174 writer.append(new HLog.Entry(key, entry.getEdit()));
175 }
176 } catch (IOException e) {
177 LOG.warn("Something wrong during the log split", e);
178 } finally {
179 log.close();
180 }
181 }
182
183
184
185
186 private LogWriter getOrCreateWriter(final byte[] regionName, long seqId) throws IOException {
187 LogWriter writer = regionLogWriters.get(regionName);
188 if (writer == null) {
189 Path regionDir = HRegion.getRegionDir(tableDir, Bytes.toString(regionName));
190 Path dir = HLogUtil.getRegionDirRecoveredEditsDir(regionDir);
191 fs.mkdirs(dir);
192
193 writer = new LogWriter(conf, fs, dir, seqId);
194 regionLogWriters.put(regionName, writer);
195 }
196 return(writer);
197 }
198 }