/* * 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.cache.asyncqueue.internal; import org.apache.geode.internal.cache.wan.AsyncEventQueueConfigurationException; import org.apache.logging.log4j.Logger; import org.apache.geode.cache.Cache; import org.apache.geode.cache.asyncqueue.AsyncEventListener; import org.apache.geode.cache.asyncqueue.AsyncEventQueue; import org.apache.geode.cache.asyncqueue.AsyncEventQueueFactory; import org.apache.geode.cache.wan.GatewayEventFilter; import org.apache.geode.cache.wan.GatewayEventSubstitutionFilter; import org.apache.geode.cache.wan.GatewaySender; import org.apache.geode.cache.wan.GatewaySender.OrderPolicy; import org.apache.geode.cache.wan.GatewaySenderFactory; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.wan.GatewaySenderAttributes; import org.apache.geode.internal.cache.xmlcache.AsyncEventQueueCreation; import org.apache.geode.internal.cache.xmlcache.CacheCreation; import org.apache.geode.internal.cache.xmlcache.ParallelAsyncEventQueueCreation; import org.apache.geode.internal.cache.xmlcache.ParallelGatewaySenderCreation; import org.apache.geode.internal.cache.xmlcache.SerialAsyncEventQueueCreation; import org.apache.geode.internal.cache.xmlcache.SerialGatewaySenderCreation; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; public class AsyncEventQueueFactoryImpl implements AsyncEventQueueFactory { private static final Logger logger = LogService.getLogger(); /** * Used internally to pass the attributes from this factory to the real GatewaySender it is * creating. */ private GatewaySenderAttributes attrs = new GatewaySenderAttributes(); private Cache cache; /** * The default batchTimeInterval for AsyncEventQueue in milliseconds. */ public static final int DEFAULT_BATCH_TIME_INTERVAL = 5; public AsyncEventQueueFactoryImpl(Cache cache) { this.cache = cache; this.attrs = new GatewaySenderAttributes(); // set a different default for batchTimeInterval for AsyncEventQueue this.attrs.batchTimeInterval = DEFAULT_BATCH_TIME_INTERVAL; } @Override public AsyncEventQueueFactory setBatchSize(int size) { this.attrs.batchSize = size; return this; } public AsyncEventQueueFactory setPersistent(boolean isPersistent) { this.attrs.isPersistenceEnabled = isPersistent; return this; } @Override public AsyncEventQueueFactory setDiskStoreName(String name) { this.attrs.diskStoreName = name; return this; } @Override public AsyncEventQueueFactory setMaximumQueueMemory(int memory) { this.attrs.maximumQueueMemory = memory; return this; } @Override public AsyncEventQueueFactory setDiskSynchronous(boolean isSynchronous) { this.attrs.isDiskSynchronous = isSynchronous; return this; } @Override public AsyncEventQueueFactory setBatchTimeInterval(int batchTimeInterval) { this.attrs.batchTimeInterval = batchTimeInterval; return this; } @Override public AsyncEventQueueFactory setBatchConflationEnabled(boolean isConflation) { this.attrs.isBatchConflationEnabled = isConflation; return this; } @Override public AsyncEventQueueFactory setDispatcherThreads(int numThreads) { this.attrs.dispatcherThreads = numThreads; return this; } @Override public AsyncEventQueueFactory setOrderPolicy(OrderPolicy policy) { this.attrs.policy = policy; return this; } @Override public AsyncEventQueueFactory addGatewayEventFilter(GatewayEventFilter filter) { this.attrs.addGatewayEventFilter(filter); return this; } @Override public AsyncEventQueueFactory removeGatewayEventFilter(GatewayEventFilter filter) { this.attrs.eventFilters.remove(filter); return this; } @Override public AsyncEventQueueFactory setGatewayEventSubstitutionListener( GatewayEventSubstitutionFilter filter) { this.attrs.eventSubstitutionFilter = filter; return this; } public AsyncEventQueueFactory removeGatewayEventAlternateValueProvider( GatewayEventSubstitutionFilter provider) { return this; } public AsyncEventQueueFactory addAsyncEventListener(AsyncEventListener listener) { this.attrs.addAsyncEventListener(listener); return this; } public AsyncEventQueue create(String asyncQueueId, AsyncEventListener listener) { if (listener == null) { throw new IllegalArgumentException( LocalizedStrings.AsyncEventQueue_ASYNC_EVENT_LISTENER_CANNOT_BE_NULL.toLocalizedString()); } AsyncEventQueue asyncEventQueue = null; if (this.cache instanceof GemFireCacheImpl) { if (logger.isDebugEnabled()) { logger.debug("Creating GatewaySender that underlies the AsyncEventQueue"); } // TODO: Suranjan .separate asynceventqueue from gatewaysender // GatewaySenderFactory senderFactory = this.cache.createGatewaySenderFactory(); // senderFactory.setMaximumQueueMemory(attrs.getMaximumQueueMemory()); // senderFactory.setBatchSize(attrs.getBatchSize()); // senderFactory.setBatchTimeInterval(attrs.getBatchTimeInterval()); // if (attrs.isPersistenceEnabled()) { // senderFactory.setPersistenceEnabled(true); // } // senderFactory.setDiskStoreName(attrs.getDiskStoreName()); // senderFactory.setDiskSynchronous(attrs.isDiskSynchronous()); // senderFactory.setBatchConflationEnabled(attrs.isBatchConflationEnabled()); // senderFactory.setParallel(attrs.isParallel()); // senderFactory.setDispatcherThreads(attrs.getDispatcherThreads()); // if OrderPolicy is not null, set it, otherwise, let the default OrderPolicy take the charge // if (attrs.getOrderPolicy() != null) { // senderFactory.setOrderPolicy(attrs.getOrderPolicy()); // } // for (GatewayEventFilter filter : attrs.eventFilters) { // senderFactory.addGatewayEventFilter(filter); // } // senderFactory.setGatewayEventSubstitutionFilter(attrs.getGatewayEventSubstitutionFilter()); // Type cast to GatewaySenderFactory implementation impl to add the async event listener // and set the isForInternalUse to true. These methods are not exposed on GatewaySenderFactory // GatewaySenderFactory factoryImpl = (GatewaySenderFactoryImpl) senderFactory; // senderFactory.setForInternalUse(true); // senderFactory.addAsyncEventListener(listener); // senderFactory.setBucketSorted(attrs.isBucketSorted()); // add member id to differentiate between this region and the redundant bucket // region created for this queue. // GatewaySender sender = // senderFactory.create( // AsyncEventQueueImpl.getSenderIdFromAsyncEventQueueId(asyncQueueId)); addAsyncEventListener(listener); GatewaySender sender = create(AsyncEventQueueImpl.getSenderIdFromAsyncEventQueueId(asyncQueueId)); AsyncEventQueueImpl queue = new AsyncEventQueueImpl(sender, listener); asyncEventQueue = queue; ((GemFireCacheImpl) cache).addAsyncEventQueue(queue); } else if (this.cache instanceof CacheCreation) { asyncEventQueue = new AsyncEventQueueCreation(asyncQueueId, attrs, listener); ((CacheCreation) cache).addAsyncEventQueue(asyncEventQueue); } if (logger.isDebugEnabled()) { logger.debug("Returning AsyncEventQueue" + asyncEventQueue); } return asyncEventQueue; } private GatewaySender create(String id) { this.attrs.id = id; GatewaySender sender = null; if (this.attrs.getDispatcherThreads() <= 0) { throw new AsyncEventQueueConfigurationException( LocalizedStrings.AsyncEventQueue_0_CANNOT_HAVE_DISPATCHER_THREADS_LESS_THAN_1 .toLocalizedString(id)); } if (this.attrs.isParallel()) { if ((this.attrs.getOrderPolicy() != null) && this.attrs.getOrderPolicy().equals(OrderPolicy.THREAD)) { throw new AsyncEventQueueConfigurationException( LocalizedStrings.AsyncEventQueue_0_CANNOT_BE_CREATED_WITH_ORDER_POLICY_1 .toLocalizedString(id, this.attrs.getOrderPolicy())); } if (this.cache instanceof GemFireCacheImpl) { sender = new ParallelAsyncEventQueueImpl(this.cache, this.attrs); ((GemFireCacheImpl) this.cache).addGatewaySender(sender); if (!this.attrs.isManualStart()) { sender.start(); } } else if (this.cache instanceof CacheCreation) { sender = new ParallelAsyncEventQueueCreation(this.cache, this.attrs); ((CacheCreation) this.cache).addGatewaySender(sender); } } else { // if (this.attrs.getOrderPolicy() != null) { // if (this.attrs.getDispatcherThreads() == GatewaySender.DEFAULT_DISPATCHER_THREADS) { // throw new AsyncEventQueueConfigurationException( // LocalizedStrings.AsyncEventQueue_INVALID_ORDER_POLICY_CONCURRENCY_0 // .toLocalizedString(id)); // } // } if (this.attrs.getOrderPolicy() == null && this.attrs.getDispatcherThreads() > 1) { this.attrs.policy = GatewaySender.DEFAULT_ORDER_POLICY; } if (this.cache instanceof GemFireCacheImpl) { sender = new SerialAsyncEventQueueImpl(this.cache, this.attrs); ((GemFireCacheImpl) this.cache).addGatewaySender(sender); if (!this.attrs.isManualStart()) { sender.start(); } } else if (this.cache instanceof CacheCreation) { sender = new SerialAsyncEventQueueCreation(this.cache, this.attrs); ((CacheCreation) this.cache).addGatewaySender(sender); } } return sender; } public void configureAsyncEventQueue(AsyncEventQueue asyncQueueCreation) { this.attrs.batchSize = asyncQueueCreation.getBatchSize(); this.attrs.batchTimeInterval = asyncQueueCreation.getBatchTimeInterval(); this.attrs.isBatchConflationEnabled = asyncQueueCreation.isBatchConflationEnabled(); this.attrs.isPersistenceEnabled = asyncQueueCreation.isPersistent(); this.attrs.diskStoreName = asyncQueueCreation.getDiskStoreName(); this.attrs.isDiskSynchronous = asyncQueueCreation.isDiskSynchronous(); this.attrs.maximumQueueMemory = asyncQueueCreation.getMaximumQueueMemory(); this.attrs.isParallel = asyncQueueCreation.isParallel(); this.attrs.isBucketSorted = ((AsyncEventQueueCreation) asyncQueueCreation).isBucketSorted(); this.attrs.dispatcherThreads = asyncQueueCreation.getDispatcherThreads(); this.attrs.policy = asyncQueueCreation.getOrderPolicy(); this.attrs.eventFilters = asyncQueueCreation.getGatewayEventFilters(); this.attrs.eventSubstitutionFilter = asyncQueueCreation.getGatewayEventSubstitutionFilter(); this.attrs.isForInternalUse = true; this.attrs.forwardExpirationDestroy = asyncQueueCreation.isForwardExpirationDestroy(); } public AsyncEventQueueFactory setParallel(boolean isParallel) { this.attrs.isParallel = isParallel; return this; } public AsyncEventQueueFactory setBucketSorted(boolean isbucketSorted) { this.attrs.isBucketSorted = isbucketSorted; return this; } public AsyncEventQueueFactory setIsMetaQueue(boolean isMetaQueue) { this.attrs.isMetaQueue = isMetaQueue; return this; } @Override public AsyncEventQueueFactory setForwardExpirationDestroy(boolean forward) { this.attrs.forwardExpirationDestroy = forward; return this; } }