views:

197

answers:

3

Scenario

I'm going to be as succinct as possible. Basically with reference to this classdiag, I have a facade which manages a list of SocketManager ( which manages one Socket connection). Each SocketManager logs in to a remote server using a unique SocketUserId. Furthermore, each SocketManager will accept messages from clients destined for a specific list of Receipients. For discussion sake, consider these Receipients as simply as remote data buckets identified by a name.

Clients will send data like this:

SocketFacade facade = ...;

byte[] data = ...

facade.sendData( receipient, data );

When SocketFacade starts, it will query a mysql table which returns the 1-m relationship between SocketUserId and Receipients. I will use a MultiValuedMap to represent this 1-m relationship. Multiple SocketManager will be then be started by iterating through the map.

(1) Map< SocketUserId, List<Receipient> >

e.g. Suppose we have 2 SocketManagers with SocketUserIds "alice" & "tom" respectively

            +----SocketManager1 ( "alice" ) for Receipients { "B", "C" }
            |
 SocketFacade 
            |
            +----SocketManager2 ( "tom" ) for Receipients { "A", "D" }

Question

I am in a bind as to how to implement the sendData method. Basically I need a way to map from a Receipient (e.g. "B") to its responsible SocketManager (e.g. SocketManager1).

Let's suppose I do this

(2) Map< SocketUserId, SocketManager >
(3) Map< Receipient, SocketUserId >
  • Would I need a SoftReference for the value in (2) ?
  • Should I just map from Receipient directly to SocketManager ?
  • SocketFacade also supports methods that will mutate the relationship represented by (1). If I write to the database, the in-memory data structures in (1), (2), & (3) will need to change in sync. SocketFacade must be thread safe as well. Initial idea is to have some sort of a publish subscribe system whereby an add/remove to the DB will cause the changes to propagate via callbacks.

    interface Callback { void receipientAdded( Receipient r ); void receipientDeleted( Receipient r ); }

Any comments much appreciated.

+1  A: 

Keep a reference to the SocketManager in each Receipient. That way, you can avoid the map (which needs more RAM, is slower and doesn't add any value).

In the SocketManager, keep a list of Receipient's. As you add and remove the Receipient's, update the pointer to the SocketManager.

In the SocketFacade, you need a map which takes the SocketUserId and returns a SocketManager. That map is filled by querying for the IDs in the map. After all managers exist, add the recipients to each. That takes two SQL queries.

This is very easy to map with any ORM tool.

Aaron Digulla
In my opinion it isn't very nice to put the SocketManager into the recipient. The Recipient would then expose the SocketManager to the SocketFacade's client/caller. The question behind this is "Does the Recipient need to know which SocketManager is responsible for him.". As how I understand this scenario, this isn't desired and should be hidden behind the facade. It's just a matter of the facade's setup. Am I getting this right so far?
rudolfson
ashitaka
@rudolfson: Ah, then I misunderstood. I thought this is like "send a message to all recipients of a SocketManager". Hm. Back to the drawing board.
Aaron Digulla
+1  A: 

Since you have a 1-1 relationship between SocketUserId and SocketManager, can't you just add a reference to the SocketUserId in the SocketMananger, and a reference to the SocketManager in the Recipient ?

Then you would have in your facade one Map containing the recipient, and the List of SocketManager. In the sendData function you would get the recipient From the map, and obtain from this recipient the reference to its SocketManager.

regards

Guillaume

PATRY
I was apprehensive about sticking the SocketManager into a map at first because underneath it runs 2 threads and a Socket channel. I'm planning to hold a List<SocketManager> so that is is convenient for me to iterate and call shutdown. What do you think ? Yes SocketManager will have a ref to a SocketUserId( 1-1 ). Since one Recipient is related to only one SocketManager, why would I need a List of SocketManager ? From your idea, I'll just have Map< ReceipientKey, Recipient>. Do I understand you correctly ?
ashitaka
@ashitaka: Huh? From your example, SocketManager to Recipient is 1:N!
Aaron Digulla
@AaronDigulla I made a mistake. I meant to say that "Since one SocketUserId is related to only one SocketManager ...". SocketManager to Recipient is 1:N
ashitaka
Yes. From my point of view, the List of SocketManager is not strictly necessary, but as you said, you may want to manage the socketManager (start, stop, get the current state, get some information on traffic...)
PATRY
A: 

At an abstract level, you have: 1 Thing that relates to n OtherThings. You could model this by creating a special relationship object that refers back to Thing and contains a java.util.List<OtherThing> of references to the n OtherThings. This leaves your domain objects (Things) uncluttered with relationship information. But if it seems right, its simpler to add the java.util.List directly to class Thing (or a subclass). The List variable can be left null and populated with a java.util.ArrayList<OtherThing> only when you need to establish the relationship.

Jim Ferrans