ActiveIO - 1.0

Clover coverage report - ActiveIO - 1.0 Coverage timestamp: Fri Apr 22 2005 14:27:22 PDT FRAMES NO FRAMES |
file stats: | LOC: | 193 |  | Methods: | 12
| NCLOC: | 128 |  | Classes: | 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
Source file | Conditionals | Statements | Methods | TOTAL
AsynchChannelToConcurrentRequestChannel.java | 0% | 0% | 0% | 0% |

1 |  |
     /**
2 |  |
      *
3 |  |
      * Copyright 2004 Hiram Chirino
4 |  |
      *
5 |  |
      *  Licensed under the Apache License, Version 2.0 (the "License");
6 |  |
      *  you may not use this file except in compliance with the License.
7 |  |
      *  You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      *  Unless required by applicable law or agreed to in writing, software
12 |  |
      *  distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      *  See the License for the specific language governing permissions and
15 |  |
      *  limitations under the License.
16 |  |
      */
17 |  |
     package org.activeio.adapter;
18 |  |
19 |  |
     import java.io.IOException;
20 |  |
     import java.io.InterruptedIOException;
21 |  |
22 |  |
     import org.activeio.AsynchChannel;
23 |  |
     import org.activeio.ChannelFactory;
24 |  |
     import org.activeio.FilterAsynchChannel;
25 |  |
     import org.activeio.Packet;
26 |  |
     import org.activeio.PacketData;
27 |  |
     import org.activeio.RequestChannel;
28 |  |
     import org.activeio.RequestListener;
29 |  |
     import org.activeio.packet.AppendedPacket;
30 |  |
     import org.activeio.packet.ByteArrayPacket;
31 |  |
32 |  |
     import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
33 |  |
     import EDU.oswego.cs.dl.util.concurrent.Executor;
34 |  |
     import EDU.oswego.cs.dl.util.concurrent.Slot;
35 |  |
36 |  |
37 |  |
     /**
38 |  |
      * Creates a {@see org.activeio.RequestChannel} out of a {@see org.activeio.AsynchChannel}.  This
39 |  |
      * {@see org.activeio.RequestChannel} is thread safe and mutiplexes concurrent requests and responses over
40 |  |
      * the underlying {@see org.activeio.AsynchChannel}.
41 |  |
      *
42 |  |
      * @version $Revision$
43 |  |
      */
44 |  |
     final public class AsynchChannelToConcurrentRequestChannel extends FilterAsynchChannel implements RequestChannel {
45 |  |
46 |  |
         private static final byte PASSTHROUGH = 0x00;
47 |  |
         private static final byte REQUEST = 0x01;
48 |  |
         private static final byte RESPONSE = 0x02;
49 |  |
         private static final ByteArrayPacket PASSTHROUGH_PACKET = new ByteArrayPacket(new byte[]{PASSTHROUGH});
50 |  |
51 |  |
         private final ConcurrentHashMap requestMap = new ConcurrentHashMap();
52 |  |
         private final Executor requestExecutor;
53 |  |
         private short nextRequestId = 0;
54 |  |
         private final Object writeMutex = new Object();
55 |  |
56 |  |
         private RequestListener requestListener;
57 |  |
58 | 0 |
         public AsynchChannelToConcurrentRequestChannel(AsynchChannel next) {
59 | 0 |
             this(next, ChannelFactory.DEFAULT_EXECUTOR);
60 |  |
         }
61 |  |
62 | 0 |
         public AsynchChannelToConcurrentRequestChannel(AsynchChannel next, Executor requestExecutor) {
63 | 0 |
             super(next);
64 | 0 |
             this.requestExecutor=requestExecutor;
65 |  |
         }
66 |  |
67 | 0 |
         synchronized short getNextRequestId() {
68 | 0 |
             return nextRequestId++;
69 |  |
         }
70 |  |
71 |  |
         /**
72 |  |
          * @see org.activeio.FilterAsynchChannel#write(org.activeio.channel.Packet)
73 |  |
          */
74 | 0 |
         public void write(Packet packet) throws IOException {
75 | 0 |
             Packet passThrough = AppendedPacket.join(PASSTHROUGH_PACKET.duplicate(), packet);
76 | 0 |
             synchronized(writeMutex) {
77 | 0 |
                 super.write(passThrough);
78 |  |
             }
79 |  |
         }
80 |  |
81 |  |
         /**
82 |  |
          * @see org.activeio.FilterAsynchChannel#onPacket(org.activeio.channel.Packet)
83 |  |
          */
84 | 0 |
         public void onPacket(final Packet packet) {
85 | 0 |
                 switch( packet.read() ) {
86 |  |
                     case PASSTHROUGH:
87 | 0 |
                         super.onPacket(packet);
88 | 0 |
                         break;
89 |  |
                     case REQUEST:
90 | 0 |
                         try {
91 | 0 |
                             requestExecutor.execute(new Runnable(){
92 | 0 |
                                 public void run() {
93 | 0 |
                                     serviceRequest(packet);
94 |  |
                                 }
95 |  |
                             });
96 |  |
                         } catch (InterruptedException e) {
97 | 0 |
                             Thread.currentThread().interrupt();
98 |  |
                         }
99 | 0 |
                         break;
100 |  |
                     case RESPONSE:
101 | 0 |
                         serviceReponse(packet);
102 | 0 |
                         break;
103 |  |
                 }
104 |  |
         }
105 |  |
106 | 0 |
         private void serviceRequest(Packet packet) {
107 | 0 |
             try {
108 | 0 |
                 if( requestListener ==null )
109 | 0 |
                     throw new IOException("The RequestListener has not been set.");
110 |  |
111 | 0 |
                 PacketData data = new PacketData(packet);
112 | 0 |
                 short requestId = data.readShort();
113 | 0 |
                 Packet reponse = requestListener.onRequest(packet);
114 |  |
115 |  |
                 // Send the response...
116 | 0 |
                 Packet header = createHeaderPacket(RESPONSE, requestId);
117 | 0 |
                 Packet rc = AppendedPacket.join(header, packet);
118 | 0 |
                 synchronized(writeMutex) {
119 | 0 |
                     super.write(rc);
120 |  |
                 }
121 |  |
             } catch (IOException e) {
122 | 0 |
                 super.onPacketError(e);
123 |  |
             }
124 |  |
125 |  |
         }
126 |  |
127 | 0 |
         private void serviceReponse(Packet packet) {
128 |  |
129 | 0 |
             try {
130 |  |
131 | 0 |
                 PacketData data = new PacketData(packet);
132 | 0 |
                 short requestId = data.readShort();
133 |  |
134 | 0 |
                 Slot responseSlot = (Slot) requestMap.get(new Short(requestId));
135 | 0 |
                 responseSlot.put(packet);
136 |  |
137 |  |
             } catch (IOException e) {
138 | 0 |
                 super.onPacketError(e);
139 |  |
             } catch (InterruptedException e) {
140 | 0 |
                 Thread.currentThread().interrupt();
141 |  |
             }
142 |  |
143 |  |
144 |  |
         }
145 |  |
146 | 0 |
         public Packet request(Packet request, long timeout) throws IOException {
147 |  |
148 | 0 |
             Short requestId = new Short(getNextRequestId());
149 | 0 |
             Slot responseSlot = new Slot();
150 | 0 |
             requestMap.put(requestId, responseSlot);
151 |  |
152 | 0 |
             Packet header = createHeaderPacket(REQUEST, requestId.shortValue());
153 | 0 |
             Packet packet = AppendedPacket.join(header, request);
154 |  |
155 | 0 |
             synchronized(writeMutex) {
156 | 0 |
                 super.write(packet);
157 |  |
             }
158 |  |
159 | 0 |
             try {
160 |  |
161 | 0 |
                 if( timeout == WAIT_FOREVER_TIMEOUT ) {
162 | 0 |
                     return (Packet) responseSlot.take();
163 | 0 |
                 } else if (timeout == NO_WAIT_TIMEOUT ) {
164 | 0 |
                     return (Packet) responseSlot.poll(1);
165 |  |
                 } else {
166 | 0 |
                     return (Packet) responseSlot.poll(timeout);
167 |  |
                 }
168 |  |
169 |  |
             } catch (InterruptedException e) {
170 | 0 |
                 throw new InterruptedIOException(e.getMessage());
171 |  |
             } finally {
172 | 0 |
                 requestMap.remove(requestId);
173 |  |
             }
174 |  |
         }
175 |  |
176 | 0 |
         private Packet createHeaderPacket(byte type, short requestId) throws IOException {
177 | 0 |
             ByteArrayPacket header = new ByteArrayPacket(new byte[]{3});
178 | 0 |
             PacketData data = new PacketData(header);
179 | 0 |
             data.writeByte(type);
180 | 0 |
             data.writeShort(requestId);
181 | 0 |
             header.flip();
182 | 0 |
             return header;
183 |  |
         }
184 |  |
185 | 0 |
         public void setRequestListener(RequestListener requestListener) throws IOException {
186 | 0 |
             this.requestListener = requestListener;
187 |  |
         }
188 |  |
189 | 0 |
         public RequestListener getRequestListener() {
190 | 0 |
             return requestListener;
191 |  |
         }
192 |  |
     }
193 |  |