GeeCON Prague 2014*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes NX: [UrlyBird 1.3.1] - locking and [client] thread death Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "NX: [UrlyBird 1.3.1] - locking and [client] thread death" Watch "NX: [UrlyBird 1.3.1] - locking and [client] thread death" New topic
Author

NX: [UrlyBird 1.3.1] - locking and [client] thread death

james render
Ranch Hand

Joined: May 08, 2003
Posts: 72
Hi guys,
saw some earlier posts discussing the required behaviour for situations where a thread has locked a particular record and then, for whatever reason, died - leaving the record locked.
Max suggested keeping the locks in a WeakHashMap, so that they would be garbage collected eventually.
But...
1) What thread death scenarios are we talking about here? Exceptions on the server side? Client disconnections
2) Couldn't this problem be handled soley by finally blocks?

Hmm let me just check my old programmer notes about finally sections...
Okay my notes say that there are 4 scenarios where finally won't get run.
a) death of the thread
b) system.exit()
c) no power to cpu
d) an exception in the finally block
don't need to worry about b and c, as this would require the server to be restarted and all locks released.
I suppose that there is an outside chance of an exception whilst unlocking, though struggling to think of one
What are the situations where the thread could just give up the ghost and die??
Is this a real threat that needs to be accounted for??
thanks guys, keep the good work going!
James


[SCJP][SCWCD][SCJD]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
1) What thread death scenarios are we talking about here? Exceptions on the server side? Client disconnections
Client disconnections, mostly. At least, that's the part you have least control over from the server.
2) Couldn't this problem be handled soley by finally blocks?
I believe so, given the limitations of what we're actually required to do. (But I have Contractor, not UrlyBird, so check your requirements carefully.) The method you show looks pretty risky to me - how do we know the record hasn't been updated by another thread recently? We should do a read() before updating to see what's there. For many types of possible updates, we should probably do something like:
  • lock record
  • read current (latest) record data
  • display data to user (so they are aware of latest data before they decide to overwrite it)
  • wait for user to decide whether or how to update the data
  • perform update
  • unlock
  • That third step is the problem - we have no control over how long that might take. So trying to do this all in a single method may be problematic. (Though there may be ways to do it.)
    Now for our actual requirement: the only type of updates we're required to do are updates of fields that are currently null or blank (to "check out" or "reserve" a record/room/flight/whatever). In this case it's possible to do the whole thing in one method without waiting for the user. We just need to check is the record still eligible for update, or not? If so, complete the update, if not, tell the user he's too late. Either way, it's possible to structure the code so that we gather all required user input before we perform the lock - and thus there's no need for waiting afterwards.
    So - it seems to me that for our actual requirements, using finally can be sufficient. However if we're planning for possible future enhancements, it's easy to imagine cases where it would be necessary to separate the lock() and unlock() with an arbitrary delay in between - and if your code does allow this possibility, then you probably need to provide some way to eventually unlock a record in the event the client becomes disconnected.
    [ June 25, 2003: Message edited by: Jim Yingst ]

    "I'm not back." - Bill Harding, Twister
    james render
    Ranch Hand

    Joined: May 08, 2003
    Posts: 72
    Thanks for the reply Jim.
    Yeah, my exact method has a read and checking of the record owner, doing exactly what you said - just chucking it back to the client if its already booked. Don't want to give everything away
    I completely agree that having multi-staged client-server processing is beyond the requirements, thats one big can of worms to open.
    Thanks.
    James
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    Cool. But the flip side of this is that a lot of other folks here seem to be concerning themselves more with this issue, so maybe one of them will point out something we're overlooking...
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi Jim & James,

    James: 1) What thread death scenarios are we talking about here? Exceptions on the server side? Client disconnections
    Jim: Client disconnections, mostly. At least, that's the part you have least control over from the server.

    I agree with this - that was all I was trying to guard against.

    James: 2) Couldn't this problem be handled soley by finally blocks?

    A finally block in the client code will not handle a client application crashing, or a network disconnection, or a power outage on the client machine (the client must be able to run on a different machine than the server), or a badly written client application failing to clear it's locks (who's to say that only your client will ever be used).
    I think we should take reasonable steps to write a robust server. Using a WeakHashMap is not so difficult that it would be classified as unreasonable. Even my total "unreferenced and handling bad clients" code is only around 60 lines of code (not counting documentation) so I dont consider it to be unreasonable.
    Now if you decide to have the "lock / verify / modify / unlock" calls all hidden inside one "update" method on the server, then your concept of using finally should work. However I have other reasons for not liking that solution.
    Regards, Andrew


    The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    Now if you decide to have the "lock / verify / modify / unlock" calls all hidden inside one "update" method on the server, then your concept of using finally should work.
    Yes, I should have explicitly said that I was talking about finally on the server, not the client.
    However I have other reasons for not liking that solution.
    Such as?
    Thanks...
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi Jim
    I think that it is more extensible if you have the client doing explicit locking. I will give some examples, but I acknowledge that they are out of scope.
    Consider an enhancement in the future where you have to allow two items to be modified simultaneously, but the modification is only to be performed if both can succeed.
    Or consider if you had to do some updates to a record that may be changing rapidly. You need to make sure that the fields that you are basing your calculation on do not change while you are doing your calculation (client side) othewise the result of your calculation which is then saved in the record itself will be wrong which will cause later calculations to also fail.
    Both of these can be handled fairly easily if you perform the lock on the client side.
    Both might be achievable if you added rollback functionality to the server.
    If you are currently doing locking on the server side, then to change to locking client side, or to add rollback functionality, you are going to have to change the server. This will involve regression testing of the server (with all known clients, not just your client), and at least one server outage (it may only be for a few milliseconds, but it is still an outage).
    If you are currently doing locking on the server side, then to change to locking client side you are going to have to rewrite whole sections of the client code, and test thorougly. If a bug is found in the client code while you are doing these major changes, you will either have to ignore it, or maintain two copies of the client code: one for the old version, and one for the new version.
    Regards, Andrew
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    Thanks, Andrew. I've been vacillating on this issue, for many of the same arguments you describe. Though the ease of updating clients while keeping the server running is a good point I hadn't considered. Hmmm... time for more ruminations...
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi Jim,
    Just as long as you are not getting bored
    Just checked whether I could lock a record in Oracle in a similar manner. Can do (using the SELECT .. FOR UPDATE OF ... clause). If Oracle allow the user to lock records, then I guess we cannot be marked as wrong if we do the same.
    Regards, Andrew
    james render
    Ranch Hand

    Joined: May 08, 2003
    Posts: 72
    Thanks for the feedback Andrew and Jim.
    Andrew, vaguely recall you quoting a Wiki Web principle of you aren't gonna need it. Looking at your arguments for client side locking, most of them are based on, 'at some point in the future'.
    Now the only thing that concerns me is the fact that locking has 80 points allocated to it (at least it does on UrlyBird 1.3.1). I noticed that when you completed the assignment Andrew you scored 58/80 for locking, was this using client side locking or a more (how to phrase) server-side solution?
    I'm comfortable with my server-side locking, I think it meets the requirements BUT am very interested in ideas that gain extra points (duh obvious)..
    thanks again
    James
    james render
    Ranch Hand

    Joined: May 08, 2003
    Posts: 72
    Been trawling through the forums a bit more on this issue. I think that the UrlyBird 1.3.1 has different requirements on the locking than the contractors. My DBMain interface has no client id cookie element to it on the lock() and unlock(), just a record number. This implies to me that other assignments might require client side locking, but that its beyond the scope of my version of UrlyBird.
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi James,
    Andrew, vaguely recall you quoting a Wiki Web principle of you aren't gonna need it. Looking at your arguments for client side locking, most of them are based on, 'at some point in the future'.

    Kind of.
    The YAGNI principle would apply to not developing code for something you dont need right now. Such as deadlock (as oposed to dead client) detection.
    But in this case, we are not talkiing about creating code that is only going to be used in the future. We are talking about where code we have to write anyway should logically reside.
    So I think I can get away with my arguments
    I noticed that when you completed the assignment Andrew you scored 58/80 for locking

    Sorry, you are thinking about someone else here. I was doing the old assignment, which had different marking criteria. I got 49 / 53 for the Server section, but there was no breakdown of where I lost those 4 marks. The server section contains:
  • locking (30)
  • error handling (8)
  • search algorithm: clarity and efficiency (15)
    I could have lost my 4 marks in any of them, but I don't know which ones.
    was this using client side locking or a more (how to phrase) server-side solution?

    I didnt really have a choice for my assignment since it has a requirement that the client call the methods of the Data class. So I had the client call the lock methods etc., and I had unreferenced code in my server to catch dead clients.
    Regards, Andrew
  • james render
    Ranch Hand

    Joined: May 08, 2003
    Posts: 72
    spooky! posted at precisely the same time. Either you're working extremely early or late, or you live in Europe like me
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi James,
    Working late here in Sydney - about to shut down.
    Been trawling through the forums a bit more on this issue. I think that the UrlyBird 1.3.1 has different requirements on the locking than the contractors. My DBMain interface has no client id cookie element to it on the lock() and unlock(), just a record number. This implies to me that other assignments might require client side locking, but that its beyond the scope of my version of UrlyBird.

    It is even scarier than that. Different versions of the UrlyBird assignment have different requirements for locking. Here are the signatures for unlock for the versions I know of UrlyBird:

    You are lucky - you have the option of doing locking server side. With Fly By Night Services, we had to do locking client side (in my reading of the instructions) but we could not use cookies either.
    Regards, Andrew
    james render
    Ranch Hand

    Joined: May 08, 2003
    Posts: 72
    Yeah, read something on a post, didn't check it out throughly. Feeling lucky about that - hmmm now I am worried that its more difficult somewhere else
    btw just returned to the UK from 7 months in Oz, including about 5 trips to Sydney - beautiful city, especially the manly ferry ride.
    bloody pom backpackers!!
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    if Oracle allow the user to lock records, then I guess we cannot be marked as wrong if we do the same.
    Maybe, but we're not rewarded for extra work either, and Oracle does quite a few things that are outside the scope of this assignment. I'm now leaning back towards agreeing with you and allowing clients to lock records (in fact that's what my solution currently does; just questioning whether it should be refactored). But the Oracle argument isn't really very convincing in this context.
    My DBMain interface has no client id cookie element to it on the lock() and unlock(), just a record number. This implies to me that other assignments might require client side locking, but that its beyond the scope of my version of UrlyBird.
    Actually the cookies are among my main motives to slap some sort of facade on top of the DB interface even while it's still on the server, so that no other classes have to think about those cookies. They just seem so pointless to me; I have a strong urge to abstract them away as soon as possible. If performance were more of a concern I could justify this by noting that there's much less network traffic to send one update request than it is to send a lock, get a cookie, send and update with cookie, and then send an unlock with cookie. Or we could still have lock and unlock, but forget the cookies - that would help. But performance isn't currently that much of a concern, and even if it was, you get much more network traffic from those "find all records" requests than you do from individual updates. So OK, I will probably go ahead and export the entire DB interface to the client, unsimplified by any facade. Need an extra adapter class to do something with RemoteExceptions since they're not allowed by the DB interface, but that's no biggie - it's the same as dealing with IOExceptions thrown by the FileChannel. In fact RemoteException extends FileChannel, so I guess I don't really need a new adapter...
    The YAGNI principle would apply to not developing code for something you dont need right now. Such as deadlock (as oposed to dead client) detection.
    Moreover, our customer has explicitly requested a design that will make future enhancements easier, so there is some justification for making consideration for those future enhancements part of what you do need now. And YAGNI makes more sense in an XP-like context where there's an ongoing dialog with the customer. You give the customer the simplest thing that seems to fit his needs, let him see the results, and then if at that point he wants more, or something different than what he said earlier, then you adapt from there. YAGNI is good for dynamic requirements adjustment. But here, we don't have that. Once we turn in the assignment, we can't change it. This gives us a bit more incentive to anticipate the customer's future needs now, since there is no later. Not that YAGNI isn't still a useful concept for us, but it's a bit weaker here than it would be in the real world, IMO.
    I didnt really have a choice for my assignment since it has a requirement that the client call the methods of the Data class.
    Ah. Yeah, my requirements are vague on this point. Though I can see that once you've decided to implement nearly the same DB interface on the client, you might as well make it exact - then it's easier to swap around different parts of your system (e.g. server vs. standalone mode) and handle various future enhancements with minimal effort.
    beautiful city, especially the manly ferry ride.
    What's a manly ferry? Is it anything like a manly fairy?
    [ June 26, 2003: Message edited by: Jim Yingst ]
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi James & Jim
    btw just returned to the UK from 7 months in Oz, including about 5 trips to Sydney

    I've just returned to Oz after 1 year in London (Ealing) preceeded by two years in Holland. I enjoyed living in the other countries, but I am glad to be home. Especially since the depths of winter at the moment are still getting up to around 16 degrees Celcius each day
    What's a manly ferry? Is it anything like a manly fairy?


    It is the ferry for tourists (and locals) to catch in Sydney. From the center of the CBD to one of the more popular surf beaches in under half an hour.
    Fortunately I live close to a different surf beach: 5 minute bike ride there, 20 minutes back again (damn hills).
    Better stop going so far off topic before a moderator yells.
    Regards, Andrew
    Rob Pearson
    Greenhorn

    Joined: Jun 12, 2003
    Posts: 19
    FYI:
    Moreover, our customer has explicitly requested a design that will make future enhancements easier, so there is some justification for making consideration for those future enhancements part of what you do need now.

    Hmmm...interesting, my requirements are almost the opposite:
    The IT director does not anticipate much reuse of the first Java technology system, but intends to use that system as a learning exercise before going on to a web based system.

    So i'm going very YAGNI, but doing things ways I haven't used much before (RMI, FileChannels, Ant, JUnit etc).
    Cheers
    Rob


    Assignment: URLyBird 1.3.3, using Java 1.4.0_01<br />Status: Designing, Experimenting, Reading.
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    Oops, I had forgotten about that part. I was thinking of this:
    Your user interface should be designed with the expectation of future functionality enhancements, and it should establish a framework that will support this with minimal disruption to the users when this occurs.

    Which meshes nicely with Andrew's comments about updating clients without shutting down the server. Except that this comment was stuck under "user interface", but it really seems to effect the whole system. Urg. Further evidence that our client doesn't really know what he wants. Which is actually why I didn't remember the "does not anticipate much reuse" quote - I figured that's the sort of thing he might say now, but I've seen a number of systems at companies that were kept in service far longer than originally intended, because the company didn't have the resources later to do the grandiose rebuild from scratch that they once had planned for. So my sympathies lie more naturally with the
    "build for extensibility" mentatilty more than the "build a prototype and throw it away" school which the other quote seems to invoke.
    So i'm going very YAGNI, but doing things ways I haven't used much before (RMI, FileChannels, Ant, JUnit etc).
    Well I'm hardly anti-YANGI, just less pro- than I might be elsewhere. I definitely agree with the idea of using this as an excuse to delve into new technologies though. I was sorely tempted to try something with SocketChannels and Selectors too, but finally admitted that would be a bit overboard for these requirements. And I hadn't really worked with RMI either, so what the heck...
    Rag Srinivasan
    Greenhorn

    Joined: Jun 05, 2003
    Posts: 11
    Interesting thread.
    I am also going through some soul searching on server-side vs client-side lock/unlock. No where in the requirements is there a reference to clients being able to do it. "Your server must be capable of handling multiple concurrent request, and as part of this capability, must provide locking functionality as specified in the interface provided above.", later, "therefore your locking system only needs to be concerned with multiple concurrent clients of your server. Any attempt to lock a resource that is already locked should cause the current thread to give up the CPU, consuming no CPU cycles until the desired resource becomes available."
    I plan on writing an adapter class, as several others have mentioned. This adapter class resides on the server side and sits between the server thread and Data Object. When it gets a request (say) an "update" call, it calls lock, update, unlock on the Data object.

    // data is a singleton instance of Data that the adapter holds
    void update(int recNo) {
    data.lock(recNo);
    data.update(recNo);
    data.unlock(recNo);
    }
    Any opinions if this is a sound approach ?
    One doubt about the locking: What is the purpose of isLocked(int recNo) method ? I cannot figure out where to use it. My clients cannot access lock/unlock/isLocked anyway, unless I am supposed to use isLocked from inside lock itself (I mean use isLocked to check if the lock has been obtained by another thread and if so wait()). Considering that locking has a appallingly disproportionate weight in the grade than something more important as say OO design, it is worth hearing as many opinions as possible. So please comment freely.
    thanks
    -- Rag
    Steve Wang
    Greenhorn

    Joined: Jun 27, 2003
    Posts: 18
    Hi, Rag
    I am doing this assignment (v1.3.1) too. According to DBMain interface specification, I do not think that I need to keep track of any client ID for coding simplicity (as there may be no need to if I implement all business logic with lock/unlock at the server side).
    I also simply wrap up all business logic in a data adapter and use some sort of connection factory to export this adapter interface to client.
    Regarding isLocked, I invoke it from lock()/unlock(), inside which I simply check if isLocked and then go to either wait/notify(All). This public isLocked feature may be used for extensibility as assignement says. I think server-side locking is neater than client-side for this assignemnt. I am not going far from Sun's specification. Just exactly follow as specified with no additional fancy features.
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11465
        
      94

    Hi Rag,
    Regarding your code:
    I hope that you are checking that the record may still be modified between the call to lock and the call to update. Otherwise this should be fine.
    What is the purpose of isLocked(int recNo) method ? I cannot figure out where to use it.

    As Steve says, this may be used for extensibility later. You may not need to use it in your assignment at all. However to give you something to think about ....
    (Warning: this is presented for thinking about. I am not suggesting that you have to do anything like this for your assignment).
    Remember that lock() is a blocking call. At present this is unlikely to cause a problem since the only modification you are allowing is via the update method which should be fast, so the block should be very short. But if you were writing client side locking, then the potential exists for a bad client to hold a lock for a long period (or just to crash, which means the lock should be held for 20 minutes) - in either case you might not want to be blocked for that length of time. You could use the isLocked method to find out whether the lock has been granted to someone else before attempting to do the lock, thereby saving yourself from becoming blocked.
    This concept creates other issues, but it should give you an idea of how that method could be used.
    Regards, Andrew
     
    GeeCON Prague 2014
     
    subject: NX: [UrlyBird 1.3.1] - locking and [client] thread death