• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Implementing Lock/Unlock

 
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK now the thread stuff is working like charm. I have also implemented the Unreferenced method. It cleared the client connection in about 10 minutes.
Test Scenario:-
One client locked a record and other client waiting for the lock. After about 10-12 minutes the server released all the locks and the waiting client continued.
Back on the idea of server communicating to the clients that "I am going down". I have a question what if the server does not goes down gracefully (crashes), in that case also it be sending the abnormal shutdown message or the client will automatically catch the RemoteException and will display a message to the user.
Thanks.
 
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Samual,
When 5 heartbeats are missed, the client panics and assumes the connection to the server is lost and locks the GUI except for the ablility to display help and exit. The 5 heartbeats are arbitrary.
BTW congrats on getting everything working.
Michael Morris
[ August 19, 2002: Message edited by: Michael Morris ]
 
Samual Harvey
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes. Much Thanks to you and Nate and everybody on this forum is just gr8 and friendly.
 
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Michael

This is a good discussion on using Unreferenced. Pay close attention to Peter's posts on the subject, he's the real guru here.


Will appreciate if u cld refer me to Peter's postings... i mean in case u'r refering to a particular posting of his.
It'll be good that I go through the issuses before I start on my the server design and the lock manager.
At present am still working on the ui.
Thanks once again... u'v been a lot of help to many...
Sarita
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Originally posted by Sarita Gupta:
Will appreciate if u cld refer me to Peter's postings... i mean in case u'r refering to a particular posting of his.


I was referring to this thread that Samual asked my opinion:
Past Discussion

I was trying to point out the fact that Peter, in his posts, not only explained in detail what the Unreferenced interface is and more importantly what it is not, but built an excellant case on why this assignment is perfect for implementing it on our client connection objects.
Hope this helps,
Michael Morris
 
Samual Harvey
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now I am working on the GUI and I have this question:-
1. How should I determine what record number to lock or unlock? Should I create a method in the data class to get the record number?
Thanks.
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Samual,


Now I am working on the GUI and I have this question:-
1. How should I determine what record number to lock or unlock? Should I create a method in the data class to get the record number?


Well that really depends on your design. I wrapped all the DataInfos from the db into FBNDataInfos which had a method to return the record number. I think it would be better not to add anything to Data that you don't have to, but that's just opinion. One way or the other, you will need a DataInfo to accomplish booking, if you are using a Facade for booking you could just pull the record number out in your doBooking (or whatever you call it) method if you pass in a DataInfo. Ultimately though, you'll have to decide how and where to get the record number based on your design.
Hope this helps,
Michael Morris
 
Samual Harvey
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How about if I do this:-
Add a method inside DataAccessFacade and pass it the flight number from the GUI. This method will call the find method in Data which returns the DataInfo object. Now it will call the getRecordNumber on the returned DataInfo object and will return the recordNumber that can be passed to the lock method.
Thanks.
 
Samual Harvey
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One more thing that I would like to ask is while performing the entire database lock with lock(-1), should I also store the clientID who is asking for the database lock. And then while asking for the database unlock unlock(-1) should I also chek the clientID and if its the same clintID who did database lock, it will unlock the database.
Thanks.
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Samual,


Add a method inside DataAccessFacade and pass it the flight number from the GUI. This method will call the find method in Data which returns the DataInfo object. Now it will call the getRecordNumber on the returned DataInfo object and will return the recordNumber that can be passed to the lock method.


That's not the way I did it, but as my Granny used to say "There's more than one way to skin a cat." Your way is as good as mine.


One more thing that I would like to ask is while performing the entire database lock with lock(-1), should I also store the clientID who is asking for the database lock. And then while asking for the database unlock unlock(-1) should I also chek the clientID and if its the same clintID who did database lock, it will unlock the database.


That's what I did. Why not do that? For all we know the db my be locked temporarily to add new flights or compact the db (remove deleted records) and then be unlocked. In that scenario, suppose we had a bug (heaven forbid such a thing!) in the client that caused it to somehow call unlock(-1). Needless to say, chaos would ensue for all connected clients.
Hope this helps,
Micheal Morris
 
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Samual, Michael,
This is a really good discussion. I had a similar design for my lock/unlock mechanism. However, for my design, I am bypassing the lock and unlock methods in the Data.java. Doesn't your design bypassing them as well? Is this the right thing to do?
Thank you!
Christy
 
christy smile
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Samuel, Michael,
I had a similar design as yours for the locking/unlocking mechanism; however, I realized that I am bypassing the lock() and unlock() in Data.java compeletely. I read your post and feel that you are bypassing these functions as well, is that true? Does it matter if we bypass the functions defined in the Data.java at all?
Thank you!
christy
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Christy,


... I read your post and feel that you are bypassing these functions as well, is that true? Does it matter if we bypass the functions defined in the Data.java at all?


That's what I did. I just left lock() and unlock() empty methods in Data. My remote connection objects were composites that contained a referenct to a Data, a reference to a LockManager and a reference to a CriteriaSearch. So all I did to Data was fix the deprecated methods and perform some cosmetic fixes like edit the javadoc comments or format error messages better, etc.
Hope this helps,
Michael Morris
 
Samual Harvey
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes I did the same. Data.java has two empty methods lock and unlock. These methods I also added inside my DataInterface. So it is implemented by both the remote and local classes, although in local mode I do not use the lock and unlock.
 
christy smile
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Samuel, Michael,
Thank you so much for replying!!! I have been sitting on this locking/unlocking issue for more than 4 months (of course, I have been doing something else than SCJD project). I read so many posting of the connection object, just could not figure out how to use the lock() and unlock() for the Data class. What a relieve! Thank you again, and good luck to all of us for the project ^_^
Christy
 
christy smile
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Samuel, Michael,
By the way, how do you justify the decision about bypassing the functions in Data.java in the design document?
Thank you!
Christy
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Christy,


By the way, how do you justify the decision about bypassing the functions in Data.java in the design document?


Well, I used a Builder Pattern to create different composites: local, remote and control. My argument was that composition is a better overall design scheme than inheritance, because composition can be dynamically implemented whereas inheritance is always static. I further argued that modifying a known "working" class was generally a mistake and that Data's role should be limited to data retrieval and modification. You may have other arguments. To implement it in this way, you must have some strong opinion in the matter. Just articulate that as you would in any argument. My reasoning may be totally different from yours even though we came up with a similar solution.
Hope this helps,
Michael Morris
 
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why do you need a LockManager at all? It seems to me that the only reason the existing Data class is inadequate is that, in order to book a flight, you first need to re-read that record (since it may have been modified by someone else, while you were making up your mind), and then immediately afterward (without allowing anyone else access to the database) modify the record (if sufficient seats are still available). Simply stated, you need to implement read-modify as a transaction.
So, why not simply add a synchronized readModifyTransaction() method to the Data class, which would first call the existing read method, then the modify method?
 
Ranch Hand
Posts: 109
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Samual Harvey:
Yes I did the same. Data.java has two empty methods lock and unlock. These methods I also added inside my DataInterface. So it is implemented by both the remote and local classes, although in local mode I do not use the lock and unlock.


What are people's thought on lock/unlock in local mode? As it stands, my implementation is like Samual's - locking over RMI, empty lock/unlock in Data.java, and no locking in local mode. The only thing I'm wondering is if you are to expect that more than 1 local client might access the same database (maybe with remote X11 or whatever), and in such a case, you would want locking just like when you are serving multiple clients via the network.
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Originally posted by Pete Lyons:
... The only thing I'm wondering is if you are to expect that more than 1 local client might access the same database (maybe with remote X11 or whatever), and in such a case, you would want locking just like when you are serving multiple clients via the network.


Nope. The whole point of local mode is for one client to access one database in one VM. So there is no point in locking/unlocking in local mode.
Michael Morris
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Originally posted by Thomas Fly:
Why do you need a LockManager at all? ...
So, why not simply add a synchronized readModifyTransaction() method to the Data class, which would first call the existing read method, then the modify method?


Because in OO design, classes should be limited to a very narrow role. Data's duty is to retrieve and modify records and provide persistence to those records. Adding transaction management to Data is a clear violation of this principle. It is for that same reason that for the best design of this project, a LockManager is nearly a must. Its narrow role is to provide a safe means of concurrent modification of records. Furthermore if you use transaction management without locking you fail to address the requirement to implement lock and unlock.
Michael Morris
 
Thomas Fly
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Michael, I expected something like that, but as one still not entirely out of the C swamp, I just wanted to hear somebody say it.
For you or anybody else then, where does lockManager "hook-in," so as to prevent other threads from accessing locked records?
It appears to me that Data.seek(recno) should be modified, so as to check whether or not a locked record is being accessed, and then wait() if the client isn't the lock owner.
Presumably, lockManager will have a checkLock() method for this purpose.
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Thomas,


Thanks Michael, I expected something like that, but as one still not entirely out of the C swamp, I just wanted to hear somebody say it.


I'm still paying the price for writing 1000's of lines of procedural code. Even today, I'm trying to add a simple feature to some code I wrote ten years ago that we're still using here. So trust me when I say OO is much better. I cherish the day when I get everything converted to Java.


For you or anybody else then, where does lockManager "hook-in," so as to prevent other threads from accessing locked records?


Well, I suppose if you have 100 developers, you'll get at least 90 different ways of accomplishing it. If you think in terms of interface istead of object or procedure, then there are any number of ways to do it. My remote implementation class (which exposed all the public Data interface) had a reference to a Data object and a reference to a LockManager. So when the client called lock(record), the remote object just passed it on to lockManager.lock(record, this). LockManager's lock and unlock methods were synchronized. If a client requested a lock on an already locked record then wait() was called. When a client called unlock() then notifyAll() was called. Now, to keep Data uncoupled from the LockManager, any volatile method in the remote object (modify, delete, etc.) verified that it owned the lock on the record by checking the set of owned locks it contained as well as calling lockManager.isRecordLocked(record, this) before perfoming the volatile operation. That's my implementation of LockManager in a nutshell.


It appears to me that Data.seek(recno) should be modified, so as to check whether or not a locked record is being accessed, and then wait() if the client isn't the lock owner.


Now there you go thinking like a C programmer again.


Presumably, lockManager will have a checkLock() method for this purpose.


Right, or as I called it isRecordLocked().
Hope this helps,
Michael Morris
 
Thomas Fly
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm... well how did you implement criteriaFind? For that matter, how does your locking mechanism work in the case of the provided find(String toMatch) method, which can loop over all the records in the database? Wouldn't "find" be able to sneek under the radar, and access locked records?
Or, in the case of "find" (and presumably, criteriaSearch) do you just wait() if any record is locked?
 
Thomas Fly
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Actually, I believe I see the answer to my own question: it's permissible to read a record that may be include in a transaction that will ultimately modify the record; the primary point of record locking is to ensure database integrity (e.g., 2 different clients purchasing tickets "simultaneously" will result in 2 fewer seats on the plane).
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Thomas,


... it's permissible to read a record that may be include in a transaction that will ultimately modify the record; the primary point of record locking is to ensure database integrity (e.g., 2 different clients purchasing tickets "simultaneously" will result in 2 fewer seats on the plane).


Bingo! It is a "write" lock only as stated in the instructions.


Hmm... well how did you implement criteriaFind?


I had a third reference to a DataSearch implementation. DataSearch was an interface that had one method: criteriaFind(). Doing it like that makes it very easy to add more robust searching later without breaking any existing clients. So, in my design, none of the methods required in the assignment, ie lock(), unlock() and criteriaFind(), were implemented in Data. Data just pretty much stayed as is other than fixing the deprecated methods.
Michael Morris
 
Thomas Fly
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Cool- thanks for the insights. One more day, and then it's on to documentation!
 
Thomas Fly
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have two additional nit-picking points/questions regarding locking, the first of which has to do with the absolute need for using a clientID.
It's true that you don't want client B unlocking a record locked by client A, but since the application has been written by a Sun Certified Java Developer (flourish of trumpets), B will presumably do a lock before it does an unlock (i.e., lock-read-modify-unlock), just like A and every other client. It seems then that B would be blocked- waiting to acquire the lock- from unlocking the record that already has been locked by A.
It seems to me that a more troubling issue is the possibility of client A having network or power problems before having the chance to unlock the record that it's just locked.
I don't believe addressing that issue is in the requirements, so can one just mention the problem, without taking the trouble to code it?
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Thomas,


... but since the application has been written by a Sun Certified Java Developer (flourish of trumpets), B will presumably do a lock before it does an unlock (i.e., lock-read-modify-unlock), just like A and every other client. It seems then that B would be blocked- waiting to acquire the lock- from unlocking the record that already has been locked by A.


All hail the mighty knights of SCJD2 fame! But what about the schmuck that develops a different client application next year and has a subtle bug that occassionally attempts to unlock a record that it does not own?


It seems to me that a more troubling issue is the possibility of client A having network or power problems before having the chance to unlock the record that it's just locked.
I don't believe addressing that issue is in the requirements, so can one just mention the problem, without taking the trouble to code it?


That's what the Unreferenced interface is for. Three to five lines of code take care of locked records from a dead client.
Michael Morris
 
Thomas Fly
Ranch Hand
Posts: 164
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yeah, probably a C app, or... God forbid... Visual BASIC!!!
Thanks again.
reply
    Bookmark Topic Watch Topic
  • New Topic