Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
I decided not to take in consideration the case of a possible client crash because it?s not part of the requirements(?)(Should I document my decision?)
So, I can avoid dirty reading, n?est-ce pas?
I don?t either use cache. But when you validate your RecordNumber, how do you check if the concerning Record exists? Because I?m thinking to use the position of the Record in the db.db-file as the RecordNumber. But that would force me to read the whole records in the db.db each time I want to check if the RecordNumber is valid.
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
You should be aware that you are not guaranteed to get a unique number by using the Date.getTime() routine. From the API documentation for the System, under the currentTimeMillis() method:
quote:
--------------------------------------------------------------------------------
Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
--------------------------------------------------------------------------------
So if the computer is only accurate to tens of milliseconds, then it is possible to two calls to the lock method may get the same long value.
You don't have to write paragraphs on this. In fact the sentence you have above is probably all you need (although I would probably change "not part of requirements" to "outside of scope" - I think it sounds more professional )
My personal opinion is that it is better to synchronize the read and write from the disk so that it is only while a write is actually taking place that a read will be blocked.
Now some questions:
1) Why do you call notifyAll() in lock() method?
notifyAll is used to notify other threads that the lock is realesed, not acquired!
2) Why do you wait in your read method till user lock is released?
What you said will happen automatically as you thread leaves synchronized() block realeasing releasing the all. synchronized block in java IS a mutex (it calles notify himself: You did invoke wait() for that and you shouldn't invoke notifyAll()).
You need notifyAll() only in unlock method and probably in delete() (depending on your implementation).
2) Why do you wait in your read method till user lock is released?
I dont understand, does it mean that I should have a special Class ReaderWriter and have a static instance of it within Data-Class?
But it's perhaps better for a potential client crash. Ok, some lines before, I mentioned that I don't want to take in consideration a client crash. So should I for reasons of consistence omit the notifyAll-call within the lock-method
I dont understand, does it mean that I should have a special Class ReaderWriter and have a static instance of it within Data-Class?
If you guys keep this up, I'm going to be out of a job
Line 9 notifies waiting threads thats that reserveDVD is free, and the method returns.
Interesting. Can you think of anything other time that thread might need to achieve an Object's monitor?
Hi Bharat, hi everyone
I have a question to you,Bharat, because I think we have quite similar approaches of the locking procedure. But perhaps also someone else can help me?
I don�t either use cache. But when you validate your RecordNumber, how do you check if the concerning Record exists? Because I�m thinking to use the position of the Record in the db.db-file as the RecordNumber. But that would force me to read the whole records in the db.db each time I want to check if the RecordNumber is valid.
SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
I wasn't trying to be cryptic: I just didn’t want to ruin your fun.
Now, when that thread calls notifyAll, then the threads who are trying to get the lock on reservedRecords for the very first time will get an opportunity to do so.
Make sense?
Regarding checking for the RecordNumber, I do access the deleted record flag on the fly in my validateRecord method. Since I am using a random access file and since I can "seek" to a position directly, I don't have to sequentially read through all records. It is easy to compute the offset mathematically given that the records start at a certain position and that they all have fixed lengths.
Any methods that throw RecordNotFoundException should do so if a specified record does not exist or is marked as deleted in the database file.
I am a bit mystified per to why you decided not to use the "Data.this" as the key to the hashmap? It solves a number of problems for you all in one-fell-swoop! 1. It gives you the unique key that you are looking for (assuming off-course that you are using one instance of the Data class for each client strategy),
...
3. Finally, coupled with the WeakHashMap use (only the declaration is different than a regular HashMap, otherwise the usage for our purposes is exactly the same as the regular HashMap), you get the deadlock resolution for free!
do not know ReferenceQueue and how it works. I have not done it and am not going to do it until (if at all) I take care of the other requirements.
2. More importantly, how do you ascertain that a client calling unlock method is indeed the client that locked the record in the first place? Since you are computing your key (cookie, whatever) value inside the method lock, how do you make sure that it is indeed the same value available to you when you attempt to unlock? In my opinion, that value is long gone. OK, so you store it in a HashMap, but how do you re-create it in the unlock method to compare it with the stored value?
does it mean that I should have a special Class ReaderWriter and have a static instance of it within Data-Class?
that line is useless IMO. Now maybe Max will explain why all of us are wrong... (I hope so !).
But I'm sure, Max has surely a trump he hasn't played allready, I'm right?
does it mean that I should have a special Class ReaderWriter and have a static instance of it within Data-Class?
If I synchronize the read and write-method I should be fine?
Concerning this point I have two questions:
1.Where do you store the position of the records. I was thinking about to use this position as the RecordNumber. What do you think about that?
1.a:Just another question: For the implementation of the createRecord-method, which position in the file will you choose to add the new Record, at the end of the file?
SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
It depends what you mean. Do you mean ReadWriteLock mechanism (concurrent reads, exclusive writes)? Or do you mean just a mutex (exclusive reads, exclusive writes) ? I guess you ment a mutex.
If so, you don't need a separate static object. you have already one: reservedRecords. You can synchronize all you public methods on this objects.
One thing that I might not have clarified for you is that I have NO CACHING AT ALL!
It seems like at least on my "old" laptop, a Compaq Evo N600c which is a Pentium III machine, the performance is quite acceptable.
We have a data file with a "fixed" header. You need to compute those fixed number of bytes and store it in an instance variable. I called it "recOffset", you can call it whatever that you want. I am again assuming that you have a class similar to my "DataSchema" class that stores all this "header" information - I have made it a singleton since it needs to do all this computation only once and this information doesn't change. The data class holds a reference to the DataSchema singleton instance. You can always get the total length of the file anytime you want. Subtract the recOffset into the length of the file to get the record data bytes. I also keep the total length of the record information in my DataSchema class instance. Add one to the record length to account for the "deleted" byte flag. Now divide it into the record data bytes that you computed. This will give you total number of records current the data file both deleted and active. Now how do you count the records is upto you, but since everything in Java is zero based, I chose to count the records starting with zero to keep everything in sync with the data structures (ArrayList, Array t name a few) that I use. Therefore record zero is really record one and so on. Now, consider the delete method signature for example: it takes recNo as a parameter - i.e., delete(int recNo). You do not have to store the record numbers
So you store the position where the Records-bytes begin in the variable recOffset, then you store the number of bytes of one Record, 160, in another variable, for example recLen. The size of the ArrayList determine the number of the Records and the RecNo is the position in the ArrayList. I'm right?
Just another question: For accessing the Data-File, within Data.class do you read suncertify.properties to get the position of the db.file?
SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
One thing that I forgot to mention or reply to is that for the create method you sequentially start accessing the deleted flag for record number 0,1,2,3... and so on. If you find a deleted record, stop, update it (really overwrite it) with your new records data keeping in mind the fixed length strings.
I am trying to. That is the only significant piece that I have left. Unfortunately, my attempts to create a dialog-box derived from the JDialog box have not been successful thus far. See my last post in URLy Bird 1.3.1 Suncertify.properties thread.
Just one question : what are you doing with ArrayList structure(s) indexed by recNo if you have no cache ?
SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
I could have just easily used a TreeSet instead.
You don't annoy me at all! I wouldn't worry about it if I were you
I am a bit mystified per to why you decided not to use the "Data.this" as the key to the hashmap? It solves a number of problems for you all in one-fell-swoop! 1. It gives you the unique key that you are looking for (assuming off-course that you are using one instance of the Data class for each client strategy),
...
3. Finally, coupled with the WeakHashMap use (only the declaration is different than a regular HashMap, otherwise the usage for our purposes is exactly the same as the regular HashMap), you get the deadlock resolution for free!
In my Data class, I make use of ArrayList structure only in the find method where I am not sure how many records will match a given criteria. Once I have populated the ArrayList with desired record set, I create an array of "int" to return to the calling class (DataAdapter in my case) so that it matches the method signature specified by the DBMain interface
After reflecting a while, I think I will also go this way.
But I worried about the situation which I described above:
I'm also a little bit afraid because my Data-class won't be the Remote-implementing Class. Like Max for the Danny's DVDStore, I want to create an Adapter-Class, so for example the booking-method would be very similar to yours, which you posted in another thread. So if the client crashes, there will still be a reference to Data.this in the Adapter-instance. But probably now, the instance of the Adapter-Class can also be garbage collected and then I'm fine?
I don't know if you have followed the discussion between Vlad, Max and me above. Because at Topic: NX: URLy Bird 1.3.1 Explicit Fatal Exception Handling I saw that you also include a notifyAll()-call in your lock-method. We are still waiting for Max's reply,
I have a problem understanding the use of your ArrayList in the Data-Class:
Supposed a client is connecting to the server, then there will be a call to get all the Records of the File to be shown at the GUI, I name it getRecords(). I store the Records as String-Arrays, including the RecordNumber, in an ArrayList, check which are valid and give them back as a Collection to the client.
So each time a client makes a request of booking, I got the RecordNumber from him and I can directly access the Record at the concerning position in the File
But if the client wants to find Records with search-criterias, I will read once more the File, store all once more all Records in an ArrayList, create a new local ArrayList and iterates through it to get the RecordNumbers which match with the search-criterias and give the int-Array with the RecordNumbers back to the client.
Is that the way it works?
SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
You (Ulrich) wrote:
quote:
--------------------------------------------------------------------------------
I don't know if you have followed the discussion between Vlad, Max and me above. Because at Topic: NX: URLy Bird 1.3.1 Explicit Fatal Exception Handling I saw that you also include a notifyAll()-call in your lock-method. We are still waiting for Max's reply,
--------------------------------------------------------------------------------
I am not doing anything unusual here, just following Max's lead. Did you follow the DVD example lock method in his book? It is the same concept.
I called it DBClient, this interface defines only the business methods book() and find().
Supposed a client is connecting to the server, then there will be a call to get all the Records of the File to be shown at the GUI, I name it getRecords().
A reference to the Data class is contained in the DataAdapter class which stays around until the client is around and disappears when the client terminates the session normally or abnormally (it crashes!). In both of these situations, the DataAdapter class and hence the Data class are eligible for the garbage collection. Therefore, the WeakHashMap will eventually remove this instance of the Data Class. Now, I haven't simulated this crash-test yet, but am willing to take Max's word for it until I get to the point (quite soon!) where I can test it myself!
Think about it. The ArrayList is a dynamic data structure which will store the "live" records matching the supplied "criteria". It does not mean that the zeroth postion of the ArrayList stores record number zero and so on. Suppose for example, the record numer zero, one, and two are deleted records in the datafile and also suppose that the third record in the data file is a live record and it also matches the find criteria supplied. You will store its number, i.e., 3 in the zeroth cell for the ArrayList. Now when you convert the ArrayList into an Array of ints (or longs if that is what your method signature says), then the zeroth cell of the record number array will contain the value 3! Another thing to keep in mind is that you want to declare an ArrayList as an instance variable in the DataAdapter class and set the returned array from the Data class to this ArrayList. This is the ArrayList that is given to the GUI TableModel to construct the tabular display of the rooms. Depending on whichever row (proxy for the room to be booked) is selected by the user, you look-up the record number in the ArrayList. Therefore, the ArrayList stored in the DataAdapter class is really a list of pointers! It is really cool! I owe it to Andrew/Max/Phil/Vlad to walk me through this process. Take your time doing it, you will be quite pleased with how elegant this all turns out to be.
Why do you define only two methods in this interface? Shouldn't you have at least getRecords()?
Because I wrote:
Isn't that the way your implementation works?
SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
I am not sure what is your RuntimeInterruptedException in the find method within the DataAdapter class?
Tongue wrestling. It's not what you think. And here, take this tiny ad. You'll need it.
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
|