/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*/
package com.sun.sgs.impl.service.channel;
import com.sun.sgs.app.Delivery;
import java.io.IOException;
import java.math.BigInteger;
import java.rmi.Remote;
/**
* A remote interface for communicating channel events and other
* channel-related requests between peer channel services. <p>
*
* Each channel event (join, leave, send, close) is assigned a
* <i>timestamp</i> when the event is added to the channel's event queue.
* An event queue's current timestamp records the timestamp of the latest
* send event that the queue has started to process. The initial event
* timestamp is <code>1</code>. A send event increments the next
* timestamp, so all future join and leave events will have a later
* timestamp. Because only a send event increments the next timestamp,
* join, leave, and send requests may share the same timestamp. If a send
* event at timestamp <code><i>t</i></code> is followed directly by a
* series of join and leave events, the join and leave events will all
* have the later timestamp <code><i>t+1</i></code>. The next send event
* for the channel will also have timestamp <code><i>t+1</i></code>.<p>
*
* If a session becomes a channel member at a given timestamp
* <code><i>t</i></code>, then it should receive all channel messages
* with a timestamp greater than or equal to <code><i>t</i></code>. If a
* session leaves a channel at a given timestamp <code><i>t</i></code>,
* the session should receive channel messages up to timestamp
* <code><i>t-1</i></code>, but should not receive channel messages
* greater than or equal to timestamp <code><i>t</i></code>.<p>
*
* A channel server that receives a channel event notification (for
* delivery to a client session) uses the event's timestamp to determine
* whether the event needs to be delivered to a local session. The
* timestamp is used to determine duplicate events (in the case of
* coordinator recovery), and if a client session relocates, the
* session's current timestamp for a channel can be used to determine
* whether the session missed any channel messages while relocating.
*/
public interface ChannelServer extends Remote {
/** Membership status. */
public enum MembershipStatus {
/** Member. */
MEMBER,
/** Non-member. */
NON_MEMBER,
/** Unknown (because session is non-local). */
UNKNOWN;
};
/**
* Notifies this server that it should service the event queue of
* the channel with the specified {@code channelRefId}.
*
* @param channelRefId a channel ID
* @throws IOException if a communication problem occurs while
* invoking this method
*/
void serviceEventQueue(BigInteger channelRefId) throws IOException;
/**
* If the session with the specified {@code sessionRefId} is connected to
* the local node, returns {@link MembershipStatus#MEMBER} if the session
* is a member of the channel with the specified {@code channelRefId} and
* returns {@link MembershipStatus#NON_MEMBER} if the session is not a
* member of the channel. If the session is not connected to the local
* node, then this method returns {@link MembershipStatus#UNKNOWN}.
*
* @param channelRefId a channel ID
* @param sessionRefId a session ID
* @return the membership status of the session with the
* specified {@code sessionRefId} for the channel with
* the specified {@code channelRefId}
* @throws IOException if a communication problem occurs while
* invoking this method
*/
MembershipStatus isMember(BigInteger channelRefId, BigInteger sessionRefId)
throws IOException;
/**
* Notifies this server that the locally-connected session with
* the specified {@code sessionRefId} has joined the channel with
* the specified {@code name} and {@code channelRefId}.
*
* @param name a channel name
* @param channelRefId a channel ID
* @param deliveryOrdinal the channel's delivery requirement, as a {@link
* Delivery} ordinal
* @param timestamp the timestamp of the last channel message sent
* @param sessionRefId a session ID
* @return {@code true} if the join succeeded (either was delivered or
* enqueued for a relocating session), and {@code false} if
* the session is not locally connected and is not known to be
* relocating
* @throws IOException if a communication problem occurs while
* invoking this method
*/
boolean join(String name, BigInteger channelRefId, byte deliveryOrdinal,
long timestamp, BigInteger sessionRefId)
throws IOException;
/**
* Notifies this server that the locally-connected session with
* the specified {@code sessionRefId} has left the channel with the
* specified {@code channelRefId}.
*
* @param channelRefId a channel ID
* @param timestamp the timestamp of the last channel message sent
* @param sessionRefId a session ID
* @return {@code true} if the leave succeeded (either was delivered or
* enqueued for a relocating session), and {@code false} if
* the session is not locally connected and is not known to be
* relocating
* @throws IOException if a communication problem occurs while
* invoking this method
*/
boolean leave(BigInteger channelRefId, long timestamp,
BigInteger sessionRefId)
throws IOException;
/**
* Returns an array containing the client session ID of each client
* session on this node that is a member of the channel with the
* specified {@code channelRefId}.
*
* @param channelRefId a channel ID
* @return an array of members' session IDs
* @throws IOException if a communication problem occurs while
* invoking this method
*/
BigInteger[] getSessions(BigInteger channelRefId)
throws IOException;
/**
* Sends the specified message to all locally-connected sessions
* that are members of the channel with the specified {@code
* channelRefId}.
*
* @param channelRefId a channel ID
* @param message a channel message
* @param timestamp the message's timestamp
* @throws IOException if a communication problem occurs while
* invoking this method
*/
void send(BigInteger channelRefId, byte[] message, long timestamp)
throws IOException;
/**
* Notifies this server that the client session with the specified
* {@code sessionRefId} is relocating from the node (specified by
* {@code oldNodeId}) to the new node (i.e., the local node) and that
* the session's channel memberships should be updated accordingly.
* The {@code channelRefIds} array contains the channel ID of each
* channel that the client session belongs to. The {@code
* deliveryOrdinals} array contains the delivery ordinal of each
* corresponding channel. The {@code msgTimestamps} array contains the
* timestamp of the latest message received by the specified session
* (at the point that relocation started) for each corresponding
* channel.<p>
*
* This server must update its local channel membership cache for the
* specified session and add persistent membership information to
* indicate that the specified session on the local node is now joined
* to each channel. When the cache and persistent membership
* information is updated, the {@link #relocateChannelMembershipsCompleted
* relocateChannelMembershipsCompleted} method should be invoked on the
* old node's {@code ChannelServer} with the specified {@code
* sessionRefId} and the new node's ID.
*
* @param sessionRefId the ID of a client session relocating to the
* local node
* @param oldNodeId the ID of the node the session is relocating from
* @param channelRefIds an array that contains the channel ID of each
* channel that the client session is a member of
* @param deliveryOrdinals an array that contains the delivery ordinal
* of each channel that the client session is a member of
* @param msgTimestamps an array that contains the message timestamp
* of each channel that the client session is a member of
* @throws IOException if a communication problem occurs while
* invoking this method
*/
void relocateChannelMemberships(BigInteger sessionRefId, long oldNodeId,
BigInteger[] channelRefIds,
byte[] deliveryOrdinals,
long[] msgTimestamps)
throws IOException;
/**
* Notifies this server that the channel server on the node specified
* by {@code newNodeId} has completed updating the channel memberships
* for the client session with the specified {@code sessionRefId} in
* preparation for the session's relocation to the new node. This
* method is invoked when the work associated with a previous
* invocation to {@link #relocateChannelMemberships
* relocateChannelMemberships} on the new node's channel server is
* complete. This channel server should clean up any remaining
* persistent channel membership information for the session on the old
* node (i.e., the local node).
*
* @param sessionRefId the ID of a relocating client session
* @param newNodeId ID of the node the session is relocating to
* @throws IOException if a communication problem occurs while
* invoking this method
*/
void relocateChannelMembershipsCompleted(
BigInteger sessionRefId, long newNodeId)
throws IOException;
/**
* Notifies this server that the channel with the specified {@code
* channelRefId} is closed.
*
* @param channelRefId a channel ID
* @param timestamp the timestamp of the last channel message sent
* @throws IOException if a communication problem occurs while
* invoking this method
*/
void close(BigInteger channelRefId, long timestamp) throws IOException;
}