1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.ipc;
19
20 import io.netty.channel.ChannelDuplexHandler;
21 import io.netty.channel.ChannelHandlerContext;
22 import io.netty.channel.ChannelPromise;
23
24 import java.io.IOException;
25 import java.util.HashMap;
26 import java.util.Map;
27
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29
30
31
32
33
34 @InterfaceAudience.Private
35 class BufferCallBeforeInitHandler extends ChannelDuplexHandler {
36
37 private enum BufferCallAction {
38 FLUSH, FAIL
39 }
40
41 public static final class BufferCallEvent {
42
43 public final BufferCallAction action;
44
45 public final IOException error;
46
47 private BufferCallEvent(BufferCallBeforeInitHandler.BufferCallAction action,
48 IOException error) {
49 this.action = action;
50 this.error = error;
51 }
52
53 public static BufferCallBeforeInitHandler.BufferCallEvent success() {
54 return SUCCESS_EVENT;
55 }
56
57 public static BufferCallBeforeInitHandler.BufferCallEvent fail(IOException error) {
58 return new BufferCallEvent(BufferCallAction.FAIL, error);
59 }
60 }
61
62 private static final BufferCallEvent SUCCESS_EVENT = new BufferCallEvent(BufferCallAction.FLUSH,
63 null);
64
65 private final Map<Integer, Call> id2Call = new HashMap<>();
66
67 @Override
68 public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
69 if (msg instanceof Call) {
70 Call call = (Call) msg;
71 id2Call.put(call.id, call);
72
73
74 promise.trySuccess();
75 } else {
76 ctx.write(msg, promise);
77 }
78 }
79
80 @Override
81 public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
82 if (evt instanceof BufferCallEvent) {
83 BufferCallEvent bcEvt = (BufferCallBeforeInitHandler.BufferCallEvent) evt;
84 switch (bcEvt.action) {
85 case FLUSH:
86 for (Call call : id2Call.values()) {
87 ctx.write(call);
88 }
89 break;
90 case FAIL:
91 for (Call call : id2Call.values()) {
92 call.setException(bcEvt.error);
93 }
94 break;
95 }
96 ctx.flush();
97 ctx.pipeline().remove(this);
98 } else if (evt instanceof CallEvent) {
99
100 id2Call.remove(((CallEvent) evt).call.id);
101 } else {
102 ctx.fireUserEventTriggered(evt);
103 }
104 }
105 }