Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

FBNS: Final locking architecture, comment please...

 
Klaas van Gelder
Ranch Hand
Posts: 111
Java Linux PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi goeroes...,
I think it is better to start a new thread for this :-)
After reading many discussions on the forum concerning the lock mechanism, whether or not to modify the Data.lock and .unlock signatures and the use of a lockmanager, I came up with the following (final ?) design:
EAch client recieves his own copy of the remote object FlightDataImpl, which encapsulates a FlightDataAdapter object.
There is, however, only one Data object, created in the RemoteConnectionFactoryImpl class and passed in to the FlightDataImpl constructor.

This makes it impossible to use the original Data.lock and unlock methods method without changing the signature. The data class has no knowledge of different clients and as there is only one Data object, the this identifier cannot be used for identifying the client who performed the lock.
Adding an extra parameter to the lock method for passing in a reference to the FlightDataAdapter class would be sufficient, but clearly violates the specs telling us to implement the original lock and unlock methods.

Therefore I started reading about the use of a lock manager, containing the static Map of locked records and the lock/unlock methods. The lock/unlock methods in the Data class remain useless because the Data class has no way of making difference between clients.
Therefore I leave the methods unchanged and empty.

In my new approach, I create a Data instance and a LockManager instance in the RemoteConnectionFactoryImpl constuctor.
The getConnection method creates and returns an instance of FlightDataImpl, passing both Data and LockManager instances.
The bookSeats method of FlightDataImpl now calls the lock.unlock methods as below:



The this parameter refers to the current FlightDataImpl object and IS unique for each client !
So we have transformed the locking actions to the remote object where they IMHO actually belong. When in local mode, we instantiate a DataAdapter object directly and we have nothing to do with the locking issue anymore.
The only remaining issue is that the DAta.lock/unlock methods are now void and unused. But is this really a violation of the specs ?
Further, because there is only one lockManager object, it is not useful to make the lockedRecords static. Am I right ?
I would be possible to make the LockedRecords a singleton because only one instance has to be created. A good idea ?
Any feedback in my final solution is very welcome !!!

Regards, Klaas



class FlightDataImpl<>-(1)------------(1)-> class FlightDataAdapter <>-(N)--------(1)-> class Data
extends UnicastRemoteObject        implements FlightDataServices
implements FlightDataRemote, Unreferenced
--------------------
+ FlightDataImpl(data, lockManager)
+ bookSeats(recNum, seatsToBook)




---------------------------
class RemoteConnectionFactoryImpl
extends UnicastRemoteObject
implements RemoteConnectionFactory
---------------------------
-data : Data
-lockManager : LockManager
---------------------------
+ createConnection() : FlightDataRemote
(creates a Data and a LockManager object
and passes these to the FlightDataImpl
constructor)
---------------------------


class LockManager
- final Map lockedRecords = new HashMap();
+ lock(int record, Object owner) throws DatabaseException
+ unlock(int record, Object owner)
+ unlockAll(Object owner);

[ July 24, 2004: Message edited by: Klaas van Gelder ]

[ July 26, 2004: Message edited by: Klaas van Gelder ]
[ July 26, 2004: Message edited by: Klaas van Gelder ]
 
Klaas van Gelder
Ranch Hand
Posts: 111
Java Linux PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By the way, for handling client crashes, I finally choosed to have the remote class FlightDataImpl implement the Unreferenced interface.
The unreferenced() method calls the unlockAll method, which unlocks all records which have been locked by this client.
Though there is some time delation, I think this solution is much simpler than using a separate thread for polling disconnected clients, and already extends the requirements...
(I place an answer on my original message instead of modifying it to move my message to the top of the list again, maybe anybody will reat now ;-) )

 
Anton Golovin
Ranch Hand
Posts: 527
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Klaas! I am also thinking about locking, and this is what I came up with:

I am going to use a static data structure in the data class to keep track of locked records. However, I am going to make the assumption that a record is never deleted from the database. If it is marked deleted, it can be overwritten by a new record, but it is never wiped. Thus, I can safely state that the offset byte count for each record (where the file starts to be read) is going to be the same record after record. Thus, I can use this offset value as the security cookie, and also I can use this value to calculate the record number. This offset value is guaranteed to be uniqie for each record that I lock.

Another problem, and unfortunately the hardest to solve, is the global db search. I handle it in this way: If the tracking data structure contains a zero, then threads waiting to lock the record must wait and defer. This way, zero is the flag that eventually clears the file of locks and allows the find method to execute. I am not sure how efficient it is, but it seems like the only alternative. The problem arises when there are multiple searches pending, and that is why a search thread must check if a zero is already in the data structure before depositing its own.

I was thinking of implementing a Map where the key is the offset and the value is the record number, or vice versa.
[ July 26, 2004: Message edited by: Anton Golovin ]
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Klaas,

The solution that you have come up with is spookily very very similar (even in class and method naming) to the one I submitted for FBNS earlier in the year. I think that the main consideration here is that Sun don't mind whether you use the original locks or a LockManager class so long as you justify your decision with sufficient knowledge and reasoning to convince the reviewers that you know what you are doing - assuming that it actually works when they test it!

After much frustration, thinking, designing and redesigning, I decided to change my opinion from using the original methods to a LockManager and found that the solution simplified itself. However, like I pointed out, it wasn't the fact that I made the LockManager choice that got me full marks for locking but the fact that I could justify my decision in the Design Choices document and final exam. The long design process that I forced myself to complete worked in the end and gained me a pass percentage of 93% - design, think, consider and (if necesary) redesign - unlike "real" commercial projects, deadlines are not an issue.

Good luck,

Ian Roberts
 
Klaas van Gelder
Ranch Hand
Posts: 111
Java Linux PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanx Ian, and it give me confidence that you got full locking score with a solution coming so close to my own... :-)
One issue remains. I create one instance of the LockManager and pass that instance to all newly created remote objects. MAybe this could be a reason to make LockManager a singleton class. Actually, i rarely used singletons before, and I doubt whether its use has added value in this context.
I am curious what is your opinion about this...
Greetings, Klaas
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic