- X 2
Guys, here are the tests I created to test the main functionalities of my implementation of the Data class and the locking mechanism. It also contains a header I created for each class. Some customization of this code will be necessary, according to the implementation of each developer. For instance, my project was the URLyBird 1.3.1, and my lock method does not return any value, and there are some cases where the lock method returns a long value, so this would be a case of customization. Throughout the code, you guys will notice that I used a class called Room and a class called RoomRetriever. The Room class is a representation of a database record, and the RoomRetriever class has 2 methods: one to transform a String array to a Room object, and a Room object to a String array.
This test is supposed to be executed in less than 1 second, so if it doesn't finish in less than 1 second, then the deadlock occurred. It is a very simple and objective test, nothing fancy, but it really helped me getting 80/80 for my locking mechanism and 40/40 for my data storage implementation.
I really hope this helps everyone still working on the assignment!!!
This is the header I used in the classes of the assignment, and I just took the opportunity to show it here, and suggest to people still working on the assignment how the header of the classes could be.
Is it possible that the test is done but main thread is running. do i need to set that as daemon thread.
if i do have deadlock,, how would go for that..
* Practically, it is not necessary to execute this loop more than 1
* time, but if you want, you can increase the controller variable,
* so it is executed as many times as you want
When i changed the loop to run only one instead of 10 times, I exit out in less than 1 sec.
But when i run it i<10, i am stuck..
I would guess you're having a problem in your locking section if it's running for ever. it seems you've deadlock.
Because i just finished the reading/writing to the db, so no locking yet (so no use of calling this test). but i would investigate it a little bit more.
and to be really sure your locking/synchronization code is ok, i would even increment the loop-number to 10000. because if your code deadlocks, you'll get a 0 for locking (i assume) and it would be very difficult to pass the exam
this is what i found. When i run your test case it work some times but then I notice that your unlock method was not in finally section. If i move it to finally section, it works and I can run 1000 to 2000 threads..
Let me know what you think about that..this is what i did where i see unlock method.
I created some kind of "brute-force" test method that create 500 threads that access (Create Read Update Delete) the same record number at the same time to find out if my locking mechanism would not break.
Jeffry Kristianto Yanuar (Java Instructor) SCJP 5.0, SCJA, SCJD (UrlyBird 1.3.2)
Payal, I believe the problem that was happening in your case was that the record was being locked, but the unlock instruction was not being reached, so I believe some Exception was occurring in the update/delete methods (since it worked when you moved the unlock instruction to a finally block). Please verify if this was the case.
that was the case. by putting unlock in the finally section i make sure that record release the lock incase where there is an excpetion. I did the same thing when i did my test cases.
So is that ok if I put your unlock in finally section? I just want to make sure i do not have deadlock..
Thank you so much for sharing your test case..
Just to be sure : you don't handle the deadlock on the server side, don't you? If, on the client side, the client crashes (shut down for example) right after having call the lock method, which is equivalent in your test to comment the data.unlock as shown above. This implies that any other client that call the lock method on this record is lock indefinetly,
am I right?
Well, this is something to be handled in each particular implementation. For instance, depending on your implementation, you'll have to put the call to the unlock method in a finally block. In my case, when performing these tests, I didn't have to because I use memory caching, so an exception can never occur when calling the update method, only when calling the lock method. Now, you can choose to handle the deadlock with some monitoring mechanism that verifies how long a record has been locked. In my case, I didn't implement such mechanism, because it isn't really required, but you can certainly implement one. The tests I suggested are very generic, so they should work with different implementations.
If your program finishes, it's ok. if it doesn't, you have deadlock.
you can simulate a deadlock situation, by uncommenting both lines containing in UpdatingRecord1Thread and DeletingRecord1Thread. It will deadlock for sure, even if your counter of the loop is set to 1 instead of 1000.
I ran it and only got 2 exceptions caused by recordNotFound, I think my lock systems is good = )
About locks, I try to get a thin client ... I'm using lock and unlock on server side, so if a client crashes there is not a problem because the operation will be done.
best regards and thanks again Perillo for the support and share this tool.
Matheus Mendes wrote:What should be the output guys ?
There is no expected output. The program hangs (deadlock) or runs fine (no deadlock). As easy as that.
And you can simulate the deadlock situation by commenting the lines where you unlock the record in UpdatingRecord1Thread and DeletingRecord1Thread
So, the output should be the output of these tests (i.e. "88 trying to lock record #1 on UpdatingRecord1Thread") + the output of your Data class (so, technically, there's no final output, like, "Passed =)" or "Failed =("). It is normal to eventually get a RecordNotFoundException when running these tests. For instance, the UpdatingRandomRecordThread tries to update a record whose number may not exist, so your lock method should indeed throw a RecordNotFoundException.
I used a service layer to interact with the Data class. So the GUI test really doing the service layer methods.
According to my GUI test I got, given A and B represent remote clients:
A then B = A gets results then B gets results
B then A = B gets results then A gets results
A and B simultaneously with same parameters = A and B both get respective results
A and B simultaneously with different parameters = A and B both get respective results
Book Action (my book method checks if there is a duplicate customer ID already used before from a set)
A then B = A updates then B updates
B then A = B updates then A updates
A and B simultaneously same record same ID = A updates then B gets customer ID already used
A and B simultaneously same record different ID = A updates then B gets room already booked
A and B simultaneously different record same ID = A updates then B gets customer ID already used
A and B simultaneously different record different ID = A updates then B updates
Check out Action
A then B = A updates then B updates
B then A = B updates then A updates
A and B simultaneously same record = A updates then B gets already checked out
A and B simultaneously different record = A updates then B updates
A then B = A deletes then B deletes
B then A = B deletes then A deletes
A and B simultaneously same record = A deletes then B gets already deleted
A and B simultaneously different record = A deletes then B deletes
Insert Action (I uses a Room object when client gets alredy created, it's really mean the Room object's equals method returns true - name+location+size are all same will return true)
A then B = A inserts then B inserts
B then A = B inserts then A inserts
A and B simultaneously same room = A inserts then B gets already created
A and B simultaneously different room = A inserts then B inserts
If A and B doing different methods eg A insert and B book - the expected results are returned such as A inserts then B updates or B updates then A inserts.
I shall use this test to do further testing cos my GUI test only using 2 threads.
Bob Perillo's test case scenario fires up the threads andf then they run randomly. I found a lot of errors (mainly wrapping exceptions)
using his scenario and adapted this for my assignment. Just be sure that your wrapping, when not critical, allows the application
to continue and advise the user of the problem. Maybe use an alert window and allow the user to continue.
I got some RecNotFound exceptions but it was foreseen......
Thanks again perillo and all folks....
The good thing is I at least know where the problem is cos when the program just about to hang (deadlock) it prints out the parms I keep track of read/write locks.
Kevin, you can say my GUI test is somewhat static. Loading 2 computers next to each other clicking same time may not be the best test but at least I try to simulate the concurrency. Of course using Threads is better which is what I'm testing now LOL.
Now suppose the lock/update/unlock in the Data class are all synchronized. After Thread1 calls lock and Thread2 comes along and calls lock. Now ideally people do this to ensure atomicity stuff:
Without synchronization inside run, what happens if Thread2 gets the object's lock flag from Thread1 after Thread1 finish calling lock before update. It looks to me this will deadlock even thought Data class lock/update/unlock methods are synchronized. Am I right?
Another way of asking is will Thread1 lose its object lock flag in between synchronized method calls, if Thread2 comes in and calls lock method?
There is no need to wrap the lock/process/unlock within a synchronized try block if you are utilizing a locking map.
The first thread to hit the lock() method will add it to the locking map and therefore block all other threads until the record is
removed. The process (update/delete etc) is then processed and then the unlock() method called which signals awaiting threads.
It's a design decision but I just Synched on the file when updating it, all other processes were done using a cache map.
And for Robert Perillo:
Just a curiosity, what were the errors you found? Most likely you found them due to the differences between the interfaces provided by Sun.
Yes the errors were only errors for me as I had a different interface from Sun
I meant to ask you some time ago - do you feel like adding a link to this in the JavaRanch SCJD FAQ? (The FAQ is just a wiki page - you can edit it yourself).
do you feel like adding a link to this in the JavaRanch SCJD FAQ?
Certainly! And... done!
unlock //Exception since record already deleted
AND my assingment says:
Any methods that throw RecordNotFoundException should do so if a specified record does not exist or is marked as deleted in the database file.
How did tackle this issue? (there is a word should, so it's not mandatory!)
puuh. already doing my submission package... some final tests
Oh: Date's give funny year
Well, the idea of the locking mechanism is to make sure that your application is able to work concurrently properly. It really depends on your particular implementation. But I'd say that, if you used the wait()/notifyAll() schema, then no deadlocks occurred!
In the UpdatingRecord1Thread, try to comment the data.unlock(1); instruction to see if you get a deadlock.