1 | package net.spy.memcached.protocol; |
2 | |
3 | import java.io.IOException; |
4 | import java.nio.ByteBuffer; |
5 | |
6 | import net.spy.memcached.MemcachedNode; |
7 | import net.spy.memcached.compat.SpyObject; |
8 | import net.spy.memcached.ops.CancelledOperationStatus; |
9 | import net.spy.memcached.ops.OperationCallback; |
10 | import net.spy.memcached.ops.OperationErrorType; |
11 | import net.spy.memcached.ops.OperationException; |
12 | import net.spy.memcached.ops.OperationState; |
13 | import net.spy.memcached.ops.OperationStatus; |
14 | |
15 | /** |
16 | * Base class for protocol-specific operation implementations. |
17 | */ |
18 | public abstract class BaseOperationImpl extends SpyObject { |
19 | |
20 | /** |
21 | * Status object for cancelled operations. |
22 | */ |
23 | public static final OperationStatus CANCELLED = |
24 | new CancelledOperationStatus(); |
25 | private OperationState state = OperationState.WRITING; |
26 | private ByteBuffer cmd = null; |
27 | private boolean cancelled = false; |
28 | private OperationException exception = null; |
29 | protected OperationCallback callback = null; |
30 | private volatile MemcachedNode handlingNode = null; |
31 | |
32 | public BaseOperationImpl() { |
33 | super(); |
34 | } |
35 | |
36 | /** |
37 | * Get the operation callback associated with this operation. |
38 | */ |
39 | public final OperationCallback getCallback() { |
40 | return callback; |
41 | } |
42 | |
43 | /** |
44 | * Set the callback for this instance. |
45 | */ |
46 | protected void setCallback(OperationCallback to) { |
47 | callback=to; |
48 | } |
49 | |
50 | public final boolean isCancelled() { |
51 | return cancelled; |
52 | } |
53 | |
54 | public final boolean hasErrored() { |
55 | return exception != null; |
56 | } |
57 | |
58 | public final OperationException getException() { |
59 | return exception; |
60 | } |
61 | |
62 | public final void cancel() { |
63 | cancelled=true; |
64 | wasCancelled(); |
65 | callback.complete(); |
66 | } |
67 | |
68 | /** |
69 | * This is called on each subclass whenever an operation was cancelled. |
70 | */ |
71 | protected void wasCancelled() { |
72 | getLogger().debug("was cancelled."); |
73 | } |
74 | |
75 | public final OperationState getState() { |
76 | return state; |
77 | } |
78 | |
79 | public final ByteBuffer getBuffer() { |
80 | return cmd; |
81 | } |
82 | |
83 | /** |
84 | * Set the write buffer for this operation. |
85 | */ |
86 | protected final void setBuffer(ByteBuffer to) { |
87 | assert to != null : "Trying to set buffer to null"; |
88 | cmd=to; |
89 | cmd.mark(); |
90 | } |
91 | |
92 | /** |
93 | * Transition the state of this operation to the given state. |
94 | */ |
95 | protected final void transitionState(OperationState newState) { |
96 | getLogger().debug("Transitioned state from %s to %s", state, newState); |
97 | state=newState; |
98 | // Discard our buffer when we no longer need it. |
99 | if(state != OperationState.WRITING) { |
100 | cmd=null; |
101 | } |
102 | if(state == OperationState.COMPLETE) { |
103 | callback.complete(); |
104 | } |
105 | } |
106 | |
107 | public final void writeComplete() { |
108 | transitionState(OperationState.READING); |
109 | } |
110 | |
111 | public abstract void initialize(); |
112 | |
113 | public abstract void readFromBuffer(ByteBuffer data) throws IOException; |
114 | |
115 | protected void handleError(OperationErrorType eType, String line) |
116 | throws IOException { |
117 | getLogger().error("Error: %s", line); |
118 | switch(eType) { |
119 | case GENERAL: |
120 | exception=new OperationException(); |
121 | break; |
122 | case SERVER: |
123 | exception=new OperationException(eType, line); |
124 | break; |
125 | case CLIENT: |
126 | exception=new OperationException(eType, line); |
127 | break; |
128 | default: assert false; |
129 | } |
130 | transitionState(OperationState.COMPLETE); |
131 | throw exception; |
132 | } |
133 | |
134 | public void handleRead(ByteBuffer data) { |
135 | assert false; |
136 | } |
137 | |
138 | public MemcachedNode getHandlingNode() { |
139 | return handlingNode; |
140 | } |
141 | |
142 | public void setHandlingNode(MemcachedNode to) { |
143 | handlingNode = to; |
144 | } |
145 | |
146 | } |