This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
the specification says that you can determine the mode (server|client|alone) by supplying either a command line parameter or none.
As far as I understand from the specifications, the user can specify the filename from a gui at startup (at least in my URLyBird 1.1.3 version) and store the settings in suncertify.properties.
The difference between server and standalone mode is that the standalone mode provides you with the server and client functionality in one single application, but bypassing any kind of network transfer.
The server application will take requests from clients over the network (using either sockets or RMI), but will not present a GUI for booking hotel rooms.
Originally posted by Son Of Liberty Wang: Hi All,
Hope you guys are doing ok on this assignment.
The instruction says the following:
"the program must allow the user to specify the location of the database, and it must also accept an indication that a local database is to be used"
- Is the user allowed to choose a different db file at any time? What if there are more than one db file on the server and the clients don't select the same file?
Also, what's the difference between server mode and standalone mode?
"The UrlyBird catches the certificate. And he's gonna FlyByNight"<br /> <br />SCJP 1.2/5.0, SCJD, SCBCD, SCWCD, SCEA
Originally posted by Son Of Liberty Wang: - Is the user allowed to choose a different db file at any time?
Depending on the mode the application is running in, and only during the start process, I allowed the user to select:
1- In standalone and server modes: the local file to use as the data file. 2- In client mode: the server and port to connect to. The file is defined at the server.
Originally posted by Son Of Liberty Wang: - What if there are more than one db file on the server and the clients don't select the same file?
Clients don't get to choose which data file to open at the server. The server opens the data file upon start and keeps on listening for requests from clients. All these requests will be run against whatever data file was opened when the server started.
Originally posted by Son Of Liberty Wang: - Also, what's the difference between server mode and standalone mode?
In standalone mode the application doesn't connect to anything. There is only one user and a data file (usually local) with exclusive access opened.
In client mode your application connects to a server that controls access to whatever data file it was setup to use, or serve requests out of.
In server mode the application opens a data file and waits for client requests, like finds, updates, locks, etc.
Thanks very very very much! Awesome clarification.
Joined: Sep 02, 2004
Remember to mention whatever assumption you make in your choices document. Also, give a brief explanation about the reasons why you decided to do a particular thing in certain way and not another.
Joined: Feb 03, 2003
Thanks a lot Ed.
I have another question, however, in regards to locking in URLyBird 1.2.2. I am not sure what is minimally required for the locking scheme. Here is my understanding of locking and please correct me if I'm wrong.
1. If some one is reading a record, no writes can be made to it, but writes can be made to other records.
2. If a write is being made to a record, no one can read it or write to it, but other records can be read or updated/deleted.
3. Concurrent reads on any record are allowed.
Are these points what the graders are looking for in the solution?
Joined: Sep 02, 2004
You are on the right track Kang, however, keep in mind that different versions of the assignment may have different interface signatures.
Search more on this forum and you will find lots of discussions about locking. Always keep in mind that your assignment's method signatures might be a little different than those been discussed, but in general you will get the idea.
Although one would ideally like to allow concurrent reads, I wasn't able to achieve this because the signature of my lock method is
public long lockRecord(long recNo) throws RecordNotFoundException;
The problem here is that I can't specify what type of lock I want to put on a record (i.e. a read lock or a write lock) and I don't think I'm allowed to add a parameter to the method.
As a workaround, I could set some flag within the object before calling this method, but then I need to be careful that another thread doesn't change this flag after I set it and before lockRecord() is called. So I reckon it's a lot easier to prohibit all concurrent access to records as there is no requirement in my assignment that I must allow concurrent reads.
SCJP, SCJD, SCWCD
Joined: Apr 08, 2005
Thanks for your reply. It's always good to hear someone else's opinion.
I use another Hashtable to achieve read locks.
private static Hashtable cookies = new Hashtable(); //used in lock() method private static Hashtable readLocks = new Hashtable();
In the readRecord method, cookies is synchronized. Then I check if cookies already contains recNo as a key. If so, it indicates that another thread has locked record recNo, and the current thread should give up CPU and wait on cookies. Otherwise, recNo is added to readLocks if it's not yet in there. I use the current thread's name as the key. When a read is finished, call readLocks.notifyAll(). Reads don't block each other.
In the lock method, I first synchronize readLocks and check if recNo is already in readLocks. If so, wait on readLocks. Otherwise, proceed to lock recNo. In this method, cookies blocks other threads from writing to the same record, and readLocks prevents simultaneous reads, writes on the same record. The signature of method lock stays the same.
Look forward to everyone's advice.
Joined: Mar 29, 2005
I thought about doing something like this, but I don't see how you can you two different Hashtables of locks without nesting locks, which are considered deadlock-prone.
For example, when you want to lock a record for writing it seems to me you should:
- lock readLock, and wait if it is already locked - while keeping the lock on readLock, lock cookies and check if another thread is already writing to the same record
If you haven't used nested locks I'd be interested to hear more details
my URLyBird-Assignment is quite similiar. No word about that I have to allow concurrent reads. One is for sure: if someone is trying to read a record while it is locked by a writer the reader has to wait until the writer is finished. And a writer can't write a record that is occupied by a reader.
Unfortunatly MY read-method doesn't has a cookie in the signature. Therefore I used to implicitly lock a record in the implementation of my read-method. At the beginning of the read-method I'm setting a lock and when the read-method is left the lock is cleared. This offers the possibility of using read-locks (because it's hidden in the impl). But this left me with some (still) unresolved problems. In this case locking a record for modification (via lock) and subsequently reading it (via read) will/may cause problems as long the server is not able to identify that the same client tries to read access the write-locked record. The client may waiting for its own write-lock to be cleared. Using the thread object for id is risky when using RMI (I decided to use RMI). And you have the standalone situation where everything is running in the same VM. And maybe the client-GUI is using worker-threads to avoid a blocking GUI which also can operate concurrently.
I'm still searching for a simple, clear and solid solution. And I'm sure that there are still some issues about that which I haven't regognized at all. What is your opinion about that? Am I wrong? Do I have missed something?
Joined: Apr 08, 2005
Dear Dan and Frank,
Thanks soooo much for your posts on this locking topic.
I absolutely agree that locking both reads and writes are deadlock-prone. Basically, in the readRecord(int recNo) method, cookies (static Hashtable storing all cookies generated by the lock method) is synchronized, and if recNo is already in readLocks (another static Hashtable for reads), the current reading thread waits on cookies indefinitely until recNo is unlocked. In this same synchronized block, after recNo is unlocked or if it's not in cookies to start with, the thread stores recNo in readLocks. Then synchronized(cookies) exits and reading is performed. I'm assuming that a thread cannot perform more than one task at the same time. It has to wait for the first task to finish before submitting a second task.
Therefore, the following scenario is assumed to never occur: - Thread A locks record 1 - Thread A tries to read record 1 but waits for 1 to be unlocked. - Thread A dead-locks itself
- lock readLock, and wait if it is already locked - while keeping the lock on readLock, lock cookies and check if another thread is already writing to the same record"
- In the lockRecord(recNo) method, if recNo is already in readLock, the thread waits on readLock without locking recNo in cookies. Am I making any sense here? PLEASE tell me if I'm missing anything.
Frank, could you elaborate more on why it may be risky to use thread name as a Hashtable key? I'm trying to use serialized objects and for every request that is sent to the server, a new thread(containing a new Data object) is created to handle it. The client waits for a response before it can send another request.
Deeply appreciate everyone's posts.
Sidenote: AC Milan advanced in Champions League. Milan Forever!
Joined: Aug 17, 2004
if you are using RMI (as I am doing) you cannot rely on thread-id. As far as I know RMI does not guarantee that subsequent requests from the same remote client are processed by the same thread in the server. RMI is using thread-pooling. At the server site a number of threads are hanging around in a pool (having a party - which means they are alive - the whole time the server is running!). If a request is commin' in one of them is grabbed from the pool (lets say its Fred) to do something useful. If Fred is finished he's returned to the pool. If a further request is commin' in another thread may be grabbed from the pool (maybe because Fred is currently busied) to do the task. Ok. I just want to be funny ... erm. The thing is: When a specific thread at a client is making subsequent requests at the server you cannot be sure that all requests are done by the same thread at the server. Threrefore, using an id of the thread is a risky and not recommendable solution.
!!! If anything I said before is incorrect someone must correct me !!!
This is very important when you dealing with hanging locks (caused by a crashed remote client). Detecting a crashed client does not work (in RMI) via checking the server-threads alive state (use instead the Unreferenced interface!). This is discussed in other threads in this forum.
The locking is primarily needed in the remote scenario to make sure that different remote clients don't access (in a modifying way) the same record concurrently. If everything is running in the same VM (stand alone situation!) you don't need cookies. You only have to make sure that only one thread at a time is (write)accessing a record (maybe sync them on the record number).
Because I am using RMI for networking I experienced that it is no good to rely on threads directly. I am trying to sync them in some way but I'll avoid to identify them at any time in my code. I am working hard on a solution for this problem.
Joined: Apr 08, 2005
I was very interested in knowing more about how RMI might work in this assignment. Thanks for sharing your knowledge.
I chose to use sockets simply because I was more familiar with it to start with. Since all business logic happens on the server and the client cannot send a second request without receiving a response for the previous request, I don't think I have to worry about relying on a thread's id. The server spawns a new thread to serve each request. This thread will use the incoming socket to send the response back to the client. This is the same socket that the request arrives in. I just open an outputstream on this socket to write the response object. Every such thread is assigned a unique name so that it can be tracked for reads. Since the client is forbid to send another request, each client will have at most one thread working for him on the server.
I will definitely play with RMI after I'm done with sockets. Just the word "RMI" sounds too cool to be igored.
Joined: Aug 17, 2004
ok, I see. If you're using sockets then you have the full control about the threads. But I think with sockets you have to care more about the networking stuff. I'm wasn't familiar with both thematics so I decided to use RMI. And as I posted before I experienced a lot of trouble while handling with thread-ids. That's the crux for RMI I think. Nevertheless, yesterday I've found a solution for myself - I hope its final.