UartBus source documentation
UartbusTransaction.java
1 package eu.javaexperience.electronic.uartbus.rpc.client;
2 
3 import java.io.Closeable;
4 import java.io.IOException;
5 import java.util.concurrent.TimeUnit;
6 
7 import eu.javaexperience.asserts.AssertArgument;
8 import eu.javaexperience.datastorage.TransactionException;
10 import eu.javaexperience.exceptions.IllegalOperationException;
11 import eu.javaexperience.log.JavaExperienceLoggingFacility;
12 import eu.javaexperience.log.LogLevel;
13 import eu.javaexperience.log.Loggable;
14 import eu.javaexperience.log.Logger;
15 import eu.javaexperience.log.LoggingTools;
16 import eu.javaexperience.multithread.notify.WaitForSingleEvent;
17 
18 /**
19  * I know, this is a blob but maybe it's easier to manager request-response
20  * as one unit.
21  * */
22 public class UartbusTransaction implements Closeable
23 {
24  protected static final Logger LOG = JavaExperienceLoggingFacility.getLogger(new Loggable("UartbusTransaction"));
25 
26  public final UartBus bus;
27 
28  public boolean zeroNamespaceAnswer;
29  public int to;
30  public int from;
31 
32  //if channel is negative, we send the request directly
33 
34  public byte[] path;
35  public byte[] payload;
36 
37  public volatile boolean revoked = false;
38 
39  public volatile byte[] responsePayload;
40 
41  public UartbusTransaction(UartBus bus)
42  {
43  this.bus = bus;
44  }
45 
46  public byte[] toPacket()
47  {
48  return UbRpcTools.toPacket(to, from, payload);
49  }
50 
51  public void send() throws IOException
52  {
53  if(isResponsed())
54  {
55  throw new IllegalOperationException("Request already sent and responded!");
56  }
57 
58  //this also add the request to the pending list.
59  bus.addPendingRequest(this);
60 
61  byte[] send = toPacket();
62  synchronized(this)
63  {
64  bus.sendPacket.publish(send);
65  }
66 
67  if(LOG.mayLog(LogLevel.TRACE))
68  {
69  LoggingTools.tryLogFormat(LOG, LogLevel.TRACE, "Request sent: %s", hashCode());
70  }
71  }
72 
73  @Override
74  public void close() throws IOException
75  {
76  revoked = true;
77  bus.revokePendingRequest(this);
78  }
79 
80  @Override
81  protected void finalize() throws Throwable
82  {
83  //safety net
84  close();
85  }
86 
87 /****************************** response section ******************************/
88  protected final WaitForSingleEvent wait = new WaitForSingleEvent();
89 
90  public boolean isResponsed()
91  {
92  return null != responsePayload;
93  }
94 
95  public boolean isRevoked()
96  {
97  return null != responsePayload && revoked;
98  }
99 
100  public boolean waitResponse(long timeout, TimeUnit unit) throws InterruptedException
101  {
102  AssertArgument.assertTrue(!revoked, "Request has been revoked");
103  long t0 = System.currentTimeMillis();
104  wait.waitForEvent(timeout, unit);
105  AssertArgument.assertTrue(!revoked, "Request has been revoked");
106  if(LOG.mayLog(LogLevel.TRACE))
107  {
108  LoggingTools.tryLogFormat(LOG, LogLevel.TRACE, "waitResponse ended for %s after %s ms with result: %s", hashCode(), System.currentTimeMillis()-t0, null != responsePayload);
109  }
110  return null != responsePayload;
111  }
112 
113  public byte[] ensureResponse(long timeout, TimeUnit unit) throws InterruptedException
114  {
115  return ensureResponse(timeout, unit, null);
116  }
117 
118  public byte[] ensureResponse(long timeout, TimeUnit unit, String errAppendMsg) throws InterruptedException
119  {
120  if(!waitResponse(timeout, unit))
121  {
122  throw new TransactionException("Device (`"+to+"`) not responded within "+timeout+" "+unit+" for the request"+(null == errAppendMsg?"":": "+errAppendMsg));
123  }
124 
125  return responsePayload;
126  }
127 
128  protected void receiveResponse(byte[] data)
129  {
130  AssertArgument.assertNotNull(data, "data");
131  responsePayload = data;
132  if(LOG.mayLog(LogLevel.TRACE))
133  {
134  LoggingTools.tryLogFormat(LOG, LogLevel.TRACE, "Response received for request: %s", hashCode());
135  }
136  wait.evenOcurred();
137  }
138 
139  public boolean tryAcceptResponse(ParsedUartBusPacket a)
140  {
141  //check response by address
142  if(a.to == this.from && a.from == this.to && a.payload.length + (zeroNamespaceAnswer?1:0) >= path.length)
143  {
144  int diff = 0;
145 
146  if(zeroNamespaceAnswer)
147  {
148  if(0 != a.payload[0])
149  {
150  return false;
151  }
152  diff = 1;
153  }
154 
155  //check response by rpc path
156  for(int i=0;i<path.length;++i)
157  {
158  if(path[i] != a.payload[diff+i])
159  {
160  return false;
161  }
162  }
163 
164  //we got the response.
165  try
166  {
167  receiveResponse(a.payload);
168  }
169  catch(Exception e)
170  {
171  e.printStackTrace();
172  }
173 
174  return true;
175  }
176  return false;
177  }
178 }