1 4 package com.tc.net.protocol; 5 6 import com.tc.bytes.TCByteBuffer; 7 import com.tc.exception.TCInternalError; 8 import com.tc.logging.TCLogger; 9 import com.tc.logging.TCLogging; 10 import com.tc.util.Assert; 11 import com.tc.util.StringUtil; 12 import com.tc.util.concurrent.SetOnceFlag; 13 14 19 public class AbstractTCNetworkMessage implements TCNetworkMessage { 20 protected static final TCLogger logger = TCLogging.getLogger(TCNetworkMessage.class); 21 22 protected AbstractTCNetworkMessage(TCNetworkHeader header) { 23 this(header, null, null, false); 24 } 25 26 protected AbstractTCNetworkMessage(TCNetworkHeader header, TCNetworkMessage msgPayload) { 27 this(header, msgPayload, null, true); 28 } 29 30 protected AbstractTCNetworkMessage(TCNetworkHeader header, TCByteBuffer[] payload) { 31 this(header, null, payload, true); 32 } 33 34 private AbstractTCNetworkMessage(TCNetworkHeader header, TCNetworkMessage msgPayload, TCByteBuffer[] payload, 35 boolean seal) { 36 Assert.eval(header != null); 37 38 this.header = header; 39 this.messagePayload = msgPayload; 40 this.payloadData = (payload == null) ? EMPTY_BUFFER_ARRAY : payload; 41 42 if (msgPayload != null) { 43 payloadData = msgPayload.getEntireMessageData(); 44 } 45 46 if (seal) { 47 seal(); 48 } 49 } 50 51 public final int getDataLength() { 52 checkSealed(); 53 return dataLength; 54 } 55 56 public final int getHeaderLength() { 57 checkSealed(); 58 return headerLength; 59 } 60 61 public final int getTotalLength() { 62 checkSealed(); 63 return totalLength; 64 } 65 66 public final TCNetworkHeader getHeader() { 67 checkNotRecycled(); 68 return header; 69 } 70 71 public final TCNetworkMessage getMessagePayload() { 72 checkNotRecycled(); 73 return messagePayload; 74 } 75 76 public final TCByteBuffer[] getPayload() { 77 checkNotRecycled(); 78 return payloadData; 79 } 80 81 protected final void setPayload(TCByteBuffer[] newPayload) { 82 checkNotSealed(); 83 84 entireMessageData = null; 85 86 if (newPayload == null) { 87 payloadData = EMPTY_BUFFER_ARRAY; 88 } else { 89 payloadData = newPayload; 90 } 91 } 92 93 protected final void setMessagePayload(TCNetworkMessage subMessage) { 94 checkNotSealed(); 95 96 entireMessageData = null; 97 98 if (subMessage == null) { 99 payloadData = EMPTY_BUFFER_ARRAY; 100 this.messagePayload = null; 101 } else { 102 if (!subMessage.isSealed()) { throw new IllegalStateException ("Message paylaod is not yet sealed"); } 103 this.messagePayload = subMessage; 104 this.payloadData = subMessage.getEntireMessageData(); 105 } 106 } 107 108 public final TCByteBuffer[] getEntireMessageData() { 109 checkSealed(); 110 111 Assert.eval(entireMessageData != null); 113 114 return entireMessageData; 115 } 116 117 public final String toString() { 118 try { 119 return toString0(); 120 } catch (Exception e) { 121 logger.warn("Exception in toString()", e); 122 return "EXCEPTION in toString(): " + e.getMessage(); 123 } 124 } 125 126 protected final String toString0() { 127 StringBuffer buf = new StringBuffer (); 128 buf.append("Message Class: ").append(getClass().getName()).append("\n"); 129 buf.append("Sealed: ").append(sealed.isSet()).append(", "); 130 buf.append("Header Length: ").append(getHeaderLength()).append(", "); 131 buf.append("Data Length: ").append(getDataLength()).append(", "); 132 buf.append("Total Length: ").append(getTotalLength()).append("\n"); 133 134 String extraMsgInfo = describeMessage(); 135 if (extraMsgInfo != null) { 136 buf.append(extraMsgInfo); 137 } 138 139 if (header != null) { 140 buf.append("Header (").append(header.getClass().getName()).append(")\n"); 141 buf.append(StringUtil.indentLines(header.toString())); 142 if (buf.charAt(buf.length() - 1) != '\n') { 143 buf.append('\n'); 144 } 145 } 146 147 buf.append("Payload:\n"); 148 if (messagePayload != null) { 149 buf.append(StringUtil.indentLines(messagePayload.toString())).append("\n"); 150 } else { 151 if (payloadData != null) { 152 buf.append(StringUtil.indentLines(describePayload())); 153 } else { 154 buf.append(StringUtil.indentLines("*** No payoad data ***\n")); 155 } 156 } 157 158 return buf.toString(); 159 } 160 161 protected String describeMessage() { 163 return null; 164 } 165 166 protected String describePayload() { 168 StringBuffer buf = new StringBuffer (); 169 170 if ((payloadData != null) && (payloadData.length != 0)) { 171 for (int i = 0; i < payloadData.length; i++) { 172 if (payloadData[i] != null) { 173 } 175 176 buf.append("Buffer ").append(i).append(": "); 177 178 if (payloadData[i] != null) { 179 buf.append(payloadData[i].toString()); 180 } else { 181 buf.append("null"); 182 } 183 184 buf.append("\n"); 185 } 186 } else { 187 buf.append("No payload buffers present"); 188 } 189 190 return buf.toString(); 191 } 192 193 protected String dump() { 194 StringBuffer toRet = new StringBuffer (toString()); 195 toRet.append("\n\n"); 196 if(entireMessageData != null) { 197 for (int i = 0; i < entireMessageData.length; i++) { 198 toRet.append('[').append(i).append(']').append('=').append(entireMessageData[i].toString()); 199 toRet.append(" = { "); 200 byte ba[] = entireMessageData[i].array(); 201 for (int j = 0 ; j < ba.length; j++) { 202 toRet.append(Byte.toString(ba[j])).append(' '); 203 } 204 toRet.append(" } \n\n"); 205 } 206 } 207 return toRet.toString(); 208 } 209 210 public final boolean isSealed() { 211 return sealed.isSet(); 212 } 213 214 public final void seal() { 215 if (sealed.attemptSet()) { 216 final int size = 1 + ((payloadData == null) ? 0 : payloadData.length); 217 entireMessageData = new TCByteBuffer[size]; 218 entireMessageData[0] = header.getDataBuffer(); 219 System.arraycopy(payloadData, 0, entireMessageData, 1, payloadData.length); 220 221 long dataLen = 0; 222 for (int i = 1; i < entireMessageData.length; i++) { 223 dataLen += entireMessageData[i].limit(); 224 } 225 226 if (dataLen > Integer.MAX_VALUE) { throw new TCInternalError("Message too big"); } 227 228 this.dataLength = (int) dataLen; 229 this.headerLength = header.getHeaderByteLength(); 230 this.totalLength = this.headerLength + this.dataLength; 231 } else { 232 throw new IllegalStateException ("Message is sealed"); 233 } 234 } 235 236 public final void wasSent() { 237 fireSentCallback(); 238 doRecycleOnWrite(); 239 } 240 241 public void doRecycleOnWrite() { 243 recycle(); 244 } 245 246 public void recycle() { 247 if (entireMessageData != null) { 248 int i = 0; 249 if (entireMessageData.length > 1 && entireMessageData[0].array() == entireMessageData[1].array()) { 250 i++; 254 } 255 for (; i < entireMessageData.length; i++) { 256 entireMessageData[i].recycle(); 257 } 258 entireMessageData = null; 259 } else { 260 logger.warn("Entire Message is null ! Probably recycle was called twice !"); 261 Thread.dumpStack(); 262 } 263 } 264 265 protected boolean isRecycled() { 266 return isSealed() && entireMessageData == null; 267 } 268 269 private void fireSentCallback() { 270 if (sentCallback != null) { 271 if (sentCallbackFired.attemptSet()) { 272 try { 273 sentCallback.run(); 274 } catch (Exception e) { 275 logger.error("Caught exception running sent callback", e); 276 } 277 } 278 } 279 } 280 281 public final void setSentCallback(Runnable callback) { 282 this.sentCallback = callback; 283 } 284 285 public final Runnable getSentCallback() { 286 return this.sentCallback; 287 } 288 289 private void checkNotRecycled() { 290 if (isRecycled()) { throw new IllegalStateException ("Message is already Recycled"); } 291 } 292 293 private void checkSealed() { 294 if (!isSealed()) { throw new IllegalStateException ("Message is not sealed"); } 295 } 296 297 private void checkNotSealed() { 298 if (sealed.isSet()) { throw new IllegalStateException ("Message is sealed"); } 299 } 300 301 private final SetOnceFlag sealed = new SetOnceFlag(); 302 private final SetOnceFlag sentCallbackFired = new SetOnceFlag(); 303 private static final TCByteBuffer[] EMPTY_BUFFER_ARRAY = {}; 304 private final TCNetworkHeader header; 305 private TCByteBuffer[] payloadData; 306 private TCNetworkMessage messagePayload; 307 private TCByteBuffer[] entireMessageData; 308 private int totalLength; 309 private int dataLength; 310 private int headerLength; 311 private Runnable sentCallback = null; 312 313 } | Popular Tags |