Does this guarantee a unique client?
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Thanks,
Eugene Kononov.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
yes. But why do you like to use the hashCode()?
I plan to use it in the locks Collection to identify a client. What are the other alternatives?
Thanks,
Eugene.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-

-
-
Number of slices to send:Optional 'thank-you' note:
-
-
You could use the DBServerImpl instance itself as the key in the Collection.
Right. I just wanted to see a more readable value in the locks collection.
Eugene Kononov.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
You could have the DBServer have it's own HashSet to keep track of the locks that the client has, and let the unlock() call pass through to the Data classes unlock method only if the record number is in the DBServer's HashSet.
Not knowing your DBServer interface, i might have questions where the above isn't quite correct, and things will need to be moved to the ConnectionFactoryImpl class.
Mark
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
The object itself guarantees a unique client.
Mark:
what did you mean "the object itself guarantees a unique client"? does it define a new lock method on the server side, say lock(int record, Object clientObject), and in the client side invokes lock(3, this) to lock the the third record?
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Ok well first start with the JavaRanch Naming Policy.
"Fssxing"-
Welcome to the JavaRanch! Please adjust your displayed name to meet the
JavaRanch Naming Policy.
You can change it
here.
Thanks! and welcome to the JavaRanch!
Ok now with that done, here are your answers.
First the DBServer object in Eugene's example is a Remote object, so when the client calls getConnection a new instance of it is made and used only for that one client. Hence it is unique to the client. Now I myself called the DBServer object RemoteDataAccess, but that is just symantics.(no not the virus checker software).
Second The object passes DBServer, on my submission has lock(int record) method, this passes the call to the LockManager. I suggest using a LockManager even though in my submission I didn't, but wish I had. LockManager handles all the locking for all the clients, but the DBServer keeps track of records that that client has locked, so that when you call unlock, you can check it to make sure that it has the lock in the first place.
Mark
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
LockManager handles all the locking for all the clients, but the DBServer keeps track of records that that client has locked, so that when you call unlock, you can check it to make sure that it has the lock in the first place.
Mark,
It sounds as you suggest that I should be doing the "lock" check in two places. Is that neccessary? In my design, I do not modify the signature of the lock() (1st requirement), I do ensure that if some client calls unlock() for the record that was locked by someone else it will not have effect (2nd requirement), the client can call lock() and unlock() (3rd requirement), and my check for locks is in one place (simple design). Here is what I have:
The object bound to RMI is the ConnectionFactory:
Once the client gets a reference to it, it calls the getConnection() method that returns another remote object DBServerImpl. DBServerImpl has:
and implements all public methods of Data such as in:
The lock() method of Data uses Lock manager:
synchronized public void unlock(int record) {
RecordLockManager.unlock(record, this);
//System.out.println("unlock() called from " + this.hashCode());
}
where "this" is a unique (I hope) object for every client (because it is part of unique DBServerImpl.
Finally, my lock manager is:
public class RecordLockManager {
private static HashMap locks = new HashMap();
public static void lock(int recNum, Object client) throws InterruptedException {
synchronized(locks) {
Integer record = new Integer(recNum);
while (locks.containsKey(record))
locks.wait();
locks.put(record, client);
//System.out.println("client " + client + " locked record " + recNum);
}
}
public static void unlock(int recNum, Object client) {
synchronized(locks) {
Integer record = new Integer(recNum);
if (locks.containsKey(record) && locks.get(record) == client) {
locks.remove(new Integer(recNum));
System.out.println("client " + client + " unlocked record " + recNum);
} else {
System.out.println("****** client " + client + " tried to unlock record " + recNum);
}
locks.notifyAll();
}
}
}
This entire thing works very well, and I tested it by spawning 50 threads from my GUI each trying to modify the same record multiple times. However, I have not tested it as a client/server yet, and I am questioning my use of static methods in the LockManager and whether my LockManager will actually be on the server.
Thanks for your comments,
Eugene Kononov.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
I also didn't use a LockManager(which I should have). In the LockManager you are passing a reference to the Connection Object, which is fine. In my submission that was not passed. I just had the Connection object have a HashSet with a set of the locks that client has. If it is in there then the client can pass the call to the Data class and unlock the record.
Mark
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
In the LockManager you are passing a reference to the Connection Object, which is fine.
Actually, I am passing a reference to Data, which is wrapped inside the Connection Object:
It still guarantees uniqueness, does it not?
Thanks again,
Eugene Kononov.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
If you are passing the Data reference it would be the same as all the other clients. Each client does not have it's own Data Object, but a reference to the one and only instance of Data.
Does that make sense?
Mark
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
If you are passing the Data reference it would be the same as all the other clients. Each client does not have it's own Data Object, but a reference to the one and only instance of Data.
Yes, that does make sense. I am not doing it right.
Thanks again,
Eugene.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
I have read through this thread and have come across a design decision which I find a bit confusing. Why is a ConnectionFactory required to return a new DBServer type, which is unique to every client? And secondly, if every client has its own DBServer type, why do we need to handle concurrency in a lock manager? Maybe I am reading the whole thing wrong, but my understanding is that if every client has its own DBServer there will never be any contention between clients. I thought that the DBServer should be registered in the registry and every client will get a reference to the same object stored in the registry.
I hope this make some sense.
Please comment, put me straight if I am totally off point.
Regards,
Chiji
SCJP, SCJD, SCWCD<br />"Meekness is not weakness, but power under control"
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Maybe I am reading the whole thing wrong, but my understanding is that if every client has its own DBServer there will never be any contention between clients.
Every client has its own connection object, but all of them wrap the same instance of Data (and possible the same instance of LockManager, if you use one.). So the contention is over the Data (or, more precicely, over the records in the database).
Eugene.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Assuming I had a Factory that returned DBServer objects would my DBServerImpl still need to extend UnicastRemoteObject, since I not registering the DBServer object with the rmi registry?
Thanks
Chiji
SCJP, SCJD, SCWCD<br />"Meekness is not weakness, but power under control"
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Mark
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
In my assignment I have a connection object which is unique to each connection. This connection object is made up of a clientId and a serverId. This is the code I use to create the client and server ids:
Where the client is what I refer to as a remote data client and the server is the remote object that has been created as a result of the connection made by the remote data client.
It is my aim to make the Connection object as unique as possible, which is why I am using the toString and hashCode methods. The Connection object also has its own hashCode method which adds the hashCodes of the two ids and multiplies this by some arbitrary value.
When the remote data client registers itself with the remote object, it passes its id as a paramater to the remote object.
The connection object which is returned to the client is stored on the client and passed back to the remote object when a records needs to be locked or unlocked.
I am very open to critism at this point.
Thanks
Chiji
SCJP, SCJD, SCWCD<br />"Meekness is not weakness, but power under control"
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Mark
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
| Something must be done about this. Let's start by reading this tiny ad: Paul Wheaton's 16th Kickstarter: Gardening playing cards for gardeners and homesteaders https://coderanch.com/t/889615/Paul-Wheaton-Kickstarter-Gardening-playing |











