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 java.io.IOException;
22 import java.io.InterruptedIOException;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.fs.Path;
29 import org.apache.hadoop.hbase.Cell;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.KeyValueUtil;
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33 import org.apache.hadoop.hbase.client.Scan;
34 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
35 import org.apache.hadoop.hbase.regionserver.compactions.Compactor;
36 import org.apache.hadoop.hbase.regionserver.throttle.ThroughputControlUtil;
37 import org.apache.hadoop.hbase.regionserver.throttle.ThroughputController;
38
39
40
41
42
43 @InterfaceAudience.Private
44 abstract class StoreFlusher {
45 protected Configuration conf;
46 protected Store store;
47
48 public StoreFlusher(Configuration conf, Store store) {
49 this.conf = conf;
50 this.store = store;
51 }
52
53
54
55
56
57
58
59
60
61 public abstract List<Path> flushSnapshot(MemStoreSnapshot snapshot, long cacheFlushSeqNum,
62 MonitoredTask status, ThroughputController throughputController) throws IOException;
63
64 protected void finalizeWriter(StoreFile.Writer writer, long cacheFlushSeqNum,
65 MonitoredTask status) throws IOException {
66
67
68
69 status.setStatus("Flushing " + store + ": appending metadata");
70 writer.appendMetadata(cacheFlushSeqNum, false);
71 status.setStatus("Flushing " + store + ": closing flushed file");
72 writer.close();
73 }
74
75
76
77
78
79
80
81
82 protected InternalScanner createScanner(KeyValueScanner snapshotScanner,
83 long smallestReadPoint) throws IOException {
84 InternalScanner scanner = null;
85 if (store.getCoprocessorHost() != null) {
86 scanner = store.getCoprocessorHost().preFlushScannerOpen(store, snapshotScanner,
87 smallestReadPoint);
88 }
89 if (scanner == null) {
90 Scan scan = new Scan();
91 scan.setMaxVersions(store.getScanInfo().getMaxVersions());
92 scanner = new StoreScanner(store, store.getScanInfo(), scan,
93 Collections.singletonList(snapshotScanner), ScanType.COMPACT_RETAIN_DELETES,
94 smallestReadPoint, HConstants.OLDEST_TIMESTAMP);
95 }
96 assert scanner != null;
97 if (store.getCoprocessorHost() != null) {
98 try {
99 return store.getCoprocessorHost().preFlush(store, scanner);
100 } catch (IOException ioe) {
101 scanner.close();
102 throw ioe;
103 }
104 }
105 return scanner;
106 }
107
108
109
110
111
112
113
114
115 protected void performFlush(InternalScanner scanner, Compactor.CellSink sink,
116 long smallestReadPoint, ThroughputController throughputController) throws IOException {
117 int compactionKVMax =
118 conf.getInt(HConstants.COMPACTION_KV_MAX, HConstants.COMPACTION_KV_MAX_DEFAULT);
119
120 ScannerContext scannerContext =
121 ScannerContext.newBuilder().setBatchLimit(compactionKVMax).build();
122
123 List<Cell> kvs = new ArrayList<Cell>();
124 boolean hasMore;
125 String flushName = ThroughputControlUtil.getNameForThrottling(store, "flush");
126
127 boolean control = throughputController != null && !store.getRegionInfo().isSystemTable();
128 if (control) {
129 throughputController.start(flushName);
130 }
131 try {
132 do {
133 hasMore = scanner.next(kvs, scannerContext);
134 if (!kvs.isEmpty()) {
135 for (Cell c : kvs) {
136
137
138
139 sink.append(c);
140 int len = KeyValueUtil.length(c);
141 if (control) {
142 throughputController.control(flushName, len);
143 }
144 }
145 kvs.clear();
146 }
147 } while (hasMore);
148 } catch (InterruptedException e) {
149 throw new InterruptedIOException("Interrupted while control throughput of flushing "
150 + flushName);
151 } finally {
152 if (control) {
153 throughputController.finish(flushName);
154 }
155 }
156 }
157 }