1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.regionserver;
20
21 import static org.apache.hadoop.hbase.regionserver.StripeStoreFileManager.OPEN_KEY;
22
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.SortedSet;
27 import java.util.concurrent.atomic.AtomicLong;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.fs.Path;
34 import org.apache.hadoop.hbase.KeyValue;
35 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
36 import org.apache.hadoop.hbase.regionserver.StoreFile.Writer;
37 import org.apache.hadoop.hbase.regionserver.StripeMultiFileWriter;
38 import org.apache.hadoop.hbase.regionserver.compactions.StripeCompactionPolicy;
39 import org.apache.hadoop.hbase.util.CollectionBackedScanner;
40
41 import com.google.common.annotations.VisibleForTesting;
42
43
44
45
46
47 @InterfaceAudience.Private
48 public class StripeStoreFlusher extends StoreFlusher {
49 private static final Log LOG = LogFactory.getLog(StripeStoreFlusher.class);
50 private final Object flushLock = new Object();
51 private final StripeCompactionPolicy policy;
52 private final StripeCompactionPolicy.StripeInformationProvider stripes;
53
54 public StripeStoreFlusher(Configuration conf, Store store,
55 StripeCompactionPolicy policy, StripeStoreFileManager stripes) {
56 super(conf, store);
57 this.policy = policy;
58 this.stripes = stripes;
59 }
60
61 @Override
62 public List<Path> flushSnapshot(SortedSet<KeyValue> snapshot, long cacheFlushSeqNum,
63 final TimeRangeTracker tracker, AtomicLong flushedSize, MonitoredTask status)
64 throws IOException {
65 List<Path> result = new ArrayList<Path>();
66 int kvCount = snapshot.size();
67 if (kvCount == 0) return result;
68
69 long smallestReadPoint = store.getSmallestReadPoint();
70 InternalScanner scanner = createScanner(snapshot, smallestReadPoint);
71 if (scanner == null) {
72 return result;
73 }
74
75
76 StripeFlushRequest req = this.policy.selectFlush(this.stripes, kvCount);
77
78 long flushedBytes = 0;
79 boolean success = false;
80 StripeMultiFileWriter mw = null;
81 try {
82 mw = req.createWriter();
83 StripeMultiFileWriter.WriterFactory factory = createWriterFactory(tracker, kvCount);
84 StoreScanner storeScanner = (scanner instanceof StoreScanner) ? (StoreScanner)scanner : null;
85 mw.init(storeScanner, factory, store.getComparator());
86
87 synchronized (flushLock) {
88 flushedBytes = performFlush(scanner, mw, smallestReadPoint);
89 result = mw.commitWriters(cacheFlushSeqNum, false);
90 success = true;
91 }
92 } finally {
93 if (!success && (mw != null)) {
94 for (Path leftoverFile : mw.abortWriters()) {
95 try {
96 store.getFileSystem().delete(leftoverFile, false);
97 } catch (Exception e) {
98 LOG.error("Failed to delete a file after failed flush: " + e);
99 }
100 }
101 }
102 flushedSize.set(flushedBytes);
103 try {
104 scanner.close();
105 } catch (IOException ex) {
106 LOG.warn("Failed to close flush scanner, ignoring", ex);
107 }
108 }
109 return result;
110 }
111
112 private StripeMultiFileWriter.WriterFactory createWriterFactory(
113 final TimeRangeTracker tracker, final long kvCount) {
114 return new StripeMultiFileWriter.WriterFactory() {
115 @Override
116 public Writer createWriter() throws IOException {
117 StoreFile.Writer writer = store.createWriterInTmp(
118 kvCount, store.getFamily().getCompression(),
119
120
121
122
123 writer.setTimeRangeTracker(tracker);
124 return writer;
125 }
126 };
127 }
128
129
130 public static class StripeFlushRequest {
131 @VisibleForTesting
132 public StripeMultiFileWriter createWriter() throws IOException {
133 StripeMultiFileWriter writer =
134 new StripeMultiFileWriter.SizeMultiWriter(1, Long.MAX_VALUE, OPEN_KEY, OPEN_KEY);
135 writer.setNoStripeMetadata();
136 return writer;
137 }
138 }
139
140
141 public static class BoundaryStripeFlushRequest extends StripeFlushRequest {
142 private final List<byte[]> targetBoundaries;
143
144
145 public BoundaryStripeFlushRequest(List<byte[]> targetBoundaries) {
146 this.targetBoundaries = targetBoundaries;
147 }
148
149 @Override
150 public StripeMultiFileWriter createWriter() throws IOException {
151 return new StripeMultiFileWriter.BoundaryMultiWriter(targetBoundaries, null, null);
152 }
153 }
154
155
156 public static class SizeStripeFlushRequest extends StripeFlushRequest {
157 private final int targetCount;
158 private final long targetKvs;
159
160
161
162
163
164
165 public SizeStripeFlushRequest(int targetCount, long targetKvs) {
166 this.targetCount = targetCount;
167 this.targetKvs = targetKvs;
168 }
169
170 @Override
171 public StripeMultiFileWriter createWriter() throws IOException {
172 return new StripeMultiFileWriter.SizeMultiWriter(
173 this.targetCount, this.targetKvs, OPEN_KEY, OPEN_KEY);
174 }
175 }
176 }