MultiWorkingSetIPC.h
// MultiWorkingSetIPC.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2015
@import "cxWorkingSetIpc.h"
@import "WsipcSessionProtocolId.h"
@import "WorkingSetIPC.h"
@if (false)
{
@import "Ceda/cxPersistStore/IPersistStore.h"
@import "Ceda/cxOperation/IWorkingSetMachine.h"
@import "Ceda/cxObject/Object.h"
#include "Ceda/cxMessage/MultiplexedMsg.h"
#include "Ceda/cxMessage/MClientServer.h"
#include "Ceda/cxMessage/Socket.h"
#include "Ceda/cxUtils/Guid.h"
/*
A MwsipcSession allows for synchronisation using DeltaRW/ROD messages of any number of working
sets using a single stream oriented connection.
The set of working sets which can be synchronised over the connection is dynamic - i.e. it
can change over the life of the session (this rules out directly using the multiplexing
capabilities of the MultiplexedMsgConnection to multiplex messages across different working sets).
*/
namespace ceda
{
$class MultiplexedMsgConnection;
// Uniquely identifies a working set
$typedef+ Guid TWorkingSetId;
// MwsipcSession has a ptr<IMwsipcSessionHandler> in order to make callbacks into the caller
$interface+ IMwsipcSessionHandler : IObject
{
/*
Called when AddWorkingSet() has been called on the peer and a message has been received
locally indicating that the peer wants to synchronise the working set with the given wsid.
Called without any locks on any CSpaces.
Return nullptr to reject synchronisation (in which case currently the connection is
aborted), otherwise return a WorkingSetMachine to be added as a working set to be synchronised.
Note that the MwsipcSession does not take on responsibility for closing the returned
WorkingSetMachine. For every WorkingSetMachine that is returned by this function, there will
eventually be a call to ReleaseWorkingSetMachine to indicate when it is safe to close the
WorkingSetMachine. Note that it is sufficient to close the working set machines after the
MultiplexedMsgConnection has been closed.
*/
WorkingSetMachine* OnReceiveUnmatchedWorkingSetId(const TWorkingSetId& wsid);
/*
Called when the MwsipcSession is no longer referencing the given WorkingSetMachine making
it safe for it to be closed.
Called without any locks on any CSpaces. This makes it safe to close the WorkingSetMachine
from within the implementation of this function.
*/
void ReleaseWorkingSetMachine(WorkingSetMachine* wsm);
};
$adt+ MwsipcSession
{
/*
Working sets can be added/removed dynamically over the life of the session.
These functions can be called with or without locks on the CSpace of the working set.
There functions have an asynchronous nature. They do not need to be paired.
There is a tendency for the last call to dominate previous calls. E.g. calling AddWorkingSet
then RemoveWorkingSet for a given working set probably means it ends up being removed, however
exactly what happens depends on the peer (which can also have called AddWorkingSet).
These functions must not be called after the associated MultiplexedMsgConnection has been
closed.
*/
/*
Subject to various assumptions a call to AddWorkingSet() eventually causes a working set to be
synchronised with the peer. The peer doesn't need to also call AddWorkingSet(). If it does
that is fine, alternatively it can work passively and add a WorkingSetMachine when requested
in its implementation of OnReceiveUnmatchedWorkingSetId().
An attempt to add a working set that is already being synchronised is not an error, the attempt
to do so is simply ignored.
Note that the MwsipcSession does not take on responsibility for closing the given
WorkingSetMachine. The given WorkingSetMachine must not be closed until after the
MultiplexedMsgConnection is closed.
*/
void AddWorkingSet(const TWorkingSetId& wsid, WorkingSetMachine* wsm);
/*
Subject to various assumptions a call to RemoveWorkingSet() eventually stops the sending of
messages both locally and remotely to synchronise a working set, but this can take some time to
eventuate.
It is not necessary for the peer to also call RemoveWorkingSet() - syncing of a working set is
stopped when either or both sides call RemoveWorkingSet().
It must not be assumed that the WorkingSetMachine can be closed after calling this function.
Currently the only safe thing to do is to close all the WorkingSetMachines after the
MultiplexedMsgConnection is closed.
RemoveWorkingSet() can be called safely on a working set that was never added and it can safely
be called more than once on a given working set. The implementation simply ignores redundant
calls to RemoveWorkingSet().
It is not necessary to remove all working sets before the MultiplexedMsgConnection is closed.
*/
void RemoveWorkingSet(const TWorkingSetId& wsid);
};
/*
Performs the following:
* Creates an implementation of IMessageWriter that sends working set deltas and ROD objects,
and calls AddWriter() on the given MultiplexedMsgConnection.
* Creates an implementation of IMessageReader that receives and applies working set
deltas and ROD objects, and calls AddReader() on the given MultiplexedMsgConnection.
* Ensures that calls to NotifyMoreMessagesToWrite() will be made as required on the
given MultiplexedMsgConnection when there are changes to a working set that are
ready to be sent as a working set delta.
The created MwsipcSession is concerned with supporting interactive collaboration, by sending and
receiving working set deltas on each WorkingSetMachine. The protocol begins with an exchange of
datasetids, siteids and vector times for each WorkingSetMachine.
It is expected that the peer will call the same function in order to set up their side of
the connection.
Assumes the given MultiplexedMsgConnection has been created but OpenConnection() hasn't been
called yet. After calling OpenConnection() the client will need to make a single call to
NotifyMoreMessagesToWrite() in order to kick-start the message sending.
The given MultiplexedMsgConnection takes ownership of the returned MwsipcSession - i.e. the
MwsipcSession is automatically deleted when the MultiplexedMsgConnection is closed.
WorkingSetMachines are pushed to the MwsipcSession by calling AddWorkingSet() and pulled by the
MwsipcSession when it calls OnReceiveUnmatchedWorkingSetId() on the handler. In either case
it is very important not to close a WorkingSetMachine until after the MultiplexedMsgConnection
has been closed.
*/
$function+ MwsipcSession* CreateMwsipcSession(
ptr<IMwsipcSessionHandler> handler, // Can be null
MultiplexedMsgConnection* c,
const WsipcSessionProtocolId& protocolId);
@api MultiplexedMsgConnection* CreateSimpleWorkingSetConnection(
Iocp* iocp,
WorkingSetMachine* wsm,
SocketHandle socket,
const WsipcSessionProtocolId& protocolId,
const MessageReaderSettings& readerSettings,
const MessageWriterSettings& writerSettings);
// Create a server that listens on the given port
// Returns NULL if server could not be created. A more specific windows error can be obtained
// with a call to GetLastError().
$function+ MServer* CreateSimpleWsipcServer(
Iocp* iocp,
WorkingSetMachine* wsm,
const WsipcSessionProtocolId& protocolId,
SOCKET_PORT port,
const TcpSettings& tcpSettings = TcpSettings());
// Create a client that tries to connect to the given host that is listening on the given port
// todo : discuss error conditions
$function+ MClient* CreateSimpleWsipcClient(
Iocp* iocp,
WorkingSetMachine* wsm,
const WsipcSessionProtocolId& protocolId,
ConstStringZ hostname, SOCKET_PORT port,
const TcpSettings& tcpSettings = TcpSettings());
} // namespace ceda
} // false