wood burning stoves 2.0*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Deadlock with multiple clients Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Deadlock with multiple clients" Watch "Deadlock with multiple clients" New topic
Author

Deadlock with multiple clients

Gavin Las
Greenhorn

Joined: Feb 07, 2001
Posts: 7
Hello,
I have hit a problem when testing multiple clients connecting to the database.
I implement the lock read write unlock process. However, if a client crashes (is stopped) mid-way throgh this process, the database is locked forever.
I have considered two alternatives:
1) The server cleans locks that have been held for a certain time
2) The clients notify the server when they die.
I would like to go for the second option. However, I do not know how to get the RMI objects to test if they are alive.
Any help, ideas would be appreciated.
Also, for the entire database locking, what do you do if clients have already locked records and do you queue entire dblocks up just as you do for record locks.
Cheers
Gavin
luis veron
Ranch Hand

Joined: Mar 07, 2001
Posts: 35
I'm using the same design on lock/unlock as Gavin have mentioned.
any suggestion regarding the "deadlock"..How we can cleanly handle this scenario.
Waiting for your reply.
Thanks
Dilip kumar
Ranch Hand

Joined: Oct 16, 2000
Posts: 360
Hi,
I'm planning to implement point # 1 i.e "The server cleans locks that have been held for a certain time". I'm wondering how much time we should consider before cleaning. Is 5 mins okay considering network traffic ?
Thanks
Rudy Yeung
Ranch Hand

Joined: Dec 27, 2000
Posts: 183
This is a good point as I never think of the client's abnormal termination situation during db updatingin my design. As the specification never mentions this point, I am not going to implement it, but will take a note for the written exam.
Thx,
Rudy
Gavin Las
Greenhorn

Joined: Feb 07, 2001
Posts: 7
Hello,
I actually implemented the lock cleaner with a swing timer. It was very easy to do and works very well.
I am still having problems with the entire database lock. I can not work out when to lock the entire database and what to do with existing clients.
Cheers
Dilip kumar
Ranch Hand

Joined: Oct 16, 2000
Posts: 360
Swing timer logic sounds good. Actually I was planning to implement the cleanup process from the client side.
1. Client A locks the record 1 at 1:00pm
2. Client A terminates the application before unlocking.
3. Client B wants to lock same record. It checks the timestamp of record 1. If the time difference is more than 5mins Client B locks this record ( updates timestamp) else wait.
Any suggestions ?
Adrian Yan
Ranch Hand

Joined: Oct 02, 2000
Posts: 688
I don't want to sound rude. But why even bother? I can't find anywhere from the instruction that ask me to worry about client dying in midway. However, I do use the following as a fail-safe (havn't throroughtly tested yet).
try{
lock
read
modify
write
}catch(Exception){
blablablah
}finally{
unlock
}
Since I put the booking on server-side, if anything should happened, finally(unlock) gets executed no matter what. Also, because clients call this book method, only one client can execute this at a time, I don't even need to track clients.
Anyone would like to discuss on this?
Dilip kumar
Ranch Hand

Joined: Oct 16, 2000
Posts: 360
Adrian,
I liked the idea of having booking method @ server side. So when the user performs booking lock(), read(), modify() and unlock() executes on server side as a single transaction.
But I'm getting one doubt. If we implement booking on server side is it necessary to implement lock(), unlock() methods in data client ? Specs mentions that we need to implement all public methods in data client.
Thanks
Adrian Yan
Ranch Hand

Joined: Oct 02, 2000
Posts: 688
Yes, you need to implement the lock/unlock. However, they are the same as the other methods.
Rahul Rathore
Ranch Hand

Joined: Sep 30, 2000
Posts: 324
I think Adrian's idea is quite brilliant.
Without touching the generic Data class itself, we can define another class on the server-side maybe called StoredProcedures or something and this class may define a remote interface containing business logic methods i.e. book() method etc. which interact with the Data class. The Data class itself may include a factory method getStoredProcedures() to return a remote reference to an instance of StoredProcedure.
That would certainly give many advantages of reducing network traffic, faster processing etc.
But the most significant advantage is that the locking design would become much simpler. We need not retain client-ID, because all calls to lock and unlock will come from the server-side itself- We are assured that every lock() will always be followed by unlock() in a well-behaved manner. We need not be bothered about unpredictable clients and unpredictable network connections. The only situation where lock-unlock sequence may fail is where the server itself crashes- but we don't need to bother about that because- server crash is a rare event, and it is an event in which all locks should be automatically cleared- so there is no danger of redundant locking. The server will restart from a clean slate.
I wish I had got this insight earlier. But now it is too late.
However if book method etc. are defined within the Data class itself, then I think it may not be a good design. It may not be easy to justify- although it will make the code terribly simple. In fact if we are defining a synchronized book() method etc. within the Data class then we do NOT need to implement any lock() or unlock() methods. Because the object lock/monitor acquired in executing the book() method would also act as a transaction lock.


[This message has been edited by Rahul Rathore (edited April 04, 2001).]
Aron J. Skantz
Greenhorn

Joined: Oct 12, 2000
Posts: 26
I've implemented my locking the exact same way that Adrian decribes, even down to the unlock in the finally{ }.
When I first read the criterias this was the way I felt it must be done, later on I read various posts about using client-ID for tracking but still think this is beyond the criteras.
Anyway, just wanted to assure Adrian that I have tested this thoroughly, and as far as i can tell it works perfectly.
Regards,
Aron
Douglas Kent
Ranch Hand

Joined: Oct 06, 2000
Posts: 171
I implemented two synchronized methods in the Data class--lock and unlock. If a thread wanting to lock a certain record finds it locked, it calls "wait()" until awakened by the JVM (unlock will call notify) and tests the the lock again until it gets it. On the subject of a thread dying while leaving the lock in place--I would document this as a catastrophic failure requiring restart. If you HAD to implement this, you might set up a counter that tests the number of times a lock has been requested, then grant it after x times, assuming something bad had happened to the lock holder.
Adrian Yan
Ranch Hand

Joined: Oct 02, 2000
Posts: 688
Kent, from what I understand, the only way a thread can dy in the middle of a transaction is come kind of runtime error i.e. computer shutdown, user killing the java process, etc.. According to JLS, these types of error are not required to be handled by the programmers, since there are nothing we can do to stop an user from unplugging the machine.
Rahul, I thought about using adapter pattern in reusing Data class, then add the booking functionality into the adpater class, (my rmi server class). However, my justification for what I did is this: making the code simple and easy is a reason by itself.
I have been looking over my code over and over again, it's so simple that I can't believe it. My booking, locking, and unlocking methods are simpler than most of the other methods.
Anyway, Aron, thanks for clearing some of my own self-doubts.
------------------
Rahul Rathore
Ranch Hand

Joined: Sep 30, 2000
Posts: 324
Adrian, are you putting the book() within the Data class itself? If yes, then don't you think including business logic with a generic database class is bad design? I think merging business logic into the Database would be contrary to the very basic and fundamental principles of good designing. Mere simplicity may not be good enough justification. It appears simple because the data functionality and business logic we are required to implement currently is very rudimentary, but try extending it to approach any real-world requirement- the inextricable intertwining of database responsibility and business logic will be a design horror. It would also be contrary to the precepts of Object Oriented programming.
I think the business logic must be in a separate class, even if that class is located on the server. And that separate class should not even be the adaptor class. Rather it should be a class dedicated to storing of business logic.
Also if we include the book method within the data class and making it synchronized, we don't even need to implement the lock() and unlock() methods. So even the lock(), unlock() methods would become redundant. I don't think that is the intent of the assignment.
Dilip kumar
Ranch Hand

Joined: Oct 16, 2000
Posts: 360
I was also thinking same way : Not having application specific methods in data class. I think all classes ( except GUI class ) should be generic ( not sure whether it's possible ). If somebody wants to develop some other application like selling/buying stocks they should be able to use the same application just by modifying GUI class. Right now I have Book ticket method in data client which in turn calls lock(), read(), modify() and unlock() methods of data client . Now I am thinking of having Book Method in GUI class so that data client will be more gerenic.
Any comments/ suggestions ?
Adrian Yan
Ranch Hand

Joined: Oct 02, 2000
Posts: 688
Rahul: you are absolutely right about not having business in the Data class. When I made my decision, it has alot to do with criteriaFind method, even thought it's a very generic solution. It still should be considered as a business logic, in my opinion.
In the real world, of course I would put booking in a seperate class. However, after considering the pros and cons of having book on data class:
Pros:
1. In RMI mode, less overhead, more efficient;
2. ACID transaction is easily achieve, without complex solutions;
3. GUI mode is more generic;
Cons:
1. Mixing business logic with data logic;
2. More overhead in RMI;
3. More responsibilities are put on the client;
4. Increased complexity;
Since I havn't finished the assignment yet, more changes will be made, therefore, my decisions are not all final yet.
I would love to make my application perfect, but I'm looking at the requirements, if my app meets them, then I would be ok with it.
Also, Rahul, I'm not sure how you would create a business logic class without using some type of adapter pattern, or extend.
My thought is that, let's create a class (Logic.class), it will create a Data class, it calls lock, read, modify, write, unlock in one of its method (probably the only one besides the constructor.
We need the RMI server class to create both Data and Logic, and it calls the Data and Logic methods appropriately, I'm assuming the RMI server class has this method call book(XXXX).
The client establishes connection to this server and call booking, everything is fine (no problems here).
Now, we need local access, since we don't have a single point of entry like we have in RMI server(all cients call to rmi server), we need somehow create a class that can act like a server. Should we put this responsibility into the DataClient class? I would not do that, because DataClient has to handle both RMI and Local access, we don't want to create to many clients. Beside, we don't want the client to handle logics.
So, the other solution is to create a class functioning similar to RMI server class to provide single point of entry.
As you can see, the solutions have become increasingly complex.
The only solution that I can think of that would seperate the business logic and data logic is to extend Data class, in your subclass, you create the booking method.
Any comments on this? I might misundertood your comments Rahul, if that's the case, please correct me.
Rahul Rathore
Ranch Hand

Joined: Sep 30, 2000
Posts: 324

Now, we need local access, since we don't have a single point of entry like we have in RMI server(all cients call to rmi server), we need somehow create a class that can act like a server. Should we put this responsibility into the DataClient class? I would not do that, because DataClient has to handle both RMI and Local access, we don't want to create to many clients. Beside, we don't want the client to handle logics.
So, the other solution is to create a class functioning similar to RMI server class to provide single point of entry

Sorry I couldn't understand what you are saying. Can you explain further? What do you mean by "single point of entry" and how is your local access different from remote access? What do you mean by saying that we need to "create a class like a server" ?
I disagree with you that we would separate the business logic and data functionality by extending the Data class. That kind of specialization is not object-oriented. That would be saying that "Business logic is a Data" which makes no sense. Whether by direct modification of Data class, or modification in a subclass, I think this merging of business logic into data is not good.
The Data class simply represents a dedicated and efficient data container which can generically hold any kind of data. Its main concerns are reading and writing data from primary storage, preserving the integrity, durability of data and to provide lock mechanisms to ensure ACID transactions. The Data must remain generic and usable for any application whether flight booking or stock market or whatever. The aforesaid database/storage concerns constitute a distinct and a major responsibility.
Business logic are business operations which are carried out using the data. It is concerned with implementing the particular rules of a particular business. In implementing these rules it interacts with the data container without being burdened by the database/storage concerns. Business logic by its very nature is frequently changeable and flexible and it can get very complicated. If for every change/extension in business logic we must tinker with the Data class then there is something very wrong in the design. It would be like integrating the driver of a car with its engine. To change the driver of a car, we would need to change its engine !! It would be unmaintainable, expensive, error-prone if not dangerous.

I could not understand your point about the difference in local and remote access. The only difference in the local access is that you are not using the networking mode- which simply means that you are invoking methods on the real instance and not a stub (the only difficult decision is about handling different exceptions). The Data class should always be a singleton, whether we are using a local or remote access.
I was thinking of a design which should not cause much problem. Instead of defining book() methods etc. within Data class/subclass what we may define is a factory method within the Data class/subclass say getStoredProcedures() returning a reference to an instance of a remote interface StoredProcedures. It would be something like:
public StoredProcedures getStoredProcedures() throws ... {
StoredProcedures sp=new StoredProceduresImpl(this);
return sp;
}
StoredProcedures extends java.rmi.Remote would define business logic methods and will be implemented in a separate class say StoredProceduresImpl, which would have a constructor StoredProceduresImpl(Data db). Define the book() methods (lock-read-write-unlock) etc. within this class.
So on the server-side there would be 2 remote interfaces- one implemented by the adaptor class and another implemented by StoredProceduresImpl.
When there would be a remote invocation on getStoredProcedures() what will be returned is a remote reference to the instance of Stored procedures (over RMI returned objects are either serialized or their remote reference is returned if remote interface is extended), and when there is a local invocation a reference to the actual instance of the StoredProcedures will be returned.

The Data client on the client will follow the following idiom:-
class DataClient {
Data db; //local or remote reference
public void book(XXX) throws ...{
StoredProcedures sp=db.getStoredProcedures();
sp.book(XXX);
}
...
}
I think the idiom is similar to ejb idiom. The ejb client first gets reference to EJBHome and then using EJBHome it gets reference to EJBObject which has the business methods.
I think there a number of other ways we can decouple the business logic from the data even further. Some kind of Factory class could be defined on the server which returns instances of logic class ... but I am feeling too lazy to apply my mind any further.

[This message has been edited by Rahul Rathore (edited April 05, 2001).]
Adrian Yan
Ranch Hand

Joined: Oct 02, 2000
Posts: 688
Rahul:
In your comments, are you saying that StoredProcedure has only one method: book(). If that's the case, clients can only do a book operation (local or remote), if the clients want to do search etc. They have to get a Data object as well.
Can you please give more detail to this?
Rahul Rathore
Ranch Hand

Joined: Sep 30, 2000
Posts: 324
No, not only book. All business logic methods which need to be implemented by a series of read/write calls to the database in an atomic manner. For the assignment we have the book() method only. If it is extended subsequently (not in this assignment) it can be the cancelBooking(), modifyBookings() methods or ....
But in any case, in the design I suggested, the DataClient will first keep a reference (local/remote) to the Data object in a member variable - this will be the initialization in the constructor of the DataClient. When the reference to the StoredProcedures is required it will be obtained only from factory method of the data object. Since the Data client always has reference to the Data object, the other methods like search etc. may easily be invoked on the Data class directly.
As I see it the DataClient embodies the business logic. But for reasons of efficiency, speed, robustness of transactions, certain parts of the business logic are put on the server-side itself. The StoredProcedures basically encapsulates the server-side extension of the business logic. The StoredProcedures is the extension of the data client, or its agent/helper one may say.
I welcome any contradiction and am open to a debate.
[This message has been edited by Rahul Rathore (edited April 05, 2001).]
Adrian Yan
Ranch Hand

Joined: Oct 02, 2000
Posts: 688
Rahul, are you kind of seperating business logic in two different classes also bad design?
Like you say before, if we later have to do a upgrade, that means we have to goto two seperate classes to do the modification.
The only relationship between Data and the business logic (let's call it FBNData) is FBNData uses Data, am I right?
So my new idea is simply creates FBNData, it should contains the business logic such as load data to client, search for client, and booking for client.
So basically, FBNData holds a Data object, FBNData contains three basic method:
1. loadData;
2. searchData;
3. bookData;
Each of these methods in turn calls or implements the appropriate methods in Data.
This solution is really easy for RMI Server.
Now in the local mode, however, it does get abit complicated. In the requirements, we need to implement DataClient with all Data class public interface. I'm not sure using Factory will help much.
I'm still searching for an answer for local mode.
Anyone would like to join the discussion?
Rahul Rathore
Ranch Hand

Joined: Sep 30, 2000
Posts: 324
The name FBNData may be misleading, because it suggests a subclass of Data, which I think we can avoid.
What I mean is that the logic layer is separate from the data layer. I have never said that the logic layer can only comprise a single class. Normally there is a main class and there are supporting classes. In the real-world the logic layer can comprise a number of classes. So I don't think that should be a drawback. And this architecture is accepted that stored procedures are server-side extension of the business logic. That is what stored procedures are in Oracle or any database.
I still think the factory method is the best. It automatically returns a remote reference in the remote mode, and local reference in the local mode (I hope that is clear).
But I guess that everybody must follow his own reasoning. And in any case I too am not implementing the above design.
Best of luck!!
Gavin Las
Greenhorn

Joined: Feb 07, 2001
Posts: 7
Hello,
Looks like I started a very active discussion.
I must say that putting the logic on the server side sounds like a great idea.
At the moment I have implemented a very complex locking mechanism and hit the problem of clients dying midway through the transaction. Throw entire database locking on top of this and you are looking at some very tricky code.

I plan to still allow the client to remotely call all the Data methods... but I will put the booking logic on the server were it is much safer. Hopefully, that gives me the best of both worlds.
Cheers
Sam Wong
Ranch Hand

Joined: Dec 07, 2000
Posts: 133
Last resort is to have some code in the finalize() method to notify the the rmi server that the application is going down and to release the lock on record #x. Just brainstorming. Not sure if this solution is feasible.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Deadlock with multiple clients
 
Similar Threads
Unique Id for lock/unlock
Post Database lock scenario
synchronized on method or object
Locking the Complete Database
URLyBird Requirement Questions