/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ /** * */ package org.apache.geode.internal.cache.tier.sockets.command; import org.apache.geode.internal.Version; import org.apache.geode.internal.cache.LocalRegion; import org.apache.geode.internal.cache.tier.CachedRegionHelper; import org.apache.geode.internal.cache.tier.Command; import org.apache.geode.internal.cache.tier.InterestType; import org.apache.geode.internal.cache.tier.MessageType; import org.apache.geode.internal.cache.tier.sockets.*; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import org.apache.geode.internal.security.AuthorizeRequest; import org.apache.geode.cache.DynamicRegionFactory; import org.apache.geode.cache.InterestResultPolicy; import org.apache.geode.cache.operations.RegisterInterestOperationContext; import org.apache.geode.i18n.StringId; import java.io.IOException; import java.util.List; /** * * All keys of the register interest list are being sent as a single part since 6.6. There is no * need to send no keys as a separate part.In earlier versions {@link RegisterInterestList61} number * of keys & each individual key was sent as a separate part. * * * @since GemFire 6.6 */ public class RegisterInterestList66 extends BaseCommand { private final static RegisterInterestList66 singleton = new RegisterInterestList66(); public static Command getCommand() { return singleton; } RegisterInterestList66() {} @Override public void cmdExecute(Message msg, ServerConnection servConn, long start) throws IOException, InterruptedException { Part regionNamePart = null, keyPart = null;// numberOfKeysPart = null; String regionName = null; Object key = null; InterestResultPolicy policy; List keys = null; CachedRegionHelper crHelper = servConn.getCachedRegionHelper(); int numberOfKeys = 0, partNumber = 0; servConn.setAsTrue(REQUIRES_RESPONSE); servConn.setAsTrue(REQUIRES_CHUNKED_RESPONSE); ChunkedMessage chunkedResponseMsg = servConn.getRegisterInterestResponseMessage(); // bserverStats.incLong(readDestroyRequestTimeId, // DistributionStats.getStatTime() - start); // bserverStats.incInt(destroyRequestsId, 1); // start = DistributionStats.getStatTime(); // Retrieve the data from the message parts regionNamePart = msg.getPart(0); regionName = regionNamePart.getString(); // Retrieve the InterestResultPolicy try { policy = (InterestResultPolicy) msg.getPart(1).getObject(); } catch (Exception e) { writeChunkedException(msg, e, false, servConn); servConn.setAsTrue(RESPONDED); return; } boolean isDurable = false; try { Part durablePart = msg.getPart(2); byte[] durablePartBytes = (byte[]) durablePart.getObject(); isDurable = durablePartBytes[0] == 0x01; } catch (Exception e) { writeChunkedException(msg, e, false, servConn); servConn.setAsTrue(RESPONDED); return; } // region data policy byte[] regionDataPolicyPartBytes; boolean serializeValues = false; try { Part regionDataPolicyPart = msg.getPart(msg.getNumberOfParts() - 1); regionDataPolicyPartBytes = (byte[]) regionDataPolicyPart.getObject(); if (servConn.getClientVersion().compareTo(Version.GFE_80) >= 0) { // The second byte here is serializeValues serializeValues = regionDataPolicyPartBytes[1] == (byte) 0x01; } } catch (Exception e) { writeChunkedException(msg, e, false, servConn); servConn.setAsTrue(RESPONDED); return; } partNumber = 3; Part list = msg.getPart(partNumber); try { keys = (List) list.getObject(); numberOfKeys = keys.size(); } catch (Exception e) { writeChunkedException(msg, e, false, servConn); servConn.setAsTrue(RESPONDED); return; } boolean sendUpdatesAsInvalidates = false; try { Part notifyPart = msg.getPart(partNumber + 1); byte[] notifyPartBytes = (byte[]) notifyPart.getObject(); sendUpdatesAsInvalidates = notifyPartBytes[0] == 0x01; } catch (Exception e) { writeChunkedException(msg, e, false, servConn); servConn.setAsTrue(RESPONDED); return; } if (logger.isDebugEnabled()) { logger.debug( "{}: Received register interest 66 request ({} bytes) from {} for the following {} keys in region {}: {}", servConn.getName(), msg.getPayloadLength(), servConn.getSocketString(), numberOfKeys, regionName, keys); } /* * AcceptorImpl acceptor = servConn.getAcceptor(); * * // Check if the Server is running in NotifyBySubscription=true mode. if * (!acceptor.getCacheClientNotifier().getNotifyBySubscription()) { // This should have been * taken care at the client. String err = LocalizedStrings. * RegisterInterest_INTEREST_REGISTRATION_IS_SUPPORTED_ONLY_FOR_SERVERS_WITH_NOTIFYBYSUBSCRIPTION_SET_TO_TRUE * .toLocalizedString(); writeChunkedErrorResponse(msg, * MessageType.REGISTER_INTEREST_DATA_ERROR, err, servConn); servConn.setAsTrue(RESPONDED); * return; } */ // Process the register interest request if (keys.isEmpty() || regionName == null) { StringId errMessage = null; if (keys.isEmpty() && regionName == null) { errMessage = LocalizedStrings.RegisterInterestList_THE_INPUT_LIST_OF_KEYS_IS_EMPTY_AND_THE_INPUT_REGION_NAME_IS_NULL_FOR_THE_REGISTER_INTEREST_REQUEST; } else if (keys.isEmpty()) { errMessage = LocalizedStrings.RegisterInterestList_THE_INPUT_LIST_OF_KEYS_FOR_THE_REGISTER_INTEREST_REQUEST_IS_EMPTY; } else if (regionName == null) { errMessage = LocalizedStrings.RegisterInterest_THE_INPUT_REGION_NAME_FOR_THE_REGISTER_INTEREST_REQUEST_IS_NULL; } String s = errMessage.toLocalizedString(); logger.warn("{}: {}", servConn.getName(), s); writeChunkedErrorResponse(msg, MessageType.REGISTER_INTEREST_DATA_ERROR, s, servConn); servConn.setAsTrue(RESPONDED); } // key not null LocalRegion region = (LocalRegion) servConn.getCache().getRegion(regionName); if (region == null) { logger.info(LocalizedMessage.create( LocalizedStrings.RegisterInterestList_0_REGION_NAMED_1_WAS_NOT_FOUND_DURING_REGISTER_INTEREST_LIST_REQUEST, new Object[] {servConn.getName(), regionName})); // writeChunkedErrorResponse(msg, // MessageType.REGISTER_INTEREST_DATA_ERROR, message); // responded = true; } // else { // region not null try { this.securityService.authorizeRegionRead(regionName); AuthorizeRequest authzRequest = servConn.getAuthzRequest(); if (authzRequest != null) { if (!DynamicRegionFactory.regionIsDynamicRegionList(regionName)) { RegisterInterestOperationContext registerContext = authzRequest.registerInterestListAuthorize(regionName, keys, policy); keys = (List) registerContext.getKey(); } } // Register interest servConn.getAcceptor().getCacheClientNotifier().registerClientInterest(regionName, keys, servConn.getProxyID(), isDurable, sendUpdatesAsInvalidates, true, regionDataPolicyPartBytes[0], true); } catch (Exception ex) { // If an interrupted exception is thrown , rethrow it checkForInterrupt(servConn, ex); // Otherwise, write an exception message and continue writeChunkedException(msg, ex, false, servConn); servConn.setAsTrue(RESPONDED); return; } // Update the statistics and write the reply // bserverStats.incLong(processDestroyTimeId, // DistributionStats.getStatTime() - start); // start = DistributionStats.getStatTime(); boolean isPrimary = servConn.getAcceptor().getCacheClientNotifier() .getClientProxy(servConn.getProxyID()).isPrimary(); if (!isPrimary) { chunkedResponseMsg.setMessageType(MessageType.RESPONSE_FROM_SECONDARY); chunkedResponseMsg.setTransactionId(msg.getTransactionId()); chunkedResponseMsg.sendHeader(); chunkedResponseMsg.setLastChunk(true); if (logger.isDebugEnabled()) { logger.debug( "{}: Sending register interest response chunk from secondary for region: {} for key: {} chunk=<{}>", servConn.getName(), regionName, key, chunkedResponseMsg); } chunkedResponseMsg.sendChunk(servConn); } else { // isPrimary // Send header which describes how many chunks will follow chunkedResponseMsg.setMessageType(MessageType.RESPONSE_FROM_PRIMARY); chunkedResponseMsg.setTransactionId(msg.getTransactionId()); chunkedResponseMsg.sendHeader(); // Send chunk response try { fillAndSendRegisterInterestResponseChunks(region, keys, InterestType.KEY, serializeValues, policy, servConn); servConn.setAsTrue(RESPONDED); } catch (Exception e) { // If an interrupted exception is thrown , rethrow it checkForInterrupt(servConn, e); // otherwise send the exception back to client writeChunkedException(msg, e, false, servConn); servConn.setAsTrue(RESPONDED); return; } if (logger.isDebugEnabled()) { // logger.debug(getName() + ": Sent chunk (1 of 1) of register interest // response (" + chunkedResponseMsg.getBufferLength() + " bytes) for // region " + regionName + " key " + key); logger.debug( "{}: Sent register interest response for the following {} keys in region {}: {}", servConn.getName(), numberOfKeys, regionName, keys); } // bserverStats.incLong(writeDestroyResponseTimeId, // DistributionStats.getStatTime() - start); // bserverStats.incInt(destroyResponsesId, 1); } // isPrimary // } // region not null } }