• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Unique Id for lock/unlock

 
Venkatesh Krishnappa
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To validate whether the client invoking unlock() on a record is the current owner of the lock, what are the possible solutions ?
1. Using a unique client id
2. Making the calls lock-modify-unlock atomic (synchronized)
please lemme know your comments on the 2nd solution ?
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Venkatesh
I will assume you are doing the Fly By Night Services assignment.
1. Using a unique client id

Where would you use this unique client ID? The lock / modify / unlock methods provided by Sun do not allow for it. And you have to provide the same method signatures to your client.
2. Making the calls lock-modify-unlock atomic (synchronized)

Where would you do this synchronization? If you do it on the client, then it is only the client code that is synchronized: the server is still unsynchronized. And you cannot really do it on the server, since you have to provide access to the lock method to the client.
For both the solutions above, you would have to break some part of the requirements. I know that people have done this in the past and passed, so you might decide that this is the way to go.
However there is a solution that does not break the requirements. Perhaps you should do a search for ConnectionFactory in this forum - see if it gives you any ideas.
Regards, Andrew
 
Max Habibi
town drunk
( and author)
Sheriff
Posts: 4118
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Venkatesh, welcome to SCJD.
Basically, you have to keep track of the client who initiated the lock. That is, you need some mechanism for knowing that user A is holding lock #1, and so on. How you do this is a matter of some debate, but in general, most people use some of singleton and/or static structure that either is a Map, or has access to a map. If you start thinking along those lines, you'll start to see the light pretty soon.
All best,
M
 
Venkatesh Krishnappa
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Andrew/Max, thanks for your instant replies.
coming back to the issue:
Andrew, I saw the ConnectionFactory design. so, the solution would be to create a new RemoteData object for each client and use the RemoteData's object id (using java.rmi.server.ObjID)to track the ownership of lock and unlock in the LockManager. right ?
we end up creating new objects for the sole purpose of trackig clients ....
what about the foll solution :
* generating a unique id by the server and client uses this id for lock and unlock. this requires us to change the method signatures of lock and unlock. but it's still okay I believe if we properly document the reasons !
what do you think ?
by this way we don't have to worry about the garbage collection of the new objects created for each clients.
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Venkatesh
The ConnectionFactory is one solution - not necessarily the only solution. It is not even the only solution that works without changing the signatures of the methods (another way would be to have a serialized class that gets shipped over to the client side via RMI).
create a new RemoteData object for each client

Yes, that is the essence of what the ConnectionFactory solution will do for you.
and use the RemoteData's object id (using java.rmi.server.ObjID)to track the ownership of lock and unlock in the LockManager. right ?

Well, I didn't have a LockManager, and I didn't track ownership of locks at the Data class. But your suggestion could work.

what about the foll solution :
* generating a unique id by the server and client uses this id for lock and unlock. this requires us to change the method signatures of lock and unlock. but it's still okay I believe if we properly document the reasons !

Well the specification states:

The remote client code that you write must provide all the public methods of the suncertify.db.Data class.

I don't like your solution because it changes the signature. I therefore believe it does not meet that "must" requirement.
by this way we don't have to worry about the garbage collection of the new objects created for each clients.

What is your concern with garbage collection? The created objects get cleaned up by the RMI JVM - you should not have to do anything special to handle garbage collection.
Regards, Andrew
 
Max Habibi
town drunk
( and author)
Sheriff
Posts: 4118
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Venkatesh Krishnappa:
Andrew/Max, thanks for your instant replies.
coming back to the issue:
Andrew, I saw the ConnectionFactory design. so, the solution would be to create a new RemoteData object for each client and use the RemoteData's object id (using java.rmi.server.ObjID)to track the ownership of lock and unlock in the LockManager. right ?
we end up creating new objects for the sole purpose of trackig clients ....
what about the foll solution :
* generating a unique id by the server and client uses this id for lock and unlock. this requires us to change the method signatures of lock and unlock. but it's still okay I believe if we properly document the reasons !
what do you think ?
by this way we don't have to worry about the garbage collection of the new objects created for each clients.

Venkatesh,
A couple of issues here. First, I probably wouldn't change the method sig: doing really avoids the problem Sun asked you to solve, in lieu of solving a problem that you find easier. I think a grader could fail you on the spot, and there would really be nothing you could say.
Second: the goal of the connector architecture is really to provide a mediator pattern: that is, providing an partner for you GUI code. Thus, it provide advantages outside of simply being something to track.
All best,
M
[ July 09, 2003: Message edited by: Max Habibi ]
 
Patrick Cobbett
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm getting worried. All the solutions posed above seem more complex than necessary. Surely RMI assigns a new thread for each client. Therefore, when a lock() operation is performed you can determine which client has locked the particular record by calling Thread.currentThread(). Associate record locks with threads, ofwhich each client is assigned a unique one.
Sorry if this is too simple for the cow boy coders out there :-)
 
Max Habibi
town drunk
( and author)
Sheriff
Posts: 4118
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Patrick Cobbett:
I'm getting worried. All the solutions posed above seem more complex than necessary. Surely RMI assigns a new thread for each client. Therefore, when a lock() operation is performed you can determine which client has locked the particular record by calling Thread.currentThread(). Associate record locks with threads, ofwhich each client is assigned a unique one.
Sorry if this is too simple for the cow boy coders out there :-)


Patric,
I can understand why you might feel that way. It does seem like a lot of us just like to noodle with complexity, doesn't it?
But the fact is, it's neccessary in this case. RMI doesn't assign a new thread per client: it has a pool of threads, and recycles those. Here's a simple test you can perform. Create 15 clients and track the remote thread IDs assigned to each. Now drop 5 of them, and create 5 more. That should be enough to get RMI to start recyclig threads on most PCs, and the demo will probably prove the point more strongly then any statement I could make.
good luck,
M
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Surely RMI assigns a new thread for each client.
No, this seems reasonable but is not necessarily the case. The RMI Spec specifically refuses to make any such guarantee. It's possible that two method calls from the same client will use different threads; it's also possible that two calls from different clients use the same thread (though not at the same time of course) if some sort of thread pooling is being employed. So unfortunately, we can't really do anything useful with a reference to Thread.currentThread().
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It does seem like a lot of us just like to noodle with complexity, doesn't it?
I'm sure I don't know who you might be thinking of, Max.
 
Patrick Cobbett
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Max Habibi, that is a subtle and very valid point. I was days aways from submitting my assignment, i think you just saved me there. By the way i own a copy of your book, great read.
If you are aware of the Fly by Night services assignment (or anyone else) perhaps you can help me on this one:
The requirements specify that the Data client(in my case connection) should provide the same interface as the Data class. However, the method close() in Data is to close the database. I can only hope that they don't expect clients to be able to close the database! Therefore i can only assume that they intend for close() to close the connection to the database. What should be implemented for this method? Perhaps a call to unlock(-1) to guarantee that there are no locked records, although a well behaved client should release records it has locked. I had been wondering how to free up it's assigned thread, but as you say there is a thread pool so no resources need 'freeing'. What is expected? I notice that in your example in your book clients do not have an equivalent method.
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Patrick
However, the method close() in Data is to close the database. I can only hope that they don't expect clients to be able to close the database! Therefore i can only assume that they intend for close() to close the connection to the database. What should be implemented for this method? Perhaps a call to unlock(-1) to guarantee that there are no locked records, although a well behaved client should release records it has locked.

I tracked on the server side which records a client had locked. If they called close or if the client crashed then I released any outstanding locks.
I hadn't thought about a client calling unlock(-1) to unlock any locks it has though: my thinking was that you would only call that if you had locked the entire database. However I can see that unlock(-1) could be implemented as a "release all locks owned by this client" - this would still work whether you had locked the entire database or several individual records.
I also used a connection factory. This meant that I could also take the view that calling close() meant that the connection could no longer be used to query the database. This provides similar functionality to the Data.close() method which claims that you cannot get results from other methods once you have called close().
Regards, Andrew
[ July 11, 2003: Message edited by: Andrew Monkhouse ]
 
Patrick Cobbett
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Something which confused me in the requirements is that the definition for unlock() is described as below, taken directly from the assignment:
"The unlock method simply removes the lock from the specified record. If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken."
I assumed this mean't that the Data class itself should be aware of the 'connection' which invoked the method. Afterall this is how the method is described in the contract. At first i thought that the 'connection' would be associated with a thread, seeing as no more parameters are allowed in to the method declaration. I didn't understand how Data would know what connection invoked it.
Am i to assume that the methods lock() and unlock() operate the same no matter what the invoking source. Is the description as provided in assignment describing the interface from the network layer which is built on top of Data? Having had good feedback from people i can only assume this is what is intended. I just think that it was pretty unclear in the project hand-out!
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Patrick

The unlock method simply removes the lock from the specified record. If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken.

I took those as two separate statements. If you consider the sentence "If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken." on it's own, then it becomes a little easier - all you have to do is ensure that the connection does not pass any calls to unlock for any record that the connection has not locked. This saves the issue of trying to get the Data class aware of who is performing the lock.
Regards, Andrew
 
Patrick Cobbett
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, thanks. I think i'm with you. So, as far as the Data class is concerned, it doesn't care who locks or unlocks what, regardless of who invoked the locks? So that last statement..
"If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken."
.. is not actually part of the Data contract.
So the functionality as described in the requirements is actually describing the way inwhich the Data class should be used- not the way it operates?
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Patrick
That's the way that I interpreted it.
Each connection was still safe though - a connection (the client code) could not release a lock that it had not aquired.
Regards, Andrew
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic