aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes NX:URlyBird 1.3.2/ A question for Database cache. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "NX:URlyBird 1.3.2/ A question for Database cache." Watch "NX:URlyBird 1.3.2/ A question for Database cache." New topic
Author

NX:URlyBird 1.3.2/ A question for Database cache.

Joe J. Wang
Ranch Hand

Joined: Feb 26, 2003
Posts: 67
Hi there,
I met a problem with the database cache. I tried to cache the database to memory with a helper class, Database. It is static member of Data class. But if the rmi server and a standalone client or more are running on the same machine, then there is a problem of the persistant of the two/more cache instance(one is for the server, and the others are for the standalone clients). If every database write access (I allow dirty read) will go to the database file first, then is there any need for a cache?
I am really lost. I think there are many guys here useing the cache, can somebody give me some suggestions? Thanks a lot!
Best,
Joe


SCJP, SCJD, SCWCD, SCEA I.
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Joe,
I met a problem with the database cache. I tried to cache the database to memory with a helper class, Database

Just a comment before answering your question : if your Database class is a cache, it could be better named Cache.
But if the rmi server and a standalone client or more are running on the same machine (...)

There is no issue, because, under "Locking" the instructions state that "You may assume that at any moment, at most one program is accessing the database file".
BTW Joe, is your design 2-tiers or 3-tiers ? If it is 3-tiers, you may vote in this thread.
To Andrew :
Best,
Phil.
[ October 14, 2003: Message edited by: Philippe Maquet ]
Joe J. Wang
Ranch Hand

Joined: Feb 26, 2003
Posts: 67
Hi Phil,
Thanks for the reply and make me clear that is not a problem and the suggestion on the naming of the cache class and introducing me to the thread for 2 tier/3 tier discussion and all your efforts on this forum! I really learn a lot here reading all kinds of the discussions from you guys.
My design is a 3 tier one, and hide the lock/unlock from the client. I read thourgh the thread (it's really a long one), I think all of you gave great ideas and explanations. I agree with that if the 3 tier is "hated" by sun and the marker, Tony can't get a full score on the Server part.
So I decide to stay with 3 tier.
Thanks,
Joe
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Joe,
My design is a 3 tier one, and hide the lock/unlock from the client.

Good boy ! I'll remember your name.
Best,
Phil.
PS: Don't forget to post your nice vote in the right thread.
[ October 15, 2003: Message edited by: Philippe Maquet ]
Joe J. Wang
Ranch Hand

Joined: Feb 26, 2003
Posts: 67
Hi Phil,
I have another question about the business tier. Do we need to provide the implementation for business create, delete and update? I am planning to provide business create and delete, but not update. Since the update is mainly for the booking. What do you think?
Thanks,
Joe
Joe J. Wang
Ranch Hand

Joined: Feb 26, 2003
Posts: 67
Another question.
Is there any good solution for solving the client crash(may cause the deadlock)? I tried use the WeakHashMap, but met a problem. When I started the first network gui and tried to book a room for the first time, there is a error sometimes. The error is in the DataAdapter's book method. Here is the method's code.

The error occured in unlock(recNo). After the update(), the key of recNo has gone in the WeakHashMap. So the unlock is failed.
But it will be OK for all the other booking after the first book. Strange.
So I use HashMap, then it is fine. But it don't have the feature of WeakHashMap that can handle the client crash.
Best,
Joe
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Joe,
I have another question about the business tier. Do we need to provide the implementation for business create, delete and update? I am planning to provide business create and delete, but not update. Since the update is mainly for the booking. What do you think?

Mmh. While replying to you, I feel Andrew ROFL behind my shoulders : talking to you about the 2-tiers/3-tiers design choice in this thread was just a way to tease Andrew ... who must enjoy now to see me grabbed by my own trap. Anyway, Andrew, let's assume it !
Joe, create, delete and update are part of your database tier, not the business one. Update will be used by your business book() method, while create() and delete() won't be used at all. create() and delete() won't be used, but you must implement them anyway, because your instructions require it.
Best,
Phil.
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Joe,
Another question.
Is there any good solution for solving the client crash(may cause the deadlock)? I tried use the WeakHashMap, but met a problem. When I started the first network gui and tried to book a room for the first time, there is a error sometimes. The error is in the DataAdapter's book method. Here is the method's code.
code:
--------------------------------------------------------------------------------
lock(recNo);
read(recNo);
if the owner is blank then update(recNo, Data);
unlock(recNO)
--------------------------------------------------------------------------------
The error occured in unlock(recNo). After the update(), the key of recNo has gone in the WeakHashMap. So the unlock is failed.
But it will be OK for all the other booking after the first book. Strange.

Oops !
Your pseudo-code looks OK. I don't know where you got the WeakHashMap solution for storing locks (but I guess), but the WeakHashMap by itself shouldn't be guilty. Btw, is Max still around here ?
How do you form your WeakHashMap keys and values ?
So I use HashMap, then it is fine. But it don't have the feature of WeakHashMap that can handle the client crash.

Using a HashMap instead is not the right solution IMO. If you reply the question above, we (I mean someone here) should be able to find why your WeakHashMap solution failed.
Best,
Phil.
[ October 15, 2003: Message edited by: Philippe Maquet ]
Joe J. Wang
Ranch Hand

Joined: Feb 26, 2003
Posts: 67
Hi Phil,
Yeah, I implements the delete() and create() in the Data class. But they are not thread safe.
So you mean the locking of this assignment is mainly for the business operation -- booking, right? There is no need to implements create and delete in the business tier since the instruction doesn't require us to do that. What I was thinking is maybe a remote user with admin privilege wants to delete a record or create a record.
Anyway, it seems there is no need to do what the instruction not require to do. Thanks Phil, hope you will continue the talk on the deadlock detection on that thread.
Best,
Joe
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Thanks Phil, hope you will continue the talk on the deadlock detection on that thread.

Which one ?!
Best,
Phil.
Joe J. Wang
Ranch Hand

Joined: Feb 26, 2003
Posts: 67
Hi Phil,
The longest one!
The thread

Anyway, after you'll vote for the 3-tiers design, we'll discuss further about deadlock detection is you want.
Best,
Phil.
[ October 14, 2003: Message edited by: Philippe Maquet ]

I've voted for the 3-tier design, and decide to stick to it. So you should continue the talk on deadlock detection.
Thank you for the reply on WeakHashMap. I don't have my codes at my office. I will check it when I go back home. Hopefully, I can find what is wrong.
So you think the WeakHashMap is ok with handling the client crash/dead lock?
Best,
Joe
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hey Joe ! In that thread, I was trying to buy Deep's vote, not yours (!), it was just for the fun (I cannot write any post without kidding at least once), and ... BTW, I didn't see your vote in that thread yet ...
Now seriously, it's a good idea from time to time to initiate new "global" discussions relating to main design choices. OOH such threads quicly become "huge" (the bad side), but OTOH they centralize a lot of useful ideas (their good side). I have a few "main titles" in mind :
  • Data access : IO or NIO ?
  • Network : sockets or RMI ?
  • Locking : how to handle deadlocks ?
  • Multiple-tables or Single-Table DB system ?
  • ...


  • If you really want a discussion on deadlock detection, I suggest that you start a new thread ("Locking : how to handle deadlocks ?" seems OK to me), where you would expose your own ideas on the subject (some personal research is enriching), and you'll be suprised of how your thread will grow (a few pages) in just a few days. With a few good ideas per page, you'll get (and all of us) a lot of good ideas for free !
    I'am looking forward for your thread on deadlock detection !
    Best,
    Phil.
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Phil,
    You are right, a global discussion is much much better. But I think the deadlock(concerning the one caused by the client crash) is different for 2-tier from the one for 3-tier. (Now I think the client crash may not cause the deadlock if the lock/unlock is hidden from the client. ) So I am afraid if I start a thread of NX: 3-tier design, deadlock handling, there won't be other people joining in the thread excepts you and me.
    Rrgarding to the thought that the client crash may not cause the deadlock if the lock/unlock is hidden from the client, I think maybe HashMap is OK for the storage of the locked records. Well, I am home now, and still work on the WeakHashMap problem. I hope that I can solve it today, and I can submit the assignment this weekend and then take the essay next monday or tuesday. I am really out of time for my later schedule. Sigh...... Hope I can pass it.
    thanks,
    Joe
    Philippe Maquet
    Bartender

    Joined: Jun 02, 2003
    Posts: 1872
    Hi Joe,
    You are right, a global discussion is much much better. But I think the deadlock(concerning the one caused by the client crash) is different for 2-tier from the one for 3-tier. (Now I think the client crash may not cause the deadlock if the lock/unlock is hidden from the client.)

    Agreed 95% for deadlocks caused by crashed clients. Even 100% if you lock/unlock server side within a try .. finally construct. But crashed clients are only one cause out of two possible causes of deadlock.
    So I am afraid if I start a thread of NX: 3-tier design, deadlock handling, there won't be other people joining in the thread excepts you and me.

    Indeed ! But there is a good side : if you initiate that thread, it will never get huge.
    I hope that I can solve it today, and I can submit the assignment this weekend and then take the essay next monday or tuesday.

    It's really too late to discuss deadlock detection then !
    Best,
    Phil.
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Hi Joe,
    The error occured in unlock(recNo). After the update(), the key of recNo has gone in the WeakHashMap. So the unlock is failed.

    So I use HashMap, then it is fine.

    It sounds like your WeakHashMap entry is getting garbage collected. It will get garbage collected at an indeterminate time as soon as there are no other references to the key (it is a weak reference). That is why the problem appears sometimes and not other times. One of the reasons that many people seem to be using the Data instance as the key - not what I'm doing, though
    I hope someone else can confirm my guess at the cause of the problem.
    cheers,
    Deep
    [ October 15, 2003: Message edited by: Amardeep Cheema ]
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11481
        
      94

    Hi everyone,
    I don't think client death should be a problem for 3 tier RMI solutions. I don't know about for 3 tier Socket solutions, but it probably shouldn't be a problem.
    I don't think that the problem with the WeakHashMap is due to the Key being garbage collected. Whatever the key is should persist between the call to lock() and the call to unlock(). If it didn't then it should never work - not just fail on the first attempt and work thereafter.
    So I would be suspicious that there is some other problem within the locking code.
    Regards, Andrew


    The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Oops! Sorry for the misleading answer.
    The reason for my answer is that I had a similar problem when first using WeakHashMap. I was testing my LockManager with lots of threads. Each thread goes through a number of lock/unlock iterations (eg 100) and has a random sleep time between the lock and unlock (and also chooses the record to lock at random). In short, by varying the number of threads, the number of records and the sleep time, you can vary the amount of contention.
    When I had only a few threads (eg 10), there were no problems. When I had 100 threads, I suddenly had all kinds of funny exceptions being thrown, including the WeakHashMap entry disappearing between lock and unlock. The problem did not occur with a normal HashMap.
    The cause of the problem was that I was using an Integer wrapper around the record number as the Key in the WeakHashMap. There were no references to it from anywhere else, so it was getting garbage collected.
    Now the difference with your problem is that my errors only occurred after there was a lot going on. Exactly what you would expect if it was garbage collection.
    So I will also be interested in the eventual real explanation of your problem!
    Deep
    PS just in case anyone thinks the testing strategy above is complete - it isn't. There's a few more variables you can throw in for even more fun.
    [ October 15, 2003: Message edited by: Amardeep Cheema ]
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Deep&Andrew,
    Thank you for the sugggestions!
    Sorry I didn't come here yesterday after I solved the problem. I guess Deep is right. The WeakHashMap entry is getting GC for the first try of booking. But I don't know why. Yeah, I used the Integer as the key. Coz I remember that I read a threadsome time ago, Max said it is ok to use Integer in that thread. (sorry, I can't find it now). But yesterday, I just change to using the Data instance as the key and Integer as the value. And the problem is gone.
    Andrew, I agree with you, the client crash can't cause the deadlock in 3-tier design. Anyway, I still keep the WeakHashMap, and use the while() {lockedRecords.wait(timeout)} instead of while() {lockedRecords.wait()}.
    So can you guys tell me what is the other cause for the dead lock? I think maybe I won't change my code anymore, and just make statements in my choice document.
    Thanks a lot!
    Joe
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Phew! Self-esteem still intact..

    Deep
    Philippe Maquet
    Bartender

    Joined: Jun 02, 2003
    Posts: 1872
    Hi Joe,
    So can you guys tell me what is the other cause for the dead lock? I think maybe I won't change my code anymore, and just make statements in my choice document.

    Now that you wrote this :
    But yesterday, I just change to using the Data instance as the key and Integer as the value.

    ... there is no other possible cause for deadlock anymore : Because, by design, you won't allow more than one lock to be granted at a time. But for people who allow it, here is a deadlock situation :
    Client A is granted a lock on recNo 100
    Client B is granted a lock on recNo 200
    Client A is claiming a lock on recNo 200
    Client B is claiming a lock on recNo 100
    --> deadlock !
    Best,
    Phil.
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Phil,
    I am very glad to hear that there is no deadlock anymore.
    Yeah, I remember that there is a thread talking about this classic deadlock some time ago. But again, I can't find it. Yeah, if this is the second cause of deadlock, then in my assignment, it is not an issue. Coz the instruction says, the GUI
    must allow the user to book a selected record, updating the database file accordingly.

    Thanks a lot! now I am more confident to submit it.
    Joe
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Hi Joe,
    here's another deadlock
    Client A grabs lock on Record 100
    Client A attempts to lock Record 100
    Depending on your design, you could substitute Thread A for Client A, and then you would have to think about it...
    Deep
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Deep,
    Can you give me a scenario about it? I am a kind of (stupid)man without any imagination.
    My one is a 3-tier design. The GUIController calls the book() in DataAdapter, then the DataAdapter calls the Data.lock(recNo), Data.read(recNo), check if the record is available or not, if yes, calls Data.update(recNo, data), calls Data.unlock(recNo).
    Do you mean if the user will double click on the BOOK button? Or the RMI will use the same Thread to serve two book requests on the same reocrd?
    Thank you for the question!!
    Joe
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Sorry, I should have said potential deadlock. It depends on if your lock is reentrant, like the Java synchronized function, or not.
    Deep
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Deep,
    Thanks for the explanation!
    I think my lock is not a reentrant one. The lock is on the server side (middle tier). If a client starts a book operation, a DataAdapter instance will call lock(), do something, and unlock() consecutively. I think the lock is not reentrant from the client/UI. Am I right?
    Thanks,
    Joe
    Bharat Ruparel
    Ranch Hand

    Joined: Jul 30, 2003
    Posts: 493
    Hello Joe,
    You wrote:

    Andrew, I agree with you, the client crash can't cause the deadlock in 3-tier design. Anyway, I still keep the WeakHashMap, and use the while() {lockedRecords.wait(timeout)} instead of while() {lockedRecords.wait()}.

    I am curious. Why do you use a timeout in the wait method? Did
    lockedRecords.wait() cause a problem in your testing?
    Will appreciate your response.
    Regards.
    Bharat


    SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Bharat,
    Actually, I am not sure if it is a good idea or not.
    The idea is for avoid the following situation happened.
    One client locks a record, and another client(let's assume there are only two clients) tries to lock the same record and of coz it need to wait for the notify. if the first client crashes now and does not call the notify/notifyall, then the second client will always wait there.
    What do you think?
    Thanks,
    Joe
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Hi Joe and Bharat,
    That is a good question, Bharat. I have the following instructions
    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 interpreted this to mean no wait timeout. I am interested to know if there is room for a different interpretation, because this has implications for deadlock recovery attempts. Anyone else care to comment?
    Joe, if your book() method only does the sequence lock-refresh-update-unlock on one record at a time, then my deadlock scenario does not apply. I think you don't have to worry about it.
    However, if we have slightly more complex business methods then we might find ourselves having to lock multiple records (possibly with nested or recursive method calls) before doing the -refresh-update- part of the sequence.
    In this case we should protect our lock mechanism from hanging in case a client tries to lock a record that it already owns the lock on. It is not alway obvious that there will be two attempts to lock the same record because it could happen with indirect references.
    Here is a very simple imaginary scenario which I already used in a different discussion:
    We have a business method moveBeds(RoomFrom, RoomTo, numberOfBeds).
    This must do the following sequence:
    Lock(RoomFrom)
    Lock(RoomTo)
    RoomFrom(-numberofBeds)
    RoomTo(+numberOfBeds)
    Unlock(RoomTo)
    Unlock(RoomFrom)
    In theory the method can be called as follows:
    moveBeds(Room1, Room1, 0)
    Boom!
    Instead of putting complex validation code in all business methods where this situation could occur or creating complex (unenforceable) contracts for all users of this API, I would simply ignore the 2nd lock attempt (within the lock method itself).
    This is also what the Java synchronized keyword does, which is why I mentioned it.
    Hope that clears up the confusion.
    Good luck with your submission and exam. Hope to get there soon myself, but I haven't even started on the GUI yet.
    Deep
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Here are Andrew's comments from another thread:
    (...) whether the signature of the lock method allows deadlock handling.
    There are some people who's signature for the lock() method does not allow them to handle deadlock.

    So I am reluctantly coming to the conclusion that I should not attempt deadlock recovery. Now does that mean I should do nothing, I am asking myself...
    Deep
    [ October 16, 2003: Message edited by: Amardeep Cheema ]
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Deep,
    Thanks a lot for the reply!!
    Yeah, I think you are right for the interpretation of the locking istruction. I should change back to no timeout! I only think about the deadlock when I use the timeout but forgot to double check the instruction.
    Anyway, for the locking on server side, I think if a client crashes immediatly after calls a book operation, the whole action(lock, read, update, unlock) at the server side will be completed by the local DataAdpater instance at the server side. Am I right? Andrew, please comments if you have time. Thanks!
    The following is quoted from the RMI specification.
    As long as a local reference to a remote object exists, it cannot be garbage-collected and it can be passed in remote calls or returned to clients. Passing a remote object adds the identifier for the virtual machine to which it was passed to the referenced set. A remote object needing unreferenced notification must implement the java.rmi.server.Unreferenced interface. When those references no longer exist, the unreferenced method will be invoked. unreferenced is called when the set of references is found to be empty so it might be called more than once. Remote objects are only collected when no more references, either local or remote, still exist.

    Thanks,
    Joe
    Amardeep Cheema
    Greenhorn

    Joined: Oct 08, 2003
    Posts: 17
    Hi Joe,
    I think the answer is somewhere in this thread.
    Cheers, Deep
    Joe J. Wang
    Ranch Hand

    Joined: Feb 26, 2003
    Posts: 67
    Hi Deep,
    Thanks for the link !
    Best,
    Joe
    Bharat Ruparel
    Ranch Hand

    Joined: Jul 30, 2003
    Posts: 493
    Hello Amardeep,
    You wrote:

    I interpreted this to mean no wait timeout.

    I did too. That is why I asked Joe the question.
    Hello Joe,
    You wrote:

    Yeah, I think you are right for the interpretation of the locking istruction. I should change back to no timeout! I only think about the deadlock when I use the timeout but forgot to double check the instruction.

    I agree with you. I have no timeout too, but it is a good strategy for testing.
    Regards.
    Bharat
    Andrew Monkhouse
    author and jackaroo
    Marshal Commander

    Joined: Mar 28, 2003
    Posts: 11481
        
      94

    Hi Joe,
    Originally posted by Joe J. Wang:
    Anyway, for the locking on server side, I think if a client crashes immediatly after calls a book operation, the whole action(lock, read, update, unlock) at the server side will be completed by the local DataAdpater instance at the server side. Am I right? Andrew, please comments if you have time. Thanks!

    Thanks for pointing to the other thread Deep
    Originally posted by Joe J. Wang:
    The following is quoted from the RMI specification.
    As long as a local reference to a remote object exists, it cannot be garbage-collected and it can be passed in remote calls or returned to clients. Passing a remote object adds the identifier for the virtual machine to which it was passed to the referenced set. A remote object needing unreferenced notification must implement the java.rmi.server.Unreferenced interface. When those references no longer exist, the unreferenced method will be invoked. unreferenced is called when the set of references is found to be empty so it might be called more than once. Remote objects are only collected when no more references, either local or remote, still exist.

    This paragraph is unrelated to your earlier question (except that by reading between the lines you can sort of get the answer, maybe).
    This paragraph is talking about the possibility that unreferenced() could be called more than once on any given instance of your remote code. Here is one example of how that could happen:

  • Client gets reference to remote code on MidTier
  • Client starts executing someMethod() on MidTier
  • Client dies
  • Sometime afterwards the DGC calls the remote unreferenced() method on MidTier
  • Either in the remote unreferenced() method or in the remote someMethod() the reference to the MidTier instance is passed to another remote client - the BackEnd. (From the unreferenced() or someMethod() perspective, they would be passing a local reference to some remote method)
  • When the BackEnd discards it's reference to the MidTier instance, then unreferenced on the MidTier will be called for the second time

  • Note: that was just one example of how unreferenced() could be called more than once for any given instance.
    Now the implication is that since this could happen, then your remote code (in my example the code on the MidTier) must survive client death. But that is really reading between the lines.
    I prefer the other thread that Deep pointed you to which gives an example so you can try this for yourself and see what happens
    Regards, Andrew
    [ October 16, 2003: Message edited by: Andrew Monkhouse ]
     
    jQuery in Action, 2nd edition
     
    subject: NX:URlyBird 1.3.2/ A question for Database cache.