PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/gemfire-core/src/main/java/com/gemstone/gemfire/cache/client/internal/DestroyOp.java

https://gitlab.com/kidaa/incubator-geode
Java | 282 lines | 210 code | 25 blank | 47 comment | 45 complexity | 79696530b5060d20085ce4a041fb076a MD5 | raw file
  1. /*=========================================================================
  2. * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
  3. * This product is protected by U.S. and international copyright
  4. * and intellectual property laws. Pivotal products are covered by
  5. * more patents listed at http://www.pivotal.io/patents.
  6. *=========================================================================
  7. */
  8. package com.gemstone.gemfire.cache.client.internal;
  9. import org.apache.logging.log4j.Logger;
  10. import com.gemstone.gemfire.cache.CacheClosedException;
  11. import com.gemstone.gemfire.cache.EntryNotFoundException;
  12. import com.gemstone.gemfire.cache.Operation;
  13. import com.gemstone.gemfire.cache.client.AllConnectionsInUseException;
  14. import com.gemstone.gemfire.cache.client.ServerConnectivityException;
  15. import com.gemstone.gemfire.cache.client.ServerOperationException;
  16. import com.gemstone.gemfire.cache.util.BridgeWriterException;
  17. import com.gemstone.gemfire.distributed.internal.ServerLocation;
  18. import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
  19. import com.gemstone.gemfire.internal.cache.EntryEventImpl;
  20. import com.gemstone.gemfire.internal.cache.LocalRegion;
  21. import com.gemstone.gemfire.internal.cache.tier.MessageType;
  22. import com.gemstone.gemfire.internal.cache.tier.sockets.Message;
  23. import com.gemstone.gemfire.internal.cache.tier.sockets.Part;
  24. import com.gemstone.gemfire.internal.cache.versions.VersionTag;
  25. import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
  26. import com.gemstone.gemfire.internal.logging.LogService;
  27. /**
  28. * Does a region destroy on a server
  29. * @author darrel
  30. * @since 5.7
  31. */
  32. public class DestroyOp {
  33. private static final Logger logger = LogService.getLogger();
  34. public static final int HAS_VERSION_TAG = 0x01;
  35. public static final int HAS_ENTRY_NOT_FOUND_PART = 0x02;
  36. /**
  37. * Does a region entry destroy on a server using connections from the given pool
  38. * to communicate with the server.
  39. * @param pool the pool to use to communicate with the server.
  40. * @param region the region to do the entry destroy on
  41. * @param key the entry key to do the destroy on
  42. * @param event the event for this destroy operation
  43. * @param callbackArg an optional callback arg to pass to any cache callbacks
  44. */
  45. public static Object execute(ExecutablePool pool, LocalRegion region,
  46. Object key,
  47. Object expectedOldValue, Operation operation,
  48. EntryEventImpl event, Object callbackArg,
  49. boolean prSingleHopEnabled) {
  50. if (logger.isDebugEnabled()) {
  51. logger.debug("Preparing DestroyOp for {} operation={}", key, operation);
  52. }
  53. AbstractOp op = new DestroyOpImpl(region, key, expectedOldValue,
  54. operation, event, callbackArg, prSingleHopEnabled);
  55. if (prSingleHopEnabled) {
  56. ClientMetadataService cms = region.getCache()
  57. .getClientMetadataService();
  58. ServerLocation server = cms.getBucketServerLocation(region,
  59. Operation.DESTROY, key, null, callbackArg);
  60. if (server != null) {
  61. try {
  62. PoolImpl poolImpl = (PoolImpl)pool;
  63. boolean onlyUseExistingCnx = ((poolImpl.getMaxConnections() != -1 && poolImpl
  64. .getConnectionCount() >= poolImpl.getMaxConnections()) ? true
  65. : false);
  66. return pool.executeOn(server, op, true, onlyUseExistingCnx);
  67. }
  68. catch (AllConnectionsInUseException e) {
  69. }
  70. catch (ServerConnectivityException e) {
  71. if (e instanceof ServerOperationException) {
  72. throw e; // fixed 44656
  73. }
  74. cms.removeBucketServerLocation(server);
  75. }
  76. catch (BridgeWriterException e) {
  77. if (e.getCause() instanceof ServerConnectivityException)
  78. cms.removeBucketServerLocation(server);
  79. }
  80. }
  81. }
  82. return pool.execute(op);
  83. }
  84. /**
  85. * Does a region entry destroy on a server using the given connection to
  86. * communicate with the server.
  87. *
  88. * @param con
  89. * the connection to use to send to the server
  90. * @param pool
  91. * the pool to use to communicate with the server.
  92. * @param region
  93. * the region to do the entry destroy on
  94. * @param key
  95. * the entry key to do the destroy on
  96. * @param event
  97. * the event for this destroy operation
  98. * @param callbackArg
  99. * an optional callback arg to pass to any cache callbacks
  100. */
  101. public static void execute(Connection con,
  102. ExecutablePool pool,
  103. String region,
  104. Object key,
  105. Object expectedOldValue,
  106. Operation operation,
  107. EntryEventImpl event,
  108. Object callbackArg)
  109. {
  110. AbstractOp op = new DestroyOpImpl(region, key, expectedOldValue,
  111. operation, event, callbackArg);
  112. pool.executeOn(con, op);
  113. }
  114. /** this is set if a response is received indicating that the entry was not found on the server */
  115. public static boolean TEST_HOOK_ENTRY_NOT_FOUND;
  116. private DestroyOp() {
  117. // no instances allowed
  118. }
  119. private static class DestroyOpImpl extends AbstractOp {
  120. Object key = null;
  121. private LocalRegion region;
  122. private Operation operation;
  123. private boolean prSingleHopEnabled = false;
  124. private Object callbackArg;
  125. private EntryEventImpl event;
  126. /**
  127. * @throws com.gemstone.gemfire.SerializationException if serialization fails
  128. */
  129. public DestroyOpImpl(LocalRegion region,
  130. Object key,
  131. Object expectedOldValue,
  132. Operation operation,
  133. EntryEventImpl event,
  134. Object callbackArg,
  135. boolean prSingleHopEnabled) {
  136. super(MessageType.DESTROY, callbackArg != null ? 6 : 5);
  137. this.key = key;
  138. this.region = region ;
  139. this.operation = operation;
  140. this.prSingleHopEnabled = prSingleHopEnabled;
  141. this.callbackArg = callbackArg ;
  142. this.event = event;
  143. getMessage().addStringPart(region.getFullPath());
  144. getMessage().addStringOrObjPart(key);
  145. getMessage().addObjPart(expectedOldValue);
  146. getMessage().addObjPart(operation==Operation.DESTROY? null : operation); // server interprets null as DESTROY
  147. getMessage().addBytesPart(event.getEventId().calcBytes());
  148. if (callbackArg != null) {
  149. getMessage().addObjPart(callbackArg);
  150. }
  151. }
  152. public DestroyOpImpl(String region, Object key, Object expectedOldValue,
  153. Operation operation, EntryEventImpl event,
  154. Object callbackArg) {
  155. super(MessageType.DESTROY, callbackArg != null ? 6 : 5);
  156. this.key = key;
  157. this.event = event;
  158. getMessage().addStringPart(region);
  159. getMessage().addStringOrObjPart(key);
  160. getMessage().addObjPart(expectedOldValue);
  161. getMessage().addObjPart(operation==Operation.DESTROY? null : operation); // server interprets null as DESTROY
  162. getMessage().addBytesPart(event.getEventId().calcBytes());
  163. if (callbackArg != null) {
  164. getMessage().addObjPart(callbackArg);
  165. }
  166. }
  167. @Override
  168. protected Object processResponse(Message msg) throws Exception {
  169. throw new UnsupportedOperationException();
  170. }
  171. @Override
  172. protected Object processResponse(Message msg, Connection con) throws Exception {
  173. processAck(msg, "destroy");
  174. boolean isReply = (msg.getMessageType() == MessageType.REPLY);
  175. int partIdx = 0;
  176. int flags = 0;
  177. if (isReply) {
  178. flags = msg.getPart(partIdx++).getInt();
  179. if ((flags & HAS_VERSION_TAG) != 0) {
  180. VersionTag tag = (VersionTag)msg.getPart(partIdx++).getObject();
  181. // we use the client's ID since we apparently don't track the server's ID in connections
  182. tag.replaceNullIDs((InternalDistributedMember) con.getEndpoint().getMemberId());
  183. this.event.setVersionTag(tag);
  184. if (logger.isDebugEnabled()) {
  185. logger.debug("received Destroy response with {}", tag);
  186. }
  187. } else if (logger.isDebugEnabled()) {
  188. logger.debug("received Destroy response with no version tag");
  189. }
  190. }
  191. if (prSingleHopEnabled) {
  192. byte version = 0 ;
  193. // if (log.fineEnabled()) {
  194. // log.fine("reading prSingleHop part #" + (partIdx+1));
  195. // }
  196. Part part = msg.getPart(partIdx++);
  197. byte[] bytesReceived = part.getSerializedForm();
  198. if (bytesReceived[0] != ClientMetadataService.INITIAL_VERSION
  199. && bytesReceived.length == ClientMetadataService.SIZE_BYTES_ARRAY_RECEIVED) {
  200. if (this.region != null) {
  201. ClientMetadataService cms = null;
  202. try {
  203. cms = region.getCache().getClientMetadataService();
  204. version = cms.getMetaDataVersion(region, Operation.UPDATE,
  205. key, null, callbackArg);
  206. }
  207. catch (CacheClosedException e) {
  208. return null;
  209. }
  210. if (bytesReceived[0] != version) {
  211. cms.scheduleGetPRMetaData(region, false,bytesReceived[1]);
  212. }
  213. }
  214. }
  215. } else {
  216. partIdx++; // skip OK byte
  217. }
  218. boolean entryNotFound = false;
  219. if (msg.getMessageType() == MessageType.REPLY && (flags & HAS_ENTRY_NOT_FOUND_PART) != 0) {
  220. entryNotFound = (msg.getPart(partIdx++).getInt() == 1);
  221. if (logger.isDebugEnabled() && (flags & HAS_ENTRY_NOT_FOUND_PART) != 0) {
  222. logger.debug("destroy response has entryNotFound={}", entryNotFound);
  223. }
  224. if (entryNotFound) {
  225. TEST_HOOK_ENTRY_NOT_FOUND = true;
  226. }
  227. }
  228. if (this.operation == Operation.REMOVE && entryNotFound) {
  229. if (logger.isDebugEnabled()) {
  230. logger.debug("received REMOVE response from server with entryNotFound={}", entryNotFound);
  231. }
  232. return new EntryNotFoundException(LocalizedStrings.AbstractRegionMap_ENTRY_NOT_FOUND_WITH_EXPECTED_VALUE.toLocalizedString());
  233. }
  234. return null;
  235. }
  236. @Override
  237. protected boolean isErrorResponse(int msgType) {
  238. return msgType == MessageType.DESTROY_DATA_ERROR;
  239. }
  240. @Override
  241. protected long startAttempt(ConnectionStats stats) {
  242. return stats.startDestroy();
  243. }
  244. @Override
  245. protected void endSendAttempt(ConnectionStats stats, long start) {
  246. stats.endDestroySend(start, hasFailed());
  247. }
  248. @Override
  249. protected void endAttempt(ConnectionStats stats, long start) {
  250. stats.endDestroy(start, hasTimedOut(), hasFailed());
  251. }
  252. @Override
  253. public String toString() {
  254. return "DestroyOp:"+key;
  255. }
  256. }
  257. }