Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* File: MessagePublisher.java
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* The contents of this file are subject to the terms and conditions of
* the Common Development and Distribution License 1.0 (the "License").
*
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the License by consulting the LICENSE.txt file
* distributed with this file, or by consulting
* or https://oss.oracle.com/licenses/CDDL
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file LICENSE.txt.
*
* MODIFICATIONS:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*/
package com.oracle.coherence.patterns.messaging;
import com.oracle.coherence.common.identifiers.Identifier;
import com.oracle.coherence.common.ranges.Range;
import com.oracle.coherence.common.ranges.Ranges;
import com.oracle.coherence.common.ticketing.Ticket;
import com.oracle.coherence.common.ticketing.TicketBook;
import com.oracle.coherence.patterns.messaging.Destination.DestinationType;
import com.oracle.coherence.patterns.messaging.entryprocessors.PublishMessageProcessor;
import com.tangosol.net.BackingMapManager;
import com.tangosol.net.BackingMapManagerContext;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.CacheService;
import com.tangosol.net.NamedCache;
import com.tangosol.util.InvocableMap.EntryProcessor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.processor.ExtractorProcessor;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The {@link MessagePublisher} is responsible for generating {@link MessageIdentifier}s and putting a
* message in the message cache. The {@link MessagePublisher} is a JVM only object, it is not
* stored in the cache. It is created on demand the first time it is needed and exists for the life
* of the JVM or until the message partition it services is transferred to another member.
* There is a {@link MessagePublisher} created for each destination/partition pair.
* When the {@link PublishMessageProcessor} .process() method executes, it calls {@link MessagePublisherManager} to
* get the publisher. The {@link MessagePublisherManager} looks up the publisher in a local, static map.
* If the publisher doesn't exist, it is created and put in the map. That publisher exists for the life of the JVM.
*
* In the case of a member failure the entire map will be recreated. If the message partition moves to another member, then
* the Publisher will need to be recreated and rebuilt. A Message backing map listener will generate the events needed
* to rebuild the entry (entry events, and partition events).
*
* To publisher a message, the client must call MessagingSession.publisherMessage(..). Every MessagingSession
* has a unique publisher identifier that is used as a key when invoking the PublishMessageProcesser. This
* forces the processor to execute in the member that owns that key, even though there isn't yet an
* entry in the cache for that key. This class then gets the partitionId assigned to that key and puts
* the message into the partition. The message key used to store the message is a combination of destinationId,
* partitionId and a sequence number.
*
* Copyright (c) 2010. All Rights Reserved. Oracle Corporation.
* Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
*
* @author Brian Oliver
* @author Paul Mackin
*/
@SuppressWarnings("serial")
public class MessagePublisher
{
/**
* Logger
*/
private static Logger logger = Logger.getLogger(MessagePublisher.class.getName());
/**
* The identifier of the partition serviced by this {@link MessagePublisher}.
*/
private int partitionId = 0;
/**
* Type of destination.
*/
private Destination.DestinationType destinationType = null;
/**
* Destination {@link Identifier} used as a cache key.
*/
private Identifier destinationIdentifier = null;
/**
* {@link TicketBook} used to generate monotonically increasing message sequence numbers.
*/
private TicketBook messageSequenceNumberTicketBook = new TicketBook(partitionId);
/**
* Minimum message sequence number for all messages that arriving as a result
* of a partition transfer to this member for the partition/destination managed
* by this {@link MessagePublisher}.
*/
private long minArrivingSeqNum;
/**
* Maximum message sequence number for all messages that arriving as a result
* of a partition transfer to this member for the partition/destination managed
* by this {@link MessagePublisher}.
*/
private long maxArrivingSeqNum;
/**
* Minimum message sequence number for all messages that arriving that need additional
* processing by an event processor.
*/
private long minDeliverySeqNum;
/**
* Maximum message sequence number for all messages that arriving that need additional
* processing by an event processor.
*/
private long maxDeliverySeqNum;
/**
* A map of the highest request sequence number for each publisher indexed by the publisher id. This
* is used to prevent putting a message in the cache in the case of an entry processor failure.
*/
private HashMap requestIdentifierMap = new HashMap();
/**
* Constructor. Initialize variables and create a new {@link TicketBook}
*
* @param destinationIdentifier destination identifier
* @param partitionId partition identifier
*/
MessagePublisher(Identifier destinationIdentifier,
int partitionId)
{
this.destinationIdentifier = destinationIdentifier;
this.partitionId = partitionId;
initDestinationType();
reset();
}
/**
* Publish the message by creating a {@link Message} object and putting it directly into
* the backing map. See {@link PublishMessageProcessor} for further explanation.
*
* Note: This method must be synchronized since multiple publishers may be writing to the
* same partition. It is imperative that the backing map event is called is the message sequence
* number order. This ensures that {@link MessageCacheInterceptor} exposes the
* messages in monotonically increasing order.
*
* @param requestId request identifier
* @param payload message payload
*/
@SuppressWarnings("unchecked")
public synchronized void publishMessage(PublishRequestIdentifier requestId,
Object payload)
{
// Note: if the destination is a topic with no subscriptions then the
// message is deleted in the event processor. This allows the message to
// be put into the cache.
// without getting the topic from the destination cache.
Message message = new Message(this.destinationIdentifier, requestId, generateMessageId(), payload);
// Get the backing map manager context.
NamedCache cache = CacheFactory.getCache(Message.CACHENAME);
CacheService service = cache.getCacheService();
BackingMapManager manager = service.getBackingMapManager();
BackingMapManagerContext context = manager.getContext();
// Put the message into the cache via the backing map. This will
// generate an event where we will inform all the subscribers that the
// message has arrived.
Map